netxen: fix the version code macro
[safe/jmp/linux-2.6] / drivers / net / netxen / netxen_nic_init.c
index 869725f..7bdcbc6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * Source file for NIC routines to initialize the Phantom Hardware
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
 #include <linux/delay.h>
 #include "netxen_nic.h"
 #include "netxen_nic_hw.h"
-#include "netxen_nic_ioctl.h"
 #include "netxen_nic_phan_reg.h"
 
 struct crb_addr_pair {
-       long addr;
-       long data;
+       u32 addr;
+       u32 data;
 };
 
 #define NETXEN_MAX_CRB_XFORM 60
 static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
-#define NETXEN_ADDR_ERROR ((unsigned long ) 0xffffffff )
+#define NETXEN_ADDR_ERROR (0xffffffff)
 
 #define crb_addr_transform(name) \
        crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \
@@ -53,13 +49,9 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
 
 #define NETXEN_NIC_XDMA_RESET 0x8000ff
 
-static inline void
-netxen_nic_locked_write_reg(struct netxen_adapter *adapter,
-                           unsigned long off, int *data)
-{
-       void __iomem *addr = pci_base_offset(adapter, off);
-       writel(*data, addr);
-}
+static void
+netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+               struct nx_host_rds_ring *rds_ring);
 
 static void crb_addr_transform_setup(void)
 {
@@ -111,121 +103,233 @@ static void crb_addr_transform_setup(void)
        crb_addr_transform(CAM);
        crb_addr_transform(C2C1);
        crb_addr_transform(C2C0);
+       crb_addr_transform(SMB);
+       crb_addr_transform(OCM0);
+       crb_addr_transform(I2C0);
 }
 
-int netxen_init_firmware(struct netxen_adapter *adapter)
+void netxen_release_rx_buffers(struct netxen_adapter *adapter)
 {
-       u32 state = 0, loops = 0, err = 0;
+       struct netxen_recv_context *recv_ctx;
+       struct nx_host_rds_ring *rds_ring;
+       struct netxen_rx_buffer *rx_buf;
+       int i, ring;
+
+       recv_ctx = &adapter->recv_ctx;
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &recv_ctx->rds_rings[ring];
+               for (i = 0; i < rds_ring->num_desc; ++i) {
+                       rx_buf = &(rds_ring->rx_buf_arr[i]);
+                       if (rx_buf->state == NETXEN_BUFFER_FREE)
+                               continue;
+                       pci_unmap_single(adapter->pdev,
+                                       rx_buf->dma,
+                                       rds_ring->dma_size,
+                                       PCI_DMA_FROMDEVICE);
+                       if (rx_buf->skb != NULL)
+                               dev_kfree_skb_any(rx_buf->skb);
+               }
+       }
+}
+
+void netxen_release_tx_buffers(struct netxen_adapter *adapter)
+{
+       struct netxen_cmd_buffer *cmd_buf;
+       struct netxen_skb_frag *buffrag;
+       int i, j;
+       struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
+
+       cmd_buf = tx_ring->cmd_buf_arr;
+       for (i = 0; i < tx_ring->num_desc; i++) {
+               buffrag = cmd_buf->frag_array;
+               if (buffrag->dma) {
+                       pci_unmap_single(adapter->pdev, buffrag->dma,
+                                        buffrag->length, PCI_DMA_TODEVICE);
+                       buffrag->dma = 0ULL;
+               }
+               for (j = 0; j < cmd_buf->frag_count; j++) {
+                       buffrag++;
+                       if (buffrag->dma) {
+                               pci_unmap_page(adapter->pdev, buffrag->dma,
+                                              buffrag->length,
+                                              PCI_DMA_TODEVICE);
+                               buffrag->dma = 0ULL;
+                       }
+               }
+               if (cmd_buf->skb) {
+                       dev_kfree_skb_any(cmd_buf->skb);
+                       cmd_buf->skb = NULL;
+               }
+               cmd_buf++;
+       }
+}
 
-       /* Window 1 call */
-       state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+void netxen_free_sw_resources(struct netxen_adapter *adapter)
+{
+       struct netxen_recv_context *recv_ctx;
+       struct nx_host_rds_ring *rds_ring;
+       struct nx_host_tx_ring *tx_ring;
+       int ring;
 
-       if (state == PHAN_INITIALIZE_ACK)
-               return 0;
+       recv_ctx = &adapter->recv_ctx;
 
-       while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
-               udelay(100);
-               /* Window 1 call */
-               state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+       if (recv_ctx->rds_rings == NULL)
+               goto skip_rds;
 
-               loops++;
-       }
-       if (loops >= 2000) {
-               printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
-                      state);
-               err = -EIO;
-               return err;
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &recv_ctx->rds_rings[ring];
+               vfree(rds_ring->rx_buf_arr);
+               rds_ring->rx_buf_arr = NULL;
        }
-       /* Window 1 call */
-       writel(MPORT_SINGLE_FUNCTION_MODE,
-              NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
-       writel(PHAN_INITIALIZE_ACK,
-              NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+       kfree(recv_ctx->rds_rings);
 
-       return err;
-}
+skip_rds:
+       if (adapter->tx_ring == NULL)
+               return;
 
-#define NETXEN_ADDR_LIMIT 0xffffffffULL
+       tx_ring = adapter->tx_ring;
+       vfree(tx_ring->cmd_buf_arr);
+}
 
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
-                  struct pci_dev **used_dev)
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
 {
-       void *addr;
+       struct netxen_recv_context *recv_ctx;
+       struct nx_host_rds_ring *rds_ring;
+       struct nx_host_sds_ring *sds_ring;
+       struct nx_host_tx_ring *tx_ring;
+       struct netxen_rx_buffer *rx_buf;
+       int ring, i, size;
+
+       struct netxen_cmd_buffer *cmd_buf_arr;
+       struct net_device *netdev = adapter->netdev;
+       struct pci_dev *pdev = adapter->pdev;
+
+       size = sizeof(struct nx_host_tx_ring);
+       tx_ring = kzalloc(size, GFP_KERNEL);
+       if (tx_ring == NULL) {
+               dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n",
+                      netdev->name);
+               return -ENOMEM;
+       }
+       adapter->tx_ring = tx_ring;
+
+       tx_ring->num_desc = adapter->num_txd;
 
-       addr = pci_alloc_consistent(pdev, sz, ptr);
-       if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
-               *used_dev = pdev;
-               return addr;
+       cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
+       if (cmd_buf_arr == NULL) {
+               dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
+                      netdev->name);
+               return -ENOMEM;
        }
-       pci_free_consistent(pdev, sz, addr, *ptr);
-       addr = pci_alloc_consistent(NULL, sz, ptr);
-       *used_dev = NULL;
-       return addr;
-}
+       memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
+       tx_ring->cmd_buf_arr = cmd_buf_arr;
 
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
-{
-       int ctxid, ring;
-       u32 i;
-       u32 num_rx_bufs = 0;
-       struct netxen_rcv_desc_ctx *rcv_desc;
-
-       DPRINTK(INFO, "initializing some queues: %p\n", adapter);
-       for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
-               for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       struct netxen_rx_buffer *rx_buf;
-                       rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
-                       rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
-                       rcv_desc->begin_alloc = 0;
-                       rx_buf = rcv_desc->rx_buf_arr;
-                       num_rx_bufs = rcv_desc->max_rx_desc_count;
-                       /*
-                        * Now go through all of them, set reference handles
-                        * and put them in the queues.
-                        */
-                       for (i = 0; i < num_rx_bufs; i++) {
-                               rx_buf->ref_handle = i;
-                               rx_buf->state = NETXEN_BUFFER_FREE;
-                               DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
-                                       "%p\n", ctxid, i, rx_buf);
-                               rx_buf++;
+       recv_ctx = &adapter->recv_ctx;
+
+       size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring);
+       rds_ring = kzalloc(size, GFP_KERNEL);
+       if (rds_ring == NULL) {
+               dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
+                      netdev->name);
+               return -ENOMEM;
+       }
+       recv_ctx->rds_rings = rds_ring;
+
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &recv_ctx->rds_rings[ring];
+               switch (ring) {
+               case RCV_RING_NORMAL:
+                       rds_ring->num_desc = adapter->num_rxd;
+                       if (adapter->ahw.cut_through) {
+                               rds_ring->dma_size =
+                                       NX_CT_DEFAULT_RX_BUF_LEN;
+                               rds_ring->skb_size =
+                                       NX_CT_DEFAULT_RX_BUF_LEN;
+                       } else {
+                               rds_ring->dma_size = RX_DMA_MAP_LEN;
+                               rds_ring->skb_size =
+                                       MAX_RX_BUFFER_LENGTH;
                        }
+                       break;
+
+               case RCV_RING_JUMBO:
+                       rds_ring->num_desc = adapter->num_jumbo_rxd;
+                       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+                               rds_ring->dma_size =
+                                       NX_P3_RX_JUMBO_BUF_MAX_LEN;
+                       else
+                               rds_ring->dma_size =
+                                       NX_P2_RX_JUMBO_BUF_MAX_LEN;
+                       rds_ring->skb_size =
+                               rds_ring->dma_size + NET_IP_ALIGN;
+                       break;
+
+               case RCV_RING_LRO:
+                       rds_ring->num_desc = adapter->num_lro_rxd;
+                       rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+                       rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+                       break;
+
                }
