Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / net / starfire.c
index 236bdd3..9b7805b 100644 (file)
@@ -2,7 +2,7 @@
 /*
        Written 1998-2000 by Donald Becker.
 
 /*
        Written 1998-2000 by Donald Becker.
 
-       Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please
+       Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
        send all bug reports to me, and not to Donald Becker, as this code
        has been heavily modified from Donald's original version.
 
        send all bug reports to me, and not to Donald Becker, as this code
        has been heavily modified from Donald's original version.
 
        - put the chip to a D3 slumber on driver unload
        - added config option to enable/disable NAPI
 
        - put the chip to a D3 slumber on driver unload
        - added config option to enable/disable NAPI
 
-TODO:  bugfixes (no bugs known as of right now)
+       LK1.4.2 (Ion Badulescu)
+       - finally added firmware (GPL'ed by Adaptec)
+       - removed compatibility code for 2.2.x
+
+       LK1.4.2.1 (Ion Badulescu)
+       - fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM
+       - added 32-bit padding to outgoing skb's, removed previous workaround
+
+TODO:  - fix forced speed/duplexing code (broken a long time ago, when
+       somebody converted the driver to use the generic MII code)
+       - fix VLAN support
 */
 
 #define DRV_NAME       "starfire"
 */
 
 #define DRV_NAME       "starfire"
-#define DRV_VERSION    "1.03+LK1.4.1"
-#define DRV_RELDATE    "February 10, 2002"
+#define DRV_VERSION    "1.03+LK1.4.2.1"
+#define DRV_RELDATE    "October 3, 2005"
 
 #include <linux/config.h>
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -145,40 +154,32 @@ TODO:     bugfixes (no bugs known as of right now)
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-/*
- * Adaptec's license for their drivers (which is where I got the
- * firmware files) does not allow one to redistribute them. Thus, we can't
- * include the firmware with this driver.
- *
- * However, should a legal-to-distribute firmware become available,
- * the driver developer would need only to obtain the firmware in the
- * form of a C header file.
- * Once that's done, the #undef below must be changed into a #define
- * for this driver to really use the firmware. Note that Rx/Tx
- * hardware TCP checksumming is not possible without the firmware.
- *
- * WANTED: legal firmware to include with this GPL'd driver.
- */
-#undef HAS_FIRMWARE
+#include "starfire_firmware.h"
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
  */
 #define HAS_BROKEN_FIRMWARE
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
  */
 #define HAS_BROKEN_FIRMWARE
+
 /*
 /*
- * Define this if using the driver with the zero-copy patch
+ * If using the broken firmware, data must be padded to the next 32-bit boundary.
  */
  */
-#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)
-#define ZEROCOPY
+#ifdef HAS_BROKEN_FIRMWARE
+#define PADDING_MASK 3
 #endif
 
 #endif
 
-#ifdef HAS_FIRMWARE
-#include "starfire_firmware.h"
-#endif /* HAS_FIRMWARE */
+/*
+ * Define this if using the driver with the zero-copy patch
+ */
+#define ZEROCOPY
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define VLAN_SUPPORT
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define VLAN_SUPPORT
@@ -200,13 +201,9 @@ static int max_interrupt_work = 20;
 static int mtu;
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
 static int mtu;
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 512;
+static const int multicast_filter_limit = 512;
 /* Whether to do TCP/UDP checksums in hardware */
 /* Whether to do TCP/UDP checksums in hardware */
-#ifdef HAS_FIRMWARE
 static int enable_hw_cksum = 1;
 static int enable_hw_cksum = 1;
-#else
-static int enable_hw_cksum = 0;
-#endif
 
 #define PKT_BUF_SZ     1536            /* Size of each temporary Rx buffer.*/
 /*
 
 #define PKT_BUF_SZ     1536            /* Size of each temporary Rx buffer.*/
 /*
@@ -271,9 +268,10 @@ static int full_duplex[MAX_UNITS] = {0, };
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM) && (LINUX_VERSION_CODE > 0x20500 || defined(CONFIG_HIGHMEM64G))) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || 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. */
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS    /* This chip uses 64 bit addresses. */
+#define netdrv_addr_t u64
 #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
 #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
@@ -282,6 +280,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 TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
 #define RX_DESC_ADDR_SIZE RxDescAddr64bit
 #else  /* 32-bit dma_addr_t */
