diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-16 19:15:25 +0200 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-06-16 22:48:09 +0200 |
commit | d645f4dad056a98089df904294f66b96d04e91b6 (patch) | |
tree | 993ec9d0c64dac6fb4e1214f213220fbc0e29f63 | |
parent | 29ad14cddd6246d17ff22f496363dfd6b3de8964 (diff) |
firewire: core: fix iso context shutdown on card removal
If isochronous contexts existed when firewire-ohci was unloaded, the
core iso shutdown functions crashed with NULL dereferences, and buffers
etc. weren't released.
How the fix works: We first copy the card driver's iso shutdown hooks
into the dummy driver, then fw_destroy_nodes notifies upper layers of
devices going away, these should shut down (including their iso
contexts), wait_for_completion(&card->done) will be triggered after
upper layers gave up all fw_device references, after which the card
driver's shutdown proceeds.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/core-card.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 667603ac14b..543fccac81b 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -461,11 +461,11 @@ EXPORT_SYMBOL(fw_card_add); /* - * The next few functions implements a dummy driver that use once a - * card driver shuts down an fw_card. This allows the driver to - * cleanly unload, as all IO to the card will be handled by the dummy - * driver instead of calling into the (possibly) unloaded module. The - * dummy driver just fails all IO. + * The next few functions implement a dummy driver that is used once a card + * driver shuts down an fw_card. This allows the driver to cleanly unload, + * as all IO to the card will be handled (and failed) by the dummy driver + * instead of calling into the module. Only functions for iso context + * shutdown still need to be provided by the card driver. */ static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) @@ -512,7 +512,7 @@ static int dummy_enable_phys_dma(struct fw_card *card, return -ENODEV; } -static struct fw_card_driver dummy_driver = { +static const struct fw_card_driver dummy_driver_template = { .enable = dummy_enable, .update_phy_reg = dummy_update_phy_reg, .set_config_rom = dummy_set_config_rom, @@ -531,6 +531,8 @@ void fw_card_release(struct kref *kref) void fw_core_remove_card(struct fw_card *card) { + struct fw_card_driver dummy_driver = dummy_driver_template; + card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); fw_core_initiate_bus_reset(card, 1); @@ -539,7 +541,9 @@ void fw_core_remove_card(struct fw_card *card) list_del_init(&card->link); mutex_unlock(&card_mutex); - /* Set up the dummy driver. */ + /* Switch off most of the card driver interface. */ + dummy_driver.free_iso_context = card->driver->free_iso_context; + dummy_driver.stop_iso = card->driver->stop_iso; card->driver = &dummy_driver; fw_destroy_nodes(card); |