+               rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+                       vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
+               if (rds_ring->rx_buf_arr == NULL) {
+                       printk(KERN_ERR "%s: Failed to allocate "
+                               "rx buffer ring %d\n",
+                               netdev->name, ring);
+                       /* free whatever was already allocated */
+                       goto err_out;
+               }
+               memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
+               INIT_LIST_HEAD(&rds_ring->free_list);
+               /*
+                * Now go through all of them, set reference handles
+                * and put them in the queues.
+                */
+               rx_buf = rds_ring->rx_buf_arr;
+               for (i = 0; i < rds_ring->num_desc; i++) {
+                       list_add_tail(&rx_buf->list,
+                                       &rds_ring->free_list);
+                       rx_buf->ref_handle = i;
+                       rx_buf->state = NETXEN_BUFFER_FREE;
+                       rx_buf++;
+               }
+               spin_lock_init(&rds_ring->lock);
        }
-}
 
-void netxen_initialize_adapter_hw(struct netxen_adapter *adapter)
-{
-       int ports = 0;
-       struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
-
-       if (netxen_nic_get_board_info(adapter) != 0)
-               printk("%s: Error getting board config info.\n",
-                      netxen_nic_driver_name);
-       get_brd_port_by_type(board_info->board_type, &ports);
-       if (ports == 0)
-               printk(KERN_ERR "%s: Unknown board type\n",
-                      netxen_nic_driver_name);
-       adapter->ahw.max_ports = ports;
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               sds_ring->irq = adapter->msix_entries[ring].vector;
+               sds_ring->adapter = adapter;
+               sds_ring->num_desc = adapter->num_rxd;
+
+               for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
+                       INIT_LIST_HEAD(&sds_ring->free_list[i]);
+       }
+
+       return 0;
+
+err_out:
+       netxen_free_sw_resources(adapter);
+       return -ENOMEM;
 }
 
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 {
-       switch (adapter->ahw.board_type) {
+       adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
+       adapter->set_multi = netxen_p2_nic_set_multi;
+
+       switch (adapter->ahw.port_type) {
        case NETXEN_NIC_GBE:
                adapter->enable_phy_interrupts =
                    netxen_niu_gbe_enable_phy_interrupts;
                adapter->disable_phy_interrupts =
                    netxen_niu_gbe_disable_phy_interrupts;
-               adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
-               adapter->macaddr_set = netxen_niu_macaddr_set;
                adapter->set_mtu = netxen_nic_set_mtu_gb;
                adapter->set_promisc = netxen_niu_set_promiscuous_mode;
-               adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
                adapter->phy_read = netxen_niu_gbe_phy_read;
                adapter->phy_write = netxen_niu_gbe_phy_write;
                adapter->init_port = netxen_niu_gbe_init_port;
-               adapter->init_niu = netxen_nic_init_niu_gb;
                adapter->stop_port = netxen_niu_disable_gbe_port;
                break;
 
@@ -234,28 +338,32 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
                    netxen_niu_xgbe_enable_phy_interrupts;
                adapter->disable_phy_interrupts =
                    netxen_niu_xgbe_disable_phy_interrupts;
-               adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
-               adapter->macaddr_set = netxen_niu_xg_macaddr_set;
                adapter->set_mtu = netxen_nic_set_mtu_xgb;
                adapter->init_port = netxen_niu_xg_init_port;
                adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
-               adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
                adapter->stop_port = netxen_niu_disable_xg_port;
                break;
 
        default:
                break;
        }
+
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+               adapter->set_mtu = nx_fw_cmd_set_mtu;
+               adapter->set_promisc = netxen_p3_nic_set_promisc;
+               adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
+               adapter->set_multi = netxen_p3_nic_set_multi;
+       }
 }
 
 /*
  * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB
  * address to external PCI CRB address.
  */
-unsigned long netxen_decode_crb_addr(unsigned long addr)
+static u32 netxen_decode_crb_addr(u32 addr)
 {
        int i;
-       unsigned long base_addr, offset, pci_base;
+       u32 base_addr, offset, pci_base;
 
        crb_addr_transform_setup();
 
@@ -275,10 +383,10 @@ unsigned long netxen_decode_crb_addr(unsigned long addr)
                return (pci_base + offset);
 }
 
-static long rom_max_timeout = 10000;
-static long rom_lock_timeout = 1000000;
+static long rom_max_timeout = 100;
+static long rom_lock_timeout = 10000;
 
-static inline int rom_lock(struct netxen_adapter *adapter)
+static int rom_lock(struct netxen_adapter *adapter)
 {
        int iter;
        u32 done = 0;
@@ -286,8 +394,7 @@ static inline int rom_lock(struct netxen_adapter *adapter)
 
        while (!done) {
                /* acquire semaphore2 from PCI HW block */
-               netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
-                                  &done);
+               done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK));
                if (done == 1)
                        break;
                if (timeout >= rom_lock_timeout)
@@ -304,17 +411,19 @@ static inline int rom_lock(struct netxen_adapter *adapter)
                                cpu_relax();    /*This a nop instr on i386 */
                }
        }
-       netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+       NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
        return 0;
 }
 
-int netxen_wait_rom_done(struct netxen_adapter *adapter)
+static int netxen_wait_rom_done(struct netxen_adapter *adapter)
 {
        long timeout = 0;
        long done = 0;
 
+       cond_resched();
+
        while (done == 0) {
-               done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
+               done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS);
                done &= 2;
                timeout++;
                if (timeout >= rom_max_timeout) {
@@ -325,146 +434,75 @@ int netxen_wait_rom_done(struct netxen_adapter *adapter)
        return 0;
 }
 
-static inline int netxen_rom_wren(struct netxen_adapter *adapter)
+static void netxen_rom_unlock(struct netxen_adapter *adapter)
 {
-       /* Set write enable latch in ROM status register */
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-                            M25P_INSTR_WREN);
-       if (netxen_wait_rom_done(adapter)) {
-               return -1;
-       }
-       return 0;
-}
-
-static inline unsigned int netxen_rdcrbreg(struct netxen_adapter *adapter,
-                                          unsigned int addr)
-{
-       unsigned int data = 0xdeaddead;
-       data = netxen_nic_reg_read(adapter, addr);
-       return data;
-}
-
-static inline int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
-{
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-                            M25P_INSTR_RDSR);
-       if (netxen_wait_rom_done(adapter)) {
-               return -1;
-       }
-       return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
-}
-
-static inline void netxen_rom_unlock(struct netxen_adapter *adapter)
-{
-       u32 val;
-
        /* release semaphore2 */
-       netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
-
-}
-
-int netxen_rom_wip_poll(struct netxen_adapter *adapter)
-{
-       long timeout = 0;
-       long wip = 1;
-       int val;
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-       while (wip != 0) {
-               val = netxen_do_rom_rdsr(adapter);
-               wip = val & 1;
-               timeout++;
-               if (timeout > rom_max_timeout) {
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
-                                   int data)
-{
-       if (netxen_rom_wren(adapter)) {
-               return -1;
-       }
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_WDATA, data);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-                            M25P_INSTR_PP);
-       if (netxen_wait_rom_done(adapter)) {
-               netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-               return -1;
-       }
+       NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK));
 
-       return netxen_rom_wip_poll(adapter);
 }
 
-static inline int
-do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+static int do_rom_fast_read(struct netxen_adapter *adapter,
+                           int addr, int *valp)
 {
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-       udelay(100);            /* prevent bursting on CRB */
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
        if (netxen_wait_rom_done(adapter)) {
                printk("Error waiting for rom done\n");
                return -EIO;
        }
        /* reset abyte_cnt and dummy_byte_cnt */
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-       udelay(100);            /* prevent bursting on CRB */
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+       udelay(10);
+       NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
 
-       *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
+       *valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA);
        return 0;
 }
 
-int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
+static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
+                                 u8 *bytes, size_t size)
 {
-       int ret;
+       int addridx;
+       int ret = 0;
 
-       if (rom_lock(adapter) != 0)
-               return -EIO;
+       for (addridx = addr; addridx < (addr + size); addridx += 4) {
+               int v;
+               ret = do_rom_fast_read(adapter, addridx, &v);
+               if (ret != 0)
+                       break;
+               *(__le32 *)bytes = cpu_to_le32(v);
+               bytes += 4;
+       }
 
-       ret = do_rom_fast_read(adapter, addr, valp);
-       netxen_rom_unlock(adapter);
        return ret;
 }
 
-int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
+int
+netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
+                               u8 *bytes, size_t size)
 {
-       int ret = 0;
+       int ret;
+
+       ret = rom_lock(adapter);
+       if (ret < 0)
+               return ret;
+
+       ret = do_rom_fast_read_words(adapter, addr, bytes, size);
 
-       if (rom_lock(adapter) != 0) {
-               return -1;
-       }
-       ret = do_rom_fast_write(adapter, addr, data);
        netxen_rom_unlock(adapter);
        return ret;
 }
-int netxen_do_rom_se(struct netxen_adapter *adapter, int addr)
-{
-       netxen_rom_wren(adapter);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-       netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-                            M25P_INSTR_SE);
-       if (netxen_wait_rom_done(adapter)) {
-               netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-               return -1;
-       }
-       return netxen_rom_wip_poll(adapter);
-}
 
