headers: remove sched.h from interrupt.h
[safe/jmp/linux-2.6] / drivers / net / typhoon.c
index e49e8b5..5921f5b 100644 (file)
@@ -86,7 +86,7 @@ static const int multicast_filter_limit = 32;
 #define RESPONSE_RING_SIZE     (RESPONSE_ENTRIES * sizeof(struct resp_desc))
 
 /* The 3XP will preload and remove 64 entries from the free buffer
- * list, and we need one entry to keep the ring from wrapping, so 
+ * list, and we need one entry to keep the ring from wrapping, so
  * to keep this a power of two, we use 128 entries.
  */
 #define RXFREE_ENTRIES         128
@@ -100,13 +100,15 @@ static const int multicast_filter_limit = 32;
 #define PKT_BUF_SZ             1536
 
 #define DRV_MODULE_NAME                "typhoon"
-#define DRV_MODULE_VERSION     "1.5.7"
-#define DRV_MODULE_RELDATE     "05/01/07"
+#define DRV_MODULE_VERSION     "1.5.9"
+#define DRV_MODULE_RELDATE     "Mar 2, 2009"
 #define PFX                    DRV_MODULE_NAME ": "
 #define ERR_PFX                        KERN_ERR PFX
+#define FIRMWARE_NAME          "3com/typhoon.bin"
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
@@ -117,6 +119,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
@@ -127,19 +130,18 @@ static const int multicast_filter_limit = 32;
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/in6.h>
-#include <asm/checksum.h>
-#include <linux/version.h>
 #include <linux/dma-mapping.h>
+#include <linux/firmware.h>
 
 #include "typhoon.h"
-#include "typhoon-firmware.h"
 
-static const char version[] __devinitdata =
+static char version[] __devinitdata =
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
 MODULE_VERSION(DRV_MODULE_VERSION);
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(FIRMWARE_NAME);
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
 MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
                               "the buffer given back to the NIC. Default "
@@ -178,7 +180,7 @@ enum typhoon_cards {
 };
 
 /* directly indexed by enum typhoon_cards, above */
-static const struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
        { "3Com Typhoon (3C990-TX)",
                TYPHOON_CRYPTO_NONE},
        { "3Com Typhoon (3CR990-TX-95)",
@@ -269,7 +271,7 @@ struct rxbuff_ent {
 
 struct typhoon {
        /* Tx cache line section */
-       struct transmit_ring    txLoRing        ____cacheline_aligned;  
+       struct transmit_ring    txLoRing        ____cacheline_aligned;
        struct pci_dev *        tx_pdev;
        void __iomem            *tx_ioaddr;
        u32                     txlo_dma_addr;
@@ -284,6 +286,7 @@ struct typhoon {
        struct basic_ring       rxLoRing;
        struct pci_dev *        pdev;
        struct net_device *     dev;
+       struct napi_struct      napi;
        spinlock_t              state_lock;
        struct vlan_group *     vlgrp;
        struct basic_ring       rxHiRing;
@@ -299,9 +302,9 @@ struct typhoon {
        const char *            name;
        struct typhoon_shared * shared;
        dma_addr_t              shared_dma;
-       u16                     xcvr_select;
-       u16                     wol_events;
-       u32                     offload;
+       __le16                  xcvr_select;
+       __le16                  wol_events;
+       __le32                  offload;
 
        /* unused stuff (future use) */
        int                     capabilities;
@@ -333,12 +336,6 @@ enum state_values {
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP  ((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT           ((1000000 / 2) / TYPHOON_UDELAY)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
-#define typhoon_synchronize_irq(x) synchronize_irq()
-#else
-#define typhoon_synchronize_irq(x) synchronize_irq(x)
-#endif
-
 #if defined(NETIF_F_TSO)
 #define skb_tso_size(x)                (skb_shinfo(x)->gso_size)
 #define TSO_NUM_DESCRIPTORS    2
@@ -643,7 +640,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
 
        typhoon_inc_cmd_index(&ring->lastWrite, num_cmd);
 
-       /* "I feel a presence... another warrior is on the the mesa."
+       /* "I feel a presence... another warrior is on the mesa."
         */
        wmb();
        iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
@@ -745,16 +742,6 @@ typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
        spin_unlock_bh(&tp->state_lock);
 }
 
-static void
-typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-       struct typhoon *tp = netdev_priv(dev);
-       spin_lock_bh(&tp->state_lock);
-       if(tp->vlgrp)
-               tp->vlgrp->vlan_devices[vid] = NULL;
-       spin_unlock_bh(&tp->state_lock);
-}
-
 static inline void
 typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing,
                        u32 ring_dma)
@@ -776,7 +763,7 @@ typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing,
        tcpd->status = 0;
 }
 
-static int
+static netdev_tx_t
 typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct typhoon *tp = netdev_priv(dev);
@@ -805,7 +792,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
         * If problems develop with TSO, check this first.
         */
        numDesc = skb_shinfo(skb)->nr_frags + 1;
-       if(skb_tso_size(skb))
+       if (skb_is_gso(skb))
                numDesc++;
 
        /* When checking for free space in the ring, we need to also
@@ -826,11 +813,10 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
        first_txd->flags = TYPHOON_TX_DESC | TYPHOON_DESC_VALID;
        first_txd->numDesc = 0;
        first_txd->len = 0;
-       first_txd->addr = (u64)((unsigned long) skb) & 0xffffffff;
-       first_txd->addrHi = (u64)((unsigned long) skb) >> 32;
+       first_txd->tx_addr = (u64)((unsigned long) skb);
        first_txd->processFlags = 0;
 
-       if(skb->ip_summed == CHECKSUM_HW) {
+       if(skb->ip_summed == CHECKSUM_PARTIAL) {
                /* The 3XP will figure out if this is UDP/TCP */
                first_txd->processFlags |= TYPHOON_TX_PF_TCP_CHKSUM;
                first_txd->processFlags |= TYPHOON_TX_PF_UDP_CHKSUM;
@@ -841,11 +827,11 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
                first_txd->processFlags |=
                    TYPHOON_TX_PF_INSERT_VLAN | TYPHOON_TX_PF_VLAN_PRIORITY;
                first_txd->processFlags |=
-                   cpu_to_le32(htons(vlan_tx_tag_get(skb)) <<
+                   cpu_to_le32(ntohs(vlan_tx_tag_get(skb)) <<
                                TYPHOON_TX_PF_VLAN_TAG_SHIFT);
        }
 
-       if(skb_tso_size(skb)) {
+       if (skb_is_gso(skb)) {
                first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
                first_txd->numDesc++;
 
@@ -863,8 +849,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
                                       PCI_DMA_TODEVICE);
                txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
                txd->len = cpu_to_le16(skb->len);
-               txd->addr = cpu_to_le32(skb_dma);
-               txd->addrHi = 0;
+               txd->frag.addr = cpu_to_le32(skb_dma);
+               txd->frag.addrHi = 0;
                first_txd->numDesc++;
        } else {
                int i, len;
@@ -874,8 +860,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
                                         PCI_DMA_TODEVICE);
                txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
                txd->len = cpu_to_le16(len);
-               txd->addr = cpu_to_le32(skb_dma);
-               txd->addrHi = 0;
+               txd->frag.addr = cpu_to_le32(skb_dma);
+               txd->frag.addrHi = 0;
                first_txd->numDesc++;
 
                for(i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -893,8 +879,8 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
                                         PCI_DMA_TODEVICE);
                        txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
                        txd->len = cpu_to_le16(len);
-                       txd->addr = cpu_to_le32(skb_dma);
-                       txd->addrHi = 0;
+                       txd->frag.addr = cpu_to_le32(skb_dma);
+                       txd->frag.addrHi = 0;
                        first_txd->numDesc++;
                }
        }
@@ -924,7 +910,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
                        netif_wake_queue(dev);
        }
 
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void
@@ -933,12 +919,10 @@ typhoon_set_rx_mode(struct net_device *dev)
        struct typhoon *tp = netdev_priv(dev);
        struct cmd_desc xp_cmd;
        u32 mc_filter[2];
-       u16 filter;
+       __le16 filter;
 
        filter = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST;
        if(dev->flags & IFF_PROMISC) {
-               printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                      dev->name);
                filter |= TYPHOON_RX_FILTER_PROMISCOUS;
        } else if((dev->mc_count > multicast_filter_limit) ||
                  (dev->flags & IFF_ALLMULTI)) {
@@ -992,12 +976,12 @@ typhoon_do_get_stats(struct typhoon *tp)
         * ethtool_ops->get_{strings,stats}()
         */
        stats->tx_packets = le32_to_cpu(s->txPackets);
-       stats->tx_bytes = le32_to_cpu(s->txBytes);
+       stats->tx_bytes = le64_to_cpu(s->txBytes);
        stats->tx_errors = le32_to_cpu(s->txCarrierLost);
        stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost);
        stats->collisions = le32_to_cpu(s->txMultipleCollisions);
        stats->rx_packets = le32_to_cpu(s->rxPacketsGood);
-       stats->rx_bytes = le32_to_cpu(s->rxBytesGood);
+       stats->rx_bytes = le64_to_cpu(s->rxBytesGood);
        stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns);
        stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
                        le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors);
@@ -1071,9 +1055,9 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
                if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
                        strcpy(info->fw_version, "Unknown runtime");
                } else {
-                       u32 sleep_ver = xp_resp[0].parm2;
+                       u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
                        snprintf(info->fw_version, 32, "%02x.%03x.%03x",
-                                sleep_ver >> 24, (sleep_ver >> 12) & 0xfff, 
+                                sleep_ver >> 24, (sleep_ver >> 12) & 0xfff,
                                 sleep_ver & 0xfff);
                }
        }
@@ -1146,7 +1130,7 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct typhoon *tp = netdev_priv(dev);
        struct cmd_desc xp_cmd;
-       int xcvr;
+       __le16 xcvr;
        int err;
 
        err = -EINVAL;
@@ -1172,7 +1156,7 @@ typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        }
 
        INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_XCVR_SELECT);
-       xp_cmd.parm1 = cpu_to_le16(xcvr);
+       xp_cmd.parm1 = xcvr;
        err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
        if(err < 0)
                goto out;
@@ -1243,7 +1227,7 @@ typhoon_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
        ering->tx_pending = TXLO_ENTRIES - 1;
 }
 
-static struct ethtool_ops typhoon_ethtool_ops = {
+static const struct ethtool_ops typhoon_ethtool_ops = {
        .get_settings           = typhoon_get_settings,
        .set_settings           = typhoon_set_settings,
        .get_drvinfo            = typhoon_get_drvinfo,
@@ -1251,11 +1235,8 @@ static struct ethtool_ops typhoon_ethtool_ops = {
        .set_wol                = typhoon_set_wol,
        .get_link               = ethtool_op_get_link,
        .get_rx_csum            = typhoon_get_rx_csum,
-       .get_tx_csum            = ethtool_op_get_tx_csum,
        .set_tx_csum            = ethtool_op_set_tx_csum,
-       .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
-       .get_tso                = ethtool_op_get_tso,
        .set_tso                = ethtool_op_set_tso,
        .get_ringparam          = typhoon_get_ringparam,
 };
@@ -1338,7 +1319,7 @@ typhoon_init_interface(struct typhoon *tp)
        tp->txLoRing.writeRegister = TYPHOON_REG_TX_LO_READY;
        tp->txHiRing.writeRegister = TYPHOON_REG_TX_HI_READY;
 
-       tp->txlo_dma_addr = iface->txLoAddr;
+       tp->txlo_dma_addr = le32_to_cpu(iface->txLoAddr);
        tp->card_state = Sleeping;
        smp_wmb();
 
@@ -1366,17 +1347,77 @@ typhoon_init_rings(struct typhoon *tp)
        tp->txHiRing.lastRead = 0;
 }
 
+static const struct firmware *typhoon_fw;
+
+static int
+typhoon_request_firmware(struct typhoon *tp)
+{
+       const struct typhoon_file_header *fHdr;
+       const struct typhoon_section_header *sHdr;
+       const u8 *image_data;
+       u32 numSections;
+       u32 section_len;
+       u32 remaining;
+       int err;
+
+       if (typhoon_fw)
+               return 0;
+
+       err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev);
+       if (err) {
+               printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+                               tp->name, FIRMWARE_NAME);
+               return err;
+       }
+
+       image_data = (u8 *) typhoon_fw->data;
+       remaining = typhoon_fw->size;
+       if (remaining < sizeof(struct typhoon_file_header))
+               goto invalid_fw;
+
+       fHdr = (struct typhoon_file_header *) image_data;
+       if (memcmp(fHdr->tag, "TYPHOON", 8))
+               goto invalid_fw;
+
+       numSections = le32_to_cpu(fHdr->numSections);
+       image_data += sizeof(struct typhoon_file_header);
+       remaining -= sizeof(struct typhoon_file_header);
+
+       while (numSections--) {
+               if (remaining < sizeof(struct typhoon_section_header))
+                       goto invalid_fw;
+
+               sHdr = (struct typhoon_section_header *) image_data;
+               image_data += sizeof(struct typhoon_section_header);
+               section_len = le32_to_cpu(sHdr->len);
+
+               if (remaining < section_len)
+                       goto invalid_fw;
+
+               image_data += section_len;
+               remaining -= section_len;
+       }
+
+       return 0;
+
+invalid_fw:
+       printk(KERN_ERR "%s: Invalid firmware image\n", tp->name);
+       release_firmware(typhoon_fw);
+       typhoon_fw = NULL;
+       return -EINVAL;
+}
+
 static int
 typhoon_download_firmware(struct typhoon *tp)
 {
        void __iomem *ioaddr = tp->ioaddr;
        struct pci_dev *pdev = tp->pdev;
-       struct typhoon_file_header *fHdr;
-       struct typhoon_section_header *sHdr;
-       u8 *image_data;
+       const struct typhoon_file_header *fHdr;
+       const struct typhoon_section_header *sHdr;
+       const u8 *image_data;
        void *dpage;
        dma_addr_t dpage_dma;
-       unsigned int csum;
+       __sum16 csum;
        u32 irqEnabled;
        u32 irqMasked;
        u32 numSections;
@@ -1387,20 +1428,12 @@ typhoon_download_firmware(struct typhoon *tp)
        int i;
        int err;
 
-       err = -EINVAL;
-       fHdr = (struct typhoon_file_header *) typhoon_firmware_image;
-       image_data = (u8 *) fHdr;
-
-       if(memcmp(fHdr->tag, "TYPHOON", 8)) {
-               printk(KERN_ERR "%s: Invalid firmware image!\n", tp->name);
-               goto err_out;
-       }
+       image_data = (u8 *) typhoon_fw->data;
+       fHdr = (struct typhoon_file_header *) image_data;
 
        /* Cannot just map the firmware image using pci_map_single() as
-        * the firmware is part of the kernel/module image, so we allocate
-        * some consistent memory to copy the sections into, as it is simpler,
-        * and short-lived. If we ever split out and require a userland
-        * firmware loader, then we can revisit this.
+        * the firmware is vmalloc()'d and may not be physically contiguous,
+        * so we allocate some consistent memory to copy the sections into.
         */
        err = -ENOMEM;
        dpage = pci_alloc_consistent(pdev, PAGE_SIZE, &dpage_dma);
@@ -1468,13 +1501,13 @@ typhoon_download_firmware(struct typhoon *tp)
                         * summing. Fortunately, due to the properties of
                         * the checksum, we can do this once, at the end.
                         */
-                       csum = csum_partial_copy_nocheck(image_data, dpage,
-                                                        len, 0);
-                       csum = csum_fold(csum);
-                       csum = le16_to_cpu(csum);
+                       csum = csum_fold(csum_partial_copy_nocheck(image_data,
+                                                                 dpage, len,
+                                                                 0));
 
                        iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
-                       iowrite32(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
+                       iowrite32(le16_to_cpu((__force __le16)csum),
+                                       ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
                        iowrite32(load_addr,
                                        ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
                        iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
@@ -1554,7 +1587,7 @@ out_timeout:
 
 static u32
 typhoon_clean_tx(struct typhoon *tp, struct transmit_ring *txRing,
-                       volatile u32 * index)
+                       volatile __le32 * index)
 {
        u32 lastRead = txRing->lastRead;
        struct tx_desc *tx;
@@ -1569,13 +1602,13 @@ typhoon_clean_tx(struct typhoon *tp, struct transmit_ring *txRing,
                if(type == TYPHOON_TX_DESC) {
                        /* This tx_desc describes a packet.
                         */
-                       unsigned long ptr = tx->addr | ((u64)tx->addrHi << 32);
+                       unsigned long ptr = tx->tx_addr;
                        struct sk_buff *skb = (struct sk_buff *) ptr;
                        dev_kfree_skb_irq(skb);
                } else if(type == TYPHOON_FRAG_DESC) {
                        /* This tx_desc describes a memory mapping. Free it.
                         */
-                       skb_dma = (dma_addr_t) le32_to_cpu(tx->addr);
+                       skb_dma = (dma_addr_t) le32_to_cpu(tx->frag.addr);
                        dma_len = le16_to_cpu(tx->len);
                        pci_unmap_single(tp->pdev, skb_dma, dma_len,
                                       PCI_DMA_TODEVICE);
@@ -1590,7 +1623,7 @@ typhoon_clean_tx(struct typhoon *tp, struct transmit_ring *txRing,
 
 static void
 typhoon_tx_complete(struct typhoon *tp, struct transmit_ring *txRing,
-                       volatile u32 * index)
+                       volatile __le32 * index)
 {
        u32 lastRead;
        int numDesc = MAX_SKB_FRAGS + 1;
@@ -1614,7 +1647,7 @@ typhoon_recycle_rx_skb(struct typhoon *tp, u32 idx)
        struct rx_free *r;
 
        if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) ==
-                               indexes->rxBuffCleared) {
+                               le32_to_cpu(indexes->rxBuffCleared)) {
                /* no room in ring, just drop the skb
                 */
                dev_kfree_skb_any(rxb->skb);
@@ -1645,7 +1678,7 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
        rxb->skb = NULL;
 
        if((ring->lastWrite + sizeof(*r)) % (RXFREE_ENTRIES * sizeof(*r)) ==
-                               indexes->rxBuffCleared)
+                               le32_to_cpu(indexes->rxBuffCleared))
                return -ENOMEM;
 
        skb = dev_alloc_skb(PKT_BUF_SZ);
@@ -1680,8 +1713,8 @@ typhoon_alloc_rx_skb(struct typhoon *tp, u32 idx)
 }
 
 static int
-typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
-          volatile u32 * cleared, int budget)
+typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * ready,
+          volatile __le32 * cleared, int budget)
 {
        struct rx_desc *rx;
        struct sk_buff *skb, *new_skb;
@@ -1691,7 +1724,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
        u32 rxaddr;
        int pkt_len;
        u32 idx;
-       u32 csum_bits;
+       __le32 csum_bits;
        int received;
 
        received = 0;
@@ -1715,12 +1748,11 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
 
                if(pkt_len < rx_copybreak &&
                   (new_skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
-                       new_skb->dev = tp->dev;
                        skb_reserve(new_skb, 2);
                        pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
                                                    PKT_BUF_SZ,
                                                    PCI_DMA_FROMDEVICE);
-                       eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
+                       skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
                        pci_dma_sync_single_for_device(tp->pdev, dma_addr,
                                                       PKT_BUF_SZ,
                                                       PCI_DMA_FROMDEVICE);
@@ -1752,7 +1784,6 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
                        netif_receive_skb(new_skb);
                spin_unlock(&tp->state_lock);
 
-               tp->dev->last_rx = jiffies;
                received++;
                budget--;
        }
@@ -1776,12 +1807,11 @@ typhoon_fill_free_ring(struct typhoon *tp)
 }
 
 static int
-typhoon_poll(struct net_device *dev, int *total_budget)
+typhoon_poll(struct napi_struct *napi, int budget)
 {
-       struct typhoon *tp = netdev_priv(dev);
+       struct typhoon *tp = container_of(napi, struct typhoon, napi);
        struct typhoon_indexes *indexes = tp->indexes;
-       int orig_budget = *total_budget;
-       int budget, work_done, done;
+       int work_done;
 
        rmb();
        if(!tp->awaiting_resp && indexes->respReady != indexes->respCleared)
@@ -1790,30 +1820,16 @@ typhoon_poll(struct net_device *dev, int *total_budget)
        if(le32_to_cpu(indexes->txLoCleared) != tp->txLoRing.lastRead)
                typhoon_tx_complete(tp, &tp->txLoRing, &indexes->txLoCleared);
 
-       if(orig_budget > dev->quota)
-               orig_budget = dev->quota;
-
-       budget = orig_budget;
        work_done = 0;
-       done = 1;
 
        if(indexes->rxHiCleared != indexes->rxHiReady) {
-               work_done = typhoon_rx(tp, &tp->rxHiRing, &indexes->rxHiReady,
+               work_done += typhoon_rx(tp, &tp->rxHiRing, &indexes->rxHiReady,
                                        &indexes->rxHiCleared, budget);
-               budget -= work_done;
        }
 
        if(indexes->rxLoCleared != indexes->rxLoReady) {
                work_done += typhoon_rx(tp, &tp->rxLoRing, &indexes->rxLoReady,
-                                       &indexes->rxLoCleared, budget);
-       }
-
-       if(work_done) {
-               *total_budget -= work_done;
-               dev->quota -= work_done;
-
-               if(work_done >= orig_budget)
-                       done = 0;
+                                       &indexes->rxLoCleared, budget - work_done);
        }
 
        if(le32_to_cpu(indexes->rxBuffCleared) == tp->rxBuffRing.lastWrite) {
@@ -1821,21 +1837,21 @@ typhoon_poll(struct net_device *dev, int *total_budget)
                typhoon_fill_free_ring(tp);
        }
 
-       if(done) {
-               netif_rx_complete(dev);
+       if (work_done < budget) {
+               napi_complete(napi);
                iowrite32(TYPHOON_INTR_NONE,
                                tp->ioaddr + TYPHOON_REG_INTR_MASK);
                typhoon_post_pci_writes(tp->ioaddr);
        }
 
-       return (done ? 0 : 1);
+       return work_done;
 }
 
 static irqreturn_t
-typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+typhoon_interrupt(int irq, void *dev_instance)
 {
-       struct net_device *dev = (struct net_device *) dev_instance;
-       struct typhoon *tp = dev->priv;
+       struct net_device *dev = dev_instance;
+       struct typhoon *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->ioaddr;
        u32 intr_status;
 
@@ -1845,10 +1861,10 @@ typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
 
        iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
 
-       if(netif_rx_schedule_prep(dev)) {
+       if (napi_schedule_prep(&tp->napi)) {
                iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
                typhoon_post_pci_writes(ioaddr);
-               __netif_rx_schedule(dev);
+               __napi_schedule(&tp->napi);
        } else {
                printk(KERN_ERR "%s: Error, poll already scheduled\n",
                        dev->name);
@@ -1873,7 +1889,7 @@ typhoon_free_rx_rings(struct typhoon *tp)
 }
 
 static int
-typhoon_sleep(struct typhoon *tp, pci_power_t state, u16 events)
+typhoon_sleep(struct typhoon *tp, pci_power_t state, __le16 events)
 {
        struct pci_dev *pdev = tp->pdev;
        void __iomem *ioaddr = tp->ioaddr;
@@ -1961,8 +1977,8 @@ typhoon_start_runtime(struct typhoon *tp)
                goto error_out;
 
        INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_MAC_ADDRESS);
-       xp_cmd.parm1 = cpu_to_le16(ntohs(*(u16 *)&dev->dev_addr[0]));
-       xp_cmd.parm2 = cpu_to_le32(ntohl(*(u32 *)&dev->dev_addr[2]));
+       xp_cmd.parm1 = cpu_to_le16(ntohs(*(__be16 *)&dev->dev_addr[0]));
+       xp_cmd.parm2 = cpu_to_le32(ntohl(*(__be32 *)&dev->dev_addr[2]));
        err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
        if(err < 0)
                goto error_out;
@@ -1983,7 +1999,7 @@ typhoon_start_runtime(struct typhoon *tp)
                goto error_out;
 
        INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_VLAN_TYPE_WRITE);
-       xp_cmd.parm1 = __constant_cpu_to_le16(ETH_P_8021Q);
+       xp_cmd.parm1 = cpu_to_le16(ETH_P_8021Q);
        err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
        if(err < 0)
                goto error_out;
@@ -2125,20 +2141,28 @@ typhoon_open(struct net_device *dev)
        struct typhoon *tp = netdev_priv(dev);
        int err;
 
+       err = typhoon_request_firmware(tp);
+       if (err)
+               goto out;
+
        err = typhoon_wakeup(tp, WaitSleep);
        if(err < 0) {
                printk(KERN_ERR "%s: unable to wakeup device\n", dev->name);
                goto out_sleep;
        }
 
-       err = request_irq(dev->irq, &typhoon_interrupt, SA_SHIRQ,
+       err = request_irq(dev->irq, &typhoon_interrupt, IRQF_SHARED,
                                dev->name, dev);
        if(err < 0)
                goto out_sleep;
 
+       napi_enable(&tp->napi);
+
        err = typhoon_start_runtime(tp);
-       if(err < 0)
+       if(err < 0) {
+               napi_disable(&tp->napi);
                goto out_irq;
+       }
 
        netif_start_queue(dev);
        return 0;
@@ -2154,7 +2178,7 @@ out_sleep:
                goto out;
        }
 
-       if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) 
+       if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
                printk(KERN_ERR "%s: unable to go back to sleep\n", dev->name);
 
 out:
@@ -2167,12 +2191,12 @@ typhoon_close(struct net_device *dev)
        struct typhoon *tp = netdev_priv(dev);
 
        netif_stop_queue(dev);
+       napi_disable(&tp->napi);
 
        if(typhoon_stop_runtime(tp, WaitSleep) < 0)
                printk(KERN_ERR "%s: unable to stop runtime\n", dev->name);
 
        /* Make sure there is no irq handler running on a different CPU. */
-       typhoon_synchronize_irq(dev->irq);
        free_irq(dev->irq, dev);
 
        typhoon_free_rx_rings(tp);
@@ -2212,7 +2236,6 @@ typhoon_resume(struct pci_dev *pdev)
        }
 
        netif_device_attach(dev);
-       netif_start_queue(dev);
        return 0;
 
 reset:
@@ -2257,8 +2280,8 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
        }
 
        INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_MAC_ADDRESS);
-       xp_cmd.parm1 = cpu_to_le16(ntohs(*(u16 *)&dev->dev_addr[0]));
-       xp_cmd.parm2 = cpu_to_le32(ntohl(*(u32 *)&dev->dev_addr[2]));
+       xp_cmd.parm1 = cpu_to_le16(ntohs(*(__be16 *)&dev->dev_addr[0]));
+       xp_cmd.parm2 = cpu_to_le32(ntohl(*(__be32 *)&dev->dev_addr[2]));
        if(typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL) < 0) {
                printk(KERN_ERR "%s: unable to set mac address in suspend\n",
                                dev->name);
@@ -2284,12 +2307,6 @@ need_resume:
        typhoon_resume(pdev);
        return -EBUSY;
 }
-
-static int
-typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
-       return pci_enable_wake(pdev, state, enable);
-}
 #endif
 
 static int __devinit
@@ -2338,6 +2355,19 @@ out:
        return mode;
 }
 
+static const struct net_device_ops typhoon_netdev_ops = {
+       .ndo_open               = typhoon_open,
+       .ndo_stop               = typhoon_close,
+       .ndo_start_xmit         = typhoon_start_tx,
+       .ndo_set_multicast_list = typhoon_set_rx_mode,
+       .ndo_tx_timeout         = typhoon_tx_timeout,
+       .ndo_get_stats          = typhoon_get_stats,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = typhoon_set_mac_address,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_vlan_rx_register   = typhoon_vlan_rx_register,
+};
+
 static int __devinit
 typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2350,7 +2380,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dma_addr_t shared_dma;
        struct cmd_desc xp_cmd;
        struct resp_desc xp_resp[3];
-       int i;
        int err = 0;
 
        if(!did_version++)
@@ -2363,7 +2392,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                err = -ENOMEM;
                goto error_out;
        }
-       SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        err = pci_enable_device(pdev);
@@ -2379,7 +2407,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto error_out_disable;
        }
 
-       err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if(err < 0) {
                printk(ERR_PFX "%s: No usable DMA configuration\n",
                       pci_name(pdev));
@@ -2500,8 +2528,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto error_out_reset;
        }
 
-       *(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
-       *(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
+       *(__be16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
+       *(__be32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
 
        if(!is_valid_ether_addr(dev->dev_addr)) {
                printk(ERR_PFX "%s: Could not obtain valid ethernet address, "
@@ -2539,18 +2567,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* The chip-specific entries in the device structure. */
-       dev->open               = typhoon_open;
-       dev->hard_start_xmit    = typhoon_start_tx;
-       dev->stop               = typhoon_close;
-       dev->set_multicast_list = typhoon_set_rx_mode;
-       dev->tx_timeout         = typhoon_tx_timeout;
-       dev->poll               = typhoon_poll;
-       dev->weight             = 16;
+       dev->netdev_ops         = &typhoon_netdev_ops;
+       netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
        dev->watchdog_timeo     = TX_TIMEOUT;
-       dev->get_stats          = typhoon_get_stats;
-       dev->set_mac_address    = typhoon_set_mac_address;
-       dev->vlan_rx_register   = typhoon_vlan_rx_register;
-       dev->vlan_rx_kill_vid   = typhoon_vlan_rx_kill_vid;
+
        SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
 
        /* We can handle scatter gather, up to 16 entries, and
@@ -2568,12 +2588,11 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: %s at %s 0x%lx, ",
+       printk(KERN_INFO "%s: %s at %s 0x%llx, %pM\n",
               dev->name, typhoon_card_info[card_id].name,
-              use_mmio ? "MMIO" : "IO", pci_resource_start(pdev, use_mmio));
-       for(i = 0; i < 5; i++)
-               printk("%2.2x:", dev->dev_addr[i]);
-       printk("%2.2x\n", dev->dev_addr[i]);
+              use_mmio ? "MMIO" : "IO",
+              (unsigned long long)pci_resource_start(pdev, use_mmio),
+              dev->dev_addr);
 
        /* xp_resp still contains the response to the READ_VERSIONS command.
         * For debugging, let the user know what version he has.
@@ -2601,7 +2620,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                        "(%u:%04x)\n", dev->name, xp_resp[0].numDesc,
                        le32_to_cpu(xp_resp[0].parm2));
        }
-               
+
        return 0;
 
 error_out_reset:
@@ -2652,19 +2671,20 @@ static struct pci_driver typhoon_driver = {
 #ifdef CONFIG_PM
        .suspend        = typhoon_suspend,
        .resume         = typhoon_resume,
-       .enable_wake    = typhoon_enable_wake,
 #endif
 };
 
 static int __init
 typhoon_init(void)
 {
-       return pci_module_init(&typhoon_driver);
+       return pci_register_driver(&typhoon_driver);
 }
 
 static void __exit
 typhoon_cleanup(void)
 {
+       if (typhoon_fw)
+               release_firmware(typhoon_fw);
        pci_unregister_driver(&typhoon_driver);
 }