aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/ub.c
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2008-11-10 23:11:11 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-11-13 17:45:04 -0500
commitd73b7aff28bc53c04e1f2e5ccaa5ea43089fb4a4 (patch)
tree05918d1868cff57a9ae2818b75ad39e47f4716d1 /drivers/block/ub.c
parent859ff4072027ea7741121b902c59763f090e00c2 (diff)
ub: stub pre_reset and post_reset to fix oops
Due to recent changes to usb_reset_device, the following hang occurs: events/0 D 0000000000000000 0 6 2 ffff880037477cc0 0000000000000046 ffff880037477c50 ffffffff80237434 ffffffff80574c80 00000001000a015c 0000000000000286 ffff8800374757d0 ffff88002a31c860 ffff880037475a00 0000000036779140 ffff880037475a00 Call Trace: [<ffffffff80237434>] try_to_del_timer_sync+0x52/0x5b [<ffffffff8026f86c>] dma_pool_free+0x1a7/0x1ec [<ffffffffa02a928a>] ub_disconnect+0x8e/0x1ad [ub] [<ffffffff802407c9>] autoremove_wake_function+0x0/0x2e [<ffffffff80378959>] usb_unbind_interface+0x5c/0xb7 [<ffffffff8036ab70>] __device_release_driver+0x95/0xbd [<ffffffff8036ac70>] device_release_driver+0x21/0x2d [<ffffffff803789f8>] usb_driver_release_interface+0x44/0x83 [<ffffffff80378ab9>] usb_forced_unbind_intf+0x17/0x1d [<ffffffff80371ba4>] usb_reset_device+0x7d/0x114 [<ffffffffa02aaffd>] ub_reset_task+0x0/0x293 [ub] [<ffffffffa02ab1c1>] ub_reset_task+0x1c4/0x293 [ub] [<ffffffff8033dd1e>] flush_to_ldisc+0x0/0x1cd [<ffffffffa02aaffd>] ub_reset_task+0x0/0x293 [ub] [<ffffffff8023d302>] run_workqueue+0x87/0x114 [<ffffffff8023d467>] worker_thread+0xd8/0xe7 [<ffffffff802407c9>] autoremove_wake_function+0x0/0x2e [<ffffffff8023d38f>] worker_thread+0x0/0xe7 [<ffffffff802404c1>] kthread+0x47/0x73 [<ffffffff8022c8dd>] schedule_tail+0x27/0x60 [<ffffffff8020c249>] child_rip+0xa/0x11 [<ffffffff8024047a>] kthread+0x0/0x73 [<ffffffff8020c23f>] child_rip+0x0/0x11 This is because usb_reset_device now unbinds, and that calls disconnect, which in case of ub waits until the reset completes... which deadlocks. Worse, this deadlocks keventd and this takes whole box down. I'm going to fix this properly later, but let's unbreak the driver quickly for non-composite devices at least. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/block/ub.c')
-rw-r--r--drivers/block/ub.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index fccac18d3111..048d71d244d7 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1546,8 +1546,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
1546 1546
1547/* 1547/*
1548 * Reset management 1548 * Reset management
1549 * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing.
1550 * XXX Make usb_sync_reset asynchronous.
1551 */ 1549 */
1552 1550
1553static void ub_reset_enter(struct ub_dev *sc, int try) 1551static void ub_reset_enter(struct ub_dev *sc, int try)
@@ -1633,6 +1631,22 @@ static void ub_reset_task(struct work_struct *work)
1633} 1631}
1634 1632
1635/* 1633/*
1634 * XXX Reset brackets are too much hassle to implement, so just stub them
1635 * in order to prevent forced unbinding (which deadlocks solid when our
1636 * ->disconnect method waits for the reset to complete and this kills keventd).
1637 *
1638 * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device,
1639 * or else the post_reset is invoked, and restats I/O on a locked device.
1640 */
1641static int ub_pre_reset(struct usb_interface *iface) {
1642 return 0;
1643}
1644
1645static int ub_post_reset(struct usb_interface *iface) {
1646 return 0;
1647}
1648
1649/*
1636 * This is called from a process context. 1650 * This is called from a process context.
1637 */ 1651 */
1638static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) 1652static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
@@ -2446,6 +2460,8 @@ static struct usb_driver ub_driver = {
2446 .probe = ub_probe, 2460 .probe = ub_probe,
2447 .disconnect = ub_disconnect, 2461 .disconnect = ub_disconnect,
2448 .id_table = ub_usb_ids, 2462 .id_table = ub_usb_ids,
2463 .pre_reset = ub_pre_reset,
2464 .post_reset = ub_post_reset,
2449}; 2465};
2450 2466
2451static int __init ub_init(void) 2467static int __init ub_init(void)