-int netxen_rom_se(struct netxen_adapter *adapter, int addr)
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
 {
-       int ret = 0;
-       if (rom_lock(adapter) != 0) {
-               return -1;
-       }
-       ret = netxen_do_rom_se(adapter, addr);
+       int ret;
+
+       if (rom_lock(adapter) != 0)
+               return -EIO;
+
+       ret = do_rom_fast_read(adapter, addr, valp);
        netxen_rom_unlock(adapter);
        return ret;
 }
@@ -472,29 +510,21 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr)
 #define NETXEN_BOARDTYPE               0x4008
 #define NETXEN_BOARDNUM                0x400c
 #define NETXEN_CHIPNUM                 0x4010
-#define NETXEN_ROMBUS_RESET            0xFFFFFFFF
-#define NETXEN_ROM_FIRST_BARRIER       0x800000000ULL
-#define NETXEN_ROM_FOUND_INIT          0x400
 
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
 {
-       int addr, val, status;
-       int n, i;
-       int init_delay = 0;
+       int addr, val;
+       int i, n, init_delay = 0;
        struct crb_addr_pair *buf;
-       unsigned long off;
+       unsigned offset;
+       u32 off;
 
        /* resetall */
-       status = netxen_nic_get_board_info(adapter);
-       if (status)
-               printk("%s: netxen_pinit_from_rom: Error getting board info\n",
-                      netxen_nic_driver_name);
-
-       netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-                                   NETXEN_ROMBUS_RESET);
+       rom_lock(adapter);
+       NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff);
+       netxen_rom_unlock(adapter);
 
        if (verbose) {
-               int val;
                if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
                        printk("P2 ROM board type: 0x%08x\n", val);
                else
@@ -509,117 +539,349 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
                        printk("Could not read chip number\n");
        }
 
-       if (netxen_rom_fast_read(adapter, 0, &n) == 0
-           && (n & NETXEN_ROM_FIRST_BARRIER)) {
-               n &= ~NETXEN_ROM_ROUNDUP;
-               if (n < NETXEN_ROM_FOUND_INIT) {
-                       if (verbose)
-                               printk("%s: %d CRB init values found"
-                                      " in ROM.\n", netxen_nic_driver_name, n);
-               } else {
-                       printk("%s:n=0x%x Error! NetXen card flash not"
-                              " initialized.\n", __FUNCTION__, n);
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+               if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+                       (n != 0xcafecafe) ||
+                       netxen_rom_fast_read(adapter, 4, &n) != 0) {
+                       printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+                                       "n: %08x\n", netxen_nic_driver_name, n);
                        return -EIO;
                }
-               buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
-               if (buf == NULL) {
-                       printk("%s: netxen_pinit_from_rom: Unable to calloc "
-                              "memory.\n", netxen_nic_driver_name);
-                       return -ENOMEM;
+               offset = n & 0xffffU;
+               n = (n >> 16) & 0xffffU;
+       } else {
+               if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+                       !(n & 0x80000000)) {
+                       printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+                                       "n: %08x\n", netxen_nic_driver_name, n);
+                       return -EIO;
                }
-               for (i = 0; i < n; i++) {
-                       if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
-                           || netxen_rom_fast_read(adapter, 8 * i + 8,
-                                                   &addr) != 0)
-                               return -EIO;
+               offset = 1;
+               n &= ~0x80000000;
+       }
 
-                       buf[i].addr = addr;
-                       buf[i].data = val;
+       if (n < 1024) {
+               if (verbose)
+                       printk(KERN_DEBUG "%s: %d CRB init values found"
+                              " in ROM.\n", netxen_nic_driver_name, n);
+       } else {
+               printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
+                      " initialized.\n", __func__, n);
+               return -EIO;
+       }
 
-                       if (verbose)
-                               printk("%s: PCI:     0x%08x == 0x%08x\n",
-                                      netxen_nic_driver_name, (unsigned int)
-                                      netxen_decode_crb_addr((unsigned long)
-                                                             addr), val);
+       buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+       if (buf == NULL) {
+               printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
+                               netxen_nic_driver_name);
+               return -ENOMEM;
+       }
+       for (i = 0; i < n; i++) {
+               if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+               netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
+                       kfree(buf);
+                       return -EIO;
                }
-               for (i = 0; i < n; i++) {
 
-                       off =
-                           netxen_decode_crb_addr((unsigned long)buf[i].addr) +
-                           NETXEN_PCI_CRBSPACE;
-                       /* skipping cold reboot MAGIC */
-                       if (off == NETXEN_CAM_RAM(0x1fc))
+               buf[i].addr = addr;
+               buf[i].data = val;
+
+               if (verbose)
+                       printk(KERN_DEBUG "%s: PCI:     0x%08x == 0x%08x\n",
+                               netxen_nic_driver_name,
+                               (u32)netxen_decode_crb_addr(addr), val);
+       }
+       for (i = 0; i < n; i++) {
+
+               off = netxen_decode_crb_addr(buf[i].addr);
+               if (off == NETXEN_ADDR_ERROR) {
+                       printk(KERN_ERR"CRB init value out of range %x\n",
+                                       buf[i].addr);
+                       continue;
+               }
+               off += NETXEN_PCI_CRBSPACE;
+               /* skipping cold reboot MAGIC */
+               if (off == NETXEN_CAM_RAM(0x1fc))
+                       continue;
+
+               if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+                       /* do not reset PCI */
+                       if (off == (ROMUSB_GLB + 0xbc))
+                               continue;
+                       if (off == (ROMUSB_GLB + 0xa8))
                                continue;
+                       if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
+                               continue;
+                       if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
+                               continue;
+                       if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
+                               continue;
+                       if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
+                               buf[i].data = 0x1020;
+                       /* skip the function enable register */
+                       if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
+                               continue;
+                       if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
+                               continue;
+                       if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
+                               continue;
+               }
 
-                       /* After writing this register, HW needs time for CRB */
-                       /* to quiet down (else crb_window returns 0xffffffff) */
-                       if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
-                               init_delay = 1;
+               if (off == NETXEN_ADDR_ERROR) {
+                       printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
+                                       netxen_nic_driver_name, buf[i].addr);
+                       continue;
+               }
+
+               init_delay = 1;
+               /* After writing this register, HW needs time for CRB */
+               /* to quiet down (else crb_window returns 0xffffffff) */
+               if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+                       init_delay = 1000;
+                       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
                                /* hold xdma in reset also */
                                buf[i].data = NETXEN_NIC_XDMA_RESET;
+                               buf[i].data = 0x8000ff;
                        }
+               }
 
-                       if (ADDR_IN_WINDOW1(off)) {
-                               writel(buf[i].data,
-                                      NETXEN_CRB_NORMALIZE(adapter, off));
-                       } else {
-                               netxen_nic_pci_change_crbwindow(adapter, 0);
-                               writel(buf[i].data,
-                                      pci_base_offset(adapter, off));
+               NXWR32(adapter, off, buf[i].data);
 
-                               netxen_nic_pci_change_crbwindow(adapter, 1);
-                       }
-                       if (init_delay == 1) {
-                               ssleep(1);
-                               init_delay = 0;
-                       }
-                       msleep(1);
+               msleep(init_delay);
+       }
+       kfree(buf);
+
+       /* disable_peg_cache_all */
+
+       /* unreset_net_cache */
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+               val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
+               NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
+       }
+
+       /* p2dn replyCount */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+       /* disable_peg_cache 0 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+       /* disable_peg_cache 1 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+       /* peg_clr_all */
+
+       /* peg_clr 0 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+       /* peg_clr 1 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+       /* peg_clr 2 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+       /* peg_clr 3 */
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+       NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
+       return 0;
+}
+
+int
+netxen_load_firmware(struct netxen_adapter *adapter)
+{
+       u64 *ptr64;
+       u32 i, flashaddr, size;
+       const struct firmware *fw = adapter->fw;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
+
+       if (fw) {
+               __le64 data;
+
+               size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
+
+               ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
+               flashaddr = NETXEN_BOOTLD_START;
+
+               for (i = 0; i < size; i++) {
+                       data = cpu_to_le64(ptr64[i]);
+                       adapter->pci_mem_write(adapter, flashaddr, &data, 8);
+                       flashaddr += 8;
+               }
+
+               size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
+               size = (__force u32)cpu_to_le32(size) / 8;
+
+               ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
+               flashaddr = NETXEN_IMAGE_START;
+
+               for (i = 0; i < size; i++) {
+                       data = cpu_to_le64(ptr64[i]);
+
+                       if (adapter->pci_mem_write(adapter,
+                                               flashaddr, &data, 8))
+                               return -EIO;
+
+                       flashaddr += 8;
+               }
+       } else {
+               u32 data;
+
+               size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
+               flashaddr = NETXEN_BOOTLD_START;
+
+               for (i = 0; i < size; i++) {
+                       if (netxen_rom_fast_read(adapter,
+                                       flashaddr, (int *)&data) != 0)
+                               return -EIO;
+
+                       if (adapter->pci_mem_write(adapter,
+                                               flashaddr, &data, 4))
+                               return -EIO;
+
+                       flashaddr += 4;
                }
-               kfree(buf);
-
-               /* disable_peg_cache_all */
-
-               /* unreset_net_cache */
-               netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
-                                     4);
-               netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-                                           (val & 0xffffff0f));
-               /* p2dn replyCount */
-               netxen_crb_writelit_adapter(adapter,
-                                           NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
-               /* disable_peg_cache 0 */
-               netxen_crb_writelit_adapter(adapter,
-                                           NETXEN_CRB_PEG_NET_D + 0x4c, 8);
-               /* disable_peg_cache 1 */
-               netxen_crb_writelit_adapter(adapter,
-                                           NETXEN_CRB_PEG_NET_I + 0x4c, 8);
-
-               /* peg_clr_all */
-
-               /* peg_clr 0 */
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
-                                           0);
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
-                                           0);
-               /* peg_clr 1 */
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
-                                           0);
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
-                                           0);
-               /* peg_clr 2 */
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
-                                           0);
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
-                                           0);
-               /* peg_clr 3 */
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
-                                           0);
-               netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
-                                           0);
        }
