r8169: Support RX-ALL flag.
authorBen Greear <greearb@candelatech.com>
Fri, 10 Feb 2012 15:04:33 +0000 (15:04 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 24 Feb 2012 09:56:27 +0000 (01:56 -0800)
This allows the NIC to receive packets with bad FCS and
Runts, which can help when sniffing.

NOTE:  r8169, at least on my NIC, silently drops packets
with bad FCS instead of counting them.  It seems they are
only received in any fashion if the RxCRC flag is set
(which this patch allows).

Signed-off-by: Ben Greear <greearb@candelatech.com>
drivers/net/ethernet/realtek/r8169.c

index 5eb6858ed0a7dbedbb49cab2007593ce3b3cf4fb..0517a6a252f1f1808ab20fec7cf5a749385f5da3 100644 (file)
@@ -1626,21 +1626,32 @@ static void __rtl8169_set_features(struct net_device *dev,
                                   netdev_features_t features)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
-
+       netdev_features_t changed = features ^ dev->features;
        void __iomem *ioaddr = tp->mmio_addr;
 
-       if (features & NETIF_F_RXCSUM)
-               tp->cp_cmd |= RxChkSum;
-       else
-               tp->cp_cmd &= ~RxChkSum;
+       if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
+               return;
 
-       if (dev->features & NETIF_F_HW_VLAN_RX)
-               tp->cp_cmd |= RxVlan;
-       else
-               tp->cp_cmd &= ~RxVlan;
+       if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
+               if (features & NETIF_F_RXCSUM)
+                       tp->cp_cmd |= RxChkSum;
+               else
+                       tp->cp_cmd &= ~RxChkSum;
 
-       RTL_W16(CPlusCmd, tp->cp_cmd);
-       RTL_R16(CPlusCmd);
+               if (dev->features & NETIF_F_HW_VLAN_RX)
+                       tp->cp_cmd |= RxVlan;
+               else
+                       tp->cp_cmd &= ~RxVlan;
+
+               RTL_W16(CPlusCmd, tp->cp_cmd);
+               RTL_R16(CPlusCmd);
+       }
+       if (changed & NETIF_F_RXALL) {
+               int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
+               if (features & NETIF_F_RXALL)
+                       tmp |= (AcceptErr | AcceptRunt);
+               RTL_W32(RxConfig, tmp);
+       }
 }
 
 static int rtl8169_set_features(struct net_device *dev,
@@ -4174,6 +4185,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                /* 8110SCd requires hardware Rx VLAN - disallow toggling */
                dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
 
+       dev->hw_features |= NETIF_F_RXALL;
+
        tp->hw_start = cfg->hw_start;
        tp->event_slow = cfg->event_slow;
 
@@ -5747,11 +5760,20 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
                                rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
                                dev->stats.rx_fifo_errors++;
                        }
+                       if ((status & (RxRUNT | RxCRC)) &&
+                           !(status & (RxRWT | RxFOVF)) &&
+                           (dev->features & NETIF_F_RXALL))
+                               goto process_pkt;
+
                        rtl8169_mark_to_asic(desc, rx_buf_sz);
                } else {
                        struct sk_buff *skb;
-                       dma_addr_t addr = le64_to_cpu(desc->addr);
-                       int pkt_size = (status & 0x00003fff) - 4;
+                       dma_addr_t addr;
+                       int pkt_size;
+
+process_pkt:
+                       addr = le64_to_cpu(desc->addr);
+                       pkt_size = (status & 0x00003fff) - 4;
 
                        /*
                         * The driver does not support incoming fragmented
@@ -6025,6 +6047,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
                }
        }
 
+       if (dev->features & NETIF_F_RXALL)
+               rx_mode |= (AcceptErr | AcceptRunt);
+
        tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
 
        if (tp->mac_version > RTL_GIGA_MAC_VER_06) {