]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: 6fire: Cover the whole probe and disconnect calls with register_mutex
authorTakashi Iwai <tiwai@suse.de>
Tue, 14 Apr 2026 13:22:11 +0000 (15:22 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 15 Apr 2026 12:27:26 +0000 (14:27 +0200)
In 6fire driver, we protect the concurrent calls against probe and
disconnect with the register_mutex, but it's applied only partially.
Since we handle two global pointers in devices[] and chips[] pairs,
the assignment of the latter can be inconsistent upon concurrent
interface probes, and the refcount handling isn't properly protected
at disconnect, either.

This patch extends the mutex application range to the whole probe and
disconnect functions.  It makes the code safer against potential
concurrent probles and disconnects, while it makes the code easier to
read, too.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20260414132218.411013-2-tiwai@suse.de
sound/usb/6fire/chip.c

index 874f6cd503ca595ce02d5f286494f45050bd034e..18a25449bcd39ce165fc5492dbdbe0ff2b54c1f0 100644 (file)
@@ -83,22 +83,21 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
        struct snd_card *card = NULL;
 
        /* look if we already serve this card and return if so */
-       scoped_guard(mutex, &register_mutex) {
-               for (i = 0; i < SNDRV_CARDS; i++) {
-                       if (devices[i] == device) {
-                               if (chips[i])
-                                       chips[i]->intf_count++;
-                               usb_set_intfdata(intf, chips[i]);
-                               return 0;
-                       } else if (!devices[i] && regidx < 0)
-                               regidx = i;
-               }
-               if (regidx < 0) {
-                       dev_err(&intf->dev, "too many cards registered.\n");
-                       return -ENODEV;
-               }
-               devices[regidx] = device;
+       guard(mutex)(&register_mutex);
+       for (i = 0; i < SNDRV_CARDS; i++) {
+               if (devices[i] == device) {
+                       if (chips[i])
+                               chips[i]->intf_count++;
+                       usb_set_intfdata(intf, chips[i]);
+                       return 0;
+               } else if (!devices[i] && regidx < 0)
+                       regidx = i;
+       }
+       if (regidx < 0) {
+               dev_err(&intf->dev, "too many cards registered.\n");
+               return -ENODEV;
        }
+       devices[regidx] = device;
 
        /* check, if firmware is present on device, upload it if not */
        ret = usb6fire_fw_init(intf);
@@ -165,14 +164,13 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
        struct sfire_chip *chip;
        struct snd_card *card;
 
+       guard(mutex)(&register_mutex);
        chip = usb_get_intfdata(intf);
        if (chip) { /* if !chip, fw upload has been performed */
                chip->intf_count--;
                if (!chip->intf_count) {
-                       scoped_guard(mutex, &register_mutex) {
-                               devices[chip->regidx] = NULL;
-                               chips[chip->regidx] = NULL;
-                       }
+                       devices[chip->regidx] = NULL;
+                       chips[chip->regidx] = NULL;
 
                        /*
                         * Save card pointer before teardown.