From 288379f050284087578b77e04f040b57db3db3f8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 19 Jan 2009 16:43:59 -0800 Subject: net: Remove redundant NAPI functions Following the removal of the unused struct net_device * parameter from the NAPI functions named *netif_rx_* in commit 908a7a1, they are exactly equivalent to the corresponding *napi_* functions and are therefore redundant. Signed-off-by: Ben Hutchings Acked-by: Neil Horman Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 26474c92193f..ffe466e0afb9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3687,12 +3687,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) mod_timer(&adapter->watchdog_timer, jiffies + 1); } - if (likely(netif_rx_schedule_prep(&adapter->napi))) { + if (likely(napi_schedule_prep(&adapter->napi))) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } else e1000_irq_enable(adapter); @@ -3747,12 +3747,12 @@ static irqreturn_t e1000_intr(int irq, void *data) ew32(IMC, ~0); E1000_WRITE_FLUSH(); } - if (likely(netif_rx_schedule_prep(&adapter->napi))) { + if (likely(napi_schedule_prep(&adapter->napi))) { adapter->total_tx_bytes = 0; adapter->total_tx_packets = 0; adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; - __netif_rx_schedule(&adapter->napi); + __napi_schedule(&adapter->napi); } else /* this really should not happen! if it does it is basically a * bug, but not a hard error, so enable ints and continue */ @@ -3793,7 +3793,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) if (work_done < budget) { if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); - netif_rx_complete(napi); + napi_complete(napi); e1000_irq_enable(adapter); } -- cgit v1.2.3 From 8017943e6b177f117e4be71f09a38e2c9fd56193 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 21 Jan 2009 14:42:47 -0800 Subject: e1000: drop lltx, remove unnecessary lock LLTX is deprecated, don't use it. This completes the removal of LLTX from the Intel Network drivers. Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ffe466e0afb9..7ec1a0c5a0cf 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -31,7 +31,7 @@ char e1000_driver_name[] = "e1000"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -#define DRV_VERSION "7.3.20-k3-NAPI" +#define DRV_VERSION "7.3.21-k2-NAPI" const char e1000_driver_version[] = DRV_VERSION; static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; @@ -1048,8 +1048,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - netdev->features |= NETIF_F_LLTX; - netdev->vlan_features |= NETIF_F_TSO; netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_HW_CSUM; @@ -1368,8 +1366,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) return -ENOMEM; } - spin_lock_init(&adapter->tx_queue_lock); - /* Explicitly disable IRQ since the NIC can be in any state. */ e1000_irq_disable(adapter); @@ -1624,7 +1620,6 @@ setup_tx_desc_die: txdr->next_to_use = 0; txdr->next_to_clean = 0; - spin_lock_init(&txdr->tx_lock); return 0; } @@ -3185,7 +3180,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; unsigned int tx_flags = 0; unsigned int len = skb->len - skb->data_len; - unsigned long flags; unsigned int nr_frags; unsigned int mss; int count = 0; @@ -3290,22 +3284,15 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) (hw->mac_type == e1000_82573)) e1000_transfer_dhcp_info(adapter, skb); - if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) - /* Collision - tell upper layer to requeue */ - return NETDEV_TX_LOCKED; - /* need: count + 2 desc gap to keep tail from touching * head, otherwise try next time */ - if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) { - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) return NETDEV_TX_BUSY; - } if (unlikely(hw->mac_type == e1000_82547)) { if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) { netif_stop_queue(netdev); mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_BUSY; } } @@ -3320,7 +3307,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) tso = e1000_tso(adapter, tx_ring, skb); if (tso < 0) { dev_kfree_skb_any(skb); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_OK; } @@ -3345,7 +3331,6 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* Make sure there is space in the ring for the next send. */ e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - spin_unlock_irqrestore(&tx_ring->tx_lock, flags); return NETDEV_TX_OK; } @@ -3773,15 +3758,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) adapter = netdev_priv(poll_dev); - /* e1000_clean is called per-cpu. This lock protects - * tx_ring[0] from being cleaned by multiple cpus - * simultaneously. A failure obtaining the lock means - * tx_ring[0] is currently being cleaned anyway. */ - if (spin_trylock(&adapter->tx_queue_lock)) { - tx_cleaned = e1000_clean_tx_irq(adapter, - &adapter->tx_ring[0]); - spin_unlock(&adapter->tx_queue_lock); - } + tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]); adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); -- cgit v1.2.3 From 09640e6365c679b5642b1c41b6d7078f51689ddf Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 1 Feb 2009 00:45:17 -0800 Subject: net: replace uses of __constant_{endian} Base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c4a303023b31..40db34deebde 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2860,11 +2860,11 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter, return false; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case cpu_to_be16(ETH_P_IP): if (ip_hdr(skb)->protocol == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; break; - case __constant_htons(ETH_P_IPV6): + case cpu_to_be16(ETH_P_IPV6): /* XXX not handling all IPV6 headers */ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) cmd_len |= E1000_TXD_CMD_TCP; -- cgit v1.2.3 From 3c842138c0cf313e906538b89d88ba0d969ce747 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 19 Feb 2009 14:38:52 -0800 Subject: e1000: Removing the unused macro PAGE_USE_COUNT() Removing the unused macro PAGE_USE_COUNT(), since there is no more reference to it. The last reference was removed by Jesse's commit number 630b25cdf4e3f8c0a11eb04fc8436cc36653cd58. Signed-off-by: Breno Leitao Acked-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ca7cd7e2bf23..61b56ca00051 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1877,8 +1877,6 @@ int e1000_setup_all_rx_resources(struct e1000_adapter *adapter) * e1000_setup_rctl - configure the receive control registers * @adapter: Board private structure **/ -#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ - (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) static void e1000_setup_rctl(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; -- cgit v1.2.3 From d20b606c99c7fd9f1b6c6ec43c877eaae827d169 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 2 Mar 2009 16:03:21 -0800 Subject: e1000: fix unmap bug This is in reference to the issue shown in kerneloops (search e1000 unmap) The e1000 transmit code was calling pci_unmap_page on dma handles that it might have called pci_map_single on. Same bug as e1000e Signed-off-by: Jesse Brandeburg Acked-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 51 ++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 61b56ca00051..1f390ceb4869 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2049,14 +2049,10 @@ void e1000_free_all_tx_resources(struct e1000_adapter *adapter) static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { - if (buffer_info->dma) { - pci_unmap_page(adapter->pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } + buffer_info->dma = 0; if (buffer_info->skb) { + skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, + DMA_TO_DEVICE); dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } @@ -2907,16 +2903,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter, unsigned int mss) { struct e1000_hw *hw = &adapter->hw; - struct e1000_buffer *buffer_info; - unsigned int len = skb->len; - unsigned int offset = 0, size, count = 0, i; + unsigned int len = skb_headlen(skb); + unsigned int offset, size, count = 0, i; unsigned int f; - len -= skb->data_len; + dma_addr_t map; i = tx_ring->next_to_use; + if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + dev_kfree_skb(skb); + return -2; + } + + map = skb_shinfo(skb)->dma_maps[0]; + offset = 0; + while (len) { - buffer_info = &tx_ring->buffer_info[i]; + struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for Controller erratum -- * descriptor for non-tso packet in a linear SKB that follows a @@ -2949,11 +2953,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = - pci_map_single(adapter->pdev, - skb->data + offset, - size, - PCI_DMA_TODEVICE); + buffer_info->dma = map + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; @@ -2968,9 +2968,11 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = frag->page_offset; + map = skb_shinfo(skb)->dma_maps[f + 1]; + offset = 0; while (len) { + struct e1000_buffer *buffer_info; buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for premature desc write-backs @@ -2986,12 +2988,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = - pci_map_page(adapter->pdev, - frag->page, - offset, - size, - PCI_DMA_TODEVICE); + buffer_info->dma = map + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; @@ -3005,6 +3002,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; + smp_wmb(); return count; } @@ -3844,6 +3842,11 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; + /* + * read barrier to make sure that the ->dma member and time + * stamp are updated fully + */ + smp_rmb(); if (tx_ring->buffer_info[eop].dma && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + (adapter->tx_timeout_factor * HZ)) -- cgit v1.2.3 From 37e73df8c3f19f4733c60ec53c104ff6f79ba467 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 25 Mar 2009 21:58:45 +0000 Subject: e1000: fix tx hang detect logic and address dma mapping issues This patch changes the dma mapping to better support skb_dma_map/skb_dma_unmap and addresses and redefines the tx hang logic to be based off of time stamp instead of if the dma field is populated Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 55 +++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 1f390ceb4869..e60faabe9024 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2056,6 +2056,7 @@ static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } + buffer_info->time_stamp = 0; /* buffer_info must be completely set up in the transmit path */ } @@ -2903,24 +2904,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter, unsigned int mss) { struct e1000_hw *hw = &adapter->hw; + struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); unsigned int offset, size, count = 0, i; unsigned int f; - dma_addr_t map; + dma_addr_t *map; i = tx_ring->next_to_use; if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); - dev_kfree_skb(skb); - return -2; + return 0; } - map = skb_shinfo(skb)->dma_maps[0]; + map = skb_shinfo(skb)->dma_maps; offset = 0; while (len) { - struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for Controller erratum -- * descriptor for non-tso packet in a linear SKB that follows a @@ -2953,14 +2954,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map + offset; + buffer_info->dma = map[0] + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; len -= size; offset += size; count++; - if (unlikely(++i == tx_ring->count)) i = 0; + if (len) { + i++; + if (unlikely(i == tx_ring->count)) + i = 0; + } } for (f = 0; f < nr_frags; f++) { @@ -2968,11 +2973,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - map = skb_shinfo(skb)->dma_maps[f + 1]; offset = 0; while (len) { - struct e1000_buffer *buffer_info; + i++; + if (unlikely(i == tx_ring->count)) + i = 0; + buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); /* Workaround for premature desc write-backs @@ -2988,21 +2995,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter, size -= 4; buffer_info->length = size; - buffer_info->dma = map + offset; + buffer_info->dma = map[f + 1] + offset; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; len -= size; offset += size; count++; - if (unlikely(++i == tx_ring->count)) i = 0; } } - i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; - smp_wmb(); return count; } @@ -3318,14 +3322,20 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (likely(skb->protocol == htons(ETH_P_IP))) tx_flags |= E1000_TX_FLAGS_IPV4; - e1000_tx_queue(adapter, tx_ring, tx_flags, - e1000_tx_map(adapter, tx_ring, skb, first, - max_per_txd, nr_frags, mss)); + count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd, + nr_frags, mss); - netdev->trans_start = jiffies; + if (count) { + e1000_tx_queue(adapter, tx_ring, tx_flags, count); + netdev->trans_start = jiffies; + /* Make sure there is space in the ring for the next send. */ + e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); + } else { + dev_kfree_skb_any(skb); + tx_ring->buffer_info[first].time_stamp = 0; + tx_ring->next_to_use = first; + } return NETDEV_TX_OK; } @@ -3842,12 +3852,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; - /* - * read barrier to make sure that the ->dma member and time - * stamp are updated fully - */ - smp_rmb(); - if (tx_ring->buffer_info[eop].dma && + if (tx_ring->buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { -- cgit v1.2.3 From ccfb342c5cd584f0f3e682280f7152310edf0e39 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 25 Mar 2009 21:59:04 +0000 Subject: e1000: cleanup clean_tx_irq routine so that it completely cleans ring The tx cleanup routine was stopping after 64 packets and this was causing issues resulting in the ring not being completely cleaned. This change updates the driver to clean the entire ring and if it doesn't it then will retry on the next pass. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e60faabe9024..5c61b921ca71 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3769,7 +3769,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); - if (tx_cleaned) + if (!tx_cleaned) work_done = budget; /* If budget not fully consumed, exit the polling mode */ @@ -3796,15 +3796,16 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int i, eop; unsigned int count = 0; - bool cleaned = false; + bool cleaned; unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); - while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { - for (cleaned = false; !cleaned; ) { + while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && + (count < tx_ring->count)) { + for (cleaned = false; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); @@ -3827,10 +3828,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); -#define E1000_TX_WEIGHT 64 - /* weight of a sort for tx, to avoid endless transmit cleanup */ - if (count++ == E1000_TX_WEIGHT) - break; } tx_ring->next_to_clean = i; @@ -3852,8 +3849,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + + if (tx_ring->buffer_info[i].time_stamp && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + (adapter->tx_timeout_factor * HZ)) && !(er32(STATUS) & E1000_STATUS_TXOFF)) { @@ -3875,7 +3872,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, readl(hw->hw_addr + tx_ring->tdt), tx_ring->next_to_use, tx_ring->next_to_clean, - tx_ring->buffer_info[eop].time_stamp, + tx_ring->buffer_info[i].time_stamp, eop, jiffies, eop_desc->upper.fields.status); @@ -3886,7 +3883,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, adapter->total_tx_packets += total_tx_packets; adapter->net_stats.tx_bytes += total_tx_bytes; adapter->net_stats.tx_packets += total_tx_packets; - return cleaned; + return (count < tx_ring->count); } /** -- cgit v1.2.3 From a6c42322722976ca81e6d02e4a702f33d659d8fc Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 25 Mar 2009 21:59:22 +0000 Subject: 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 Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') 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: void e1000_down(struct e1000_adapter *adapter) { + struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; + u32 rctl, tctl; /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__E1000_DOWN, &adapter->flags); + /* disable receives in the hardware */ + rctl = er32(RCTL); + ew32(RCTL, rctl & ~E1000_RCTL_EN); + /* flush and sleep below */ + + /* can be netif_tx_disable when NETIF_F_LLTX is removed */ + netif_stop_queue(netdev); + + /* disable transmits in the hardware */ + tctl = er32(TCTL); + tctl &= ~E1000_TCTL_EN; + ew32(TCTL, tctl); + /* flush both disables and wait for them to finish */ + E1000_WRITE_FLUSH(); + msleep(10); + napi_disable(&adapter->napi); e1000_irq_disable(adapter); @@ -595,7 +613,6 @@ void e1000_down(struct e1000_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; netif_carrier_off(netdev); - netif_stop_queue(netdev); e1000_reset(adapter); e1000_clean_all_tx_rings(adapter); @@ -3744,10 +3761,12 @@ static irqreturn_t e1000_intr(int irq, void *data) adapter->total_rx_bytes = 0; adapter->total_rx_packets = 0; __napi_schedule(&adapter->napi); - } else + } else { /* this really should not happen! if it does it is basically a * bug, but not a hard error, so enable ints and continue */ - e1000_irq_enable(adapter); + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_enable(adapter); + } return IRQ_HANDLED; } @@ -3777,7 +3796,8 @@ static int e1000_clean(struct napi_struct *napi, int budget) if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); napi_complete(napi); - e1000_irq_enable(adapter); + if (!test_bit(__E1000_DOWN, &adapter->flags)) + e1000_irq_enable(adapter); } return work_done; -- cgit v1.2.3