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

Commit a3c69fef authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller
Browse files

e1000e: fix close interrupt race

As noticed by Alan Cox, it is possible for e1000e to exit its interrupt
handler or NAPI with interrupts enabled even when the driver is unloading or
being configured administratively down.

fix related to fix for: http://bugzilla.kernel.org/show_bug.cgi?id=12876



Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
CC: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a72d2b2c
Loading
Loading
Loading
Loading
+10 −6
Original line number Original line Diff line number Diff line
@@ -1261,6 +1261,7 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
	u32 icr = er32(ICR);
	u32 icr = er32(ICR);


	if (!(icr & E1000_ICR_INT_ASSERTED)) {
	if (!(icr & E1000_ICR_INT_ASSERTED)) {
		if (!test_bit(__E1000_DOWN, &adapter->state))
			ew32(IMS, E1000_IMS_OTHER);
			ew32(IMS, E1000_IMS_OTHER);
		return IRQ_NONE;
		return IRQ_NONE;
	}
	}
@@ -1278,6 +1279,7 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
	}
	}


no_link_interrupt:
no_link_interrupt:
	if (!test_bit(__E1000_DOWN, &adapter->state))
		ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
		ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);


	return IRQ_HANDLED;
	return IRQ_HANDLED;
@@ -2015,11 +2017,13 @@ static int e1000_clean(struct napi_struct *napi, int budget)
		if (adapter->itr_setting & 3)
		if (adapter->itr_setting & 3)
			e1000_set_itr(adapter);
			e1000_set_itr(adapter);
		napi_complete(napi);
		napi_complete(napi);
		if (!test_bit(__E1000_DOWN, &adapter->state)) {
			if (adapter->msix_entries)
			if (adapter->msix_entries)
				ew32(IMS, adapter->rx_ring->ims_val);
				ew32(IMS, adapter->rx_ring->ims_val);
			else
			else
				e1000_irq_enable(adapter);
				e1000_irq_enable(adapter);
		}
		}
	}


	return work_done;
	return work_done;
}
}