+       msleep(1);
+
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+               NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+       else {
+               NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+               NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0);
+       }
+
+       return 0;
+}
+
+static int
+netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
+{
+       __le32 val;
+       u32 ver, min_ver, bios;
+       struct pci_dev *pdev = adapter->pdev;
+       const struct firmware *fw = adapter->fw;
+
+       if (fw->size < NX_FW_MIN_SIZE)
+               return -EINVAL;
+
+       val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
+       if ((__force u32)val != NETXEN_BDINFO_MAGIC)
+               return -EINVAL;
+
+       val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+               min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+       else
+               min_ver = NETXEN_VERSION_CODE(3, 4, 216);
+
+       ver = NETXEN_DECODE_VERSION(val);
+
+       if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+               dev_err(&pdev->dev,
+                               "%s: firmware version %d.%d.%d unsupported\n",
+                               fwname, _major(ver), _minor(ver), _build(ver));
+               return -EINVAL;
+       }
+
+       val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
+       netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
+       if ((__force u32)val != bios) {
+               dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+                               fwname);
+               return -EINVAL;
+       }
+
+       /* check if flashed firmware is newer */
+       if (netxen_rom_fast_read(adapter,
+                       NX_FW_VERSION_OFFSET, (int *)&val))
+               return -EIO;
+       val = NETXEN_DECODE_VERSION(val);
+       if (val > ver) {
+               dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+                               fwname);
+               return -EINVAL;
+       }
+
+       NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
        return 0;
 }
 
+static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };
+
+void netxen_request_firmware(struct netxen_adapter *adapter)
+{
+       u32 capability, flashed_ver;
+       int fw_type;
+       struct pci_dev *pdev = adapter->pdev;
+       int rc = 0;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+               fw_type = NX_P2_MN_ROMIMAGE;
+               goto request_fw;
+       } else {
+               fw_type = NX_P3_CT_ROMIMAGE;
+               goto request_fw;
+       }
+
+request_mn:
+       capability = 0;
+
+       netxen_rom_fast_read(adapter,
+                       NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
+       flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
+
+       if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
+               capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
+               if (capability & NX_PEG_TUNE_MN_PRESENT) {
+                       fw_type = NX_P3_MN_ROMIMAGE;
+                       goto request_fw;
+               }
+       }
+
+       adapter->fw = NULL;
+       goto done;
+
+request_fw:
+       rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
+       if (rc != 0) {
+               if (fw_type == NX_P3_CT_ROMIMAGE) {
+                       msleep(1);
+                       goto request_mn;
+               }
+
+               adapter->fw = NULL;
+               goto done;
+       }
+
+       rc = netxen_validate_firmware(adapter, fw_name[fw_type]);
+       if (rc != 0) {
+               release_firmware(adapter->fw);
+
+               if (fw_type == NX_P3_CT_ROMIMAGE) {
+                       msleep(1);
+                       goto request_mn;
+               }
+
+               adapter->fw = NULL;
+               goto done;
+       }
+
+done:
+       if (adapter->fw)
+               dev_info(&pdev->dev, "loading firmware from file %s\n",
+                               fw_name[fw_type]);
+       else
+               dev_info(&pdev->dev, "loading firmware from flash\n");
+}
+
+
+void
+netxen_release_firmware(struct netxen_adapter *adapter)
+{
+       if (adapter->fw)
+               release_firmware(adapter->fw);
+}
+
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 {
        uint64_t addr;
@@ -627,12 +889,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
        uint32_t lo;
 
        adapter->dummy_dma.addr =
-           pci_alloc_consistent(adapter->ahw.pdev,
+           pci_alloc_consistent(adapter->pdev,
                                 NETXEN_HOST_DUMMY_DMA_SIZE,
                                 &adapter->dummy_dma.phys_addr);
        if (adapter->dummy_dma.addr == NULL) {
                printk("%s: ERROR: Could not allocate dummy DMA memory\n",
-                      __FUNCTION__);
+                      __func__);
                return -ENOMEM;
        }
 
@@ -640,423 +902,438 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
        hi = (addr >> 32) & 0xffffffff;
        lo = addr & 0xffffffff;
 
-       writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
-       writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+       NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+       NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+               uint32_t temp = 0;
+               NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp);
+       }
 
        return 0;
 }
 
 void netxen_free_adapter_offload(struct netxen_adapter *adapter)
 {
-       if (adapter->dummy_dma.addr) {
-               pci_free_consistent(adapter->ahw.pdev,
-                                   NETXEN_HOST_DUMMY_DMA_SIZE,
-                                   adapter->dummy_dma.addr,
-                                   adapter->dummy_dma.phys_addr);
+       int i = 100;
+
+       if (!adapter->dummy_dma.addr)
+               return;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+               do {
+                       if (dma_watchdog_shutdown_request(adapter) == 1)
+                               break;
+                       msleep(50);
+                       if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+                               break;
+               } while (--i);
+       }
+
+       if (i) {
+               pci_free_consistent(adapter->pdev,
+                           NETXEN_HOST_DUMMY_DMA_SIZE,
+                           adapter->dummy_dma.addr,
+                           adapter->dummy_dma.phys_addr);
                adapter->dummy_dma.addr = NULL;
+       } else {
+               printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
+                               adapter->netdev->name);
        }
 }
 
-void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
+int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
 {
        u32 val = 0;
-       int loops = 0;
+       int retries = 60;
 
-       if (!pegtune_val) {
-               while (val != PHAN_INITIALIZE_COMPLETE && loops < 200000) {
-                       udelay(100);
-                       schedule();
-                       val =
-                           readl(NETXEN_CRB_NORMALIZE
-                                 (adapter, CRB_CMDPEG_STATE));
-                       loops++;
+       if (pegtune_val)
+               return 0;
+
+       do {
+               val = NXRD32(adapter, CRB_CMDPEG_STATE);
+
+               switch (val) {
+               case PHAN_INITIALIZE_COMPLETE:
+               case PHAN_INITIALIZE_ACK:
+                       return 0;
+               case PHAN_INITIALIZE_FAILED:
+                       goto out_err;
+               default:
+                       break;
                }
-               if (val != PHAN_INITIALIZE_COMPLETE)
-                       printk("WARNING: Initial boot wait loop failed...\n");
-       }
+
+               msleep(500);
+
+       } while (--retries);
+
+       NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+       dev_warn(&adapter->pdev->dev, "firmware init failed\n");
+       return -EIO;
 }
 
-int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
+static int
+netxen_receive_peg_ready(struct netxen_adapter *adapter)
 {
-       int ctx;
-
-       for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-               struct netxen_recv_context *recv_ctx =
-                   &(adapter->recv_ctx[ctx]);
-               u32 consumer;
-               struct status_desc *desc_head;
-               struct status_desc *desc;
-
-               consumer = recv_ctx->status_rx_consumer;
-               desc_head = recv_ctx->rcv_status_desc_head;
-               desc = &desc_head[consumer];
-
-               if (((le16_to_cpu(netxen_get_sts_owner(desc)))
-                    & STATUS_OWNER_HOST))
-                       return 1;
+       u32 val = 0;
+       int retries = 2000;
+
+       do {
+               val = NXRD32(adapter, CRB_RCVPEG_STATE);
+
+               if (val == PHAN_PEG_RCV_INITIALIZED)
+                       return 0;
+
+               msleep(10);
+
+       } while (--retries);
+
+       if (!retries) {
+               printk(KERN_ERR "Receive Peg initialization not "
+                             "complete, state: 0x%x.\n", val);
+               return -EIO;
        }
 
        return 0;
 }
 
-static inline int netxen_nic_check_temp(struct netxen_adapter *adapter)
+int netxen_init_firmware(struct netxen_adapter *adapter)
 {
-       int port_num;
-       struct netxen_port *port;
-       struct net_device *netdev;
-       uint32_t temp, temp_state, temp_val;
-       int rv = 0;
-
-       temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
-
-       temp_state = nx_get_temp_state(temp);
-       temp_val = nx_get_temp_val(temp);
-
-       if (temp_state == NX_TEMP_PANIC) {
-               printk(KERN_ALERT
-                      "%s: Device temperature %d degrees C exceeds"
-                      " maximum allowed. Hardware has been shut down.\n",
-                      netxen_nic_driver_name, temp_val);
-               for (port_num = 0; port_num < adapter->ahw.max_ports;
-                    port_num++) {
-                       port = adapter->port[port_num];
-                       netdev = port->netdev;
-
-                       netif_carrier_off(netdev);
-                       netif_stop_queue(netdev);
-               }
-               rv = 1;
-       } else if (temp_state == NX_TEMP_WARN) {
-               if (adapter->temp == NX_TEMP_NORMAL) {
-                       printk(KERN_ALERT
-                              "%s: Device temperature %d degrees C "
-                              "exceeds operating range."
-                              " Immediate action needed.\n",
-                              netxen_nic_driver_name, temp_val);
-               }
-       } else {
-               if (adapter->temp == NX_TEMP_WARN) {
-                       printk(KERN_INFO
-                              "%s: Device temperature is now %d degrees C"
-                              " in normal range.\n", netxen_nic_driver_name,
-                              temp_val);
-               }
+       int err;
+
+       err = netxen_receive_peg_ready(adapter);
+       if (err)
+               return err;
+
+       NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+       NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+       NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+       NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+       if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) {
+               adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
        }
-       adapter->temp = temp_state;
-       return rv;
+
+       return err;
 }
 
-void netxen_watchdog_task(struct work_struct *work)
+static void
+netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg)
 {
-       int port_num;
-       struct netxen_port *port;
-       struct net_device *netdev;
-       struct netxen_adapter *adapter =
-               container_of(work, struct netxen_adapter, watchdog_task);
+       u32 cable_OUI;
+       u16 cable_len;
+       u16 link_speed;
+       u8  link_status, module, duplex, autoneg;
+       struct net_device *netdev = adapter->netdev;
+
+       adapter->has_link_events = 1;
+
+       cable_OUI = msg->body[1] & 0xffffffff;
+       cable_len = (msg->body[1] >> 32) & 0xffff;
+       link_speed = (msg->body[1] >> 48) & 0xffff;
+
+       link_status = msg->body[2] & 0xff;
+       duplex = (msg->body[2] >> 16) & 0xff;
+       autoneg = (msg->body[2] >> 24) & 0xff;
+
+       module = (msg->body[2] >> 8) & 0xff;
+       if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) {
+               printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n",
+                               netdev->name, cable_OUI, cable_len);
+       } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) {
+               printk(KERN_INFO "%s: unsupported cable length %d\n",
+                               netdev->name, cable_len);
+       }
 
