Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[pandora-kernel.git] / drivers / net / starfire.c
index 8b64786..1d2ef8f 100644 (file)
@@ -27,8 +27,8 @@
 */
 
 #define DRV_NAME       "starfire"
-#define DRV_VERSION    "2.0"
-#define DRV_RELDATE    "June 27, 2006"
+#define DRV_VERSION    "2.1"
+#define DRV_RELDATE    "July  6, 2008"
 
 #include <linux/module.h>
 #include <linux/kernel.h>
 #define VLAN_SUPPORT
 #endif
 
-#ifndef CONFIG_ADAPTEC_STARFIRE_NAPI
-#undef HAVE_NETDEV_POLL
-#endif
-
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
 
@@ -155,7 +151,7 @@ static int full_duplex[MAX_UNITS] = {0, };
 #if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS    /* This chip uses 64 bit addresses. */
-#define netdrv_addr_t u64
+#define netdrv_addr_t __le64
 #define cpu_to_dma(x) cpu_to_le64(x)
 #define dma_to_cpu(x) le64_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
@@ -164,7 +160,7 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
 #define RX_DESC_ADDR_SIZE RxDescAddr64bit
 #else  /* 32-bit dma_addr_t */
-#define netdrv_addr_t u32
+#define netdrv_addr_t __le32
 #define cpu_to_dma(x) cpu_to_le32(x)
 #define dma_to_cpu(x) le32_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
@@ -177,49 +173,8 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
 
