diff options
| author | Chris Boot <bootc@bootc.net> | 2011-08-22 16:38:38 -0400 |
|---|---|---|
| committer | Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> | 2011-11-21 12:54:47 -0500 |
| commit | 762c82c03d3d3fc1a6a47a578f1674ce5c86ccb3 (patch) | |
| tree | c9a54079f8ee3514b7560e15723c4a3a2045b6de /drivers/firewire | |
| parent | 5703e5dd4e25f8f309164d48c0f5a535a08ae077 (diff) | |
firewire: sbp2: fix panic after rmmod with slow targets
BugLink: http://bugs.launchpad.net/bugs/881420
commit 0278ccd9d53e07c4e699432b2fed9de6c56f506c upstream.
If firewire-sbp2 starts a login to a target that doesn't complete ORBs
in a timely manner (and has to retry the login), and the module is
removed before the operation times out, you end up with a null-pointer
dereference and a kernel panic.
[SR: This happens because sbp2_target_get/put() do not maintain
module references. scsi_device_get/put() do, but at occasions like
Chris describes one, nobody holds a reference to an SBP-2 sdev.]
This patch cancels pending work for each unit in sbp2_remove(), which
hopefully means there are no extra references around that prevent us
from unloading. This fixes my crash.
Signed-off-by: Chris Boot <bootc@bootc.net>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
Diffstat (limited to 'drivers/firewire')
| -rw-r--r-- | drivers/firewire/sbp2.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 41841a3e3f9..17cef864506 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
| @@ -1198,6 +1198,10 @@ static int sbp2_remove(struct device *dev) | |||
| 1198 | { | 1198 | { |
| 1199 | struct fw_unit *unit = fw_unit(dev); | 1199 | struct fw_unit *unit = fw_unit(dev); |
| 1200 | struct sbp2_target *tgt = dev_get_drvdata(&unit->device); | 1200 | struct sbp2_target *tgt = dev_get_drvdata(&unit->device); |
| 1201 | struct sbp2_logical_unit *lu; | ||
| 1202 | |||
| 1203 | list_for_each_entry(lu, &tgt->lu_list, link) | ||
| 1204 | cancel_delayed_work_sync(&lu->work); | ||
| 1201 | 1205 | ||
| 1202 | sbp2_target_put(tgt); | 1206 | sbp2_target_put(tgt); |
| 1203 | return 0; | 1207 | return 0; |