-       if (netxen_nic_check_temp(adapter))
-               return;
+       netxen_advert_link_change(adapter, link_status);
 
-       for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
-               port = adapter->port[port_num];
-               netdev = port->netdev;
+       /* update link parameters */
+       if (duplex == LINKEVENT_FULL_DUPLEX)
+               adapter->link_duplex = DUPLEX_FULL;
+       else
+               adapter->link_duplex = DUPLEX_HALF;
+       adapter->module_type = module;
+       adapter->link_autoneg = autoneg;
+       adapter->link_speed = link_speed;
+}
 
-               if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
-                       printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
-                              netxen_nic_driver_name, port_num, netdev->name);
-                       netif_carrier_on(netdev);
-               }
+static void
+netxen_handle_fw_message(int desc_cnt, int index,
+               struct nx_host_sds_ring *sds_ring)
+{
+       nx_fw_msg_t msg;
+       struct status_desc *desc;
+       int i = 0, opcode;
+
+       while (desc_cnt > 0 && i < 8) {
+               desc = &sds_ring->desc_head[index];
+               msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+               msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
 
-               if (netif_queue_stopped(netdev))
-                       netif_wake_queue(netdev);
+               index = get_next_index(index, sds_ring->num_desc);
+               desc_cnt--;
        }
 
-       if (adapter->handle_phy_intr)
-               adapter->handle_phy_intr(adapter);
-       mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+       opcode = netxen_get_nic_msg_opcode(msg.body[0]);
+       switch (opcode) {
+       case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+               netxen_handle_linkevent(sds_ring->adapter, &msg);
+               break;
+       default:
+               break;
+       }
 }
 
-/*
- * netxen_process_rcv() send the received packet to the protocol stack.
- * and if the number of receives exceeds RX_BUFFERS_REFILL, then we
- * invoke the routine to send more rx buffers to the Phantom...
- */
-void
-netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
-                  struct status_desc *desc)
+static int
+netxen_alloc_rx_skb(struct netxen_adapter *adapter,
+               struct nx_host_rds_ring *rds_ring,
+               struct netxen_rx_buffer *buffer)
 {
-       struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)];
-       struct pci_dev *pdev = port->pdev;
-       struct net_device *netdev = port->netdev;
-       int index = le16_to_cpu(netxen_get_sts_refhandle(desc));
-       struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
-       struct netxen_rx_buffer *buffer;
        struct sk_buff *skb;
-       u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
-       u32 desc_ctx;
-       struct netxen_rcv_desc_ctx *rcv_desc;
-       int ret;
+       dma_addr_t dma;
+       struct pci_dev *pdev = adapter->pdev;
 
-       desc_ctx = netxen_get_sts_type(desc);
-       if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
-               printk("%s: %s Bad Rcv descriptor ring\n",
-                      netxen_nic_driver_name, netdev->name);
-               return;
-       }
+       buffer->skb = dev_alloc_skb(rds_ring->skb_size);
+       if (!buffer->skb)
+               return 1;
 
-       rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
-       if (unlikely(index > rcv_desc->max_rx_desc_count)) {
-               DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
-                       index, rcv_desc->max_rx_desc_count);
-               return;
-       }
-       buffer = &rcv_desc->rx_buf_arr[index];
-       if (desc_ctx == RCV_DESC_LRO_CTXID) {
-               buffer->lro_current_frags++;
-               if (netxen_get_sts_desc_lro_last_frag(desc)) {
-                       buffer->lro_expected_frags =
-                           netxen_get_sts_desc_lro_cnt(desc);
-                       buffer->lro_length = length;
-               }
-               if (buffer->lro_current_frags != buffer->lro_expected_frags) {
-                       if (buffer->lro_expected_frags != 0) {
-                               printk("LRO: (refhandle:%x) recv frag."
-                                      "wait for last. flags: %x expected:%d"
-                                      "have:%d\n", index,
-                                      netxen_get_sts_desc_lro_last_frag(desc),
-                                      buffer->lro_expected_frags,
-                                      buffer->lro_current_frags);
-                       }
-                       return;
-               }
+       skb = buffer->skb;
+
+       if (!adapter->ahw.cut_through)
+               skb_reserve(skb, 2);
+
+       dma = pci_map_single(pdev, skb->data,
+                       rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+
+       if (pci_dma_mapping_error(pdev, dma)) {
+               dev_kfree_skb_any(skb);
+               buffer->skb = NULL;
+               return 1;
        }
 
-       pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
-                        PCI_DMA_FROMDEVICE);
+       buffer->skb = skb;
+       buffer->dma = dma;
+       buffer->state = NETXEN_BUFFER_BUSY;
+
+       return 0;
+}
+
+static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
+               struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
+{
+       struct netxen_rx_buffer *buffer;
+       struct sk_buff *skb;
+
+       buffer = &rds_ring->rx_buf_arr[index];
+
+       pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+                       PCI_DMA_FROMDEVICE);
 
-       skb = (struct sk_buff *)buffer->skb;
+       skb = buffer->skb;
+       if (!skb)
+               goto no_skb;
 
-       if (likely(netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) {
-               port->stats.csummed++;
+       if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+               adapter->stats.csummed++;
                skb->ip_summed = CHECKSUM_UNNECESSARY;
-       }
-       skb->dev = netdev;
-       if (desc_ctx == RCV_DESC_LRO_CTXID) {
-               /* True length was only available on the last pkt */
-               skb_put(skb, buffer->lro_length);
-       } else {
-               skb_put(skb, length);
-       }
+       } else
+               skb->ip_summed = CHECKSUM_NONE;
 
-       skb->protocol = eth_type_trans(skb, netdev);
+       skb->dev = adapter->netdev;
 
-       ret = netif_receive_skb(skb);
+       buffer->skb = NULL;
+no_skb:
+       buffer->state = NETXEN_BUFFER_FREE;
+       return skb;
+}
 
-       /*
-        * RH: Do we need these stats on a regular basis. Can we get it from
-        * Linux stats.
-        */
-       switch (ret) {
-       case NET_RX_SUCCESS:
-               port->stats.uphappy++;
-               break;
+static struct netxen_rx_buffer *
+netxen_process_rcv(struct netxen_adapter *adapter,
+               int ring, int index, int length, int cksum, int pkt_offset,
+               struct nx_host_sds_ring *sds_ring)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct netxen_rx_buffer *buffer;
+       struct sk_buff *skb;
+       struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
 
-       case NET_RX_CN_LOW:
-               port->stats.uplcong++;
-               break;
+       if (unlikely(index > rds_ring->num_desc))
+               return NULL;
 
-       case NET_RX_CN_MOD:
-               port->stats.upmcong++;
-               break;
+       buffer = &rds_ring->rx_buf_arr[index];
 
-       case NET_RX_CN_HIGH:
-               port->stats.uphcong++;
-               break;
+       skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
+       if (!skb)
+               return buffer;
 
-       case NET_RX_DROP:
-               port->stats.updropped++;
-               break;
+       if (length > rds_ring->skb_size)
+               skb_put(skb, rds_ring->skb_size);
+       else
+               skb_put(skb, length);
 
-       default:
-               port->stats.updunno++;
-               break;
-       }
 
-       netdev->last_rx = jiffies;
+       if (pkt_offset)
+               skb_pull(skb, pkt_offset);
 