+#define netdrv_addr_t u32
 #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
 #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
@@ -291,43 +290,15 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define RX_DESC_ADDR_SIZE RxDescAddr32bit
 #endif
 
 #define RX_DESC_ADDR_SIZE RxDescAddr32bit
 #endif
 
-#ifdef MAX_SKB_FRAGS
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
-#else  /* not MAX_SKB_FRAGS */
-#define skb_first_frag_len(skb)        (skb->len)
-#define skb_num_frags(skb) 1
-#endif /* not MAX_SKB_FRAGS */
-
-/* 2.2.x compatibility code */
-#if LINUX_VERSION_CODE < 0x20300
-
-#include "starfire-kcomp22.h"
-
-#else  /* LINUX_VERSION_CODE > 0x20300 */
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-
-#include <linux/if_vlan.h>
-
-#define init_tx_timer(dev, func, timeout) \
-       dev->tx_timeout = func; \
-       dev->watchdog_timeo = timeout;
-#define kick_tx_timer(dev, func, timeout)
-
-#define netif_start_if(dev)
-#define netif_stop_if(dev)
-
-#define PCI_SLOT_NAME(pci_dev) pci_name(pci_dev)
-
-#endif /* LINUX_VERSION_CODE > 0x20300 */
 
 #ifdef HAVE_NETDEV_POLL
 #define init_poll(dev) \
 
 #ifdef HAVE_NETDEV_POLL
 #define init_poll(dev) \
