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

Commit 27183539 authored by Niels Dossche's avatar Niels Dossche Committed by Greg Kroah-Hartman
Browse files

firewire: core: extend card->lock in fw_core_handle_bus_reset



commit a7ecbe92b9243edbe94772f6f2c854e4142a3345 upstream.

card->local_node and card->bm_retries are both always accessed under
card->lock.
fw_core_handle_bus_reset has a check whose condition depends on
card->local_node and whose body writes to card->bm_retries.
Both of these accesses are not under card->lock. Move the lock acquiring
of card->lock to before this check such that these accesses do happen
when card->lock is held.
fw_destroy_nodes is called inside the check.
Since fw_destroy_nodes already acquires card->lock inside its function
body, move this out to the callsites of fw_destroy_nodes.
Also add a comment to indicate which locking is necessary when calling
fw_destroy_nodes.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarNiels Dossche <dossche.niels@gmail.com>
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20220409041243.603210-4-o-takashi@sakamocchi.jp


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2fefc625
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -668,6 +668,7 @@ EXPORT_SYMBOL_GPL(fw_card_release);
void fw_core_remove_card(struct fw_card *card)
{
	struct fw_card_driver dummy_driver = dummy_driver_template;
	unsigned long flags;

	card->driver->update_phy_reg(card, 4,
				     PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
@@ -682,7 +683,9 @@ void fw_core_remove_card(struct fw_card *card)
	dummy_driver.stop_iso		= card->driver->stop_iso;
	card->driver = &dummy_driver;

	spin_lock_irqsave(&card->lock, flags);
	fw_destroy_nodes(card);
	spin_unlock_irqrestore(&card->lock, flags);

	/* Wait for all users, especially device workqueue jobs, to finish. */
	fw_card_put(card);
+3 −6
Original line number Diff line number Diff line
@@ -374,16 +374,13 @@ static void report_found_node(struct fw_card *card,
	card->bm_retries = 0;
}

/* Must be called with card->lock held */
void fw_destroy_nodes(struct fw_card *card)
{
	unsigned long flags;

	spin_lock_irqsave(&card->lock, flags);
	card->color++;
	if (card->local_node != NULL)
		for_each_fw_node(card, card->local_node, report_lost_node);
	card->local_node = NULL;
	spin_unlock_irqrestore(&card->lock, flags);
}

static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
@@ -509,6 +506,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
	struct fw_node *local_node;
	unsigned long flags;

	spin_lock_irqsave(&card->lock, flags);

	/*
	 * If the selfID buffer is not the immediate successor of the
	 * previously processed one, we cannot reliably compare the
@@ -520,8 +519,6 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
		card->bm_retries = 0;
	}

	spin_lock_irqsave(&card->lock, flags);

	card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
	card->node_id = node_id;
	/*