aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-05 09:08:49 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-05 09:36:25 -0500
commit0725dda207e95ff25f1aa01432250323e0ec49d6 (patch)
treec99515816090d64897dea78169c2b41a1c2f43cd
parentc922c4e87b9b5a3b50d4d17b96f189121430f511 (diff)
ALSA: usb-audio: Fix device_del() sysfs warnings at disconnect
Some USB-audio devices show weird sysfs warnings at disconnecting the devices, e.g. usb 1-3: USB disconnect, device number 3 ------------[ cut here ]------------ WARNING: CPU: 0 PID: 973 at fs/sysfs/group.c:216 device_del+0x39/0x180() sysfs group ffffffff8183df40 not found for kobject 'midiC1D0' Call Trace: [<ffffffff814a3e38>] ? dump_stack+0x49/0x71 [<ffffffff8103cb72>] ? warn_slowpath_common+0x82/0xb0 [<ffffffff8103cc55>] ? warn_slowpath_fmt+0x45/0x50 [<ffffffff813521e9>] ? device_del+0x39/0x180 [<ffffffff81352339>] ? device_unregister+0x9/0x20 [<ffffffff81352384>] ? device_destroy+0x34/0x40 [<ffffffffa00ba29f>] ? snd_unregister_device+0x7f/0xd0 [snd] [<ffffffffa025124e>] ? snd_rawmidi_dev_disconnect+0xce/0x100 [snd_rawmidi] [<ffffffffa00c0192>] ? snd_device_disconnect+0x62/0x90 [snd] [<ffffffffa00c025c>] ? snd_device_disconnect_all+0x3c/0x60 [snd] [<ffffffffa00bb574>] ? snd_card_disconnect+0x124/0x1a0 [snd] [<ffffffffa02e54e8>] ? usb_audio_disconnect+0x88/0x1c0 [snd_usb_audio] [<ffffffffa015260e>] ? usb_unbind_interface+0x5e/0x1b0 [usbcore] [<ffffffff813553e9>] ? __device_release_driver+0x79/0xf0 [<ffffffff81355485>] ? device_release_driver+0x25/0x40 [<ffffffff81354e11>] ? bus_remove_device+0xf1/0x130 [<ffffffff813522b9>] ? device_del+0x109/0x180 [<ffffffffa01501d5>] ? usb_disable_device+0x95/0x1f0 [usbcore] [<ffffffffa014634f>] ? usb_disconnect+0x8f/0x190 [usbcore] [<ffffffffa0149179>] ? hub_thread+0x539/0x13a0 [usbcore] [<ffffffff810669f5>] ? sched_clock_local+0x15/0x80 [<ffffffff81066c98>] ? sched_clock_cpu+0xb8/0xd0 [<ffffffff81070730>] ? bit_waitqueue+0xb0/0xb0 [<ffffffffa0148c40>] ? usb_port_resume+0x430/0x430 [usbcore] [<ffffffffa0148c40>] ? usb_port_resume+0x430/0x430 [usbcore] [<ffffffff8105973e>] ? kthread+0xce/0xf0 [<ffffffff81059670>] ? kthread_create_on_node+0x1c0/0x1c0 [<ffffffff814a8b7c>] ? ret_from_fork+0x7c/0xb0 [<ffffffff81059670>] ? kthread_create_on_node+0x1c0/0x1c0 ---[ end trace 40b1928d1136b91e ]--- This comes from the fact that usb-audio driver may receive the disconnect callback multiple times, per each usb interface. When a device has both audio and midi interfaces, it gets called twice, and currently the driver tries to release resources at the last call. At this point, the first parent interface has been already deleted, thus deleting a child of the first parent hits such a warning. For fixing this problem, we need to call snd_card_disconnect() and cancel pending operations at the very first disconnect while the release of the whole objects waits until the last disconnect call. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=80931 Reported-and-tested-by: Tomas Gayoso <tgayoso@gmail.com> Reported-and-tested-by: Chris J Arges <chris.j.arges@canonical.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/card.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 7ecd0e8a5c51..f61ebb17cc64 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -591,18 +591,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
591{ 591{
592 struct snd_card *card; 592 struct snd_card *card;
593 struct list_head *p; 593 struct list_head *p;
594 bool was_shutdown;
594 595
595 if (chip == (void *)-1L) 596 if (chip == (void *)-1L)
596 return; 597 return;
597 598
598 card = chip->card; 599 card = chip->card;
599 down_write(&chip->shutdown_rwsem); 600 down_write(&chip->shutdown_rwsem);
601 was_shutdown = chip->shutdown;
600 chip->shutdown = 1; 602 chip->shutdown = 1;
601 up_write(&chip->shutdown_rwsem); 603 up_write(&chip->shutdown_rwsem);
602 604
603 mutex_lock(&register_mutex); 605 mutex_lock(&register_mutex);
604 chip->num_interfaces--; 606 if (!was_shutdown) {
605 if (chip->num_interfaces <= 0) {
606 struct snd_usb_endpoint *ep; 607 struct snd_usb_endpoint *ep;
607 608
608 snd_card_disconnect(card); 609 snd_card_disconnect(card);
@@ -622,6 +623,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
622 list_for_each(p, &chip->mixer_list) { 623 list_for_each(p, &chip->mixer_list) {
623 snd_usb_mixer_disconnect(p); 624 snd_usb_mixer_disconnect(p);
624 } 625 }
626 }
627
628 chip->num_interfaces--;
629 if (chip->num_interfaces <= 0) {
625 usb_chip[chip->index] = NULL; 630 usb_chip[chip->index] = NULL;
626 mutex_unlock(&register_mutex); 631 mutex_unlock(&register_mutex);
627 snd_card_free_when_closed(card); 632 snd_card_free_when_closed(card);