+do { \
        dev->poll = &netdev_poll; \
        dev->poll = &netdev_poll; \
-       dev->weight = max_interrupt_work;
+       dev->weight = max_interrupt_work; \
+} while (0)
 #define netdev_rx(dev, ioaddr) \
 do { \
        u32 intr_enable; \
 #define netdev_rx(dev, ioaddr) \
 do { \
        u32 intr_enable; \
@@ -341,7 +312,7 @@ do { \
                /* Paranoia check */ \
                intr_enable = readl(ioaddr + IntrEnable); \
                if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
                /* Paranoia check */ \
                intr_enable = readl(ioaddr + IntrEnable); \
                if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
-                       printk("%s: interrupt while in polling mode!\n", dev->name); \
+                       printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
                        intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
                        writel(intr_enable, ioaddr + IntrEnable); \
                } \
                        intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
                        writel(intr_enable, ioaddr + IntrEnable); \
                } \
@@ -364,13 +335,14 @@ do { \
 
 
 /* These identify the driver base version and may not be removed. */
 
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
 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";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
 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";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
 module_param(max_interrupt_work, int, 0);
 module_param(mtu, int, 0);
 
 module_param(max_interrupt_work, int, 0);
 module_param(mtu, int, 0);
@@ -425,7 +397,7 @@ on the 32/64 bitness of the architecture), and relies on automatic
 minimum-length padding.  It does not use the completion queue
 consumer index, but instead checks for non-zero status entries.
 
 minimum-length padding.  It does not use the completion queue
 consumer index, but instead checks for non-zero status entries.
 
-For receive this driver uses type 0/1/2/3 receive descriptors.  The driver
+For receive this driver uses type 2/3 receive descriptors.  The driver
 allocates full frame size skbuffs for the Rx ring buffers, so all frames
 should fit in a single descriptor.  The driver does not use the completion
 queue consumer index, but instead checks for non-zero status entries.
 allocates full frame size skbuffs for the Rx ring buffers, so all frames
 should fit in a single descriptor.  The driver does not use the completion
 queue consumer index, but instead checks for non-zero status entries.
@@ -476,7 +448,7 @@ IVc. Errata
 
 */
 
 
 */
 
-\f
+
 
 enum chip_capability_flags {CanHaveMII=1, };
 
 
 enum chip_capability_flags {CanHaveMII=1, };
 
@@ -491,7 +463,7 @@ static struct pci_device_id starfire_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
 /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
 /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
-static struct chip_info {
+static const struct chip_info {
        const char *name;
        int drv_flags;
 } netdrv_tbl[] __devinitdata = {
        const char *name;
        int drv_flags;
 } netdrv_tbl[] __devinitdata = {
@@ -670,7 +642,6 @@ struct full_rx_done_desc {
        u32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
        u32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
-#ifdef HAS_FIRMWARE
 #ifdef VLAN_SUPPORT
 typedef struct full_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType3
 #ifdef VLAN_SUPPORT
 typedef struct full_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType3
@@ -678,15 +649,6 @@ typedef struct full_rx_done_desc rx_done_desc;
 typedef struct csum_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType2
 #endif /* not VLAN_SUPPORT */
 typedef struct csum_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType2
 #endif /* not VLAN_SUPPORT */
-#else  /* not HAS_FIRMWARE */
-#ifdef VLAN_SUPPORT
-typedef struct basic_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType1
-#else  /* not VLAN_SUPPORT */
-typedef struct short_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType0
-#endif /* not VLAN_SUPPORT */
-#endif /* not HAS_FIRMWARE */
 
 enum rx_done_bits {
        RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
 
 enum rx_done_bits {
        RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -898,13 +860,10 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        /* enable MWI -- it vastly improves Rx performance on sparc64 */
        pci_set_mwi(pdev);
 
        /* enable MWI -- it vastly improves Rx performance on sparc64 */
        pci_set_mwi(pdev);
 
-#ifdef MAX_SKB_FRAGS
-       dev->features |= NETIF_F_SG;
-#endif /* MAX_SKB_FRAGS */
 #ifdef ZEROCOPY
        /* Starfire can do TCP/UDP checksumming */
        if (enable_hw_cksum)
 #ifdef ZEROCOPY
        /* Starfire can do TCP/UDP checksumming */
        if (enable_hw_cksum)
-               dev->features |= NETIF_F_IP_CSUM;
+               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 #endif /* ZEROCOPY */
 #ifdef VLAN_SUPPORT
        dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
 #endif /* ZEROCOPY */
 #ifdef VLAN_SUPPORT
        dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
@@ -1008,7 +967,8 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        /* The chip-specific entries in the device structure. */
        dev->open = &netdev_open;
        dev->hard_start_xmit = &start_tx;
        /* The chip-specific entries in the device structure. */
        dev->open = &netdev_open;
        dev->hard_start_xmit = &start_tx;
-       init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
+       dev->tx_timeout = tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
        init_poll(dev);
        dev->stop = &netdev_close;
        dev->get_stats = &get_stats;
        init_poll(dev);
        dev->stop = &netdev_close;
        dev->get_stats = &get_stats;
@@ -1039,7 +999,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
                                if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
                                        break;
                        if (boguscnt == 0) {
                                if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
                                        break;
                        if (boguscnt == 0) {
-                               printk("%s: PHY reset never completed!\n", dev->name);
+                               printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
                                continue;
                        }
                        mii_status = mdio_read(dev, phy, MII_BMSR);
                                continue;
                        }
                        mii_status = mdio_read(dev, phy, MII_BMSR);
@@ -1110,6 +1070,7 @@ static int netdev_open(struct net_device *dev)
        size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
        /* Do we ever need to reset the chip??? */
        size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
        /* Do we ever need to reset the chip??? */
+
        retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
        if (retval)
                return retval;
        retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
        if (retval)
                return retval;
@@ -1129,8 +1090,10 @@ static int netdev_open(struct net_device *dev)
                rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
                np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
                np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
                rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
                np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
                np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
-               if (np->queue_mem == 0)
+               if (np->queue_mem == NULL) {
+                       free_irq(dev->irq, dev);
                        return -ENOMEM;
                        return -ENOMEM;
+               }
 
                np->tx_done_q     = np->queue_mem;
                np->tx_done_q_dma = np->queue_mem_dma;
 
                np->tx_done_q     = np->queue_mem;
                np->tx_done_q_dma = np->queue_mem_dma;
@@ -1211,7 +1174,6 @@ static int netdev_open(struct net_device *dev)
 
        writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
 
        writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
-       netif_start_if(dev);
        netif_start_queue(dev);
 
        if (debug > 1)
        netif_start_queue(dev);
 
        if (debug > 1)
@@ -1238,13 +1200,11 @@ static int netdev_open(struct net_device *dev)
        writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
        writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
-#ifdef HAS_FIRMWARE
        /* Load Rx/Tx firmware into the frame processors */
        for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
                writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
        for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
                writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
        /* Load Rx/Tx firmware into the frame processors */
        for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
                writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
        for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
                writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
-#endif /* HAS_FIRMWARE */
        if (enable_hw_cksum)
                /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
                writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
        if (enable_hw_cksum)
                /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
                writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1341,7 +1301,7 @@ static void init_ring(struct net_device *dev)
                np->rx_info[i].skb = skb;
                if (skb == NULL)
                        break;
                np->rx_info[i].skb = skb;
                if (skb == NULL)
                        break;
-               np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
                skb->dev = dev;                 /* Mark as being used by this device. */
                /* Grrr, we cannot offset to correctly align the IP header. */
                np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
                skb->dev = dev;                 /* Mark as being used by this device. */
                /* Grrr, we cannot offset to correctly align the IP header. */
                np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
@@ -1378,8 +1338,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        u32 status;
        int i;
 
        u32 status;
        int i;
 
-       kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
-
        /*
         * be cautious here, wrapping the queue has weird semantics
         * and we may not have enough slots even when it seems we do.
        /*
         * be cautious here, wrapping the queue has weird semantics
         * and we may not have enough slots even when it seems we do.
@@ -1390,21 +1348,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        }
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
        }
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
-       {
-               int has_bad_length = 0;
-
-               if (skb_first_frag_len(skb) == 1)
-                       has_bad_length = 1;
-               else {
-                       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                               if (skb_shinfo(skb)->frags[i].size == 1) {
-                                       has_bad_length = 1;
-                                       break;
-                               }
-               }
-
-               if (has_bad_length)
-                       skb_checksum_help(skb);
+       if (skb->ip_summed == CHECKSUM_HW) {
+               skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK);
+               if (skb == NULL)
+                       return NETDEV_TX_OK;
        }
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
        }
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
@@ -1433,12 +1380,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
                } else {
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
                } else {
-#ifdef MAX_SKB_FRAGS
                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
                        status |= this_frag->size;
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
                        status |= this_frag->size;
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
-#endif /* MAX_SKB_FRAGS */
                }
 
                np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
                }
 
                np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@@ -1531,7 +1476,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                                np->tx_info[entry].mapping = 0;
                                np->dirty_tx += np->tx_info[entry].used_slots;
                                entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
                                np->tx_info[entry].mapping = 0;
                                np->dirty_tx += np->tx_info[entry].used_slots;
                                entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
-#ifdef MAX_SKB_FRAGS
                                {
                                        int i;
                                        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                                {
                                        int i;
                                        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -1543,7 +1487,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                                                entry++;
                                        }
                                }
                                                entry++;
                                        }
                                }
-#endif /* MAX_SKB_FRAGS */
+
                                dev_kfree_skb_irq(skb);
                        }
                        np->tx_done_q[np->tx_done].status = 0;
                                dev_kfree_skb_irq(skb);
                        }
                        np->tx_done_q[np->tx_done].status = 0;
