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

Commit d029df83 authored by Shahjada Abul Husain's avatar Shahjada Abul Husain Committed by Greg Kroah-Hartman
Browse files

cxgb4: fix IRQ free race during driver unload



[ Upstream commit 015fe6fd29c4b9ac0f61b8c4455ef88e6018b9cc ]

IRQs are requested during driver's ndo_open() and then later
freed up in disable_interrupts() during driver unload.
A race exists where driver can set the CXGB4_FULL_INIT_DONE
flag in ndo_open() after the disable_interrupts() in driver
unload path checks it, and hence misses calling free_irq().

Fix by unregistering netdevice first and sync with driver's
ndo_open(). This ensures disable_interrupts() checks the flag
correctly and frees up the IRQs properly.

Fixes: b37987e8 ("cxgb4: Disable interrupts and napi before unregistering netdev")
Signed-off-by: default avatarShahjada Abul Husain <shahjada@chelsio.com>
Signed-off-by: default avatarRaju Rangoju <rajur@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent ae9b6443
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -2245,6 +2245,9 @@ static void detach_ulds(struct adapter *adap)
{
	unsigned int i;

	if (!is_uld(adap))
		return;

	mutex_lock(&uld_mutex);
	list_del(&adap->list_node);

@@ -6152,10 +6155,13 @@ static void remove_one(struct pci_dev *pdev)
		 */
		destroy_workqueue(adapter->workq);

		if (is_uld(adapter)) {
		detach_ulds(adapter);

		for_each_port(adapter, i)
			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
				unregister_netdev(adapter->port[i]);

		t4_uld_clean_up(adapter);
		}

		adap_free_hma_mem(adapter);

@@ -6163,10 +6169,6 @@ static void remove_one(struct pci_dev *pdev)

		cxgb4_free_mps_ref_entries(adapter);

		for_each_port(adapter, i)
			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
				unregister_netdev(adapter->port[i]);

		debugfs_remove_recursive(adapter->debugfs_root);

		if (!is_t4(adapter->params.chip))
+3 −0
Original line number Diff line number Diff line
@@ -638,6 +638,9 @@ void t4_uld_clean_up(struct adapter *adap)
{
	unsigned int i;

	if (!is_uld(adap))
		return;

	mutex_lock(&uld_mutex);
	for (i = 0; i < CXGB4_ULD_MAX; i++) {
		if (!adap->uld[i].handle)