igb: Support RX-ALL feature flag.
authorBen Greear <greearb@candelatech.com>
Tue, 6 Mar 2012 09:41:58 +0000 (09:41 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 17 Mar 2012 08:02:26 +0000 (01:02 -0700)
This allows the NIC to receive all frames available, including
those with bad FCS, un-matched vlans, ethernet control frames,
and more.

Tested by sending frames with bad FCS.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/igb_main.c

index aed217449f0dd459eebd13dfff3006a5dd414b06..89eb1f85b9fa914efbecd9c17d4ede27e73ebfaa 100644 (file)
 #define E1000_RCTL_SZ_256         0x00030000    /* rx buffer size 256 */
 #define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
 #define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
+#define E1000_RCTL_DPF            0x00400000    /* Discard Pause Frames */
+#define E1000_RCTL_PMCF           0x00800000    /* pass MAC control frames */
 #define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
 
 /*
index 99364edf0314a5c17ff0d310f4c9b0074fa26b13..c4902411d749b1469e556b9d667c766ea2ecbe20 100644 (file)
@@ -1769,10 +1769,21 @@ static int igb_set_features(struct net_device *netdev,
        netdev_features_t features)
 {
        netdev_features_t changed = netdev->features ^ features;
+       struct igb_adapter *adapter = netdev_priv(netdev);
 
        if (changed & NETIF_F_HW_VLAN_RX)
                igb_vlan_mode(netdev, features);
 
+       if (!(changed & NETIF_F_RXALL))
+               return 0;
+
+       netdev->features = features;
+
+       if (netif_running(netdev))
+               igb_reinit_locked(adapter);
+       else
+               igb_reset(adapter);
+
        return 0;
 }
 
@@ -1954,6 +1965,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
        /* copy netdev features into list of user selectable features */
        netdev->hw_features |= netdev->features;
+       netdev->hw_features |= NETIF_F_RXALL;
 
        /* set this bit last since it cannot be part of hw_features */
        netdev->features |= NETIF_F_HW_VLAN_FILTER;
@@ -3005,6 +3017,22 @@ void igb_setup_rctl(struct igb_adapter *adapter)
                wr32(E1000_QDE, ALL_QUEUES);
        }
 
+       /* 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.
+                */
+       }
+
        wr32(E1000_RCTL, rctl);
 }
 
@@ -6102,8 +6130,9 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
                        goto next_desc;
                }
 
-               if (igb_test_staterr(rx_desc,
-                                    E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+               if (unlikely((igb_test_staterr(rx_desc,
+                                              E1000_RXDEXT_ERR_FRAME_ERR_MASK))
+                            && !(rx_ring->netdev->features & NETIF_F_RXALL))) {
                        dev_kfree_skb_any(skb);
                        goto next_desc;
                }