Skip to content

Commit

Permalink
[NET]: Fix interrupt semaphore corruption in Intel drivers.
Browse files Browse the repository at this point in the history
Several of the Intel ethernet drivers keep an atomic counter used to
manage when to actually hit the hardware with a disable or an enable.

The way the net_rx_work() breakout logic works during a pending
napi_disable() is that it simply unschedules the poll even if it
still has work.

This can potentially leave interrupts disabled, but that is OK
because all of the drivers are about to disable interrupts
anyways in all such code paths that do a napi_disable().

Unfortunately, this trips up the semaphore used here in the Intel
drivers.  If you hit this case, when you try to bring the interface
back up it won't enable interrupts.  A reload of the driver module
fixes it of course.

So what we do is make sure all the sequences now go:

	napi_disable();
	atomic_set(&adapter->irq_sem, 0);
	*_irq_disable();

which makes sure the counter is always in the correct state.

Reported by Robert Olsson.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 21, 2008
1 parent 6725033 commit 49d85c5
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 4 deletions.
1 change: 1 addition & 0 deletions drivers/net/e1000/e1000_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ e1000_down(struct e1000_adapter *adapter)

#ifdef CONFIG_E1000_NAPI
napi_disable(&adapter->napi);
atomic_set(&adapter->irq_sem, 0);
#endif
e1000_irq_disable(adapter);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2183,6 +2183,7 @@ void e1000e_down(struct e1000_adapter *adapter)
msleep(10);

napi_disable(&adapter->napi);
atomic_set(&adapter->irq_sem, 0);
e1000_irq_disable(adapter);

del_timer_sync(&adapter->watchdog_timer);
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ixgb/ixgb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,11 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
{
struct net_device *netdev = adapter->netdev;

#ifdef CONFIG_IXGB_NAPI
napi_disable(&adapter->napi);
atomic_set(&adapter->irq_sem, 0);
#endif

ixgb_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev);

Expand All @@ -304,9 +309,7 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)

if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
#ifdef CONFIG_IXGB_NAPI
napi_disable(&adapter->napi);
#endif

adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1409,9 +1409,11 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
IXGBE_WRITE_FLUSH(&adapter->hw);
msleep(10);

napi_disable(&adapter->napi);
atomic_set(&adapter->irq_sem, 0);

ixgbe_irq_disable(adapter);

napi_disable(&adapter->napi);
del_timer_sync(&adapter->watchdog_timer);

netif_carrier_off(netdev);
Expand Down

0 comments on commit 49d85c5

Please sign in to comment.