-       rcv_desc->rcv_free++;
-       rcv_desc->rcv_pending--;
+       skb->protocol = eth_type_trans(skb, netdev);
 
-       /*
-        * We just consumed one buffer so post a buffer.
-        */
-       adapter->stats.post_called++;
-       buffer->skb = NULL;
-       buffer->state = NETXEN_BUFFER_FREE;
-       buffer->lro_current_frags = 0;
-       buffer->lro_expected_frags = 0;
+       napi_gro_receive(&sds_ring->napi, skb);
 
-       port->stats.no_rcv++;
-       port->stats.rxbytes += length;
+       adapter->stats.no_rcv++;
+       adapter->stats.rxbytes += length;
+
+       return buffer;
 }
 
-/* Process Receive status ring */
-u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+#define netxen_merge_rx_buffers(list, head) \
+       do { list_splice_tail_init(list, head); } while (0);
+
+int
+netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
 {
-       struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
-       struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
-       struct status_desc *desc;       /* used to read status desc here */
-       u32 consumer = recv_ctx->status_rx_consumer;
-       u32 producer = 0;
-       int count = 0, ring;
-
-       DPRINTK(INFO, "procesing receive\n");
-       /*
-        * we assume in this case that there is only one port and that is
-        * port #1...changes need to be done in firmware to indicate port
-        * number as part of the descriptor. This way we will be able to get
-        * the netdev which is associated with that device.
-        */
+       struct netxen_adapter *adapter = sds_ring->adapter;
+
+       struct list_head *cur;
+
+       struct status_desc *desc;
+       struct netxen_rx_buffer *rxbuf;
+
+       u32 consumer = sds_ring->consumer;
+
+       int count = 0;
+       u64 sts_data;
+       int opcode, ring, index, length, cksum, pkt_offset, desc_cnt;
+
        while (count < max) {
-               desc = &desc_head[consumer];
-               if (!
-                   (le16_to_cpu(netxen_get_sts_owner(desc)) &
-                    STATUS_OWNER_HOST)) {
-                       DPRINTK(ERR, "desc %p ownedby %x\n", desc,
-                               netxen_get_sts_owner(desc));
+               desc = &sds_ring->desc_head[consumer];
+               sts_data = le64_to_cpu(desc->status_desc_data[0]);
+
+               if (!(sts_data & STATUS_OWNER_HOST))
+                       break;
+
+               desc_cnt = netxen_get_sts_desc_cnt(sts_data);
+               ring   = netxen_get_sts_type(sts_data);
+
+               if (ring > RCV_RING_JUMBO)
+                       goto skip;
+
+               opcode = netxen_get_sts_opcode(sts_data);
+
+               switch (opcode) {
+               case NETXEN_NIC_RXPKT_DESC:
+               case NETXEN_OLD_RXPKT_DESC:
                        break;
+               case NETXEN_NIC_RESPONSE_DESC:
+                       netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
+               default:
+                       goto skip;
+               }
+
+               WARN_ON(desc_cnt > 1);
+
+               index  = netxen_get_sts_refhandle(sts_data);
+               length = netxen_get_sts_totallength(sts_data);
+               cksum  = netxen_get_sts_status(sts_data);
+               pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+
+               rxbuf = netxen_process_rcv(adapter, ring, index,
+                               length, cksum, pkt_offset, sds_ring);
+
+               if (rxbuf)
+                       list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+
+skip:
+               for (; desc_cnt > 0; desc_cnt--) {
+                       desc = &sds_ring->desc_head[consumer];
+                       desc->status_desc_data[0] =
+                               cpu_to_le64(STATUS_OWNER_PHANTOM);
+                       consumer = get_next_index(consumer, sds_ring->num_desc);
                }
-               netxen_process_rcv(adapter, ctxid, desc);
-               netxen_clear_sts_owner(desc);
-               netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
-               consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
                count++;
        }
-       if (count) {
-               for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
+
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               struct nx_host_rds_ring *rds_ring =
+                       &adapter->recv_ctx.rds_rings[ring];
+
+               if (!list_empty(&sds_ring->free_list[ring])) {
+                       list_for_each(cur, &sds_ring->free_list[ring]) {
+                               rxbuf = list_entry(cur,
+                                               struct netxen_rx_buffer, list);
+                               netxen_alloc_rx_skb(adapter, rds_ring, rxbuf);
+                       }
+                       spin_lock(&rds_ring->lock);
+                       netxen_merge_rx_buffers(&sds_ring->free_list[ring],
+                                               &rds_ring->free_list);
+                       spin_unlock(&rds_ring->lock);
                }
+
+               netxen_post_rx_buffers_nodb(adapter, rds_ring);
        }
 
-       /* update the consumer index in phantom */
        if (count) {
-               adapter->stats.process_rcv++;
-               recv_ctx->status_rx_consumer = consumer;
-               recv_ctx->status_rx_producer = producer;
-
-               /* Window = 1 */
-               writel(consumer,
-                      NETXEN_CRB_NORMALIZE(adapter,
-                                           recv_crb_registers[ctxid].
-                                           crb_rcv_status_consumer));
+               sds_ring->consumer = consumer;
+               NXWR32(adapter, sds_ring->crb_sts_consumer, consumer);
        }
 
        return count;
 }
 
 /* Process Command status ring */
-int netxen_process_cmd_ring(unsigned long data)
+int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 {
-       u32 last_consumer;
-       u32 consumer;
-       struct netxen_adapter *adapter = (struct netxen_adapter *)data;
-       int count1 = 0;
-       int count2 = 0;
+       u32 sw_consumer, hw_consumer;
+       int count = 0, i;
        struct netxen_cmd_buffer *buffer;
-       struct netxen_port *port;       /* port #1 */
-       struct netxen_port *nport;
-       struct pci_dev *pdev;
+       struct pci_dev *pdev = adapter->pdev;
+       struct net_device *netdev = adapter->netdev;
        struct netxen_skb_frag *frag;
-       u32 i;
-       struct sk_buff *skb = NULL;
-       int p;
-       int done;
-
-       spin_lock(&adapter->tx_lock);
-       last_consumer = adapter->last_cmd_consumer;
-       DPRINTK(INFO, "procesing xmit complete\n");
-       /* we assume in this case that there is only one port and that is
-        * port #1...changes need to be done in firmware to indicate port
-        * number as part of the descriptor. This way we will be able to get
-        * the netdev which is associated with that device.
-        */
+       int done = 0;
+       struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
-       consumer = *(adapter->cmd_consumer);
-       if (last_consumer == consumer) {        /* Ring is empty    */
-               DPRINTK(INFO, "last_consumer %d == consumer %d\n",
-                       last_consumer, consumer);
-               spin_unlock(&adapter->tx_lock);
+       if (!spin_trylock(&adapter->tx_clean_lock))
                return 1;
-       }
 
-       adapter->proc_cmd_buf_counter++;
-       adapter->stats.process_xmit++;
-       /*
-        * Not needed - does not seem to be used anywhere.
-        * adapter->cmd_consumer = consumer;
-        */
-       spin_unlock(&adapter->tx_lock);
-
-       while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) {
-               buffer = &adapter->cmd_buf_arr[last_consumer];
-               port = adapter->port[buffer->port];
-               pdev = port->pdev;
-               frag = &buffer->frag_array[0];
-               skb = buffer->skb;
-               if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
+       sw_consumer = tx_ring->sw_consumer;
+       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+       while (sw_consumer != hw_consumer) {
+               buffer = &tx_ring->cmd_buf_arr[sw_consumer];
+               if (buffer->skb) {
+                       frag = &buffer->frag_array[0];
                        pci_unmap_single(pdev, frag->dma, frag->length,
                                         PCI_DMA_TODEVICE);
+                       frag->dma = 0ULL;
                        for (i = 1; i < buffer->frag_count; i++) {
-                               DPRINTK(INFO, "getting fragment no %d\n", i);
                                frag++; /* Get the next frag */
                                pci_unmap_page(pdev, frag->dma, frag->length,
                                               PCI_DMA_TODEVICE);
+                               frag->dma = 0ULL;
                        }
 
-                       port->stats.skbfreed++;
-                       dev_kfree_skb_any(skb);
-                       skb = NULL;
-               } else if (adapter->proc_cmd_buf_counter == 1) {
-                       port->stats.txnullskb++;
-               }
-               if (unlikely(netif_queue_stopped(port->netdev)
-                            && netif_carrier_ok(port->netdev))
-                   && ((jiffies - port->netdev->trans_start) >
-                       port->netdev->watchdog_timeo)) {
-                       SCHEDULE_WORK(&port->adapter->tx_timeout_task);
+                       adapter->stats.xmitfinished++;
+                       dev_kfree_skb_any(buffer->skb);
+                       buffer->skb = NULL;
                }
 
-               last_consumer = get_next_index(last_consumer,
-                                              adapter->max_tx_desc_count);
-               count1++;
-       }
-       adapter->stats.noxmitdone += count1;
-
-       count2 = 0;
-       spin_lock(&adapter->tx_lock);
-       if ((--adapter->proc_cmd_buf_counter) == 0) {
-               adapter->last_cmd_consumer = last_consumer;
-               while ((adapter->last_cmd_consumer != consumer)
-                      && (count2 < MAX_STATUS_HANDLE)) {
-                       buffer =
-                           &adapter->cmd_buf_arr[adapter->last_cmd_consumer];
-                       count2++;
-                       if (buffer->skb)
-                               break;
-                       else
-                               adapter->last_cmd_consumer =
-                                   get_next_index(adapter->last_cmd_consumer,
-                                                  adapter->max_tx_desc_count);
-               }
+               sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
+               if (++count >= MAX_STATUS_HANDLE)
+                       break;
        }
-       if (count1 || count2) {
-               for (p = 0; p < adapter->ahw.max_ports; p++) {
-                       nport = adapter->port[p];
-                       if (netif_queue_stopped(nport->netdev)
-                           && (nport->flags & NETXEN_NETDEV_STATUS)) {
-                               netif_wake_queue(nport->netdev);
-                               nport->flags &= ~NETXEN_NETDEV_STATUS;
-                       }
+
+       if (count && netif_running(netdev)) {
+               tx_ring->sw_consumer = sw_consumer;
+
+               smp_mb();
+
+               if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+                       netif_tx_lock(netdev);
+                       if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+                               netif_wake_queue(netdev);
+                       netif_tx_unlock(netdev);
                }
        }
        /*
@@ -1072,112 +1349,66 @@ int netxen_process_cmd_ring(unsigned long data)
         * There is still a possible race condition and the host could miss an
         * interrupt. The card has to take care of this.
         */
-       if (adapter->last_cmd_consumer == consumer &&
-           (((adapter->cmd_producer + 1) %
-             adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
-               consumer = *(adapter->cmd_consumer);
-       }
-       done = (adapter->last_cmd_consumer == consumer);
+       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+       done = (sw_consumer == hw_consumer);
+       spin_unlock(&adapter->tx_clean_lock);
 
-       spin_unlock(&adapter->tx_lock);
-       DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
-               __FUNCTION__);
        return (done);
 }
 
-/*
- * netxen_post_rx_buffers puts buffer in the Phantom memory
- */
-void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
+void
+netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
+       struct nx_host_rds_ring *rds_ring)
 {
-       struct pci_dev *pdev = adapter->ahw.pdev;
-       struct sk_buff *skb;
-       struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-       struct netxen_rcv_desc_ctx *rcv_desc = NULL;
-       uint producer;
        struct rcv_desc *pdesc;
        struct netxen_rx_buffer *buffer;
-       int count = 0;
-       int index = 0;
+       int producer, count = 0;
        netxen_ctx_msg msg = 0;
-       dma_addr_t dma;
+       struct list_head *head;
 
-       adapter->stats.post_called++;
-       rcv_desc = &recv_ctx->rcv_desc[ringid];
+       producer = rds_ring->producer;
 
-       producer = rcv_desc->producer;
-       index = rcv_desc->begin_alloc;
-       buffer = &rcv_desc->rx_buf_arr[index];
-       /* We can start writing rx descriptors into the phantom memory. */
-       while (buffer->state == NETXEN_BUFFER_FREE) {
-               skb = dev_alloc_skb(rcv_desc->skb_size);
-               if (unlikely(!skb)) {
-                       /*
-                        * TODO
-                        * We need to schedule the posting of buffers to the pegs.
-                        */
-                       rcv_desc->begin_alloc = index;
-                       DPRINTK(ERR, "netxen_post_rx_buffers: "
-                               " allocated only %d buffers\n", count);
-                       break;
-               }
+       spin_lock(&rds_ring->lock);
+       head = &rds_ring->free_list;
+       while (!list_empty(head)) {
 
-               count++;        /* now there should be no failure */
-               pdesc = &rcv_desc->desc_head[producer];
+               buffer = list_entry(head->next, struct netxen_rx_buffer, list);
 
-#if defined(XGB_DEBUG)
-               *(unsigned long *)(skb->head) = 0xc0debabe;
-               if (skb_is_nonlinear(skb)) {
-                       printk("Allocated SKB @%p is nonlinear\n");
+               if (!buffer->skb) {
+                       if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
+                               break;
                }
-#endif
-               skb_reserve(skb, 2);
-               /* This will be setup when we receive the
-                * buffer after it has been filled  FSL  TBD TBD
-                * skb->dev = netdev;
-                */
-               dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
-                                    PCI_DMA_FROMDEVICE);
-               pdesc->addr_buffer = dma;
-               buffer->skb = skb;
-               buffer->state = NETXEN_BUFFER_BUSY;
-               buffer->dma = dma;
+
+               count++;
+               list_del(&buffer->list);
+
                /* make a rcv descriptor  */
-               pdesc->reference_handle = buffer->ref_handle;
-               pdesc->buffer_length = rcv_desc->dma_size;
-               DPRINTK(INFO, "done writing descripter\n");
-               producer =
-                   get_next_index(producer, rcv_desc->max_rx_desc_count);
-               index = get_next_index(index, rcv_desc->max_rx_desc_count);
-               buffer = &rcv_desc->rx_buf_arr[index];
+               pdesc = &rds_ring->desc_head[producer];
+               pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+
+               producer = get_next_index(producer, rds_ring->num_desc);
        }
-       /* if we did allocate buffers, then write the count to Phantom */
+       spin_unlock(&rds_ring->lock);
+
        if (count) {
-               rcv_desc->begin_alloc = index;
-               rcv_desc->rcv_pending += count;
-               adapter->stats.lastposted = count;
-               adapter->stats.posted += count;
-               rcv_desc->producer = producer;
-               if (rcv_desc->rcv_free >= 32) {
-                       rcv_desc->rcv_free = 0;
-                       /* Window = 1 */
-                       writel((producer - 1) &
-                              (rcv_desc->max_rx_desc_count - 1),
-                              NETXEN_CRB_NORMALIZE(adapter,
-                                                   recv_crb_registers[0].
-                                                   rcv_desc_crb[ringid].
-                                                   crb_rcv_producer_offset));
+               rds_ring->producer = producer;
+               NXWR32(adapter, rds_ring->crb_rcv_producer,
+                               (producer-1) & (rds_ring->num_desc-1));
+
+               if (adapter->fw_major < 4) {
                        /*
                         * Write a doorbell msg to tell phanmon of change in
                         * receive ring producer
+                        * Only for firmware version < 4.0.0
                         */
                        netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
                        netxen_set_msg_privid(msg);
                        netxen_set_msg_count(msg,
-                                            ((producer -
-                                              1) & (rcv_desc->
-                                                    max_rx_desc_count - 1)));
-                       netxen_set_msg_ctxid(msg, 0);
+                                            ((producer - 1) &
+                                             (rds_ring->num_desc - 1)));
+                       netxen_set_msg_ctxid(msg, adapter->portnum);
                        netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
                        writel(msg,
                               DB_NORMALIZE(adapter,
@@ -1186,339 +1417,52 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
        }
 }
 
-void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx,
-                                uint32_t ringid)
+static void
+netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+               struct nx_host_rds_ring *rds_ring)
 {
-       struct pci_dev *pdev = adapter->ahw.pdev;
-       struct sk_buff *skb;
-       struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-       struct netxen_rcv_desc_ctx *rcv_desc = NULL;
-       u32 producer;
        struct rcv_desc *pdesc;
        struct netxen_rx_buffer *buffer;
-       int count = 0;
-       int index = 0;
-
-       adapter->stats.post_called++;
-       rcv_desc = &recv_ctx->rcv_desc[ringid];
-
-       producer = rcv_desc->producer;
-       index = rcv_desc->begin_alloc;
-       buffer = &rcv_desc->rx_buf_arr[index];
-       /* We can start writing rx descriptors into the phantom memory. */
-       while (buffer->state == NETXEN_BUFFER_FREE) {
-               skb = dev_alloc_skb(rcv_desc->skb_size);
-               if (unlikely(!skb)) {
-                       /*
-                        * We need to schedule the posting of buffers to the pegs.
-                        */
-                       rcv_desc->begin_alloc = index;
-                       DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
-                               " allocated only %d buffers\n", count);
-                       break;
+       int producer, count = 0;
+       struct list_head *head;
+
+       producer = rds_ring->producer;
+       if (!spin_trylock(&rds_ring->lock))
+               return;
+
+       head = &rds_ring->free_list;
+       while (!list_empty(head)) {
+
+               buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+
+               if (!buffer->skb) {
+                       if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
+                               break;
                }
-               count++;        /* now there should be no failure */
-               pdesc = &rcv_desc->desc_head[producer];
-               skb_reserve(skb, 2);
-               /* 
-                * This will be setup when we receive the
-                * buffer after it has been filled
-                * skb->dev = netdev;
-                */
-               buffer->skb = skb;
-               buffer->state = NETXEN_BUFFER_BUSY;
-               buffer->dma = pci_map_single(pdev, skb->data,
-                                            rcv_desc->dma_size,
-                                            PCI_DMA_FROMDEVICE);
+
+               count++;
+               list_del(&buffer->list);
 
                /* make a rcv descriptor  */
-               pdesc->reference_handle = le16_to_cpu(buffer->ref_handle);
-               pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size);
+               pdesc = &rds_ring->desc_head[producer];
+               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
                pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-               DPRINTK(INFO, "done writing descripter\n");
-               producer =
-                   get_next_index(producer, rcv_desc->max_rx_desc_count);
-               index = get_next_index(index, rcv_desc->max_rx_desc_count);
-               buffer = &rcv_desc->rx_buf_arr[index];
-       }
 
-       /* if we did allocate buffers, then write the count to Phantom */
-       if (count) {
-               rcv_desc->begin_alloc = index;
-               rcv_desc->rcv_pending += count;
-               adapter->stats.lastposted = count;
-               adapter->stats.posted += count;
-               rcv_desc->producer = producer;
-               if (rcv_desc->rcv_free >= 32) {
-                       rcv_desc->rcv_free = 0;
-                       /* Window = 1 */
-                       writel((producer - 1) &
-                              (rcv_desc->max_rx_desc_count - 1),
-                              NETXEN_CRB_NORMALIZE(adapter,
-                                                   recv_crb_registers[0].
-                                                   rcv_desc_crb[ringid].
-                                                   crb_rcv_producer_offset));
-                       wmb();
-               }
+               producer = get_next_index(producer, rds_ring->num_desc);
        }
-}
 
-int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
-{
-       if (find_diff_among(adapter->last_cmd_consumer,
-                           adapter->cmd_producer,
-                           adapter->max_tx_desc_count) > 0)
-               return 1;
-
-       return 0;
-}
-
-int
-netxen_nic_fill_statistics(struct netxen_adapter *adapter,
-                          struct netxen_port *port,
-                          struct netxen_statistics *netxen_stats)
-{
-       void __iomem *addr;
-
-       if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
-               netxen_nic_pci_change_crbwindow(adapter, 0);
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_BYTE_CNT,
-                                          &(netxen_stats->tx_bytes));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_FRAME_CNT,
-                                          &(netxen_stats->tx_packets));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_BYTE_CNT,
-                                          &(netxen_stats->rx_bytes));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_FRAME_CNT,
-                                          &(netxen_stats->rx_packets));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT,
-                                          &(netxen_stats->rx_errors));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT,
-                                          &(netxen_stats->rx_crc_errors));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
-                                          &(netxen_stats->
-                                            rx_long_length_error));
-               NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
-                                          &(netxen_stats->
-                                            rx_short_length_error));
-
-               netxen_nic_pci_change_crbwindow(adapter, 1);
-       } else {
-               spin_lock_bh(&adapter->tx_lock);
-               netxen_stats->tx_bytes = port->stats.txbytes;
-               netxen_stats->tx_packets = port->stats.xmitedframes +
-                   port->stats.xmitfinished;
-               netxen_stats->rx_bytes = port->stats.rxbytes;
-               netxen_stats->rx_packets = port->stats.no_rcv;
-               netxen_stats->rx_errors = port->stats.rcvdbadskb;
-               netxen_stats->tx_errors = port->stats.nocmddescriptor;
-               netxen_stats->rx_short_length_error = port->stats.uplcong;
-               netxen_stats->rx_long_length_error = port->stats.uphcong;
-               netxen_stats->rx_crc_errors = 0;
-               netxen_stats->rx_mac_errors = 0;
-               spin_unlock_bh(&adapter->tx_lock);
+       if (count) {
+               rds_ring->producer = producer;
+               NXWR32(adapter, rds_ring->crb_rcv_producer,
+                               (producer - 1) & (rds_ring->num_desc - 1));
        }
-       return 0;
+       spin_unlock(&rds_ring->lock);
 }
 
 void netxen_nic_clear_stats(struct netxen_adapter *adapter)
 {
-       struct netxen_port *port;
-       int port_num;
-
        memset(&adapter->stats, 0, sizeof(adapter->stats));
-       for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) {
-               port = adapter->port[port_num];
-               memset(&port->stats, 0, sizeof(port->stats));
-       }
-}
-
-int
-netxen_nic_clear_statistics(struct netxen_adapter *adapter,
-                           struct netxen_port *port)
-{
-       int data = 0;
-
-       netxen_nic_pci_change_crbwindow(adapter, 0);
-
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_BYTE_CNT, &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_FRAME_CNT,
-                                   &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_BYTE_CNT, &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_FRAME_CNT,
-                                   &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_AGGR_ERROR_CNT,
-                                   &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_CRC_ERROR_CNT,
-                                   &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
-                                   &data);
-       netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
-                                   &data);
-
-       netxen_nic_pci_change_crbwindow(adapter, 1);
-       netxen_nic_clear_stats(adapter);
-       return 0;
+       return;
 }
 
