Commit ab08853fab2093e5c6f5de56827a4c93dce4b055

Authored by Anupam Chanda
Committed by David S. Miller
1 parent 0302b8622c

e1000: fix screaming IRQ

VMWare reports that the e1000 driver has a bug when bringing down the
interface, such that interrupts are not disabled in the hardware but the
driver stops reporting that it consumed the interrupt.

The fix is to set the driver's "down" flag later in the routine,
after all the timers and such have exited, preventing the interrupt
handler from being called and exiting early without handling the
interrupt.

CC: Anupam Chanda <anupamc@vmware.com>
CC: stable kernel <stable@kernel.org>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 8 additions and 4 deletions Side-by-side Diff

drivers/net/e1000/e1000_main.c
... ... @@ -31,7 +31,7 @@
31 31  
32 32 char e1000_driver_name[] = "e1000";
33 33 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
34   -#define DRV_VERSION "7.3.21-k6-NAPI"
  34 +#define DRV_VERSION "7.3.21-k8-NAPI"
35 35 const char e1000_driver_version[] = DRV_VERSION;
36 36 static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
37 37  
... ... @@ -485,9 +485,6 @@
485 485 struct net_device *netdev = adapter->netdev;
486 486 u32 rctl, tctl;
487 487  
488   - /* signal that we're down so the interrupt handler does not
489   - * reschedule our watchdog timer */
490   - set_bit(__E1000_DOWN, &adapter->flags);
491 488  
492 489 /* disable receives in the hardware */
493 490 rctl = er32(RCTL);
... ... @@ -507,6 +504,13 @@
507 504 napi_disable(&adapter->napi);
508 505  
509 506 e1000_irq_disable(adapter);
  507 +
  508 + /*
  509 + * Setting DOWN must be after irq_disable to prevent
  510 + * a screaming interrupt. Setting DOWN also prevents
  511 + * timers and tasks from rescheduling.
  512 + */
  513 + set_bit(__E1000_DOWN, &adapter->flags);
510 514  
511 515 del_timer_sync(&adapter->tx_fifo_stall_timer);
512 516 del_timer_sync(&adapter->watchdog_timer);