aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000/e1000_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/e1000/e1000_main.c')
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 4348b6fd44fa..95731c841044 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -493,7 +493,11 @@ out:
static void e1000_down_and_stop(struct e1000_adapter *adapter)
{
set_bit(__E1000_DOWN, &adapter->flags);
- cancel_work_sync(&adapter->reset_task);
+
+ /* Only kill reset task if adapter is not resetting */
+ if (!test_bit(__E1000_RESETTING, &adapter->flags))
+ cancel_work_sync(&adapter->reset_task);
+
cancel_delayed_work_sync(&adapter->watchdog_task);
cancel_delayed_work_sync(&adapter->phy_info_task);
cancel_delayed_work_sync(&adapter->fifo_stall_task);
@@ -827,9 +831,10 @@ static int e1000_set_features(struct net_device *netdev,
if (changed & NETIF_F_HW_VLAN_RX)
e1000_vlan_mode(netdev, features);
- if (!(changed & NETIF_F_RXCSUM))
+ if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL)))
return 0;
+ netdev->features = features;
adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
if (netif_running(netdev))
@@ -1074,6 +1079,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
netdev->features |= netdev->hw_features;
netdev->hw_features |= NETIF_F_RXCSUM;
+ netdev->hw_features |= NETIF_F_RXALL;
netdev->hw_features |= NETIF_F_RXFCS;
if (pci_using_dac) {
@@ -1841,6 +1847,22 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
+ /* This is useful for sniffing bad packets. */
+ if (adapter->netdev->features & NETIF_F_RXALL) {
+ /* UPE and MPE will be handled by normal PROMISC logic
+ * in e1000e_set_rx_mode */
+ rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
+ E1000_RCTL_BAM | /* RX All Bcast Pkts */
+ E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
+
+ rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */
+ E1000_RCTL_DPF | /* Allow filtered pause */
+ E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */
+ /* Do not mess with E1000_CTRL_VME, it affects transmit as well,
+ * and that breaks VLANs.
+ */
+ }
+
ew32(RCTL, rctl);
}
@@ -3243,6 +3265,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
nr_frags, mss);
if (count) {
+ skb_tx_timestamp(skb);
+
e1000_tx_queue(adapter, tx_ring, tx_flags, count);
/* Make sure there is space in the ring for the next send. */
e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
@@ -3380,7 +3404,7 @@ static void e1000_dump(struct e1000_adapter *adapter)
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i];
- struct my_u { u64 a; u64 b; };
+ struct my_u { __le64 a; __le64 b; };
struct my_u *u = (struct my_u *)tx_desc;
const char *type;
@@ -3424,7 +3448,7 @@ rx_ring_summary:
for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
struct e1000_buffer *buffer_info = &rx_ring->buffer_info[i];
- struct my_u { u64 a; u64 b; };
+ struct my_u { __le64 a; __le64 b; };
struct my_u *u = (struct my_u *)rx_desc;
const char *type;
@@ -4046,7 +4070,11 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
/* errors is only valid for DD + EOP descriptors */
if (unlikely((status & E1000_RXD_STAT_EOP) &&
(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
- u8 last_byte = *(skb->data + length - 1);
+ u8 *mapped;
+ u8 last_byte;
+
+ mapped = page_address(buffer_info->page);
+ last_byte = *(mapped + length - 1);
if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
last_byte)) {
spin_lock_irqsave(&adapter->stats_lock,
@@ -4057,6 +4085,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
irq_flags);
length--;
} else {
+ if (netdev->features & NETIF_F_RXALL)
+ goto process_skb;
/* recycle both page and skb */
buffer_info->skb = skb;
/* an error means any chain goes out the window
@@ -4069,6 +4099,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
}
#define rxtop rx_ring->rx_skb_top
+process_skb:
if (!(status & E1000_RXD_STAT_EOP)) {
/* this descriptor is only the beginning (or middle) */
if (!rxtop) {
@@ -4276,12 +4307,15 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
flags);
length--;
} else {
+ if (netdev->features & NETIF_F_RXALL)
+ goto process_skb;
/* recycle */
buffer_info->skb = skb;
goto next_desc;
}
}
+process_skb:
total_rx_bytes += (length - 4); /* don't count FCS */
total_rx_packets++;
@@ -4365,30 +4399,6 @@ e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
break;
}
- /* Fix for errata 23, can't cross 64kB boundary */
- if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
- struct sk_buff *oldskb = skb;
- e_err(rx_err, "skb align check failed: %u bytes at "
- "%p\n", bufsz, skb->data);
- /* Try again, without freeing the previous */
- skb = netdev_alloc_skb_ip_align(netdev, bufsz);
- /* Failed allocation, critical failure */
- if (!skb) {
- dev_kfree_skb(oldskb);
- adapter->alloc_rx_buff_failed++;
- break;
- }
-
- if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
- /* give up */
- dev_kfree_skb(skb);
- dev_kfree_skb(oldskb);
- break; /* while (cleaned_count--) */
- }
-
- /* Use new allocation */
- dev_kfree_skb(oldskb);
- }
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
check_page: