Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d645f4da authored by Stefan Richter's avatar Stefan Richter
Browse files

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
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -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);