Skip to content

Commit 097994b

Browse files
tiwaigregkh
authored andcommitted
ALSA: hda - Fix deadlock of controller device lock at unbinding
commit ab949d5 upstream. Imre Deak reported a deadlock of HD-audio driver at unbinding while it's still in probing. Since we probe the codecs asynchronously in a work, the codec driver probe may still be kicked off while the controller itself is being unbound. And, azx_remove() tries to process all pending tasks via cancel_work_sync() for fixing the other races (see commit [0b8c821: ALSA: hda - Cancel probe work instead of flush at remove]), now we may meet a bizarre deadlock: Unbind snd_hda_intel via sysfs: device_release_driver() -> device_lock(snd_hda_intel) -> azx_remove() -> cancel_work_sync(azx_probe_work) azx_probe_work(): codec driver probe() -> __driver_attach() -> device_lock(snd_hda_intel) This deadlock is caused by the fact that both device_release_driver() and driver_probe_device() take both the device and its parent locks at the same time. The codec device sets the controller device as its parent, and this lock is taken before the probe() callback is called, while the controller remove() callback gets called also with the same lock. In this patch, as an ugly workaround, we unlock the controller device temporarily during cancel_work_sync() call. The race against another bind call should be still suppressed by the parent's device lock. Reported-by: Imre Deak <[email protected]> Fixes: 0b8c821 ("ALSA: hda - Cancel probe work instead of flush at remove") Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fea572d commit 097994b

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

sound/pci/hda/hda_intel.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,20 @@ static void azx_remove(struct pci_dev *pci)
21662166
/* cancel the pending probing work */
21672167
chip = card->private_data;
21682168
hda = container_of(chip, struct hda_intel, chip);
2169+
/* FIXME: below is an ugly workaround.
2170+
* Both device_release_driver() and driver_probe_device()
2171+
* take *both* the device's and its parent's lock before
2172+
* calling the remove() and probe() callbacks. The codec
2173+
* probe takes the locks of both the codec itself and its
2174+
* parent, i.e. the PCI controller dev. Meanwhile, when
2175+
* the PCI controller is unbound, it takes its lock, too
2176+
* ==> ouch, a deadlock!
2177+
* As a workaround, we unlock temporarily here the controller
2178+
* device during cancel_work_sync() call.
2179+
*/
2180+
device_unlock(&pci->dev);
21692181
cancel_work_sync(&hda->probe_work);
2182+
device_lock(&pci->dev);
21702183

21712184
snd_card_free(card);
21722185
}

0 commit comments

Comments
 (0)