-#ifdef HAVE_NETDEV_POLL
-#define init_poll(dev) \
-do { \
-       dev->poll = &netdev_poll; \
-       dev->weight = max_interrupt_work; \
-} while (0)
-#define netdev_rx(dev, ioaddr) \
-do { \
-       u32 intr_enable; \
-       if (netif_rx_schedule_prep(dev)) { \
-               __netif_rx_schedule(dev); \
-               intr_enable = readl(ioaddr + IntrEnable); \
-               intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
-               writel(intr_enable, ioaddr + IntrEnable); \
-               readl(ioaddr + IntrEnable); /* flush PCI posting buffers */ \
-       } else { \
-               /* Paranoia check */ \
-               intr_enable = readl(ioaddr + IntrEnable); \
-               if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
-                       printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
-                       intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
-                       writel(intr_enable, ioaddr + IntrEnable); \
-               } \
-       } \
-} while (0)
-#define netdev_receive_skb(skb) netif_receive_skb(skb)
-#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_receive_skb(skb, vlgrp, vlid)
-static int     netdev_poll(struct net_device *dev, int *budget);
-#else  /* not HAVE_NETDEV_POLL */
-#define init_poll(dev)
-#define netdev_receive_skb(skb) netif_rx(skb)
-#define vlan_netdev_receive_skb(skb, vlgrp, vlid) vlan_hwaccel_rx(skb, vlgrp, vlid)
-#define netdev_rx(dev, ioaddr) \
-do { \
-       int quota = np->dirty_rx + RX_RING_SIZE - np->cur_rx; \
-       __netdev_rx(dev, &quota);\
-} while (0)
-#endif /* not HAVE_NETDEV_POLL */
-/* end of compatibility code */
-
-
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitdata =
+static char version[] =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
@@ -497,7 +452,7 @@ enum intr_ctrl_bits {
 
 /* The Rx and Tx buffer descriptors. */
 struct starfire_rx_desc {
-       dma_addr_t rxaddr;
+       netdrv_addr_t rxaddr;
 };
 enum rx_desc_bits {
        RxDescValid=1, RxDescEndRing=2,
@@ -505,25 +460,25 @@ enum rx_desc_bits {
 
 /* Completion queue entry. */
 struct short_rx_done_desc {
-       u32 status;                     /* Low 16 bits is length. */
+       __le32 status;                  /* Low 16 bits is length. */
 };
 struct basic_rx_done_desc {
-       u32 status;                     /* Low 16 bits is length. */
-       u16 vlanid;
-       u16 status2;
+       __le32 status;                  /* Low 16 bits is length. */
+       __le16 vlanid;
+       __le16 status2;
 };
 struct csum_rx_done_desc {
-       u32 status;                     /* Low 16 bits is length. */
-       u16 csum;                       /* Partial checksum */
-       u16 status2;
+       __le32 status;                  /* Low 16 bits is length. */
+       __le16 csum;                    /* Partial checksum */
+       __le16 status2;
 };
 struct full_rx_done_desc {
-       u32 status;                     /* Low 16 bits is length. */
-       u16 status3;
-       u16 status2;
-       u16 vlanid;
-       u16 csum;                       /* partial checksum */
-       u32 timestamp;
+       __le32 status;                  /* Low 16 bits is length. */
+       __le16 status3;
+       __le16 status2;
+       __le16 vlanid;
+       __le16 csum;                    /* partial checksum */
+       __le32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
 #ifdef VLAN_SUPPORT
@@ -540,15 +495,15 @@ enum rx_done_bits {
 
 /* Type 1 Tx descriptor. */
 struct starfire_tx_desc_1 {
-       u32 status;                     /* Upper bits are status, lower 16 length. */
-       u32 addr;
+       __le32 status;                  /* Upper bits are status, lower 16 length. */
+       __le32 addr;
 };
 
 /* Type 2 Tx descriptor. */
 struct starfire_tx_desc_2 {
-       u32 status;                     /* Upper bits are status, lower 16 length. */
-       u32 reserved;
-       u64 addr;
+       __le32 status;                  /* Upper bits are status, lower 16 length. */
+       __le32 reserved;
+       __le64 addr;
 };
 
 #ifdef ADDR_64BITS
@@ -566,9 +521,9 @@ enum tx_desc_bits {
        TxRingWrap=0x04000000, TxCalTCP=0x02000000,
 };
 struct tx_done_desc {
-       u32 status;                     /* timestamp, index. */
+       __le32 status;                  /* timestamp, index. */
 #if 0
-       u32 intrstatus;                 /* interrupt status */
+       __le32 intrstatus;              /* interrupt status */
 #endif
 };
 
@@ -599,6 +554,8 @@ struct netdev_private {
        struct tx_done_desc *tx_done_q;
        dma_addr_t tx_done_q_dma;
        unsigned int tx_done;
+       struct napi_struct napi;
+       struct net_device *dev;
        struct net_device_stats stats;
        struct pci_dev *pci_dev;
 #ifdef VLAN_SUPPORT
@@ -636,6 +593,7 @@ static int  start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void    netdev_error(struct net_device *dev, int intr_status);
 static int     __netdev_rx(struct net_device *dev, int *quota);
+static int     netdev_poll(struct napi_struct *napi, int budget);
 static void    refill_rx_ring(struct net_device *dev);
 static void    netdev_error(struct net_device *dev, int intr_status);
 static void    set_rx_mode(struct net_device *dev);
@@ -695,6 +653,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        void __iomem *base;
        int drv_flags, io_size;
        int boguscnt;
+       DECLARE_MAC_BUF(mac);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -720,7 +679,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
                printk(KERN_ERR DRV_NAME " %d: cannot alloc etherdev, aborting\n", card_idx);
                return -ENOMEM;
        }
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        irq = pdev->irq;
@@ -791,6 +749,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        dev->irq = irq;
 
        np = netdev_priv(dev);
+       np->dev = dev;
        np->base = base;
        spin_lock_init(&np->lock);
        pci_set_drvdata(pdev, dev);
@@ -851,7 +810,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        dev->hard_start_xmit = &start_tx;
        dev->tx_timeout = tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-       init_poll(dev);
+       netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
        dev->stop = &netdev_close;
        dev->get_stats = &get_stats;
        dev->set_multicast_list = &set_rx_mode;
@@ -864,11 +823,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        if (register_netdev(dev))
                goto err_out_cleardev;
 
-       printk(KERN_INFO "%s: %s at %p, ",
-                  dev->name, netdrv_tbl[chip_idx].name, base);
-       for (i = 0; i < 5; i++)
-               printk("%2.2x:", dev->dev_addr[i]);
-       printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+       printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+              dev->name, netdrv_tbl[chip_idx].name, base,
+              print_mac(mac, dev->dev_addr), irq);
 
        if (drv_flags & CanHaveMII) {
                int phy, phy_idx = 0;
@@ -965,7 +922,7 @@ static int netdev_open(struct net_device *dev)
                       dev->name, dev->irq);
 
        /* Allocate the various queues. */
-       if (np->queue_mem == 0) {
+       if (!np->queue_mem) {
                tx_done_q_size = ((sizeof(struct tx_done_desc) * DONE_Q_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
                rx_done_q_size = ((sizeof(rx_done_desc) * DONE_Q_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
                tx_ring_size = ((sizeof(starfire_tx_desc) * TX_RING_SIZE + QUEUE_ALIGN - 1) / QUEUE_ALIGN) * QUEUE_ALIGN;
@@ -1038,11 +995,11 @@ static int netdev_open(struct net_device *dev)
        writew(0, ioaddr + PerfFilterTable + 4);
        writew(0, ioaddr + PerfFilterTable + 8);
        for (i = 1; i < 16; i++) {
-               u16 *eaddrs = (u16 *)dev->dev_addr;
+               __be16 *eaddrs = (__be16 *)dev->dev_addr;
                void __iomem *setup_frm = ioaddr + PerfFilterTable + i * 16;
-               writew(cpu_to_be16(eaddrs[2]), setup_frm); setup_frm += 4;
-               writew(cpu_to_be16(eaddrs[1]), setup_frm); setup_frm += 4;
-               writew(cpu_to_be16(eaddrs[0]), setup_frm); setup_frm += 8;
+               writew(be16_to_cpu(eaddrs[2]), setup_frm); setup_frm += 4;
+               writew(be16_to_cpu(eaddrs[1]), setup_frm); setup_frm += 4;
+               writew(be16_to_cpu(eaddrs[0]), setup_frm); setup_frm += 8;
        }
 
        /* Initialize other registers. */
@@ -1056,6 +1013,8 @@ static int netdev_open(struct net_device *dev)
 
        writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
+       napi_enable(&np->napi);
+
        netif_start_queue(dev);
 
        if (debug > 1)
@@ -1329,8 +1288,28 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
 
                handled = 1;
 
-               if (intr_status & (IntrRxDone | IntrRxEmpty))
-                       netdev_rx(dev, ioaddr);
+               if (intr_status & (IntrRxDone | IntrRxEmpty)) {
+                       u32 enable;
+
+                       if (likely(netif_rx_schedule_prep(dev, &np->napi))) {
+                               __netif_rx_schedule(dev, &np->napi);
+                               enable = readl(ioaddr + IntrEnable);
+                               enable &= ~(IntrRxDone | IntrRxEmpty);
+                               writel(enable, ioaddr + IntrEnable);
+                               /* flush PCI posting buffers */
+                               readl(ioaddr + IntrEnable);
+                       } else {
+                               /* Paranoia check */
+                               enable = readl(ioaddr + IntrEnable);
+                               if (enable & (IntrRxDone | IntrRxEmpty)) {
+                                       printk(KERN_INFO
+                                              "%s: interrupt while in poll!\n",
+                                              dev->name);
+                                       enable &= ~(IntrRxDone | IntrRxEmpty);
+                                       writel(enable, ioaddr + IntrEnable);
+                               }
+                       }
+               }
 
                /* Scavenge the skbuff list based on the Tx-done queue.
                   There are redundant checks here that may be cleaned up
@@ -1410,8 +1389,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
 }
 
 
-/* This routine is logically part of the interrupt/poll handler, but separated
-   for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */
+/*
+ * This routine is logically part of the interrupt/poll handler, but separated
+ * for clarity and better register allocation.
+ */
 static int __netdev_rx(struct net_device *dev, int *quota)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -1470,13 +1451,15 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                }
 #ifndef final_version                  /* Remove after testing. */
                /* You will want this info for the initial debug. */
-               if (debug > 5)
-                       printk(KERN_DEBUG "  Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
-                              "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x.\n",
-                              skb->data[0], skb->data[1], skb->data[2], skb->data[3],
-                              skb->data[4], skb->data[5], skb->data[6], skb->data[7],
-                              skb->data[8], skb->data[9], skb->data[10],
-                              skb->data[11], skb->data[12], skb->data[13]);
+               if (debug > 5) {
+                       printk(KERN_DEBUG "  Rx data " MAC_FMT " " MAC_FMT
+                              " %2.2x%2.2x.\n",
+                              skb->data[0], skb->data[1], skb->data[2],
+                              skb->data[3], skb->data[4], skb->data[5],
+                              skb->data[6], skb->data[7], skb->data[8],
+                              skb->data[9], skb->data[10], skb->data[11],
+                              skb->data[12], skb->data[13]);
+               }
 #endif
 
                skb->protocol = eth_type_trans(skb, dev);
@@ -1504,13 +1487,20 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                }
 #ifdef VLAN_SUPPORT
                if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
-                       if (debug > 4)
-                               printk(KERN_DEBUG "  netdev_rx() vlanid = %d\n", le16_to_cpu(desc->vlanid));
-                       /* vlan_netdev_receive_skb() expects a packet with the VLAN tag stripped out */
-                       vlan_netdev_receive_skb(skb, np->vlgrp, le16_to_cpu(desc->vlanid) & VLAN_VID_MASK);
+                       u16 vlid = le16_to_cpu(desc->vlanid);
+
+                       if (debug > 4) {
+                               printk(KERN_DEBUG "  netdev_rx() vlanid = %d\n",
+                                      vlid);
+                       }
+                       /*
+                        * vlan_hwaccel_rx expects a packet with the VLAN tag
+                        * stripped out.
+                        */
+                       vlan_hwaccel_rx(skb, np->vlgrp, vlid);
                } else
 #endif /* VLAN_SUPPORT */
-                       netdev_receive_skb(skb);
+                       netif_receive_skb(skb);
                dev->last_rx = jiffies;
                np->stats.rx_packets++;
 
@@ -1529,41 +1519,36 @@ static int __netdev_rx(struct net_device *dev, int *quota)
        return retcode;
 }
 
-
-#ifdef HAVE_NETDEV_POLL
-static int netdev_poll(struct net_device *dev, int *budget)
+static int netdev_poll(struct napi_struct *napi, int budget)
 {
+       struct netdev_private *np = container_of(napi, struct netdev_private, napi);
+       struct net_device *dev = np->dev;
        u32 intr_status;
-       struct netdev_private *np = netdev_priv(dev);
        void __iomem *ioaddr = np->base;
-       int retcode = 0, quota = dev->quota;
+       int quota = budget;
 
        do {
                writel(IntrRxDone | IntrRxEmpty, ioaddr + IntrClear);
 
-               retcode = __netdev_rx(dev, &quota);
-               *budget -= (dev->quota - quota);
-               dev->quota = quota;
-               if (retcode)
+               if (__netdev_rx(dev, &quota))
                        goto out;
 
                intr_status = readl(ioaddr + IntrStatus);
        } while (intr_status & (IntrRxDone | IntrRxEmpty));
 
-       netif_rx_complete(dev);
+       netif_rx_complete(dev, napi);
        intr_status = readl(ioaddr + IntrEnable);
        intr_status |= IntrRxDone | IntrRxEmpty;
        writel(intr_status, ioaddr + IntrEnable);
 
  out:
        if (debug > 5)
-               printk(KERN_DEBUG "  exiting netdev_poll(): %d.\n", retcode);
+               printk(KERN_DEBUG "  exiting netdev_poll(): %d.\n",
+                      budget - quota);
 
        /* Restart Rx engine if stopped. */
-       return retcode;
+       return budget - quota;
 }
-#endif /* HAVE_NETDEV_POLL */
-
 
 static void refill_rx_ring(struct net_device *dev)
 {
@@ -1739,7 +1724,7 @@ static void set_rx_mode(struct net_device *dev)
                        if (vlan_group_get_device(np->vlgrp, i)) {
                                if (vlan_count >= 32)
                                        break;
-                               writew(cpu_to_be16(i), filter_addr);
+                               writew(i, filter_addr);
                                filter_addr += 16;
                                vlan_count++;
                        }
@@ -1764,26 +1749,26 @@ static void set_rx_mode(struct net_device *dev)
        } else if (dev->mc_count <= 14) {
                /* Use the 16 element perfect filter, skip first two entries. */
                void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16;
-               u16 *eaddrs;
+               __be16 *eaddrs;
                for (i = 2, mclist = dev->mc_list; mclist && i < dev->mc_count + 2;
                     i++, mclist = mclist->next) {
-                       eaddrs = (u16 *)mclist->dmi_addr;
-                       writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[0]), filter_addr); filter_addr += 8;
+                       eaddrs = (__be16 *)mclist->dmi_addr;
+                       writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8;
                }
-               eaddrs = (u16 *)dev->dev_addr;
+               eaddrs = (__be16 *)dev->dev_addr;
                while (i++ < 16) {
-                       writew(cpu_to_be16(eaddrs[0]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 8;
+                       writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 8;
                }
                rx_mode |= AcceptBroadcast|PerfectFilter;
        } else {
                /* Must use a multicast hash table. */
                void __iomem *filter_addr;
-               u16 *eaddrs;
-               u16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));      /* Multicast hash filter */
+               __be16 *eaddrs;
+               __le16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));   /* Multicast hash filter */
 
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -1791,17 +1776,17 @@ static void set_rx_mode(struct net_device *dev)
                        /* The chip uses the upper 9 CRC bits
                           as index into the hash table */
                        int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
-                       __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
+                       __le32 *fptr = (__le32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
                        *fptr |= cpu_to_le32(1 << (bit_nr & 31));
                }
                /* Clear the perfect filter list, skip first two entries. */
                filter_addr = ioaddr + PerfFilterTable + 2 * 16;
-               eaddrs = (u16 *)dev->dev_addr;
+               eaddrs = (__be16 *)dev->dev_addr;
                for (i = 2; i < 16; i++) {
-                       writew(cpu_to_be16(eaddrs[0]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;
-                       writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 8;
+                       writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
+                       writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 8;
                }
                for (filter_addr = ioaddr + HashTable, i = 0; i < 32; filter_addr+= 16, i++)
                        writew(mc_filter[i], filter_addr);
@@ -1905,6 +1890,8 @@ static int netdev_close(struct net_device *dev)
 
        netif_stop_queue(dev);
 
+       napi_disable(&np->napi);
+
        if (debug > 1) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
                           dev->name, (int) readl(ioaddr + IntrStatus));
@@ -2039,11 +2026,8 @@ static int __init starfire_init (void)
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
        printk(version);
-#ifdef HAVE_NETDEV_POLL
+
        printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
-#else
-       printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n");
-#endif
 #endif
 
        /* we can do this test only at run-time... sigh */