@@ -1603,7 +1547,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
                if (!(desc_status & RxOK)) {
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
                if (!(desc_status & RxOK)) {
-                       /* There was a error. */
+                       /* There was an error. */
                        if (debug > 2)
                                printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
                        np->stats.rx_errors++;
                        if (debug > 2)
                                printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
                        np->stats.rx_errors++;
@@ -1632,7 +1576,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                        pci_dma_sync_single_for_cpu(np->pci_dev,
                                                    np->rx_info[entry].mapping,
                                                    pkt_len, PCI_DMA_FROMDEVICE);
                        pci_dma_sync_single_for_cpu(np->pci_dev,
                                                    np->rx_info[entry].mapping,
                                                    pkt_len, PCI_DMA_FROMDEVICE);
-                       eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
+                       eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
                        pci_dma_sync_single_for_device(np->pci_dev,
                                                       np->rx_info[entry].mapping,
                                                       pkt_len, PCI_DMA_FROMDEVICE);
                        pci_dma_sync_single_for_device(np->pci_dev,
                                                       np->rx_info[entry].mapping,
                                                       pkt_len, PCI_DMA_FROMDEVICE);
@@ -1656,11 +1600,10 @@ static int __netdev_rx(struct net_device *dev, int *quota)
 #endif
 
                skb->protocol = eth_type_trans(skb, dev);
 #endif
 
                skb->protocol = eth_type_trans(skb, dev);
-#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT)
+#ifdef VLAN_SUPPORT
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
 #endif
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
 #endif
-#ifdef HAS_FIRMWARE
                if (le16_to_cpu(desc->status2) & 0x0100) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        np->stats.rx_compressed++;
                if (le16_to_cpu(desc->status2) & 0x0100) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        np->stats.rx_compressed++;
@@ -1679,7 +1622,6 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                        skb->csum = le16_to_cpu(desc->csum);
                        printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
                }
                        skb->csum = le16_to_cpu(desc->csum);
                        printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
                }
-#endif /* HAS_FIRMWARE */
 #ifdef VLAN_SUPPORT
                if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
                        if (debug > 4)
 #ifdef VLAN_SUPPORT
                if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
                        if (debug > 4)
@@ -1758,7 +1700,7 @@ static void refill_rx_ring(struct net_device *dev)
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        np->rx_info[entry].mapping =
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        np->rx_info[entry].mapping =
-                               pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                               pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        skb->dev = dev; /* Mark as being used by this device. */
                        np->rx_ring[entry].rxaddr =
                                cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
                        skb->dev = dev; /* Mark as being used by this device. */
                        np->rx_ring[entry].rxaddr =
                                cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
@@ -1900,9 +1842,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 }
 
 
 }
 
 
-/* Chips may use the upper or lower CRC bits, and may reverse and/or invert
-   them.  Select the endian-ness that results in minimal calculations.
-*/
 static void set_rx_mode(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
 static void set_rx_mode(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -1969,6 +1908,8 @@ static void set_rx_mode(struct net_device *dev)
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                     i++, mclist = mclist->next) {
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                     i++, mclist = mclist->next) {
+                       /* 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];
 
                        int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
                        __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
@@ -2001,7 +1942,7 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        struct netdev_private *np = netdev_priv(dev);
        strcpy(info->driver, DRV_NAME);
        strcpy(info->version, DRV_VERSION);
        struct netdev_private *np = netdev_priv(dev);
        strcpy(info->driver, DRV_NAME);
        strcpy(info->version, DRV_VERSION);
-       strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev));
+       strcpy(info->bus_info, pci_name(np->pci_dev));
 }
 
 static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 }
 
 static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2083,7 +2024,6 @@ static int netdev_close(struct net_device *dev)
        int i;
 
        netif_stop_queue(dev);
        int i;
 
        netif_stop_queue(dev);
-       netif_stop_if(dev);
 
        if (debug > 1) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
 
        if (debug > 1) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
@@ -2144,14 +2084,45 @@ static int netdev_close(struct net_device *dev)
        return 0;
 }
 
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int starfire_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               netif_device_detach(dev);
+               netdev_close(dev);
+       }
+
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev,state));
+
+       return 0;
+}
+
+static int starfire_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       if (netif_running(dev)) {
+               netdev_open(dev);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct netdev_private *np = netdev_priv(dev);
 
 
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct netdev_private *np = netdev_priv(dev);
 
-       if (!dev)
-               BUG();
+       BUG_ON(!dev);
 
        unregister_netdev(dev);
 
 
        unregister_netdev(dev);
 
@@ -2175,6 +2146,10 @@ static struct pci_driver starfire_driver = {
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
        .remove         = __devexit_p(starfire_remove_one),
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
        .remove         = __devexit_p(starfire_remove_one),
+#ifdef CONFIG_PM
+       .suspend        = starfire_suspend,
+       .resume         = starfire_resume,
+#endif /* CONFIG_PM */
        .id_table       = starfire_pci_tbl,
 };
 
        .id_table       = starfire_pci_tbl,
 };
 
@@ -2184,18 +2159,19 @@ static int __init starfire_init (void)
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
        printk(version);
 /* 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
-#ifndef ADDR_64BITS
+#endif
+
        /* we can do this test only at run-time... sigh */
        /* we can do this test only at run-time... sigh */
-       if (sizeof(dma_addr_t) == sizeof(u64)) {
-               printk("This driver has not been ported to this 64-bit architecture yet\n");
+       if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
+               printk("This driver has dma_addr_t issues, please send email to maintainer\n");
                return -ENODEV;
        }
                return -ENODEV;
        }
-#endif /* not ADDR_64BITS */
-#ifndef HAS_FIRMWARE
-       /* unconditionally disable hw cksums if firmware is not present */
-       enable_hw_cksum = 0;
-#endif /* not HAS_FIRMWARE */
+
        return pci_module_init (&starfire_driver);
 }
 
        return pci_module_init (&starfire_driver);
 }