Skip to content

Commit

Permalink
8139too: Support RX-ALL logic.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Greear authored and Jeff Kirsher committed Feb 24, 2012
1 parent b0d1562 commit d95089d
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions drivers/net/ethernet/realtek/8139too.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,33 @@ static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -1978,11 +2008,30 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
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. */

Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit d95089d

Please sign in to comment.