]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/r8169.c
r8169: RX fifo overflow recovery
[linux-2.6-omap-h63xx.git] / drivers / net / r8169.c
index 9945cc6b8d90ac1fbdfca8ebad2cc6a5320c6cef..ea4f9f7bd071d84ce866248b0a612d1c8d378bbc 100644 (file)
@@ -257,10 +257,11 @@ enum RTL8169_register_content {
        RxOK = 0x01,
 
        /* RxStatusDesc */
-       RxRES = 0x00200000,
-       RxCRC = 0x00080000,
-       RxRUNT = 0x00100000,
-       RxRWT = 0x00400000,
+       RxFOVF  = (1 << 23),
+       RxRWT   = (1 << 22),
+       RxRES   = (1 << 21),
+       RxRUNT  = (1 << 20),
+       RxCRC   = (1 << 19),
 
        /* ChipCmdBits */
        CmdReset = 0x10,
@@ -1382,6 +1383,41 @@ static void rtl8169_netpoll(struct net_device *dev)
 }
 #endif
 
+static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem *ioaddr)
+{
+       unsigned int i, j;
+
+       RTL_W8(Cfg9346, Cfg9346_Unlock);
+       for (i = 0; i < 2; i++) {
+               __le32 l = 0;
+
+               for (j = 0; j < 4; j++) {
+                       l <<= 8;
+                       l |= dev->dev_addr[4*i + j];
+               }
+               RTL_W32(MAC0 + 4*i, cpu_to_be32(l));
+       }
+       RTL_W8(Cfg9346, Cfg9346_Lock);
+}
+
+static int rtl8169_set_mac_addr(struct net_device *dev, void *p)
+{
+       struct rtl8169_private *tp = netdev_priv(dev);
+       struct sockaddr *addr = p;
+
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
+       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+       if (netif_running(dev)) {
+               spin_lock_irq(&tp->lock);
+               __rtl8169_set_mac_addr(dev, tp->mmio_addr);
+               spin_unlock_irq(&tp->lock);
+       }
+       return 0;
+}
+
 static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
                                  void __iomem *ioaddr)
 {
@@ -1406,7 +1442,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
        dev = alloc_etherdev(sizeof (*tp));
        if (dev == NULL) {
                if (netif_msg_drv(&debug))
-                       printk(KERN_ERR PFX "unable to alloc new ethernet\n");
+                       dev_err(&pdev->dev, "unable to alloc new ethernet\n");
                goto err_out;
        }
 
@@ -1418,10 +1454,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
        /* enable device (incl. PCI PM wakeup and hotplug setup) */
        rc = pci_enable_device(pdev);
        if (rc < 0) {
-               if (netif_msg_probe(tp)) {
-                       printk(KERN_ERR PFX "%s: enable failure\n",
-                              pci_name(pdev));
-               }
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev, "enable failure\n");
                goto err_out_free_dev;
        }
 
@@ -1437,37 +1471,32 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
                pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
                acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
        } else {
-               if (netif_msg_probe(tp)) {
-                       printk(KERN_ERR PFX
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev,
                               "PowerManagement capability not found.\n");
-               }
        }
 
        /* make sure PCI base addr 1 is MMIO */
        if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-               if (netif_msg_probe(tp)) {
-                       printk(KERN_ERR PFX
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev,
                               "region #1 not an MMIO resource, aborting\n");
-               }
                rc = -ENODEV;
                goto err_out_mwi;
        }
        /* check for weird/broken PCI region reporting */
        if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
-               if (netif_msg_probe(tp)) {
-                       printk(KERN_ERR PFX
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev,
                               "Invalid PCI region size(s), aborting\n");
-               }
                rc = -ENODEV;
                goto err_out_mwi;
        }
 
        rc = pci_request_regions(pdev, MODULENAME);
        if (rc < 0) {
-               if (netif_msg_probe(tp)) {
-                       printk(KERN_ERR PFX "%s: could not request regions.\n",
-                              pci_name(pdev));
-               }
+               if (netif_msg_probe(tp))
+                       dev_err(&pdev->dev, "could not request regions.\n");
                goto err_out_mwi;
        }
 
@@ -1480,10 +1509,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
        } else {
                rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
                if (rc < 0) {
-                       if (netif_msg_probe(tp)) {
-                               printk(KERN_ERR PFX
+                       if (netif_msg_probe(tp))
+                               dev_err(&pdev->dev,
                                       "DMA configuration failed.\n");
-                       }
                        goto err_out_free_res;
                }
        }
@@ -1494,7 +1522,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
        ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
        if (ioaddr == NULL) {
                if (netif_msg_probe(tp))
-                       printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
+                       dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
                rc = -EIO;
                goto err_out_free_res;
        }
@@ -1526,9 +1554,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
        if (i < 0) {
                /* Unknown chip: assume array element #0, original RTL-8169 */
                if (netif_msg_probe(tp)) {
-                       printk(KERN_DEBUG PFX "PCI device %s: "
+                       dev_printk(KERN_DEBUG, &pdev->dev,
                               "unknown chip version, assuming %s\n",
-                              pci_name(pdev), rtl_chip_info[0].name);
+                              rtl_chip_info[0].name);
                }
                i++;
        }
@@ -1617,6 +1645,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->stop = rtl8169_close;
        dev->tx_timeout = rtl8169_tx_timeout;
        dev->set_multicast_list = rtl8169_set_rx_mode;
+       dev->set_mac_address = rtl8169_set_mac_addr;
        dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
        dev->irq = pdev->irq;
        dev->base_addr = (unsigned long) ioaddr;
@@ -1726,7 +1755,7 @@ static int rtl8169_open(struct net_device *dev)
        rtl8169_set_rxbufsize(tp, dev);
 
        retval =
-           request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
+           request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, dev->name, dev);
        if (retval < 0)
                goto out;
 
@@ -1850,6 +1879,8 @@ rtl8169_hw_start(struct net_device *dev)
        /* Enable all known interrupts by setting the interrupt mask. */
        RTL_W16(IntrMask, rtl8169_intr_mask);
 
+       __rtl8169_set_mac_addr(dev, ioaddr);
+
        netif_start_queue(dev);
 }
 
@@ -2172,7 +2203,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
 static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
 {
        if (dev->features & NETIF_F_TSO) {
-               u32 mss = skb_shinfo(skb)->tso_size;
+               u32 mss = skb_shinfo(skb)->gso_size;
 
                if (mss)
                        return LargeSend | ((mss & MSSMask) << MSSShift);
@@ -2222,8 +2253,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
                len = skb->len;
 
                if (unlikely(len < ETH_ZLEN)) {
-                       skb = skb_padto(skb, ETH_ZLEN);
-                       if (!skb)
+                       if (skb_padto(skb, ETH_ZLEN))
                                goto err_update_stats;
                        len = ETH_ZLEN;
                }
@@ -2436,6 +2466,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
                                tp->stats.rx_length_errors++;
                        if (status & RxCRC)
                                tp->stats.rx_crc_errors++;
+                       if (status & RxFOVF) {
+                               rtl8169_schedule_work(dev, rtl8169_reset_task);
+                               tp->stats.rx_fifo_errors++;
+                       }
                        rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
                } else {
                        struct sk_buff *skb = tp->Rx_skbuff[entry];