-int
-netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
-                   struct netxen_port *port)
-{
-       struct netxen_nic_ioctl_data data;
-       struct netxen_nic_ioctl_data *up_data;
-       int retval = 0;
-       struct netxen_statistics netxen_stats;
-
-       up_data = (void *)u_data;
-
-       DPRINTK(INFO, "doing ioctl for %p\n", adapter);
-       if (copy_from_user(&data, (void __user *)up_data, sizeof(data))) {
-               /* evil user tried to crash the kernel */
-               DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
-               retval = -EFAULT;
-               goto error_out;
-       }
-
-       /* Shouldn't access beyond legal limits of  "char u[64];" member */
-       if (!data.ptr && (data.size > sizeof(data.u))) {
-               /* evil user tried to crash the kernel */
-               DPRINTK(ERR, "bad size: %d\n", data.size);
-               retval = -EFAULT;
-               goto error_out;
-       }
-
-       switch (data.cmd) {
-       case netxen_nic_cmd_pci_read:
-               if ((retval = netxen_nic_hw_read_ioctl(adapter, data.off,
-                                                      &(data.u), data.size)))
-                       goto error_out;
-               if (copy_to_user
-                   ((void __user *)&(up_data->u), &(data.u), data.size)) {
-                       DPRINTK(ERR, "bad copy to userland: %d\n",
-                               (int)sizeof(data));
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               data.rv = 0;
-               break;
-
-       case netxen_nic_cmd_pci_write:
-               if ((retval = netxen_nic_hw_write_ioctl(adapter, data.off,
-                                                       &(data.u), data.size)))
-                       goto error_out;
-               data.rv = 0;
-               break;
-
-       case netxen_nic_cmd_pci_mem_read:
-               if (netxen_nic_pci_mem_read_ioctl(adapter, data.off, &(data.u),
-                                                 data.size)) {
-                       DPRINTK(ERR, "Failed to read the data.\n");
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               if (copy_to_user
-                   ((void __user *)&(up_data->u), &(data.u), data.size)) {
-                       DPRINTK(ERR, "bad copy to userland: %d\n",
-                               (int)sizeof(data));
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               data.rv = 0;
-               break;
-
-       case netxen_nic_cmd_pci_mem_write:
-               if ((retval = netxen_nic_pci_mem_write_ioctl(adapter, data.off,
-                                                            &(data.u),
-                                                            data.size)))
-                       goto error_out;
-               data.rv = 0;
-               break;
-
-       case netxen_nic_cmd_pci_config_read:
-               switch (data.size) {
-               case 1:
-                       data.rv = pci_read_config_byte(adapter->ahw.pdev,
-                                                      data.off,
-                                                      (char *)&(data.u));
-                       break;
-               case 2:
-                       data.rv = pci_read_config_word(adapter->ahw.pdev,
-                                                      data.off,
-                                                      (short *)&(data.u));
-                       break;
-               case 4:
-                       data.rv = pci_read_config_dword(adapter->ahw.pdev,
-                                                       data.off,
-                                                       (u32 *) & (data.u));
-                       break;
-               }
-               if (copy_to_user
-                   ((void __user *)&(up_data->u), &(data.u), data.size)) {
-                       DPRINTK(ERR, "bad copy to userland: %d\n",
-                               (int)sizeof(data));
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               break;
-
-       case netxen_nic_cmd_pci_config_write:
-               switch (data.size) {
-               case 1:
-                       data.rv = pci_write_config_byte(adapter->ahw.pdev,
-                                                       data.off,
-                                                       *(char *)&(data.u));
-                       break;
-               case 2:
-                       data.rv = pci_write_config_word(adapter->ahw.pdev,
-                                                       data.off,
-                                                       *(short *)&(data.u));
-                       break;
-               case 4:
-                       data.rv = pci_write_config_dword(adapter->ahw.pdev,
-                                                        data.off,
-                                                        *(u32 *) & (data.u));
-                       break;
-               }
-               break;
-
-       case netxen_nic_cmd_get_stats:
-               data.rv =
-                   netxen_nic_fill_statistics(adapter, port, &netxen_stats);
-               if (copy_to_user
-                   ((void __user *)(up_data->ptr), (void *)&netxen_stats,
-                    sizeof(struct netxen_statistics))) {
-                       DPRINTK(ERR, "bad copy to userland: %d\n",
-                               (int)sizeof(netxen_stats));
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               up_data->rv = data.rv;
-               break;
-
-       case netxen_nic_cmd_clear_stats:
-               data.rv = netxen_nic_clear_statistics(adapter, port);
-               up_data->rv = data.rv;
-               break;
-
-       case netxen_nic_cmd_get_version:
-               if (copy_to_user
-                   ((void __user *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
-                    sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
-                       DPRINTK(ERR, "bad copy to userland: %d\n",
-                               (int)sizeof(data));
-                       retval = -EFAULT;
-                       goto error_out;
-               }
-               break;
-
-       default:
-               DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
-               retval = -EOPNOTSUPP;
-               goto error_out;
-       }
-       put_user(data.rv, (&(up_data->rv)));
-       DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
-
-      error_out:
-       return retval;
-}