Patchwork [v3,13/16] 8139too: Support RX-ALL logic.

login
register
mail settings
Submitter Ben Greear
Date Feb. 11, 2012, 1:04 a.m.
Message ID <1328922274-23993-14-git-send-email-greearb@candelatech.com>
Download mbox | patch
Permalink /patch/140751/
State Awaiting Upstream
Delegated to: David Miller
Headers show

Comments

Ben Greear - Feb. 11, 2012, 1:04 a.m.
From: Ben Greear <greearb@candelatech.com>

This allows the NIC to receive Runts and frames with bad
Ethernet Frame Checksums (FCS).

Useful to sniffing & diagnosing bad networks.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 1c3feb0... 1b9a090... M	drivers/net/ethernet/realtek/8139too.c
 drivers/net/ethernet/realtek/8139too.c |   52 ++++++++++++++++++++++++++++++++
 1 files changed, 52 insertions(+), 0 deletions(-)

Patch

diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 1c3feb0..1b9a090 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -907,6 +907,33 @@  err_out:
 	return ERR_PTR(rc);
 }
 
+static int rtl8139_set_features(struct net_device *dev, netdev_features_t features)
+{
+	struct rtl8139_private *tp = netdev_priv(dev);
+	unsigned long flags;
+	netdev_features_t changed = features ^ dev->features;
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	if (!(changed & (NETIF_F_RXALL)))
+		return 0;
+
+	spin_lock_irqsave(&tp->lock, flags);
+
+	if (changed & NETIF_F_RXALL) {
+		int rx_mode = tp->rx_config;
+		if (features & NETIF_F_RXALL)
+			rx_mode |= (AcceptErr | AcceptRunt);
+		else
+			rx_mode &= ~(AcceptErr | AcceptRunt);
+		tp->rx_config = rtl8139_rx_config | rx_mode;
+		RTL_W32_F(RxConfig, tp->rx_config);
+	}
+
+	spin_unlock_irqrestore(&tp->lock, flags);
+
+	return 0;
+}
+
 static const struct net_device_ops rtl8139_netdev_ops = {
 	.ndo_open		= rtl8139_open,
 	.ndo_stop		= rtl8139_close,
@@ -921,6 +948,7 @@  static const struct net_device_ops rtl8139_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= rtl8139_poll_controller,
 #endif
+	.ndo_set_features	= rtl8139_set_features,
 };
 
 static int __devinit rtl8139_init_one (struct pci_dev *pdev,
@@ -994,6 +1022,8 @@  static int __devinit rtl8139_init_one (struct pci_dev *pdev,
 	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
 	dev->vlan_features = dev->features;
 
+	dev->hw_features |= NETIF_F_RXALL;
+
 	dev->irq = pdev->irq;
 
 	/* tp zeroed and aligned in alloc_etherdev */
@@ -1978,11 +2008,30 @@  no_early_rx:
 		if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
+			if ((dev->features & NETIF_F_RXALL) &&
+			    (rx_size <= (MAX_ETH_FRAME_SIZE + 4)) &&
+			    (rx_size >= 8) &&
+			    (!(rx_status & RxStatusOK))) {
+				/* Length is at least mostly OK, but pkt has
+				 * error.  I'm hoping we can handle some of these
+				 * errors without resetting the chip. --Ben
+				 */
+				dev->stats.rx_errors++;
+				if (rx_status & RxCRCErr) {
+					dev->stats.rx_crc_errors++;
+					goto keep_pkt;
+				}
+				if (rx_status & RxRunt) {
+					dev->stats.rx_length_errors++;
+					goto keep_pkt;
+				}
+			}
 			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
 			received = -1;
 			goto out;
 		}
 
+keep_pkt:
 		/* Malloc up new buffer, compatible with net-2e. */
 		/* Omit the four octet CRC from the length. */
 
@@ -2515,6 +2564,9 @@  static void __set_rx_mode (struct net_device *dev)
 		}
 	}
 
+	if (dev->features & NETIF_F_RXALL)
+		rx_mode |= (AcceptErr | AcceptRunt);
+
 	/* We can safely update without stopping the chip. */
 	tmp = rtl8139_rx_config | rx_mode;
 	if (tp->rx_config != tmp) {