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