aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-06-16 13:15:25 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-06-16 16:48:09 -0400
commitd645f4dad056a98089df904294f66b96d04e91b6 (patch)
tree993ec9d0c64dac6fb4e1214f213220fbc0e29f63 /drivers
parent29ad14cddd6246d17ff22f496363dfd6b3de8964 (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/core-card.c18
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);
461 461
462 462
463/* 463/*
464 * The next few functions implements a dummy driver that use once a 464 * The next few functions implement a dummy driver that is used once a card
465 * card driver shuts down an fw_card. This allows the driver to 465 * driver shuts down an fw_card. This allows the driver to cleanly unload,
466 * cleanly unload, as all IO to the card will be handled by the dummy 466 * as all IO to the card will be handled (and failed) by the dummy driver
467 * driver instead of calling into the (possibly) unloaded module. The 467 * instead of calling into the module. Only functions for iso context
468 * dummy driver just fails all IO. 468 * shutdown still need to be provided by the card driver.
469 */ 469 */
470 470
471static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) 471static 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 return -ENODEV; 512 return -ENODEV;
513} 513}
514 514
515static struct fw_card_driver dummy_driver = { 515static const struct fw_card_driver dummy_driver_template = {
516 .enable = dummy_enable, 516 .enable = dummy_enable,
517 .update_phy_reg = dummy_update_phy_reg, 517 .update_phy_reg = dummy_update_phy_reg,
518 .set_config_rom = dummy_set_config_rom, 518 .set_config_rom = dummy_set_config_rom,
@@ -531,6 +531,8 @@ void fw_card_release(struct kref *kref)
531 531
532void fw_core_remove_card(struct fw_card *card) 532void fw_core_remove_card(struct fw_card *card)
533{ 533{
534 struct fw_card_driver dummy_driver = dummy_driver_template;
535
534 card->driver->update_phy_reg(card, 4, 536 card->driver->update_phy_reg(card, 4,
535 PHY_LINK_ACTIVE | PHY_CONTENDER, 0); 537 PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
536 fw_core_initiate_bus_reset(card, 1); 538 fw_core_initiate_bus_reset(card, 1);
@@ -539,7 +541,9 @@ void fw_core_remove_card(struct fw_card *card)
539 list_del_init(&card->link); 541 list_del_init(&card->link);
540 mutex_unlock(&card_mutex); 542 mutex_unlock(&card_mutex);
541 543
542 /* Set up the dummy driver. */ 544 /* Switch off most of the card driver interface. */
545 dummy_driver.free_iso_context = card->driver->free_iso_context;
546 dummy_driver.stop_iso = card->driver->stop_iso;
543 card->driver = &dummy_driver; 547 card->driver = &dummy_driver;
544 548
545 fw_destroy_nodes(card); 549 fw_destroy_nodes(card);