aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-11-22 15:09:42 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2006-12-07 17:10:23 -0500
commit8252bbb1363b7fe963a3eb6f8a36da619a6f5a65 (patch)
treebb0d1adabbc6132a541d71dda9355e9e7243a7ad /drivers
parentcec1a31196a6edb1397ffb8fbdc0410dd8946d78 (diff)
ieee1394: nodemgr: fix deadlock in shutdown
If "modprobe ohci1394" was quickly followed by "modprobe -r ohci1394", say with 1 second pause in between, the modprobe -r got stuck in uninterruptible sleep in kthread_stop. At the same time the knodemgrd slept uninterruptibly in bus_rescan_devices_helper. That's because driver_detach took the semaphore of the PCI device and bus_rescan_devices_helper wanted to take the semaphore of the FireWire host device's parent, which is the same semaphore. This was a regression since Linux 2.6.16, commit bf74ad5bc41727d5f2f1c6bedb2c1fac394de731, "Hold the device's parent's lock during probe and remove". The fix (or workaround) adds a dummy driver to the hpsb_host device. Now bus_rescan_devices_helper won't scan the host device anymore. This doesn't hurt since we have no drivers which will bind to these devices and it is unlikely that there will ever be such a driver. The dummy driver is befittingly presented as a representation of ieee1394 itself. Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=6706 Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ieee1394/nodemgr.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index d672b4db5b74..d90ec6de8183 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/kthread.h> 16#include <linux/kthread.h>
17#include <linux/module.h>
17#include <linux/moduleparam.h> 18#include <linux/moduleparam.h>
18#include <linux/freezer.h> 19#include <linux/freezer.h>
19#include <asm/atomic.h> 20#include <asm/atomic.h>
@@ -260,9 +261,20 @@ static struct device nodemgr_dev_template_ne = {
260 .release = nodemgr_release_ne, 261 .release = nodemgr_release_ne,
261}; 262};
262 263
264/* This dummy driver prevents the host devices from being scanned. We have no
265 * useful drivers for them yet, and there would be a deadlock possible if the
266 * driver core scans the host device while the host's low-level driver (i.e.
267 * the host's parent device) is being removed. */
268static struct device_driver nodemgr_mid_layer_driver = {
269 .bus = &ieee1394_bus_type,
270 .name = "nodemgr",
271 .owner = THIS_MODULE,
272};
273
263struct device nodemgr_dev_template_host = { 274struct device nodemgr_dev_template_host = {
264 .bus = &ieee1394_bus_type, 275 .bus = &ieee1394_bus_type,
265 .release = nodemgr_release_host, 276 .release = nodemgr_release_host,
277 .driver = &nodemgr_mid_layer_driver,
266}; 278};
267 279
268 280
@@ -705,11 +717,14 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
705 return 0; 717 return 0;
706 718
707 ud = container_of(dev, struct unit_directory, device); 719 ud = container_of(dev, struct unit_directory, device);
708 driver = container_of(drv, struct hpsb_protocol_driver, driver);
709
710 if (ud->ne->in_limbo || ud->ignore_driver) 720 if (ud->ne->in_limbo || ud->ignore_driver)
711 return 0; 721 return 0;
712 722
723 /* We only match drivers of type hpsb_protocol_driver */
724 if (drv == &nodemgr_mid_layer_driver)
725 return 0;
726
727 driver = container_of(drv, struct hpsb_protocol_driver, driver);
713 for (id = driver->id_table; id->match_flags != 0; id++) { 728 for (id = driver->id_table; id->match_flags != 0; id++) {
714 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && 729 if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
715 id->vendor_id != ud->vendor_id) 730 id->vendor_id != ud->vendor_id)
@@ -1900,7 +1915,7 @@ int init_ieee1394_nodemgr(void)
1900 class_unregister(&nodemgr_ne_class); 1915 class_unregister(&nodemgr_ne_class);
1901 return error; 1916 return error;
1902 } 1917 }
1903 1918 error = driver_register(&nodemgr_mid_layer_driver);
1904 hpsb_register_highlevel(&nodemgr_highlevel); 1919 hpsb_register_highlevel(&nodemgr_highlevel);
1905 return 0; 1920 return 0;
1906} 1921}