Commit d645f4da authored by Stefan Richter's avatar Stefan Richter

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: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 29ad14cd
...@@ -461,11 +461,11 @@ EXPORT_SYMBOL(fw_card_add); ...@@ -461,11 +461,11 @@ EXPORT_SYMBOL(fw_card_add);
/* /*
* The next few functions implements a dummy driver that use once a * The next few functions implement a dummy driver that is used once a card
* card driver shuts down an fw_card. This allows the driver to * driver shuts down an fw_card. This allows the driver to cleanly unload,
* cleanly unload, as all IO to the card will be handled by the dummy * as all IO to the card will be handled (and failed) by the dummy driver
* driver instead of calling into the (possibly) unloaded module. The * instead of calling into the module. Only functions for iso context
* dummy driver just fails all IO. * shutdown still need to be provided by the card driver.
*/ */
static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) 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, ...@@ -512,7 +512,7 @@ static int dummy_enable_phys_dma(struct fw_card *card,
return -ENODEV; return -ENODEV;
} }
static struct fw_card_driver dummy_driver = { static const struct fw_card_driver dummy_driver_template = {
.enable = dummy_enable, .enable = dummy_enable,
.update_phy_reg = dummy_update_phy_reg, .update_phy_reg = dummy_update_phy_reg,
.set_config_rom = dummy_set_config_rom, .set_config_rom = dummy_set_config_rom,
...@@ -531,6 +531,8 @@ void fw_card_release(struct kref *kref) ...@@ -531,6 +531,8 @@ void fw_card_release(struct kref *kref)
void fw_core_remove_card(struct fw_card *card) 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, card->driver->update_phy_reg(card, 4,
PHY_LINK_ACTIVE | PHY_CONTENDER, 0); PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
fw_core_initiate_bus_reset(card, 1); fw_core_initiate_bus_reset(card, 1);
...@@ -539,7 +541,9 @@ void fw_core_remove_card(struct fw_card *card) ...@@ -539,7 +541,9 @@ void fw_core_remove_card(struct fw_card *card)
list_del_init(&card->link); list_del_init(&card->link);
mutex_unlock(&card_mutex); 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; card->driver = &dummy_driver;
fw_destroy_nodes(card); fw_destroy_nodes(card);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment