Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
[sfrench/cifs-2.6.git] / drivers / net / netxen / netxen_nic_main.c
index ffd272c93a6be86cac90d6c1f4b9101e5e434648..36ba6a1aa3637f08da4f736fa37ce17e9cceba6f 100644 (file)
@@ -1,25 +1,25 @@
 /*
  * Copyright (C) 2003 - 2006 NetXen, Inc.
  * All rights reserved.
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- *                            
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *                                   
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  * MA  02111-1307, USA.
- * 
+ *
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.
- * 
+ *
  * Contact Information:
  *    info@netxen.com
  * NetXen,
  *
  */
 
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
 #include "netxen_nic_hw.h"
 
 #include "netxen_nic.h"
 #define DEFINE_GLOBAL_RECV_CRB
 #include "netxen_nic_phan_reg.h"
-#include "netxen_nic_ioctl.h"
 
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 
+#define PHAN_VENDOR_ID 0x4040
+
 MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
 
-char netxen_nic_driver_name[] = "netxen";
+char netxen_nic_driver_name[] = "netxen-nic";
 static char netxen_nic_driver_string[] = "NetXen Network Driver version "
-    NETXEN_NIC_LINUX_VERSIONID "-" NETXEN_NIC_BUILD_NO;
+    NETXEN_NIC_LINUX_VERSIONID;
 
 #define NETXEN_NETDEV_WEIGHT 120
 #define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
+
+u8 nx_p2_id = NX_P2_C0;
+
+#define DMA_32BIT_MASK 0x00000000ffffffffULL
+#define DMA_35BIT_MASK 0x00000007ffffffffULL
 
 /* Local functions to NetXen NIC driver */
 static int __devinit netxen_nic_probe(struct pci_dev *pdev,
@@ -60,11 +69,9 @@ static int netxen_nic_open(struct net_device *netdev);
 static int netxen_nic_close(struct net_device *netdev);
 static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
 static void netxen_tx_timeout(struct net_device *netdev);
-static void netxen_tx_timeout_task(struct net_device *netdev);
+static void netxen_tx_timeout_task(struct work_struct *work);
 static void netxen_watchdog(unsigned long);
 static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
-static int netxen_nic_ioctl(struct net_device *netdev,
-                           struct ifreq *ifr, int cmd);
 static int netxen_nic_poll(struct net_device *dev, int *budget);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void netxen_nic_poll_controller(struct net_device *netdev);
@@ -78,11 +85,16 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
        {PCI_DEVICE(0x4040, 0x0003)},
        {PCI_DEVICE(0x4040, 0x0004)},
        {PCI_DEVICE(0x4040, 0x0005)},
+       {PCI_DEVICE(0x4040, 0x0024)},
+       {PCI_DEVICE(0x4040, 0x0025)},
        {0,}
 };
 
 MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
 
+struct workqueue_struct *netxen_workq;
+static void netxen_watchdog(unsigned long);
+
 /*
  * netxen_nic_probe()
  *
@@ -101,16 +113,27 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct net_device *netdev = NULL;
        struct netxen_adapter *adapter = NULL;
        struct netxen_port *port = NULL;
-       u8 __iomem *mem_ptr = NULL;
-       unsigned long mem_base, mem_len;
+       void __iomem *mem_ptr0 = NULL;
+       void __iomem *mem_ptr1 = NULL;
+       void __iomem *mem_ptr2 = NULL;
+
+       u8 __iomem *db_ptr = NULL;
+       unsigned long mem_base, mem_len, db_base, db_len;
        int pci_using_dac, i, err;
        int ring;
        struct netxen_recv_context *recv_ctx = NULL;
        struct netxen_rcv_desc_ctx *rcv_desc = NULL;
        struct netxen_cmd_buffer *cmd_buf_arr = NULL;
        u64 mac_addr[FLASH_NUM_PORTS + 1];
-       int valid_mac;
+       int valid_mac = 0;
 
+       printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+       /* In current scheme, we use only PCI function 0 */
+       if (PCI_FUNC(pdev->devfn) != 0) {
+               DPRINTK(ERR, "NetXen function %d will not be enabled.\n",
+                       PCI_FUNC(pdev->devfn));
+               return -ENODEV;
+       }
        if ((err = pci_enable_device(pdev)))
                return err;
        if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
@@ -122,10 +145,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_disable_pdev;
 
        pci_set_master(pdev);
-       if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) &&
-           (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0))
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
+       if (nx_p2_id == NX_P2_C1 &&
+           (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
+           (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
                pci_using_dac = 1;
-       else {
+       else {
                if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
                    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
                        goto err_out_free_res;
@@ -138,13 +163,41 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        mem_len = pci_resource_len(pdev, 0);
 
        /* 128 Meg of memory */
-       mem_ptr = ioremap(mem_base, NETXEN_PCI_MAPSIZE_BYTES);
-       if (mem_ptr == 0UL) {
-               printk(KERN_ERR "%s: Cannot ioremap adapter memory aborting."
-                      ":%p\n", netxen_nic_driver_name, mem_ptr);
+       mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE);
+       mem_ptr1 =
+           ioremap(mem_base + SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_SIZE);
+       mem_ptr2 =
+           ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
+
+       if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) {
+               DPRINTK(ERR,
+                       "Cannot remap adapter memory aborting.:"
+                       "0 -> %p, 1 -> %p, 2 -> %p\n",
+                       mem_ptr0, mem_ptr1, mem_ptr2);
+
                err = -EIO;
-               goto err_out_free_res;
+               goto err_out_iounmap;
+       }
+       db_base = pci_resource_start(pdev, 4);  /* doorbell is on bar 4 */
+       db_len = pci_resource_len(pdev, 4);
+
+       if (db_len == 0) {
+               printk(KERN_ERR "%s: doorbell is disabled\n",
+                      netxen_nic_driver_name);
+               err = -EIO;
+               goto err_out_iounmap;
        }
+       DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base,
+               db_len);
+
+       db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
+       if (!db_ptr) {
+               printk(KERN_ERR "%s: Failed to allocate doorbell map.",
+                      netxen_nic_driver_name);
+               err = -EIO;
+               goto err_out_iounmap;
+       }
+       DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
 
 /*
  *      Allocate a adapter structure which will manage all the initialization
@@ -160,17 +213,21 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                       netxen_nic_driver_name,
                       (int)sizeof(struct netxen_adapter));
                err = -ENOMEM;
-               goto err_out_iounmap;
+               goto err_out_dbunmap;
        }
 
        adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS;
        adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
        adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+       adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
 
        pci_set_drvdata(pdev, adapter);
 
        cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
        if (cmd_buf_arr == NULL) {
+               printk(KERN_ERR
+                      "%s: Could not allocate cmd_buf_arr memory:%d\n",
+                      netxen_nic_driver_name, (int)TX_RINGSIZE);
                err = -ENOMEM;
                goto err_out_free_adapter;
        }
@@ -197,11 +254,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
                                break;
 
+                       case RCV_RING_LRO:
+                               rcv_desc->max_rx_desc_count =
+                                   adapter->max_lro_rx_desc_count;
+                               rcv_desc->flags = RCV_DESC_LRO;
+                               rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
+                               rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+                               break;
+
                        }
                        rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
                            vmalloc(RCV_BUFFSIZE);
 
                        if (rcv_desc->rx_buf_arr == NULL) {
+                               printk(KERN_ERR "%s: Could not allocate"
+                                      "rcv_desc->rx_buf_arr memory:%d\n",
+                                      netxen_nic_driver_name,
+                                      (int)RCV_BUFFSIZE);
                                err = -ENOMEM;
                                goto err_out_free_rx_buffer;
                        }
@@ -210,22 +279,21 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        }
 
-       adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL);
-       if (adapter->ops == NULL) {
-               printk(KERN_ERR
-                      "%s: Could not allocate memory for adapter->ops:%d\n",
-                      netxen_nic_driver_name,
-                      (int)sizeof(struct netxen_adapter));
-               err = -ENOMEM;
-               goto err_out_free_rx_buffer;
-       }
-
        adapter->cmd_buf_arr = cmd_buf_arr;
-       adapter->ahw.pci_base = mem_ptr;
+       adapter->ahw.pci_base0 = mem_ptr0;
+       adapter->ahw.pci_base1 = mem_ptr1;
+       adapter->ahw.pci_base2 = mem_ptr2;
+       adapter->ahw.db_base = db_ptr;
+       adapter->ahw.db_len = db_len;
        spin_lock_init(&adapter->tx_lock);
        spin_lock_init(&adapter->lock);
-       /* initialize the buffers in adapter */
-       netxen_initialize_adapter_sw(adapter);
+       netxen_initialize_adapter_sw(adapter);  /* initialize the buffers in adapter */
+#ifdef CONFIG_IA64
+       netxen_pinit_from_rom(adapter, 0);
+       udelay(500);
+       netxen_load_firmware(adapter);
+#endif
+
        /*
         * Set the CRB window to invalid. If any register in window 0 is
         * accessed it should set the window to 0 and then reset it to 1.
@@ -243,11 +311,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        adapter->ahw.xg_linkup = 0;
        adapter->watchdog_timer.function = &netxen_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
-       INIT_WORK(&adapter->watchdog_task,
-                 (void (*)(void *))netxen_watchdog_task, adapter);
+       INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
        adapter->ahw.pdev = pdev;
        adapter->proc_cmd_buf_counter = 0;
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id);
+       adapter->ahw.revision_id = nx_p2_id;
 
        if (pci_enable_msi(pdev)) {
                adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
@@ -262,7 +329,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        else
                valid_mac = 0;
 
+       /*
+        * Initialize all the CRB registers here.
+        */
+       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
+       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
+       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
+
+       /* do this before waking up pegs so that we have valid dummy dma addr */
+       err = netxen_initialize_adapter_offload(adapter);
+       if (err) {
+               goto err_out_free_dev;
+       }
+
+       /* Unlock the HW, prompting the boot sequence */
+       writel(1,
+              NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+
+       /* Handshake with the card before we register the devices. */
+       netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
        /* initialize the all the ports */
+       adapter->active_ports = 0;
 
        for (i = 0; i < adapter->ahw.max_ports; i++) {
                netdev = alloc_etherdev(sizeof(struct netxen_port));
@@ -288,7 +376,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                netdev->set_multicast_list = netxen_nic_set_multi;
                netdev->set_mac_address = netxen_nic_set_mac;
                netdev->change_mtu = netxen_nic_change_mtu;
-               netdev->do_ioctl = netxen_nic_ioctl;
                netdev->tx_timeout = netxen_tx_timeout;
                netdev->watchdog_timeo = HZ;
 
@@ -328,14 +415,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                       netdev->dev_addr[4],
                                       netdev->dev_addr[5]);
                        } else {
-                               if (adapter->ops->macaddr_set)
-                                       adapter->ops->macaddr_set(port,
-                                                                 netdev->
-                                                                 dev_addr);
+                               if (adapter->macaddr_set)
+                                       adapter->macaddr_set(port,
+                                                            netdev->dev_addr);
                        }
                }
-               INIT_WORK(&adapter->tx_timeout_task,
-                         (void (*)(void *))netxen_tx_timeout_task, netdev);
+               INIT_WORK(&port->tx_timeout_task, netxen_tx_timeout_task);
                netif_carrier_off(netdev);
                netif_stop_queue(netdev);
 
@@ -347,19 +432,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        goto err_out_free_dev;
                }
                adapter->port_count++;
-               adapter->active_ports = 0;
                adapter->port[i] = port;
        }
 
-       /*
-        * Initialize all the CRB registers here.
-        */
-       /* Window = 1 */
-       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
-       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
-       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
-
-       netxen_phantom_init(adapter);
+       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+       netxen_pinit_from_rom(adapter, 0);
+       udelay(500);
+       netxen_load_firmware(adapter);
+       netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
        /*
         * delay a while to ensure that the Pegs are up & running.
         * Otherwise, we might see some flaky behaviour.
@@ -391,7 +471,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        free_netdev(port->netdev);
                }
        }
-       kfree(adapter->ops);
+
+       netxen_free_adapter_offload(adapter);
 
       err_out_free_rx_buffer:
        for (i = 0; i < MAX_RCV_CTX; ++i) {
@@ -404,17 +485,24 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        }
                }
        }
-
        vfree(cmd_buf_arr);
 
-       kfree(adapter->port);
-
       err_out_free_adapter:
        pci_set_drvdata(pdev, NULL);
        kfree(adapter);
 
+      err_out_dbunmap:
+       if (db_ptr)
+               iounmap(db_ptr);
+
       err_out_iounmap:
-       iounmap(mem_ptr);
+       if (mem_ptr0)
+               iounmap(mem_ptr0);
+       if (mem_ptr1)
+               iounmap(mem_ptr1);
+       if (mem_ptr2)
+               iounmap(mem_ptr2);
+
       err_out_free_res:
        pci_release_regions(pdev);
       err_out_disable_pdev:
@@ -439,11 +527,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        netxen_nic_stop_all_ports(adapter);
        /* leave the hw in the same state as reboot */
        netxen_pinit_from_rom(adapter, 0);
-       udelay(500);
+       writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
        netxen_load_firmware(adapter);
-
-       if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
-               netxen_nic_disable_int(adapter);
+       netxen_free_adapter_offload(adapter);
 
        udelay(500);            /* Delay for a while to drain the DMA engines */
        for (i = 0; i < adapter->port_count; i++) {
@@ -460,7 +546,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                netxen_free_hw_resources(adapter);
 
-       iounmap(adapter->ahw.pci_base);
+       iounmap(adapter->ahw.db_base);
+       iounmap(adapter->ahw.pci_base0);
+       iounmap(adapter->ahw.pci_base1);
+       iounmap(adapter->ahw.pci_base2);
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
@@ -484,7 +573,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
        }
 
        vfree(adapter->cmd_buf_arr);
-       kfree(adapter->ops);
        kfree(adapter);
 }
 
@@ -496,7 +584,6 @@ static int netxen_nic_open(struct net_device *netdev)
 {
        struct netxen_port *port = netdev_priv(netdev);
        struct netxen_adapter *adapter = port->adapter;
-       struct netxen_rcv_desc_ctx *rcv_desc;
        int err = 0;
        int ctx, ring;
 
@@ -507,6 +594,8 @@ static int netxen_nic_open(struct net_device *netdev)
                        return -EIO;
                }
                netxen_nic_flash_print(adapter);
+               if (adapter->init_niu)
+                       adapter->init_niu(adapter);
 
                /* setup all the resources for the Phantom... */
                /* this include the descriptors for rcv, tx, and status */
@@ -517,35 +606,31 @@ static int netxen_nic_open(struct net_device *netdev)
                               err);
                        return err;
                }
-               if (adapter->ops->init_port
-                   && adapter->ops->init_port(adapter, port->portnum) != 0) {
+               if (adapter->init_port
+                   && adapter->init_port(adapter, port->portnum) != 0) {
                        printk(KERN_ERR "%s: Failed to initialize port %d\n",
                               netxen_nic_driver_name, port->portnum);
                        netxen_free_hw_resources(adapter);
                        return -EIO;
                }
-               if (adapter->ops->init_niu)
-                       adapter->ops->init_niu(adapter);
                for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-                       for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                               rcv_desc =
-                                   &adapter->recv_ctx[ctx].rcv_desc[ring];
+                       for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
                                netxen_post_rx_buffers(adapter, ctx, ring);
-                       }
                }
-               adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
-       }
-       adapter->active_ports++;
-       if (adapter->active_ports == 1) {
+               adapter->irq = adapter->ahw.pdev->irq;
                err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
-                                 SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
-                                 adapter);
+                                 IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+                                 netdev->name, adapter);
                if (err) {
                        printk(KERN_ERR "request_irq failed with: %d\n", err);
-                       adapter->active_ports--;
+                       netxen_free_hw_resources(adapter);
                        return err;
                }
-               adapter->irq = adapter->ahw.pdev->irq;
+
+               adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+       }
+       adapter->active_ports++;
+       if (adapter->active_ports == 1) {
                if (!adapter->driver_mismatch)
                        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -554,11 +639,14 @@ static int netxen_nic_open(struct net_device *netdev)
 
        /* Done here again so that even if phantom sw overwrote it,
         * we set it */
-       if (adapter->ops->macaddr_set)
-               adapter->ops->macaddr_set(port, netdev->dev_addr);
+       if (adapter->macaddr_set)
+               adapter->macaddr_set(port, netdev->dev_addr);
        netxen_nic_set_link_parameters(port);
 
        netxen_nic_set_multi(netdev);
+       if (adapter->set_mtu)
+               adapter->set_mtu(port, netdev->mtu);
+
        if (!adapter->driver_mismatch)
                netif_start_queue(netdev);
 
@@ -579,10 +667,6 @@ static int netxen_nic_close(struct net_device *netdev)
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
 
-       /* disable phy_ints */
-       if (adapter->ops->disable_phy_interrupts)
-               adapter->ops->disable_phy_interrupts(adapter, port->portnum);
-
        adapter->active_ports--;
 
        if (!adapter->active_ports) {
@@ -615,6 +699,7 @@ static int netxen_nic_close(struct net_device *netdev)
                        }
                        cmd_buff++;
                }
+               FLUSH_SCHEDULED_WORK();
                del_timer_sync(&adapter->watchdog_timer);
        }
 
@@ -635,7 +720,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc;
        int k;
        struct netxen_cmd_buffer *pbuf = NULL;
-       unsigned int tries = 0;
        static int dropped_packet = 0;
        int frag_count;
        u32 local_producer = 0;
@@ -690,13 +774,16 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        local_producer = adapter->cmd_producer;
        /* There 4 fragments per descriptor */
        no_of_desc = (frag_count + 3) >> 2;
-       if (skb_shinfo(skb)->gso_size > 0) {
-               no_of_desc++;
-               if (((skb->nh.iph)->ihl * sizeof(u32)) +
-                   ((skb->h.th)->doff * sizeof(u32)) +
-                   sizeof(struct ethhdr) >
-                   (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
+       if (netdev->features & NETIF_F_TSO) {
+               if (skb_shinfo(skb)->gso_size > 0) {
+
                        no_of_desc++;
+                       if (((skb->nh.iph)->ihl * sizeof(u32)) +
+                           ((skb->h.th)->doff * sizeof(u32)) +
+                           sizeof(struct ethhdr) >
+                           (sizeof(struct cmd_desc_type0) - 2)) {
+                               no_of_desc++;
+                       }
                }
        }
        k = adapter->cmd_producer;
@@ -705,27 +792,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        if ((k + no_of_desc) >=
            ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
             last_cmd_consumer)) {
+               port->stats.nocmddescriptor++;
+               DPRINTK(ERR, "No command descriptors available,"
+                       " producer = %d, consumer = %d count=%llu,"
+                       " dropping packet\n", producer,
+                       adapter->last_cmd_consumer,
+                       port->stats.nocmddescriptor);
+
+               netif_stop_queue(netdev);
+               port->flags |= NETXEN_NETDEV_STATUS;
                spin_unlock_bh(&adapter->tx_lock);
-               if (tries == 0) {
-                       local_bh_disable();
-                       netxen_process_cmd_ring((unsigned long)adapter);
-                       local_bh_enable();
-                       ++tries;
-                       goto retry_getting_window;
-               } else {
-                       port->stats.nocmddescriptor++;
-                       DPRINTK(ERR, "No command descriptors available,"
-                               " producer = %d, consumer = %d count=%llu,"
-                               " dropping packet\n", producer,
-                               adapter->last_cmd_consumer,
-                               port->stats.nocmddescriptor);
-
-                       spin_lock_bh(&adapter->tx_lock);
-                       netif_stop_queue(netdev);
-                       port->flags |= NETXEN_NETDEV_STATUS;
-                       spin_unlock_bh(&adapter->tx_lock);
-                       return NETDEV_TX_BUSY;
-               }
+               return NETDEV_TX_BUSY;
        }
        k = get_index_range(k, max_tx_desc_count, no_of_desc);
        adapter->cmd_producer = k;
@@ -740,14 +817,13 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
        /* Take skb->data itself */
        pbuf = &adapter->cmd_buf_arr[producer];
-       if (skb_shinfo(skb)->gso_size > 0) {
+       if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
                pbuf->mss = skb_shinfo(skb)->gso_size;
-               hwdesc->mss = skb_shinfo(skb)->gso_size;
+               hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
        } else {
                pbuf->mss = 0;
                hwdesc->mss = 0;
        }
-       pbuf->no_of_descriptors = no_of_desc;
        pbuf->total_length = skb->len;
        pbuf->skb = skb;
        pbuf->cmd = TX_ETHER_PKT;
@@ -757,11 +833,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len,
                                      PCI_DMA_TODEVICE);
        buffrag->length = first_seg_len;
-       CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len);
-       hwdesc->num_of_buffers = frag_count;
-       hwdesc->opcode = TX_ETHER_PKT;
+       netxen_set_cmd_desc_totallength(hwdesc, skb->len);
+       netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
+       netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
 
-       CMD_DESC_PORT_WRT(hwdesc, port->portnum);
+       netxen_set_cmd_desc_port(hwdesc, port->portnum);
        hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
        hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
 
@@ -806,7 +882,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
                        break;
                case 3:
-                       hwdesc->buffer4_length = temp_len;
+                       hwdesc->buffer4_length = cpu_to_le16(temp_len);
                        hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
                        break;
                }
@@ -820,12 +896,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* For LSO, we need to copy the MAC/IP/TCP headers into
         * the descriptor ring
         */
-       if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) {
+       if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
+           == TX_TCP_LSO) {
                int hdr_len, first_hdr_len, more_hdr;
                hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
-               if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
-                       first_hdr_len =
-                           sizeof(struct cmd_desc_type0) - NET_IP_ALIGN;
+               if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
+                       first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
                        more_hdr = 1;
                } else {
                        first_hdr_len = hdr_len;
@@ -835,7 +911,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                hwdesc = &hw->cmd_desc_head[producer];
 
                /* copy the first 64 bytes */
-               memcpy(((void *)hwdesc) + NET_IP_ALIGN,
+               memcpy(((void *)hwdesc) + 2,
                       (void *)(skb->data), first_hdr_len);
                producer = get_next_index(producer, max_tx_desc_count);
 
@@ -851,7 +927,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }
        spin_lock_bh(&adapter->tx_lock);
        port->stats.txbytes +=
-           CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]);
+           netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]);
        /* Code to update the adapter considering how many producer threads
           are currently working */
        if ((--adapter->num_threads) == 0) {
@@ -861,20 +937,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                       NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
                wmb();
                adapter->total_threads = 0;
-       } else {
-               u32 crb_producer = 0;
-               crb_producer =
-                   readl(NETXEN_CRB_NORMALIZE
-                         (adapter, CRB_CMD_PRODUCER_OFFSET));
-               if (crb_producer == local_producer) {
-                       crb_producer = get_index_range(crb_producer,
-                                                      max_tx_desc_count,
-                                                      no_of_desc);
-                       writel(crb_producer,
-                              NETXEN_CRB_NORMALIZE(adapter,
-                                                   CRB_CMD_PRODUCER_OFFSET));
-                       wmb();
-               }
        }
 
        port->stats.xmitfinished++;
@@ -891,20 +953,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 static void netxen_watchdog(unsigned long v)
 {
        struct netxen_adapter *adapter = (struct netxen_adapter *)v;
-       schedule_work(&adapter->watchdog_task);
+
+       SCHEDULE_WORK(&adapter->watchdog_task);
 }
 
 static void netxen_tx_timeout(struct net_device *netdev)
 {
        struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
-       struct netxen_adapter *adapter = port->adapter;
 
-       schedule_work(&adapter->tx_timeout_task);
+       SCHEDULE_WORK(&port->tx_timeout_task);
 }
 
-static void netxen_tx_timeout_task(struct net_device *netdev)
+static void netxen_tx_timeout_task(struct work_struct *work)
 {
-       struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+       struct netxen_port *port =
+               container_of(work, struct netxen_port, tx_timeout_task);
+       struct net_device *netdev = port->netdev;
        unsigned long flags;
 
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
@@ -930,13 +994,17 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
        if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
                int count = 0;
                u32 mask;
+               mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+               if ((mask & 0x80) == 0) {
+                       /* not our interrupt */
+                       return ret;
+               }
                netxen_nic_disable_int(adapter);
                /* Window = 0 or 1 */
                do {
-                       writel(0xffffffff, (void __iomem *)
-                              (adapter->ahw.pci_base + ISR_INT_TARGET_STATUS));
-                       mask = readl((void __iomem *)
-                                    (adapter->ahw.pci_base + ISR_INT_VECTOR));
+                       writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
+                                               ISR_INT_TARGET_STATUS));
+                       mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
                } while (((mask & 0x80) != 0) && (++count < 32));
                if ((mask & 0x80) != 0)
                        printk("Could not disable interrupt completely\n");
@@ -990,7 +1058,10 @@ irqreturn_t netxen_intr(int irq, void *data)
                netdev = port->netdev;
 
                /* process our status queue (for all 4 ports) */
-               netxen_handle_int(adapter, netdev);
+               if (netif_running(netdev)) {
+                       netxen_handle_int(adapter, netdev);
+                       break;
+               }
        }
 
        return IRQ_HANDLED;
@@ -1004,11 +1075,12 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
        int done = 1;
        int ctx;
        int this_work_done;
+       int work_done = 0;
 
        DPRINTK(INFO, "polling for %d descriptors\n", *budget);
        port->stats.polled++;
 
-       adapter->work_done = 0;
+       work_done = 0;
        for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
                /*
                 * Fairness issue. This will give undue weight to the
@@ -1025,20 +1097,20 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
                this_work_done = netxen_process_rcv_ring(adapter, ctx,
                                                         work_to_do /
                                                         MAX_RCV_CTX);
-               adapter->work_done += this_work_done;
+               work_done += this_work_done;
        }
 
-       netdev->quota -= adapter->work_done;
-       *budget -= adapter->work_done;
+       netdev->quota -= work_done;
+       *budget -= work_done;
 
-       if (adapter->work_done >= work_to_do
-           && netxen_nic_rx_has_work(adapter) != 0)
+       if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
                done = 0;
 
-       netxen_process_cmd_ring((unsigned long)adapter);
+       if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
+               done = 0;
 
        DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
-               adapter->work_done, work_to_do);
+               work_done, work_to_do);
        if (done) {
                netif_rx_complete(netdev);
                netxen_nic_enable_int(adapter);
@@ -1057,38 +1129,6 @@ static void netxen_nic_poll_controller(struct net_device *netdev)
        enable_irq(adapter->irq);
 }
 #endif
-/*
- * netxen_nic_ioctl ()    We provide the tcl/phanmon support through these
- * ioctls.
- */
-static int
-netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
-       int err = 0;
-       struct netxen_port *port = netdev_priv(netdev);
-       struct netxen_adapter *adapter = port->adapter;
-
-       DPRINTK(INFO, "doing ioctl for %s\n", netdev->name);
-       switch (cmd) {
-       case NETXEN_NIC_CMD:
-               err = netxen_nic_do_ioctl(adapter, (void *)ifr->ifr_data, port);
-               break;
-
-       case NETXEN_NIC_NAME:
-               DPRINTK(INFO, "ioctl cmd for NetXen\n");
-               if (ifr->ifr_data) {
-                       put_user(port->portnum, (u16 __user *) ifr->ifr_data);
-               }
-               break;
-
-       default:
-               DPRINTK(INFO, "ioctl cmd %x not supported\n", cmd);
-               err = -EOPNOTSUPP;
-               break;
-       }
-
-       return err;
-}
 
 static struct pci_driver netxen_driver = {
        .name = netxen_nic_driver_name,
@@ -1101,9 +1141,10 @@ static struct pci_driver netxen_driver = {
 
 static int __init netxen_init_module(void)
 {
-       printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+       if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
+               return -ENOMEM;
 
-       return pci_module_init(&netxen_driver);
+       return pci_register_driver(&netxen_driver);
 }
 
 module_init(netxen_init_module);
@@ -1113,7 +1154,7 @@ static void __exit netxen_exit_module(void)
        /*
         * Wait for some time to allow the dma to drain, if any.
         */
-       mdelay(5);
+       destroy_workqueue(netxen_workq);
        pci_unregister_driver(&netxen_driver);
 }