mlx4_en: Fix a kernel panic when waking tx queue
[safe/jmp/linux-2.6] / drivers / net / via-rhine.c
index 6654715..45daba7 100644 (file)
@@ -30,8 +30,8 @@
 */
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.4.1"
-#define DRV_RELDATE    "July-24-2006"
+#define DRV_VERSION    "1.4.3"
+#define DRV_RELDATE    "2007-03-06"
 
 
 /* A few user-configurable values.
@@ -42,7 +42,13 @@ static int max_interrupt_work = 20;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
+#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
+       || defined(CONFIG_SPARC) || defined(__ia64__) \
+       || defined(__sh__) || defined(__mips__)
+static int rx_copybreak = 1518;
+#else
 static int rx_copybreak;
+#endif
 
 /* Work-around for broken BIOSes: they are unable to get the chip back out of
    power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
@@ -67,12 +73,7 @@ static const int multicast_filter_limit = 32;
    There are no ill effects from too-large receive rings. */
 #define TX_RING_SIZE   16
 #define TX_QUEUE_LEN   10      /* Limit ring entries actually used. */
-#ifdef CONFIG_VIA_RHINE_NAPI
 #define RX_RING_SIZE   64
-#else
-#define RX_RING_SIZE   16
-#endif
-
 
 /* Operational parameters that usually are not changed. */
 
@@ -105,10 +106,12 @@ static const int multicast_filter_limit = 32;
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <linux/dmi.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
-KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n";
+static const char version[] __devinitconst =
+       KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE
+       " Written by Donald Becker\n";
 
 /* This driver was written to use PCI memory space. Some early versions
    of the Rhine may only work correctly with I/O space accesses. */
@@ -189,12 +192,13 @@ IIId. Synchronization
 
 The driver runs as two independent, single-threaded flows of control. One
 is the send-packet routine, which enforces single-threaded use by the
-dev->priv->lock spinlock. The other thread is the interrupt handler, which
-is single threaded by the hardware and interrupt handling software.
+netdev_priv(dev)->lock spinlock. The other thread is the interrupt handler,
+which is single threaded by the hardware and interrupt handling software.
 
 The send packet thread has partial control over the Tx ring. It locks the
-dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring
-is not available it stops the transmit queue by calling netif_stop_queue.
+netdev_priv(dev)->lock whenever it's queuing a Tx packet. If the next slot in
+the ring is not available it stops the transmit queue by
+calling netif_stop_queue.
 
 The interrupt handler has exclusive control over the Rx ring and records stats
 from the Tx ring. After reaping the stats, it marks the Tx queue entry as
@@ -328,16 +332,16 @@ enum wol_bits {
 
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
-       s32 rx_status;
-       u32 desc_length; /* Chain flag, Buffer/frame length */
-       u32 addr;
-       u32 next_desc;
+       __le32 rx_status;
+       __le32 desc_length; /* Chain flag, Buffer/frame length */
+       __le32 addr;
+       __le32 next_desc;
 };
 struct tx_desc {
-       s32 tx_status;
-       u32 desc_length; /* Chain flag, Tx Config, Frame length */
-       u32 addr;
-       u32 next_desc;
+       __le32 tx_status;
+       __le32 desc_length; /* Chain flag, Tx Config, Frame length */
+       __le32 addr;
+       __le32 next_desc;
 };
 
 /* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */
@@ -382,6 +386,8 @@ struct rhine_private {
 
        struct pci_dev *pdev;
        long pioaddr;
+       struct net_device *dev;
+       struct napi_struct napi;
        struct net_device_stats stats;
        spinlock_t lock;
 
@@ -404,14 +410,14 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 static int  rhine_open(struct net_device *dev);
 static void rhine_tx_timeout(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 static void rhine_tx(struct net_device *dev);
 static int rhine_rx(struct net_device *dev, int limit);
 static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct ethtool_ops netdev_ethtool_ops;
+static const struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
 static void rhine_shutdown (struct pci_dev *pdev);
 
@@ -569,38 +575,33 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 static void rhine_poll(struct net_device *dev)
 {
        disable_irq(dev->irq);
-       rhine_interrupt(dev->irq, (void *)dev, NULL);
+       rhine_interrupt(dev->irq, (void *)dev);
        enable_irq(dev->irq);
 }
 #endif
 
-#ifdef CONFIG_VIA_RHINE_NAPI
-static int rhine_napipoll(struct net_device *dev, int *budget)
+static int rhine_napipoll(struct napi_struct *napi, int budget)
 {
-       struct rhine_private *rp = netdev_priv(dev);
+       struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
+       struct net_device *dev = rp->dev;
        void __iomem *ioaddr = rp->base;
-       int done, limit = min(dev->quota, *budget);
+       int work_done;
 
-       done = rhine_rx(dev, limit);
-       *budget -= done;
-       dev->quota -= done;
+       work_done = rhine_rx(dev, budget);
 
-       if (done < limit) {
-               netif_rx_complete(dev);
+       if (work_done < budget) {
+               napi_complete(napi);
 
                iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
                          IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
                          IntrTxDone | IntrTxError | IntrTxUnderrun |
                          IntrPCIErr | IntrStatsMax | IntrLinkChange,
                          ioaddr + IntrEnable);
-               return 0;
        }
-       else
-               return 1;
+       return work_done;
 }
-#endif
 
-static void rhine_hw_init(struct net_device *dev, long pioaddr)
+static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
 {
        struct rhine_private *rp = netdev_priv(dev);
 
@@ -615,13 +616,27 @@ static void rhine_hw_init(struct net_device *dev, long pioaddr)
        rhine_reload_eeprom(pioaddr, dev);
 }
 
+static const struct net_device_ops rhine_netdev_ops = {
+       .ndo_open                = rhine_open,
+       .ndo_stop                = rhine_close,
+       .ndo_start_xmit          = rhine_start_tx,
+       .ndo_get_stats           = rhine_get_stats,
+       .ndo_set_multicast_list  = rhine_set_rx_mode,
+       .ndo_validate_addr       = eth_validate_addr,
+       .ndo_set_mac_address     = eth_mac_addr,
+       .ndo_do_ioctl            = netdev_ioctl,
+       .ndo_tx_timeout          = rhine_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller     = rhine_poll,
+#endif
+};
+
 static int __devinit rhine_init_one(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct rhine_private *rp;
        int i, rc;
-       u8 pci_rev;
        u32 quirks;
        long pioaddr;
        long memaddr;
@@ -641,27 +656,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(version);
 #endif
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
        io_size = 256;
        phy_id = 0;
        quirks = 0;
        name = "Rhine";
-       if (pci_rev < VTunknown0) {
+       if (pdev->revision < VTunknown0) {
                quirks = rqRhineI;
                io_size = 128;
        }
-       else if (pci_rev >= VT6102) {
+       else if (pdev->revision >= VT6102) {
                quirks = rqWOL | rqForceReset;
-               if (pci_rev < VT6105) {
+               if (pdev->revision < VT6105) {
                        name = "Rhine II";
                        quirks |= rqStatusWBRace;       /* Rhine-II exclusive */
                }
                else {
                        phy_id = 1;     /* Integrated PHY, phy_id fixed to 1 */
-                       if (pci_rev >= VT6105_B0)
+                       if (pdev->revision >= VT6105_B0)
                                quirks |= rq6patterns;
-                       if (pci_rev < VT6105M)
+                       if (pdev->revision < VT6105M)
                                name = "Rhine III";
                        else
                                name = "Rhine III (Management Adapter)";
@@ -673,7 +686,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                goto err_out;
 
        /* this should always be supported */
-       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (rc) {
                printk(KERN_ERR "32-bit PCI DMA addresses not supported by "
                       "the card!?\n");
@@ -699,10 +712,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
                printk(KERN_ERR "alloc_etherdev failed\n");
                goto err_out;
        }
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        rp = netdev_priv(dev);
+       rp->dev = dev;
        rp->quirks = quirks;
        rp->pioaddr = pioaddr;
        rp->pdev = pdev;
@@ -768,22 +781,12 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        rp->mii_if.reg_num_mask = 0x1f;
 
        /* The chip-specific entries in the device structure. */
-       dev->open = rhine_open;
-       dev->hard_start_xmit = rhine_start_tx;
-       dev->stop = rhine_close;
-       dev->get_stats = rhine_get_stats;
-       dev->set_multicast_list = rhine_set_rx_mode;
-       dev->do_ioctl = netdev_ioctl;
-       dev->ethtool_ops = &netdev_ethtool_ops;
-       dev->tx_timeout = rhine_tx_timeout;
+       dev->netdev_ops = &rhine_netdev_ops;
+       dev->ethtool_ops = &netdev_ethtool_ops,
        dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = rhine_poll;
-#endif
-#ifdef CONFIG_VIA_RHINE_NAPI
-       dev->poll = rhine_napipoll;
-       dev->weight = 64;
-#endif
+
+       netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
+
        if (rp->quirks & rqRhineI)
                dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
@@ -792,18 +795,14 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
        if (rc)
                goto err_out_unmap;
 
-       printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
+       printk(KERN_INFO "%s: VIA %s at 0x%lx, %pM, IRQ %d.\n",
               dev->name, name,
 #ifdef USE_MMIO
-               memaddr
+              memaddr,
 #else
-               (long)ioaddr
+              (long)ioaddr,
 #endif
-                );
-
-       for (i = 0; i < 5; i++)
-               printk("%2.2x:", dev->dev_addr[i]);
-       printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], pdev->irq);
+              dev->dev_addr, pdev->irq);
 
        pci_set_drvdata(pdev, dev);
 
@@ -923,7 +922,7 @@ static void alloc_rbufs(struct net_device *dev)
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz);
+               struct sk_buff *skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
                rp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
@@ -1057,7 +1056,7 @@ static void init_registers(struct net_device *dev)
 
        rhine_set_rx_mode(dev);
 
-       netif_poll_enable(dev);
+       napi_enable(&rp->napi);
 
        /* Enable interrupts by setting the interrupt mask. */
        iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
@@ -1192,6 +1191,8 @@ static void rhine_tx_timeout(struct net_device *dev)
        /* protect against concurrent rx interrupts */
        disable_irq(rp->pdev->irq);
 
+       napi_disable(&rp->napi);
+
        spin_lock(&rp->lock);
 
        /* clear all descriptors */
@@ -1290,7 +1291,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
 {
        struct net_device *dev = dev_instance;
        struct rhine_private *rp = netdev_priv(dev);
@@ -1314,16 +1315,12 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
 
                if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
                                   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
-#ifdef CONFIG_VIA_RHINE_NAPI
                        iowrite16(IntrTxAborted |
                                  IntrTxDone | IntrTxError | IntrTxUnderrun |
                                  IntrPCIErr | IntrStatsMax | IntrLinkChange,
                                  ioaddr + IntrEnable);
 
-                       netif_rx_schedule(dev);
-#else
-                       rhine_rx(dev, RX_RING_SIZE);
-#endif
+                       napi_schedule(&rp->napi);
                }
 
                if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
@@ -1333,7 +1330,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
                                if (debug > 2 &&
                                    ioread8(ioaddr+ChipCmd) & CmdTxOn)
                                        printk(KERN_WARNING "%s: "
-                                              "rhine_interrupt() Tx engine"
+                                              "rhine_interrupt() Tx engine "
                                               "still on.\n", dev->name);
                        }
                        rhine_tx(dev);
@@ -1484,17 +1481,16 @@ static int rhine_rx(struct net_device *dev, int limit)
                        /* Check if the packet is long enough to accept without
                           copying to a minimally-sized skbuff. */
                        if (pkt_len < rx_copybreak &&
-                               (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-                               skb->dev = dev;
-                               skb_reserve(skb, 2);    /* 16 byte align the IP header */
+                               (skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN)) != NULL) {
+                               skb_reserve(skb, NET_IP_ALIGN); /* 16 byte align the IP header */
                                pci_dma_sync_single_for_cpu(rp->pdev,
                                                            rp->rx_skbuff_dma[entry],
                                                            rp->rx_buf_sz,
                                                            PCI_DMA_FROMDEVICE);
 
-                               eth_copy_and_sum(skb,
+                               skb_copy_to_linear_data(skb,
                                                 rp->rx_skbuff[entry]->data,
-                                                pkt_len, 0);
+                                                pkt_len);
                                skb_put(skb, pkt_len);
                                pci_dma_sync_single_for_device(rp->pdev,
                                                               rp->rx_skbuff_dma[entry],
@@ -1516,12 +1512,7 @@ static int rhine_rx(struct net_device *dev, int limit)
                                                 PCI_DMA_FROMDEVICE);
                        }
                        skb->protocol = eth_type_trans(skb, dev);
-#ifdef CONFIG_VIA_RHINE_NAPI
                        netif_receive_skb(skb);
-#else
-                       netif_rx(skb);
-#endif
-                       dev->last_rx = jiffies;
                        rp->stats.rx_bytes += pkt_len;
                        rp->stats.rx_packets++;
                }
@@ -1534,7 +1525,7 @@ static int rhine_rx(struct net_device *dev, int limit)
                struct sk_buff *skb;
                entry = rp->dirty_rx % RX_RING_SIZE;
                if (rp->rx_skbuff[entry] == NULL) {
-                       skb = dev_alloc_skb(rp->rx_buf_sz);
+                       skb = netdev_alloc_skb(dev, rp->rx_buf_sz);
                        rp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;  /* Better luck next round. */
@@ -1679,9 +1670,6 @@ static void rhine_set_rx_mode(struct net_device *dev)
        u8 rx_mode;             /* Note: 0x02=accept runt, 0x01=accept errs */
 
        if (dev->flags & IFF_PROMISC) {         /* Set promiscuous. */
-               /* Unconditionally log net taps. */
-               printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                      dev->name);
                rx_mode = 0x1C;
                iowrite32(0xffffffff, ioaddr + MulticastFilter0);
                iowrite32(0xffffffff, ioaddr + MulticastFilter1);
@@ -1799,7 +1787,7 @@ static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        return 0;
 }
 
-static struct ethtool_ops netdev_ethtool_ops = {
+static const struct ethtool_ops netdev_ethtool_ops = {
        .get_drvinfo            = netdev_get_drvinfo,
        .get_settings           = netdev_get_settings,
        .set_settings           = netdev_set_settings,
@@ -1809,9 +1797,6 @@ static struct ethtool_ops netdev_ethtool_ops = {
        .set_msglevel           = netdev_set_msglevel,
        .get_wol                = rhine_get_wol,
        .set_wol                = rhine_set_wol,
-       .get_sg                 = ethtool_op_get_sg,
-       .get_tx_csum            = ethtool_op_get_tx_csum,
-       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1838,7 +1823,7 @@ static int rhine_close(struct net_device *dev)
        spin_lock_irq(&rp->lock);
 
        netif_stop_queue(dev);
-       netif_poll_disable(dev);
+       napi_disable(&rp->napi);
 
        if (debug > 1)
                printk(KERN_DEBUG "%s: Shutting down ethercard, "
@@ -1893,7 +1878,7 @@ static void rhine_shutdown (struct pci_dev *pdev)
 
        /* Make sure we use pattern 0, 1 and not 4, 5 */
        if (rp->quirks & rq6patterns)
-               iowrite8(0x04, ioaddr + 0xA7);
+               iowrite8(0x04, ioaddr + WOLcgClr);
 
        if (rp->wolopts & WAKE_MAGIC) {
                iowrite8(WOLmagic, ioaddr + WOLcrSet);
@@ -1937,6 +1922,8 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
        if (!netif_running(dev))
                return 0;
 
+       napi_disable(&rp->napi);
+
        netif_device_detach(dev);
        pci_save_state(pdev);
 
@@ -1998,6 +1985,23 @@ static struct pci_driver rhine_driver = {
        .shutdown =     rhine_shutdown,
 };
 
+static struct dmi_system_id __initdata rhine_dmi_table[] = {
+       {
+               .ident = "EPIA-M",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       {
+               .ident = "KV7",
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+               },
+       },
+       { NULL }
+};
 
 static int __init rhine_init(void)
 {
@@ -2005,7 +2009,17 @@ static int __init rhine_init(void)
 #ifdef MODULE
        printk(version);
 #endif
-       return pci_module_init(&rhine_driver);
+       if (dmi_check_system(rhine_dmi_table)) {
+               /* these BIOSes fail at PXE boot if chip is in D3 */
+               avoid_D3 = 1;
+               printk(KERN_WARNING "%s: Broken BIOS detected, avoid_D3 "
+                                   "enabled.\n",
+                      DRV_NAME);
+       }
+       else if (avoid_D3)
+               printk(KERN_INFO "%s: avoid_D3 set.\n", DRV_NAME);
+
+       return pci_register_driver(&rhine_driver);
 }