aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-03-25 17:59:22 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-26 04:00:55 -0400
commita6c42322722976ca81e6d02e4a702f33d659d8fc (patch)
tree1f3a9a036b41edb32ee00cf6c0a972dfad80b18f /drivers/net/e1000
parentccfb342c5cd584f0f3e682280f7152310edf0e39 (diff)
e1000: fix close race with interrupt
this is in regards to http://bugzilla.kernel.org/show_bug.cgi?id=12876 where it appears that e1000 can leave its interrupt enabled after exiting the driver. Fix the bug by making the interrupt enable paths more aware of the driver exiting. Thanks to Alan Cox for the poke and initial investigation. CC: Alan Cox <alan@lxorguk.ukuu.org.uk> 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>
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r--drivers/net/e1000/e1000_main.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 5c61b921ca71..93b861d032b5 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -577,12 +577,30 @@ out:
577 577
578void e1000_down(struct e1000_adapter *adapter) 578void e1000_down(struct e1000_adapter *adapter)
579{ 579{
580 struct e1000_hw *hw = &adapter->hw;
580 struct net_device *netdev = adapter->netdev; 581 struct net_device *netdev = adapter->netdev;
582 u32 rctl, tctl;
581 583
582 /* signal that we're down so the interrupt handler does not 584 /* signal that we're down so the interrupt handler does not
583 * reschedule our watchdog timer */ 585 * reschedule our watchdog timer */
584 set_bit(__E1000_DOWN, &adapter->flags); 586 set_bit(__E1000_DOWN, &adapter->flags);
585 587
588 /* disable receives in the hardware */
589 rctl = er32(RCTL);
590 ew32(RCTL, rctl & ~E1000_RCTL_EN);
591 /* flush and sleep below */
592
593 /* can be netif_tx_disable when NETIF_F_LLTX is removed */
594 netif_stop_queue(netdev);
595
596 /* disable transmits in the hardware */
597 tctl = er32(TCTL);
598 tctl &= ~E1000_TCTL_EN;
599 ew32(TCTL, tctl);
600 /* flush both disables and wait for them to finish */
601 E1000_WRITE_FLUSH();
602 msleep(10);
603
586 napi_disable(&adapter->napi); 604 napi_disable(&adapter->napi);
587 605
588 e1000_irq_disable(adapter); 606 e1000_irq_disable(adapter);
@@ -595,7 +613,6 @@ void e1000_down(struct e1000_adapter *adapter)
595 adapter->link_speed = 0; 613 adapter->link_speed = 0;
596 adapter->link_duplex = 0; 614 adapter->link_duplex = 0;
597 netif_carrier_off(netdev); 615 netif_carrier_off(netdev);
598 netif_stop_queue(netdev);
599 616
600 e1000_reset(adapter); 617 e1000_reset(adapter);
601 e1000_clean_all_tx_rings(adapter); 618 e1000_clean_all_tx_rings(adapter);
@@ -3744,10 +3761,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
3744 adapter->total_rx_bytes = 0; 3761 adapter->total_rx_bytes = 0;
3745 adapter->total_rx_packets = 0; 3762 adapter->total_rx_packets = 0;
3746 __napi_schedule(&adapter->napi); 3763 __napi_schedule(&adapter->napi);
3747 } else 3764 } else {
3748 /* this really should not happen! if it does it is basically a 3765 /* this really should not happen! if it does it is basically a
3749 * bug, but not a hard error, so enable ints and continue */ 3766 * bug, but not a hard error, so enable ints and continue */
3750 e1000_irq_enable(adapter); 3767 if (!test_bit(__E1000_DOWN, &adapter->flags))
3768 e1000_irq_enable(adapter);
3769 }
3751 3770
3752 return IRQ_HANDLED; 3771 return IRQ_HANDLED;
3753} 3772}
@@ -3777,7 +3796,8 @@ static int e1000_clean(struct napi_struct *napi, int budget)
3777 if (likely(adapter->itr_setting & 3)) 3796 if (likely(adapter->itr_setting & 3))
3778 e1000_set_itr(adapter); 3797 e1000_set_itr(adapter);
3779 napi_complete(napi); 3798 napi_complete(napi);
3780 e1000_irq_enable(adapter); 3799 if (!test_bit(__E1000_DOWN, &adapter->flags))
3800 e1000_irq_enable(adapter);
3781 } 3801 }
3782 3802
3783 return work_done; 3803 return work_done;