1 /*
2  * dice_stream.c - a part of driver for DICE based devices
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  *
7  * Licensed under the terms of the GNU General Public License, version 2.
8  */
9 
10 #include "dice.h"
11 
12 #define	CALLBACK_TIMEOUT	200
13 #define NOTIFICATION_TIMEOUT_MS	(2 * MSEC_PER_SEC)
14 
15 struct reg_params {
16 	unsigned int count;
17 	unsigned int size;
18 };
19 
20 const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
21 	/* mode 0 */
22 	[0] =  32000,
23 	[1] =  44100,
24 	[2] =  48000,
25 	/* mode 1 */
26 	[3] =  88200,
27 	[4] =  96000,
28 	/* mode 2 */
29 	[5] = 176400,
30 	[6] = 192000,
31 };
32 
33 int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
34 				  enum snd_dice_rate_mode *mode)
35 {
36 	/* Corresponding to each entry in snd_dice_rates. */
37 	static const enum snd_dice_rate_mode modes[] = {
38 		[0] = SND_DICE_RATE_MODE_LOW,
39 		[1] = SND_DICE_RATE_MODE_LOW,
40 		[2] = SND_DICE_RATE_MODE_LOW,
41 		[3] = SND_DICE_RATE_MODE_MIDDLE,
42 		[4] = SND_DICE_RATE_MODE_MIDDLE,
43 		[5] = SND_DICE_RATE_MODE_HIGH,
44 		[6] = SND_DICE_RATE_MODE_HIGH,
45 	};
46 	int i;
47 
48 	for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
49 		if (!(dice->clock_caps & BIT(i)))
50 			continue;
51 		if (snd_dice_rates[i] != rate)
52 			continue;
53 
54 		*mode = modes[i];
55 		return 0;
56 	}
57 
58 	return -EINVAL;
59 }
60 
61 /*
62  * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
63  * to GLOBAL_STATUS. Especially, just after powering on, these are different.
64  */
65 static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
66 {
67 	__be32 reg, nominal;
68 	u32 data;
69 	int i;
70 	int err;
71 
72 	err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
73 					       &reg, sizeof(reg));
74 	if (err < 0)
75 		return err;
76 
77 	data = be32_to_cpu(reg);
78 
79 	data &= ~CLOCK_RATE_MASK;
80 	for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
81 		if (snd_dice_rates[i] == rate)
82 			break;
83 	}
84 	if (i == ARRAY_SIZE(snd_dice_rates))
85 		return -EINVAL;
86 	data |= i << CLOCK_RATE_SHIFT;
87 
88 	if (completion_done(&dice->clock_accepted))
89 		reinit_completion(&dice->clock_accepted);
90 
91 	reg = cpu_to_be32(data);
92 	err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
93 						&reg, sizeof(reg));
94 	if (err < 0)
95 		return err;
96 
97 	if (wait_for_completion_timeout(&dice->clock_accepted,
98 			msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
99 		/*
100 		 * Old versions of Dice firmware transfer no notification when
101 		 * the same clock status as current one is set. In this case,
102 		 * just check current clock status.
103 		 */
104 		err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS,
105 						&nominal, sizeof(nominal));
106 		if (err < 0)
107 			return err;
108 		if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED))
109 			return -ETIMEDOUT;
110 	}
111 
112 	return 0;
113 }
114 
115 static int get_register_params(struct snd_dice *dice,
116 			       struct reg_params *tx_params,
117 			       struct reg_params *rx_params)
118 {
119 	__be32 reg[2];
120 	int err;
121 
122 	err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
123 	if (err < 0)
124 		return err;
125 	tx_params->count =
126 			min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
127 	tx_params->size = be32_to_cpu(reg[1]) * 4;
128 
129 	err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
130 	if (err < 0)
131 		return err;
132 	rx_params->count =
133 			min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
134 	rx_params->size = be32_to_cpu(reg[1]) * 4;
135 
136 	return 0;
137 }
138 
139 static void release_resources(struct snd_dice *dice)
140 {
141 	int i;
142 
143 	for (i = 0; i < MAX_STREAMS; ++i) {
144 		fw_iso_resources_free(&dice->tx_resources[i]);
145 		fw_iso_resources_free(&dice->rx_resources[i]);
146 	}
147 }
148 
149 static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
150 			 struct reg_params *params)
151 {
152 	__be32 reg;
153 	unsigned int i;
154 
155 	for (i = 0; i < params->count; i++) {
156 		reg = cpu_to_be32((u32)-1);
157 		if (dir == AMDTP_IN_STREAM) {
158 			amdtp_stream_stop(&dice->tx_stream[i]);
159 
160 			snd_dice_transaction_write_tx(dice,
161 					params->size * i + TX_ISOCHRONOUS,
162 					&reg, sizeof(reg));
163 		} else {
164 			amdtp_stream_stop(&dice->rx_stream[i]);
165 
166 			snd_dice_transaction_write_rx(dice,
167 					params->size * i + RX_ISOCHRONOUS,
168 					&reg, sizeof(reg));
169 		}
170 	}
171 }
172 
173 static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
174 			  struct fw_iso_resources *resources, unsigned int rate,
175 			  unsigned int pcm_chs, unsigned int midi_ports)
176 {
177 	bool double_pcm_frames;
178 	unsigned int i;
179 	int err;
180 
181 	// At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
182 	// one data block of AMDTP packet. Thus sampling transfer frequency is
183 	// a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
184 	// transferred on AMDTP packets at 96 kHz. Two successive samples of a
185 	// channel are stored consecutively in the packet. This quirk is called
186 	// as 'Dual Wire'.
187 	// For this quirk, blocking mode is required and PCM buffer size should
188 	// be aligned to SYT_INTERVAL.
189 	double_pcm_frames = rate > 96000;
190 	if (double_pcm_frames) {
191 		rate /= 2;
192 		pcm_chs *= 2;
193 	}
194 
195 	err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
196 					 double_pcm_frames);
197 	if (err < 0)
198 		return err;
199 
200 	if (double_pcm_frames) {
201 		pcm_chs /= 2;
202 
203 		for (i = 0; i < pcm_chs; i++) {
204 			amdtp_am824_set_pcm_position(stream, i, i * 2);
205 			amdtp_am824_set_pcm_position(stream, i + pcm_chs,
206 						     i * 2 + 1);
207 		}
208 	}
209 
210 	return fw_iso_resources_allocate(resources,
211 				amdtp_stream_get_max_payload(stream),
212 				fw_parent_device(dice->unit)->max_speed);
213 }
214 
215 static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
216 			       enum amdtp_stream_direction dir,
217 			       struct reg_params *params)
218 {
219 	enum snd_dice_rate_mode mode;
220 	int i;
221 	int err;
222 
223 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
224 	if (err < 0)
225 		return err;
226 
227 	for (i = 0; i < params->count; ++i) {
228 		__be32 reg[2];
229 		struct amdtp_stream *stream;
230 		struct fw_iso_resources *resources;
231 		unsigned int pcm_cache;
232 		unsigned int midi_cache;
233 		unsigned int pcm_chs;
234 		unsigned int midi_ports;
235 
236 		if (dir == AMDTP_IN_STREAM) {
237 			stream = &dice->tx_stream[i];
238 			resources = &dice->tx_resources[i];
239 
240 			pcm_cache = dice->tx_pcm_chs[i][mode];
241 			midi_cache = dice->tx_midi_ports[i];
242 			err = snd_dice_transaction_read_tx(dice,
243 					params->size * i + TX_NUMBER_AUDIO,
244 					reg, sizeof(reg));
245 		} else {
246 			stream = &dice->rx_stream[i];
247 			resources = &dice->rx_resources[i];
248 
249 			pcm_cache = dice->rx_pcm_chs[i][mode];
250 			midi_cache = dice->rx_midi_ports[i];
251 			err = snd_dice_transaction_read_rx(dice,
252 					params->size * i + RX_NUMBER_AUDIO,
253 					reg, sizeof(reg));
254 		}
255 		if (err < 0)
256 			return err;
257 		pcm_chs = be32_to_cpu(reg[0]);
258 		midi_ports = be32_to_cpu(reg[1]);
259 
260 		// These are important for developer of this driver.
261 		if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
262 			dev_info(&dice->unit->device,
263 				 "cache mismatch: pcm: %u:%u, midi: %u:%u\n",
264 				 pcm_chs, pcm_cache, midi_ports, midi_cache);
265 			return -EPROTO;
266 		}
267 
268 		err = keep_resources(dice, stream, resources, rate, pcm_chs,
269 				     midi_ports);
270 		if (err < 0)
271 			return err;
272 	}
273 
274 	return 0;
275 }
276 
277 static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
278 			   struct reg_params *rx_params)
279 {
280 	stop_streams(dice, AMDTP_IN_STREAM, tx_params);
281 	stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
282 
283 	snd_dice_transaction_clear_enable(dice);
284 }
285 
286 int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate)
287 {
288 	unsigned int curr_rate;
289 	int err;
290 
291 	// Check sampling transmission frequency.
292 	err = snd_dice_transaction_get_rate(dice, &curr_rate);
293 	if (err < 0)
294 		return err;
295 	if (rate == 0)
296 		rate = curr_rate;
297 
298 	if (dice->substreams_counter == 0 || curr_rate != rate) {
299 		struct reg_params tx_params, rx_params;
300 
301 		err = get_register_params(dice, &tx_params, &rx_params);
302 		if (err < 0)
303 			return err;
304 
305 		finish_session(dice, &tx_params, &rx_params);
306 
307 		release_resources(dice);
308 
309 		// Just after owning the unit (GLOBAL_OWNER), the unit can
310 		// return invalid stream formats. Selecting clock parameters
311 		// have an effect for the unit to refine it.
312 		err = ensure_phase_lock(dice, rate);
313 		if (err < 0)
314 			return err;
315 
316 		// After changing sampling transfer frequency, the value of
317 		// register can be changed.
318 		err = get_register_params(dice, &tx_params, &rx_params);
319 		if (err < 0)
320 			return err;
321 
322 		err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
323 					  &tx_params);
324 		if (err < 0)
325 			goto error;
326 
327 		err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
328 					  &rx_params);
329 		if (err < 0)
330 			goto error;
331 	}
332 
333 	return 0;
334 error:
335 	release_resources(dice);
336 	return err;
337 }
338 
339 void snd_dice_stream_release_duplex(struct snd_dice *dice)
340 {
341 	if (dice->substreams_counter == 0)
342 		release_resources(dice);
343 }
344 
345 static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
346 			 unsigned int rate, struct reg_params *params)
347 {
348 	unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
349 	int i;
350 	int err;
351 
352 	for (i = 0; i < params->count; i++) {
353 		struct amdtp_stream *stream;
354 		struct fw_iso_resources *resources;
355 		__be32 reg;
356 
357 		if (dir == AMDTP_IN_STREAM) {
358 			stream = dice->tx_stream + i;
359 			resources = dice->tx_resources + i;
360 		} else {
361 			stream = dice->rx_stream + i;
362 			resources = dice->rx_resources + i;
363 		}
364 
365 		reg = cpu_to_be32(resources->channel);
366 		if (dir == AMDTP_IN_STREAM) {
367 			err = snd_dice_transaction_write_tx(dice,
368 					params->size * i + TX_ISOCHRONOUS,
369 					&reg, sizeof(reg));
370 		} else {
371 			err = snd_dice_transaction_write_rx(dice,
372 					params->size * i + RX_ISOCHRONOUS,
373 					&reg, sizeof(reg));
374 		}
375 		if (err < 0)
376 			return err;
377 
378 		if (dir == AMDTP_IN_STREAM) {
379 			reg = cpu_to_be32(max_speed);
380 			err = snd_dice_transaction_write_tx(dice,
381 					params->size * i + TX_SPEED,
382 					&reg, sizeof(reg));
383 			if (err < 0)
384 				return err;
385 		}
386 
387 		err = amdtp_stream_start(stream, resources->channel, max_speed);
388 		if (err < 0)
389 			return err;
390 	}
391 
392 	return err;
393 }
394 
395 /*
396  * MEMO: After this function, there're two states of streams:
397  *  - None streams are running.
398  *  - All streams are running.
399  */
400 int snd_dice_stream_start_duplex(struct snd_dice *dice)
401 {
402 	struct reg_params tx_params, rx_params;
403 	unsigned int i;
404 	unsigned int rate;
405 	enum snd_dice_rate_mode mode;
406 	int err;
407 
408 	if (dice->substreams_counter == 0)
409 		return -EIO;
410 
411 	err = get_register_params(dice, &tx_params, &rx_params);
412 	if (err < 0)
413 		return err;
414 
415 	// Check error of packet streaming.
416 	for (i = 0; i < MAX_STREAMS; ++i) {
417 		if (amdtp_streaming_error(&dice->tx_stream[i]) ||
418 		    amdtp_streaming_error(&dice->rx_stream[i])) {
419 			finish_session(dice, &tx_params, &rx_params);
420 			break;
421 		}
422 	}
423 
424 	// Check required streams are running or not.
425 	err = snd_dice_transaction_get_rate(dice, &rate);
426 	if (err < 0)
427 		return err;
428 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
429 	if (err < 0)
430 		return err;
431 	for (i = 0; i < MAX_STREAMS; ++i) {
432 		if (dice->tx_pcm_chs[i][mode] > 0 &&
433 		    !amdtp_stream_running(&dice->tx_stream[i]))
434 			break;
435 		if (dice->rx_pcm_chs[i][mode] > 0 &&
436 		    !amdtp_stream_running(&dice->rx_stream[i]))
437 			break;
438 	}
439 	if (i < MAX_STREAMS) {
440 		// Start both streams.
441 		err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
442 		if (err < 0)
443 			goto error;
444 
445 		err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
446 		if (err < 0)
447 			goto error;
448 
449 		err = snd_dice_transaction_set_enable(dice);
450 		if (err < 0) {
451 			dev_err(&dice->unit->device,
452 				"fail to enable interface\n");
453 			goto error;
454 		}
455 
456 		for (i = 0; i < MAX_STREAMS; i++) {
457 			if ((i < tx_params.count &&
458 			    !amdtp_stream_wait_callback(&dice->tx_stream[i],
459 							CALLBACK_TIMEOUT)) ||
460 			    (i < rx_params.count &&
461 			     !amdtp_stream_wait_callback(&dice->rx_stream[i],
462 							 CALLBACK_TIMEOUT))) {
463 				err = -ETIMEDOUT;
464 				goto error;
465 			}
466 		}
467 	}
468 
469 	return 0;
470 error:
471 	finish_session(dice, &tx_params, &rx_params);
472 	return err;
473 }
474 
475 /*
476  * MEMO: After this function, there're two states of streams:
477  *  - None streams are running.
478  *  - All streams are running.
479  */
480 void snd_dice_stream_stop_duplex(struct snd_dice *dice)
481 {
482 	struct reg_params tx_params, rx_params;
483 
484 	if (dice->substreams_counter == 0) {
485 		if (get_register_params(dice, &tx_params, &rx_params) >= 0)
486 			finish_session(dice, &tx_params, &rx_params);
487 	}
488 }
489 
490 static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
491 		       unsigned int index)
492 {
493 	struct amdtp_stream *stream;
494 	struct fw_iso_resources *resources;
495 	int err;
496 
497 	if (dir == AMDTP_IN_STREAM) {
498 		stream = &dice->tx_stream[index];
499 		resources = &dice->tx_resources[index];
500 	} else {
501 		stream = &dice->rx_stream[index];
502 		resources = &dice->rx_resources[index];
503 	}
504 
505 	err = fw_iso_resources_init(resources, dice->unit);
506 	if (err < 0)
507 		goto end;
508 	resources->channels_mask = 0x00000000ffffffffuLL;
509 
510 	err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
511 	if (err < 0) {
512 		amdtp_stream_destroy(stream);
513 		fw_iso_resources_destroy(resources);
514 	}
515 end:
516 	return err;
517 }
518 
519 /*
520  * This function should be called before starting streams or after stopping
521  * streams.
522  */
523 static void destroy_stream(struct snd_dice *dice,
524 			   enum amdtp_stream_direction dir,
525 			   unsigned int index)
526 {
527 	struct amdtp_stream *stream;
528 	struct fw_iso_resources *resources;
529 
530 	if (dir == AMDTP_IN_STREAM) {
531 		stream = &dice->tx_stream[index];
532 		resources = &dice->tx_resources[index];
533 	} else {
534 		stream = &dice->rx_stream[index];
535 		resources = &dice->rx_resources[index];
536 	}
537 
538 	amdtp_stream_destroy(stream);
539 	fw_iso_resources_destroy(resources);
540 }
541 
542 int snd_dice_stream_init_duplex(struct snd_dice *dice)
543 {
544 	int i, err;
545 
546 	for (i = 0; i < MAX_STREAMS; i++) {
547 		err = init_stream(dice, AMDTP_IN_STREAM, i);
548 		if (err < 0) {
549 			for (; i >= 0; i--)
550 				destroy_stream(dice, AMDTP_IN_STREAM, i);
551 			goto end;
552 		}
553 	}
554 
555 	for (i = 0; i < MAX_STREAMS; i++) {
556 		err = init_stream(dice, AMDTP_OUT_STREAM, i);
557 		if (err < 0) {
558 			for (; i >= 0; i--)
559 				destroy_stream(dice, AMDTP_OUT_STREAM, i);
560 			for (i = 0; i < MAX_STREAMS; i++)
561 				destroy_stream(dice, AMDTP_IN_STREAM, i);
562 			break;
563 		}
564 	}
565 end:
566 	return err;
567 }
568 
569 void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
570 {
571 	unsigned int i;
572 
573 	for (i = 0; i < MAX_STREAMS; i++) {
574 		destroy_stream(dice, AMDTP_IN_STREAM, i);
575 		destroy_stream(dice, AMDTP_OUT_STREAM, i);
576 	}
577 }
578 
579 void snd_dice_stream_update_duplex(struct snd_dice *dice)
580 {
581 	struct reg_params tx_params, rx_params;
582 
583 	/*
584 	 * On a bus reset, the DICE firmware disables streaming and then goes
585 	 * off contemplating its own navel for hundreds of milliseconds before
586 	 * it can react to any of our attempts to reenable streaming.  This
587 	 * means that we lose synchronization anyway, so we force our streams
588 	 * to stop so that the application can restart them in an orderly
589 	 * manner.
590 	 */
591 	dice->global_enabled = false;
592 
593 	if (get_register_params(dice, &tx_params, &rx_params) == 0) {
594 		stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
595 		stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
596 	}
597 }
598 
599 int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
600 {
601 	unsigned int rate;
602 	enum snd_dice_rate_mode mode;
603 	__be32 reg[2];
604 	struct reg_params tx_params, rx_params;
605 	int i;
606 	int err;
607 
608 	/* If extended protocol is available, detect detail spec. */
609 	err = snd_dice_detect_extension_formats(dice);
610 	if (err >= 0)
611 		return err;
612 
613 	/*
614 	 * Available stream format is restricted at current mode of sampling
615 	 * clock.
616 	 */
617 	err = snd_dice_transaction_get_rate(dice, &rate);
618 	if (err < 0)
619 		return err;
620 
621 	err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
622 	if (err < 0)
623 		return err;
624 
625 	/*
626 	 * Just after owning the unit (GLOBAL_OWNER), the unit can return
627 	 * invalid stream formats. Selecting clock parameters have an effect
628 	 * for the unit to refine it.
629 	 */
630 	err = ensure_phase_lock(dice, rate);
631 	if (err < 0)
632 		return err;
633 
634 	err = get_register_params(dice, &tx_params, &rx_params);
635 	if (err < 0)
636 		return err;
637 
638 	for (i = 0; i < tx_params.count; ++i) {
639 		err = snd_dice_transaction_read_tx(dice,
640 				tx_params.size * i + TX_NUMBER_AUDIO,
641 				reg, sizeof(reg));
642 		if (err < 0)
643 			return err;
644 		dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
645 		dice->tx_midi_ports[i] = max_t(unsigned int,
646 				be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
647 	}
648 	for (i = 0; i < rx_params.count; ++i) {
649 		err = snd_dice_transaction_read_rx(dice,
650 				rx_params.size * i + RX_NUMBER_AUDIO,
651 				reg, sizeof(reg));
652 		if (err < 0)
653 			return err;
654 		dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
655 		dice->rx_midi_ports[i] = max_t(unsigned int,
656 				be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
657 	}
658 
659 	return 0;
660 }
661 
662 static void dice_lock_changed(struct snd_dice *dice)
663 {
664 	dice->dev_lock_changed = true;
665 	wake_up(&dice->hwdep_wait);
666 }
667 
668 int snd_dice_stream_lock_try(struct snd_dice *dice)
669 {
670 	int err;
671 
672 	spin_lock_irq(&dice->lock);
673 
674 	if (dice->dev_lock_count < 0) {
675 		err = -EBUSY;
676 		goto out;
677 	}
678 
679 	if (dice->dev_lock_count++ == 0)
680 		dice_lock_changed(dice);
681 	err = 0;
682 out:
683 	spin_unlock_irq(&dice->lock);
684 	return err;
685 }
686 
687 void snd_dice_stream_lock_release(struct snd_dice *dice)
688 {
689 	spin_lock_irq(&dice->lock);
690 
691 	if (WARN_ON(dice->dev_lock_count <= 0))
692 		goto out;
693 
694 	if (--dice->dev_lock_count == 0)
695 		dice_lock_changed(dice);
696 out:
697 	spin_unlock_irq(&dice->lock);
698 }
699