Merge branch 'master' into upstream
authorJeff Garzik <jeff@garzik.org>
Thu, 7 Dec 2006 09:57:19 +0000 (04:57 -0500)
committerJeff Garzik <jeff@garzik.org>
Thu, 7 Dec 2006 09:57:19 +0000 (04:57 -0500)
Conflicts:

drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_main.c

1  2 
drivers/net/mv643xx_eth.c
drivers/net/myri10ge/myri10ge.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/ns83820.c

@@@ -277,9 -277,11 +277,11 @@@ static void mv643xx_eth_tx_timeout(stru
   *
   * Actual routine to reset the adapter when a timeout on Tx has occurred
   */
- static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
+ static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly)
  {
-       struct mv643xx_private *mp = netdev_priv(dev);
+       struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private,
+                                                 tx_timeout_task);
+       struct net_device *dev = mp->mii.dev; /* yuck */
  
        if (!netif_running(dev))
                return;
@@@ -1098,7 -1100,7 +1100,7 @@@ static void eth_tx_fill_frag_descs(stru
                                         ETH_TX_ENABLE_INTERRUPT;
                        mp->tx_skb[tx_index] = skb;
                } else
 -                      mp->tx_skb[tx_index] = 0;
 +                      mp->tx_skb[tx_index] = NULL;
  
                desc = &mp->p_tx_desc_area[tx_index];
                desc->l4i_chk = 0;
@@@ -1134,7 -1136,7 +1136,7 @@@ static void eth_tx_submit_descs_for_skb
                eth_tx_fill_frag_descs(mp, skb);
  
                length = skb_headlen(skb);
 -              mp->tx_skb[tx_index] = 0;
 +              mp->tx_skb[tx_index] = NULL;
        } else {
                cmd_sts |= ETH_ZERO_PADDING |
                           ETH_TX_LAST_DESC |
@@@ -1360,8 -1362,7 +1362,7 @@@ static int mv643xx_eth_probe(struct pla
  #endif
  
        /* Configure the timeout task */
-       INIT_WORK(&mp->tx_timeout_task,
-                       (void (*)(void *))mv643xx_eth_tx_timeout_task, dev);
+       INIT_WORK(&mp->tx_timeout_task, mv643xx_eth_tx_timeout_task);
  
        spin_lock_init(&mp->lock);
  
@@@ -89,7 -89,7 +89,7 @@@ MODULE_LICENSE("Dual BSD/GPL")
  #define MYRI10GE_EEPROM_STRINGS_SIZE 256
  #define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
  
 -#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
 +#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
  #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
  
  struct myri10ge_rx_buffer_state {
@@@ -156,8 -156,8 +156,8 @@@ struct myri10ge_priv 
        int sram_size;
        unsigned long board_span;
        unsigned long iomem_base;
 -      u32 __iomem *irq_claim;
 -      u32 __iomem *irq_deassert;
 +      __be32 __iomem *irq_claim;
 +      __be32 __iomem *irq_deassert;
        char *mac_addr_string;
        struct mcp_cmd_response *cmd;
        dma_addr_t cmd_bus;
        dma_addr_t fw_stats_bus;
        struct pci_dev *pdev;
        int msi_enabled;
 -      unsigned int link_state;
 +      __be32 link_state;
        unsigned int rdma_tags_available;
        int intr_coal_delay;
 -      u32 __iomem *intr_coal_delay_ptr;
 +      __be32 __iomem *intr_coal_delay_ptr;
        int mtrr;
        int wake_queue;
        int stop_queue;
@@@ -273,11 -273,6 +273,11 @@@ MODULE_PARM_DESC(myri10ge_debug, "Debu
  
  #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
  
 +static inline void put_be32(__be32 val, __be32 __iomem *p)
 +{
 +      __raw_writel((__force __u32)val, (__force void __iomem *)p);
 +}
 +
  static int
  myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
                  struct myri10ge_cmd *data, int atomic)
  
        buf->response_addr.low = htonl(dma_low);
        buf->response_addr.high = htonl(dma_high);
 -      response->result = MYRI10GE_NO_RESPONSE_RESULT;
 +      response->result = htonl(MYRI10GE_NO_RESPONSE_RESULT);
        mb();
        myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
  
                 * (1ms will be enough for those commands) */
                for (sleep_total = 0;
                     sleep_total < 1000
 -                   && response->result == MYRI10GE_NO_RESPONSE_RESULT;
 +                   && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);
                     sleep_total += 10)
                        udelay(10);
        } else {
                /* use msleep for most command */
                for (sleep_total = 0;
                     sleep_total < 15
 -                   && response->result == MYRI10GE_NO_RESPONSE_RESULT;
 +                   && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);
                     sleep_total++)
                        msleep(1);
        }
@@@ -398,7 -393,7 +398,7 @@@ abort
  static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
  {
        char __iomem *submit;
 -      u32 buf[16];
 +      __be32 buf[16];
        u32 dma_low, dma_high;
        int i;
  
  
        buf[0] = htonl(dma_high);       /* confirm addr MSW */
        buf[1] = htonl(dma_low);        /* confirm addr LSW */
 -      buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
 +      buf[2] = MYRI10GE_NO_CONFIRM_DATA;      /* confirm data */
        buf[3] = htonl(dma_high);       /* dummy addr MSW */
        buf[4] = htonl(dma_low);        /* dummy addr LSW */
        buf[5] = htonl(enable); /* enable? */
@@@ -484,7 -479,7 +484,7 @@@ static int myri10ge_load_hotplug_firmwa
        }
  
        /* check id */
 -      hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
 +      hdr_offset = ntohl(*(__be32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
        if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
                dev_err(dev, "Bad firmware file\n");
                status = -EINVAL;
@@@ -555,7 -550,7 +555,7 @@@ static int myri10ge_adopt_running_firmw
  static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
  {
        char __iomem *submit;
 -      u32 buf[16];
 +      __be32 buf[16];
        u32 dma_low, dma_high, size;
        int status, i;
  
  
        buf[0] = htonl(dma_high);       /* confirm addr MSW */
        buf[1] = htonl(dma_low);        /* confirm addr LSW */
 -      buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);       /* confirm data */
 +      buf[2] = MYRI10GE_NO_CONFIRM_DATA;      /* confirm data */
  
        /* FIX: All newest firmware should un-protect the bottom of
         * the sram before handoff. However, the very first interfaces
@@@ -710,21 -705,21 +710,21 @@@ static int myri10ge_reset(struct myri10
  
        status |=
            myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
 -      mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0);
 +      mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0);
        if (!mgp->msi_enabled) {
                status |= myri10ge_send_cmd
                    (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
 -              mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0);
 +              mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
  
        }
        status |= myri10ge_send_cmd
            (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
 -      mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0);
 +      mgp->intr_coal_delay_ptr = (__iomem __be32 *) (mgp->sram + cmd.data0);
        if (status != 0) {
                dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n");
                return status;
        }
 -      __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
 +      put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
  
        /* Run a small DMA test.
         * The magic multipliers to the length tell the firmware
@@@ -791,14 -786,14 +791,14 @@@ static inline voi
  myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
                    struct mcp_kreq_ether_recv *src)
  {
 -      u32 low;
 +      __be32 low;
  
        low = src->addr_low;
 -      src->addr_low = DMA_32BIT_MASK;
 +      src->addr_low = htonl(DMA_32BIT_MASK);
        myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
        mb();
        src->addr_low = low;
 -      __raw_writel(low, &dst->addr_low);
 +      put_be32(low, &dst->addr_low);
        mb();
  }
  
@@@ -944,11 -939,11 +944,11 @@@ done
        return retval;
  }
  
 -static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
 +static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
  {
        struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
  
 -      if ((skb->protocol == ntohs(ETH_P_8021Q)) &&
 +      if ((skb->protocol == htons(ETH_P_8021Q)) &&
            (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
             vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
                skb->csum = hw_csum;
  
  static inline unsigned long
  myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
 -               int bytes, int len, int csum)
 +               int bytes, int len, __wsum csum)
  {
        dma_addr_t bus;
        struct sk_buff *skb;
  
        skb->protocol = eth_type_trans(skb, mgp->dev);
        if (mgp->csum_flag) {
 -              if ((skb->protocol == ntohs(ETH_P_IP)) ||
 -                  (skb->protocol == ntohs(ETH_P_IPV6))) {
 -                      skb->csum = ntohs((u16) csum);
 +              if ((skb->protocol == htons(ETH_P_IP)) ||
 +                  (skb->protocol == htons(ETH_P_IPV6))) {
 +                      skb->csum = csum;
                        skb->ip_summed = CHECKSUM_COMPLETE;
                } else
 -                      myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
 +                      myri10ge_vlan_ip_csum(skb, csum);
        }
  
        netif_receive_skb(skb);
@@@ -1065,12 -1060,12 +1065,12 @@@ static inline void myri10ge_clean_rx_do
        int idx = rx_done->idx;
        int cnt = rx_done->cnt;
        u16 length;
 -      u16 checksum;
 +      __wsum checksum;
  
        while (rx_done->entry[idx].length != 0 && *limit != 0) {
                length = ntohs(rx_done->entry[idx].length);
                rx_done->entry[idx].length = 0;
 -              checksum = ntohs(rx_done->entry[idx].checksum);
 +              checksum = csum_unfold(rx_done->entry[idx].checksum);
                if (length <= mgp->small_bytes)
                        rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small,
                                                 mgp->small_bytes,
@@@ -1147,7 -1142,7 +1147,7 @@@ static int myri10ge_poll(struct net_dev
  
        if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
                netif_rx_complete(netdev);
 -              __raw_writel(htonl(3), mgp->irq_claim);
 +              put_be32(htonl(3), mgp->irq_claim);
                return 0;
        }
        return 1;
@@@ -1171,7 -1166,7 +1171,7 @@@ static irqreturn_t myri10ge_intr(int ir
                netif_rx_schedule(mgp->dev);
  
        if (!mgp->msi_enabled) {
 -              __raw_writel(0, mgp->irq_deassert);
 +              put_be32(0, mgp->irq_deassert);
                if (!myri10ge_deassert_wait)
                        stats->valid = 0;
                mb();
  
        myri10ge_check_statblock(mgp);
  
 -      __raw_writel(htonl(3), mgp->irq_claim + 1);
 +      put_be32(htonl(3), mgp->irq_claim + 1);
        return (IRQ_HANDLED);
  }
  
@@@ -1238,7 -1233,7 +1238,7 @@@ myri10ge_set_coalesce(struct net_devic
        struct myri10ge_priv *mgp = netdev_priv(netdev);
  
        mgp->intr_coal_delay = coal->rx_coalesce_usecs;
 -      __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
 +      put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
        return 0;
  }
  
@@@ -1753,7 -1748,7 +1753,7 @@@ static int myri10ge_open(struct net_dev
                goto abort_with_rings;
        }
  
 -      mgp->link_state = -1;
 +      mgp->link_state = htonl(~0U);
        mgp->rdma_tags_available = 15;
  
        netif_poll_enable(mgp->dev);    /* must happen prior to any irq */
@@@ -1881,7 -1876,7 +1881,7 @@@ myri10ge_submit_req(struct myri10ge_tx_
  
        /* re-write the last 32-bits with the valid flags */
        src->flags = last_flags;
 -      __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
 +      put_be32(*((__be32 *) src + 3), (__be32 __iomem *) dst + 3);
        tx->req += cnt;
        mb();
  }
@@@ -1924,8 -1919,7 +1924,8 @@@ static int myri10ge_xmit(struct sk_buf
        struct myri10ge_tx_buf *tx = &mgp->tx;
        struct skb_frag_struct *frag;
        dma_addr_t bus;
 -      u32 low, high_swapped;
 +      u32 low;
 +      __be32 high_swapped;
        unsigned int len;
        int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
        u16 pseudo_hdr_offset, cksum_offset;
@@@ -1970,6 -1964,7 +1970,6 @@@ again
                        cksum_offset = 0;
                        pseudo_hdr_offset = 0;
                } else {
 -                      pseudo_hdr_offset = htons(pseudo_hdr_offset);
                        odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
                        flags |= MXGEFW_FLAGS_CKSUM;
                }
                /* for TSO, pseudo_hdr_offset holds mss.
                 * The firmware figures out where to put
                 * the checksum by parsing the header. */
 -              pseudo_hdr_offset = htons(mss);
 +              pseudo_hdr_offset = mss;
        } else
  #endif                                /*NETIF_F_TSO */
                /* Mark small packets, and pad out tiny packets */
  #endif                                /* NETIF_F_TSO */
                        req->addr_high = high_swapped;
                        req->addr_low = htonl(low);
 -                      req->pseudo_hdr_offset = pseudo_hdr_offset;
 +                      req->pseudo_hdr_offset = htons(pseudo_hdr_offset);
                        req->pad = 0;   /* complete solid 16-byte block; does this matter? */
                        req->rdma_count = 1;
                        req->length = htons(seglen);
@@@ -2204,7 -2199,6 +2204,7 @@@ static void myri10ge_set_multicast_list
        struct myri10ge_cmd cmd;
        struct myri10ge_priv *mgp;
        struct dev_mc_list *mc_list;
 +      __be32 data[2] = {0, 0};
        int err;
  
        mgp = netdev_priv(dev);
  
        /* Walk the multicast list, and add each address */
        for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) {
 -              memcpy(&cmd.data0, &mc_list->dmi_addr, 4);
 -              memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2);
 -              cmd.data0 = htonl(cmd.data0);
 -              cmd.data1 = htonl(cmd.data1);
 +              memcpy(data, &mc_list->dmi_addr, 6);
 +              cmd.data0 = ntohl(data[0]);
 +              cmd.data1 = ntohl(data[1]);
                err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP,
                                        &cmd, 1);
  
@@@ -2620,9 -2615,10 +2620,10 @@@ static u32 myri10ge_read_reboot(struct 
   * This watchdog is used to check whether the board has suffered
   * from a parity error and needs to be recovered.
   */
- static void myri10ge_watchdog(void *arg)
+ static void myri10ge_watchdog(struct work_struct *work)
  {
-       struct myri10ge_priv *mgp = arg;
+       struct myri10ge_priv *mgp =
+               container_of(work, struct myri10ge_priv, watchdog_work);
        u32 reboot;
        int status;
        u16 cmd, vendor;
@@@ -2892,7 -2888,7 +2893,7 @@@ static int myri10ge_probe(struct pci_de
                    (unsigned long)mgp);
  
        SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
-       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp);
+       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
        status = register_netdev(netdev);
        if (status != 0) {
                dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
@@@ -1,25 -1,25 +1,25 @@@
  /*
   * Copyright (C) 2003 - 2006 NetXen, Inc.
   * All rights reserved.
 - * 
 + *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
 - *                            
 + *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
 - *                                   
 + *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   * MA  02111-1307, USA.
 - * 
 + *
   * The full GNU General Public License is included in this distribution
   * in the file called LICENSE.
 - * 
 + *
   * Contact Information:
   *    info@netxen.com
   * NetXen,
  
  #include "netxen_nic_hw.h"
  
 -#define NETXEN_NIC_BUILD_NO     "5"
 -#define _NETXEN_NIC_LINUX_MAJOR 2
 +#define NETXEN_NIC_BUILD_NO     "1"
 +#define _NETXEN_NIC_LINUX_MAJOR 3
  #define _NETXEN_NIC_LINUX_MINOR 3
 -#define _NETXEN_NIC_LINUX_SUBVERSION 59
 -#define NETXEN_NIC_LINUX_VERSIONID  "2.3.59" "-" NETXEN_NIC_BUILD_NO
 -#define NETXEN_NIC_FW_VERSIONID "2.3.59"
 +#define _NETXEN_NIC_LINUX_SUBVERSION 2
 +#define NETXEN_NIC_LINUX_VERSIONID  "3.3.2" "-" NETXEN_NIC_BUILD_NO
 +#define NETXEN_NIC_FW_VERSIONID "3.3.2"
  
  #define RCV_DESC_RINGSIZE     \
        (sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
  #define STATUS_DESC_RINGSIZE  \
        (sizeof(struct status_desc)* adapter->max_rx_desc_count)
 +#define LRO_DESC_RINGSIZE     \
 +      (sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count)
  #define TX_RINGSIZE   \
        (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
  #define RCV_BUFFSIZE  \
        (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
  #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
  
 -#define NETXEN_NETDEV_STATUS 0x1
 +#define NETXEN_NETDEV_STATUS          0x1
 +#define NETXEN_RCV_PRODUCER_OFFSET    0
 +#define NETXEN_RCV_PEG_DB_ID          2
 +#define NETXEN_HOST_DUMMY_DMA_SIZE 1024
  
  #define ADDR_IN_WINDOW1(off)  \
        ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0
 +/*
 + * In netxen_nic_down(), we must wait for any pending callback requests into
 + * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
 + * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK()
 + * does this synchronization.
 + *
 + * Normally, schedule_work()/flush_scheduled_work() could have worked, but
 + * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
 + * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
 + * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
 + * linkwatch_event() to be executed which also attempts to acquire the rtnl
 + * lock thus causing a deadlock.
 + */
 +
 +#define SCHEDULE_WORK(tp)     queue_work(netxen_workq, tp)
 +#define FLUSH_SCHEDULED_WORK()        flush_workqueue(netxen_workq)
 +extern struct workqueue_struct *netxen_workq;
  
  /* 
   * normalize a 64MB crb address to 32MB PCI window 
   * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1
   */
 -#define NETXEN_CRB_NORMAL(reg)        \
 -      (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST
 +#define NETXEN_CRB_NORMAL(reg)        \
 +      ((reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST)
  
  #define NETXEN_CRB_NORMALIZE(adapter, reg) \
        pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg))
  
 +#define DB_NORMALIZE(adapter, off) \
 +      (adapter->ahw.db_base + (off))
 +
 +#define NX_P2_C0              0x24
 +#define NX_P2_C1              0x25
 +
  #define FIRST_PAGE_GROUP_START        0
 -#define FIRST_PAGE_GROUP_END  0x400000
 +#define FIRST_PAGE_GROUP_END  0x100000
  
  #define SECOND_PAGE_GROUP_START       0x4000000
  #define SECOND_PAGE_GROUP_END 0x66BC000
  #define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
  #define THIRD_PAGE_GROUP_SIZE  THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
  
 -#define MAX_RX_BUFFER_LENGTH          2000
 +#define MAX_RX_BUFFER_LENGTH          1760
  #define MAX_RX_JUMBO_BUFFER_LENGTH    9046
 -#define RX_DMA_MAP_LEN                        (MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN)
 +#define MAX_RX_LRO_BUFFER_LENGTH      ((48*1024)-512)
 +#define RX_DMA_MAP_LEN                        (MAX_RX_BUFFER_LENGTH - 2)
  #define RX_JUMBO_DMA_MAP_LEN  \
 -      (MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN)
 +      (MAX_RX_JUMBO_BUFFER_LENGTH - 2)
 +#define RX_LRO_DMA_MAP_LEN            (MAX_RX_LRO_BUFFER_LENGTH - 2)
  #define NETXEN_ROM_ROUNDUP            0x80000000ULL
  
  /*
@@@ -181,38 -151,30 +181,38 @@@ enum 
  /* Host writes the following to notify that it has done the init-handshake */
  #define PHAN_INITIALIZE_ACK   0xf00f
  
 -#define NUM_RCV_DESC_RINGS    2       /* No of Rcv Descriptor contexts */
 +#define NUM_RCV_DESC_RINGS    3       /* No of Rcv Descriptor contexts */
  
  /* descriptor types */
  #define RCV_DESC_NORMAL               0x01
  #define RCV_DESC_JUMBO                0x02
 +#define RCV_DESC_LRO          0x04
  #define RCV_DESC_NORMAL_CTXID 0
  #define RCV_DESC_JUMBO_CTXID  1
 +#define RCV_DESC_LRO_CTXID    2
  
  #define RCV_DESC_TYPE(ID) \
 -      ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL)
 +      ((ID == RCV_DESC_JUMBO_CTXID)   \
 +              ? RCV_DESC_JUMBO        \
 +              : ((ID == RCV_DESC_LRO_CTXID)   \
 +                      ? RCV_DESC_LRO :        \
 +                      (RCV_DESC_NORMAL)))
  
  #define MAX_CMD_DESCRIPTORS           1024
  #define MAX_RCV_DESCRIPTORS           32768
 -#define MAX_JUMBO_RCV_DESCRIPTORS     1024
 +#define MAX_JUMBO_RCV_DESCRIPTORS     4096
 +#define MAX_LRO_RCV_DESCRIPTORS               2048
  #define MAX_RCVSTATUS_DESCRIPTORS     MAX_RCV_DESCRIPTORS
  #define MAX_JUMBO_RCV_DESC    MAX_JUMBO_RCV_DESCRIPTORS
  #define MAX_RCV_DESC          MAX_RCV_DESCRIPTORS
  #define MAX_RCVSTATUS_DESC    MAX_RCV_DESCRIPTORS
 -#define NUM_RCV_DESC          (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS)
  #define MAX_EPG_DESCRIPTORS   (MAX_CMD_DESCRIPTORS * 8)
 -
 +#define NUM_RCV_DESC          (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \
 +                               MAX_LRO_RCV_DESCRIPTORS)
  #define MIN_TX_COUNT  4096
  #define MIN_RX_COUNT  4096
 -
 +#define NETXEN_CTX_SIGNATURE  0xdee0
 +#define NETXEN_RCV_PRODUCER(ringid)   (ringid)
  #define MAX_FRAME_SIZE        0x10000 /* 64K MAX size for LSO */
  
  #define PHAN_PEG_RCV_INITIALIZED      0xff01
  #define get_index_range(index,length,count)   \
        (((index) + (count)) & ((length) - 1))
  
 +#define MPORT_SINGLE_FUNCTION_MODE 0x1111
 +
 +extern unsigned long long netxen_dma_mask;
 +
 +/*
 + * NetXen host-peg signal message structure
 + *
 + *    Bit 0-1         : peg_id => 0x2 for tx and 01 for rx
 + *    Bit 2           : priv_id => must be 1
 + *    Bit 3-17        : count => for doorbell
 + *    Bit 18-27       : ctx_id => Context id
 + *    Bit 28-31       : opcode
 + */
 +
 +typedef u32 netxen_ctx_msg;
 +
 +#define _netxen_set_bits(config_word, start, bits, val)       {\
 +      unsigned long long mask = (((1ULL << (bits)) - 1) << (start));  \
 +      unsigned long long value = (val);       \
 +      (config_word) &= ~mask; \
 +      (config_word) |= (((value) << (start)) & mask); \
 +}
 +
 +#define netxen_set_msg_peg_id(config_word, val)       \
 +      _netxen_set_bits(config_word, 0, 2, val)
 +#define netxen_set_msg_privid(config_word)    \
 +      set_bit(2, (unsigned long*)&config_word)
 +#define netxen_set_msg_count(config_word, val)        \
 +      _netxen_set_bits(config_word, 3, 15, val)
 +#define netxen_set_msg_ctxid(config_word, val)        \
 +      _netxen_set_bits(config_word, 18, 10, val)
 +#define netxen_set_msg_opcode(config_word, val)       \
 +      _netxen_set_bits(config_word, 28, 4, val)
 +
 +struct netxen_rcv_context {
 +      u32 rcv_ring_addr_lo;
 +      u32 rcv_ring_addr_hi;
 +      u32 rcv_ring_size;
 +      u32 rsrvd;
 +};
 +
 +struct netxen_ring_ctx {
 +
 +      /* one command ring */
 +      u64 cmd_consumer_offset;
 +      u32 cmd_ring_addr_lo;
 +      u32 cmd_ring_addr_hi;
 +      u32 cmd_ring_size;
 +      u32 rsrvd;
 +
 +      /* three receive rings */
 +      struct netxen_rcv_context rcv_ctx[3];
 +
 +      /* one status ring */
 +      u32 sts_ring_addr_lo;
 +      u32 sts_ring_addr_hi;
 +      u32 sts_ring_size;
 +
 +      u32 ctx_id;
 +} __attribute__ ((aligned(64)));
 +
  /*
   * Following data structures describe the descriptors that will be used.
   * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
  #define FLAGS_IPSEC_SA_DELETE 0x08
  #define FLAGS_VLAN_TAGGED     0x10
  
 -#define CMD_DESC_TOTAL_LENGTH(cmd_desc)       \
 -              ((cmd_desc)->length_tcp_hdr & 0x00FFFFFF)
 -#define CMD_DESC_TCP_HDR_OFFSET(cmd_desc)     \
 -              (((cmd_desc)->length_tcp_hdr >> 24) & 0x0FF)
 -#define CMD_DESC_PORT(cmd_desc)               ((cmd_desc)->port_ctxid & 0x0F)
 -#define CMD_DESC_CTX_ID(cmd_desc)     (((cmd_desc)->port_ctxid >> 4) & 0x0F)
 +#define netxen_set_cmd_desc_port(cmd_desc, var)       \
 +      ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
  
 -#define CMD_DESC_TOTAL_LENGTH_WRT(cmd_desc, var)      \
 -              ((cmd_desc)->length_tcp_hdr |= ((var) & 0x00FFFFFF))
 -#define CMD_DESC_TCP_HDR_OFFSET_WRT(cmd_desc, var)    \
 -              ((cmd_desc)->length_tcp_hdr |= (((var) << 24) & 0xFF000000))
 -#define CMD_DESC_PORT_WRT(cmd_desc, var)      \
 -              ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
 +#define netxen_set_cmd_desc_flags(cmd_desc, val)      \
 +      _netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val)
 +#define netxen_set_cmd_desc_opcode(cmd_desc, val)     \
 +      _netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val)
 +
 +#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val)        \
 +      _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val);
 +#define netxen_set_cmd_desc_totallength(cmd_desc, val)        \
 +      _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val);
 +
 +#define netxen_get_cmd_desc_opcode(cmd_desc)  \
 +      (((cmd_desc)->flags_opcode >> 7) & 0x003F)
 +#define netxen_get_cmd_desc_totallength(cmd_desc)     \
 +      (((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF)
  
  struct cmd_desc_type0 {
 -      u64 netxen_next;        /* for fragments handled by Phantom */
 +      u8 tcp_hdr_offset;      /* For LSO only */
 +      u8 ip_hdr_offset;       /* For LSO only */
 +      /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
 +      u16 flags_opcode;
 +      /* Bit pattern: 0-7 total number of segments,
 +         8-31 Total size of the packet */
 +      u32 num_of_buffers_total_length;
        union {
                struct {
                        u32 addr_low_part2;
                u64 addr_buffer2;
        };
  
 -      /* Bit pattern: 0-23 total length, 24-32 tcp header offset */
 -      u32 length_tcp_hdr;
 -      u8 ip_hdr_offset;       /* For LSO only */
 -      u8 num_of_buffers;      /* total number of segments */
 -      u8 flags;               /* as defined above */
 -      u8 opcode;
 -
        u16 reference_handle;   /* changed to u16 to add mss */
        u16 mss;                /* passed by NDIS_PACKET for LSO */
        /* Bit pattern 0-3 port, 0-3 ctx id */
                };
                u64 addr_buffer3;
        };
 -
        union {
                struct {
                        u32 addr_low_part1;
                u64 addr_buffer4;
        };
  
 +      u64 unused;
 +
  } __attribute__ ((aligned(64)));
  
  /* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
@@@ -399,49 -296,22 +399,49 @@@ struct rcv_desc 
  #define NETXEN_PROT_UNKNOWN   (0)
  
  /* Note: sizeof(status_desc) should always be a mutliple of 2 */
 -#define STATUS_DESC_PORT(status_desc) \
 -              ((status_desc)->port_status_type_op & 0x0F)
 -#define STATUS_DESC_STATUS(status_desc)       \
 -              (((status_desc)->port_status_type_op >> 4) & 0x0F)
 -#define STATUS_DESC_TYPE(status_desc) \
 -              (((status_desc)->port_status_type_op >> 8) & 0x0F)
 -#define STATUS_DESC_OPCODE(status_desc)       \
 -              (((status_desc)->port_status_type_op >> 12) & 0x0F)
 +
 +#define netxen_get_sts_desc_lro_cnt(status_desc)      \
 +      ((status_desc)->lro & 0x7F)
 +#define netxen_get_sts_desc_lro_last_frag(status_desc)        \
 +      (((status_desc)->lro & 0x80) >> 7)
 +
 +#define netxen_get_sts_port(status_desc)      \
 +      ((status_desc)->status_desc_data & 0x0F)
 +#define netxen_get_sts_status(status_desc)    \
 +      (((status_desc)->status_desc_data >> 4) & 0x0F)
 +#define netxen_get_sts_type(status_desc)      \
 +      (((status_desc)->status_desc_data >> 8) & 0x0F)
 +#define netxen_get_sts_totallength(status_desc)       \
 +      (((status_desc)->status_desc_data >> 12) & 0xFFFF)
 +#define netxen_get_sts_refhandle(status_desc) \
 +      (((status_desc)->status_desc_data >> 28) & 0xFFFF)
 +#define netxen_get_sts_prot(status_desc)      \
 +      (((status_desc)->status_desc_data >> 44) & 0x0F)
 +#define netxen_get_sts_owner(status_desc)     \
 +      (((status_desc)->status_desc_data >> 56) & 0x03)
 +#define netxen_get_sts_opcode(status_desc)    \
 +      (((status_desc)->status_desc_data >> 58) & 0x03F)
 +
 +#define netxen_clear_sts_owner(status_desc)   \
 +      ((status_desc)->status_desc_data &=     \
 +      ~(((unsigned long long)3) << 56 ))
 +#define netxen_set_sts_owner(status_desc, val)        \
 +      ((status_desc)->status_desc_data |=     \
 +      (((unsigned long long)((val) & 0x3)) << 56 ))
  
  struct status_desc {
 -      /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-15 opcode */
 -      u16 port_status_type_op;
 -      u16 total_length;       /* NIC mode */
 -      u16 reference_handle;   /* handle for the associated packet */
 -      /* Bit pattern: 0-1 owner, 2-5 protocol */
 -      u16 owner;              /* Owner of the descriptor */
 +      /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
 +         28-43 reference_handle, 44-47 protocol, 48-52 unused
 +         53-55 desc_cnt, 56-57 owner, 58-63 opcode
 +       */
 +      u64 status_desc_data;
 +      u32 hash_value;
 +      u8 hash_type;
 +      u8 msg_type;
 +      u8 unused;
 +      /* Bit pattern: 0-6 lro_count indicates frag sequence,
 +         7 last_frag indicates last frag */
 +      u8 lro;
  } __attribute__ ((aligned(8)));
  
  enum {
@@@ -689,12 -559,11 +689,12 @@@ typedef enum 
  #define PRIMARY_START                 (BOOTLD_START)
  #define FLASH_CRBINIT_SIZE    (0x4000)
  #define FLASH_BRDCFG_SIZE     (sizeof(struct netxen_board_info))
 -#define FLASH_USER_SIZE               (sizeof(netxen_user_info)/sizeof(u32))
 +#define FLASH_USER_SIZE               (sizeof(struct netxen_user_info)/sizeof(u32))
  #define FLASH_SECONDARY_SIZE  (USER_START-SECONDARY_START)
  #define NUM_PRIMARY_SECTORS   (0x20)
  #define NUM_CONFIG_SECTORS    (1)
 -#define PFX "netxen: "
 +#define PFX "NetXen: "
 +extern char netxen_nic_driver_name[];
  
  /* Note: Make sure to not call this before adapter->port is valid */
  #if !defined(NETXEN_DEBUG)
  #else
  #define DPRINTK(klevel, fmt, args...) do { \
        printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
 -              (adapter != NULL && adapter->port != NULL && \
 +              (adapter != NULL && \
                adapter->port[0] != NULL && \
                adapter->port[0]->netdev != NULL) ? \
                adapter->port[0]->netdev->name : NULL, \
@@@ -740,6 -609,7 +740,6 @@@ struct netxen_cmd_buffer 
        u8 frag_count;
        unsigned long time_stamp;
        u32 state;
 -      u32 no_of_descriptors;
  };
  
  /* In rx_buffer, we do not need multiple fragments as is a single buffer */
@@@ -748,9 -618,6 +748,9 @@@ struct netxen_rx_buffer 
        u64 dma;
        u16 ref_handle;
        u16 state;
 +      u32 lro_expected_frags;
 +      u32 lro_current_frags;
 +      u32 lro_length;
  };
  
  /* Board types */
@@@ -766,8 -633,6 +766,8 @@@ struct netxen_hardware_context 
        void __iomem *pci_base0;
        void __iomem *pci_base1;
        void __iomem *pci_base2;
 +      void __iomem *db_base;
 +      unsigned long db_len;
  
        u8 revision_id;
        u16 board_type;
        u32 qg_linksup;
        /* Address of cmd ring in Phantom */
        struct cmd_desc_type0 *cmd_desc_head;
 -      char *pauseaddr;
        struct pci_dev *cmd_desc_pdev;
        dma_addr_t cmd_desc_phys_addr;
 -      dma_addr_t pause_physaddr;
 -      struct pci_dev *pause_pdev;
        struct netxen_adapter *adapter;
  };
  
 +#define RCV_RING_LRO  RCV_DESC_LRO
 +
  #define MINIMUM_ETHERNET_FRAME_SIZE   64      /* With FCS */
  #define ETHERNET_FCS_SIZE             4
  
@@@ -836,13 -702,8 +836,13 @@@ struct netxen_recv_context 
  };
  
  #define NETXEN_NIC_MSI_ENABLED 0x02
 +#define NETXEN_DMA_MASK       0xfffffffe
 +#define NETXEN_DB_MAPSIZE_BYTES    0x1000
  
 -struct netxen_drvops;
 +struct netxen_dummy_dma {
 +      void *addr;
 +      dma_addr_t phys_addr;
 +};
  
  struct netxen_adapter {
        struct netxen_hardware_context ahw;
        spinlock_t tx_lock;
        spinlock_t lock;
        struct work_struct watchdog_task;
-       struct work_struct tx_timeout_task[NETXEN_MAX_PORTS];
+       struct work_struct tx_timeout_task;
+       struct net_device *netdev;
        struct timer_list watchdog_timer;
  
        u32 curr_window;
  
        u32 cmd_producer;
 -      u32 cmd_consumer;
 +      u32 *cmd_consumer;
  
        u32 last_cmd_consumer;
        u32 max_tx_desc_count;
        u32 max_rx_desc_count;
        u32 max_jumbo_rx_desc_count;
 +      u32 max_lro_rx_desc_count;
        /* Num of instances active on cmd buffer ring */
        u32 proc_cmd_buf_counter;
  
        struct netxen_recv_context recv_ctx[MAX_RCV_CTX];
  
        int is_up;
 -      int work_done;
 -      struct netxen_drvops *ops;
 +      int number;
 +      struct netxen_dummy_dma dummy_dma;
 +
 +      /* Context interface shared between card and host */
 +      struct netxen_ring_ctx *ctx_desc;
 +      struct pci_dev *ctx_desc_pdev;
 +      dma_addr_t ctx_desc_phys_addr;
 +      int (*enable_phy_interrupts) (struct netxen_adapter *, int);
 +      int (*disable_phy_interrupts) (struct netxen_adapter *, int);
 +      void (*handle_phy_intr) (struct netxen_adapter *);
 +      int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t);
 +      int (*set_mtu) (struct netxen_port *, int);
 +      int (*set_promisc) (struct netxen_adapter *, int,
 +                          netxen_niu_prom_mode_t);
 +      int (*unset_promisc) (struct netxen_adapter *, int,
 +                            netxen_niu_prom_mode_t);
 +      int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *);
 +      int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val);
 +      int (*init_port) (struct netxen_adapter *, int);
 +      void (*init_niu) (struct netxen_adapter *);
 +      int (*stop_port) (struct netxen_adapter *, int);
  };                            /* netxen_adapter structure */
  
  /* Max number of xmit producer threads that can run simultaneously */
@@@ -988,6 -830,25 +989,6 @@@ static inline void __iomem *pci_base(st
        return NULL;
  }
  
 -struct netxen_drvops {
 -      int (*enable_phy_interrupts) (struct netxen_adapter *, int);
 -      int (*disable_phy_interrupts) (struct netxen_adapter *, int);
 -      void (*handle_phy_intr) (struct netxen_adapter *);
 -      int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t);
 -      int (*set_mtu) (struct netxen_port *, int);
 -      int (*set_promisc) (struct netxen_adapter *, int,
 -                          netxen_niu_prom_mode_t);
 -      int (*unset_promisc) (struct netxen_adapter *, int,
 -                            netxen_niu_prom_mode_t);
 -      int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *);
 -      int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val);
 -      int (*init_port) (struct netxen_adapter *, int);
 -      void (*init_niu) (struct netxen_adapter *);
 -      int (*stop_port) (struct netxen_adapter *, int);
 -};
 -
 -extern char netxen_nic_driver_name[];
 -
  int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter,
                                          int port);
  int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
@@@ -1026,20 -887,10 +1027,20 @@@ int netxen_nic_hw_read_wx(struct netxen
                          int len);
  int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
                           int len);
 +int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
 +                           void *data, int len);
 +int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
 +                            void *data, int len);
 +int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter,
 +                                 u64 off, void *data, int size);
 +int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
 +                                u64 off, void *data, int size);
  void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
                                 unsigned long off, int data);
  
  /* Functions from netxen_nic_init.c */
 +void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 +int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
  void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
  void netxen_load_firmware(struct netxen_adapter *adapter);
  int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
@@@ -1071,12 -922,10 +1072,12 @@@ netxen_nic_do_ioctl(struct netxen_adapt
                    struct netxen_port *port);
  int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
  int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
- void netxen_watchdog_task(unsigned long v);
+ void netxen_watchdog_task(struct work_struct *work);
  void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
                            u32 ringid);
 -void netxen_process_cmd_ring(unsigned long data);
 +void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, u32 ctx,
 +                               u32 ringid);
 +int netxen_process_cmd_ring(unsigned long data);
  u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
  void netxen_nic_set_multi(struct net_device *netdev);
  int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
@@@ -1170,6 -1019,7 +1171,6 @@@ static inline void get_brd_name_by_type
  
  int netxen_is_flash_supported(struct netxen_adapter *adapter);
  int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
 -
  extern void netxen_change_ringparam(struct netxen_adapter *adapter);
  extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
                                int *valp);
@@@ -1,25 -1,25 +1,25 @@@
  /*
   * Copyright (C) 2003 - 2006 NetXen, Inc.
   * All rights reserved.
 - * 
 + *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
 - *                            
 + *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
 - *                                   
 + *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   * MA  02111-1307, USA.
 - * 
 + *
   * The full GNU General Public License is included in this distribution
   * in the file called LICENSE.
 - * 
 + *
   * Contact Information:
   *    info@netxen.com
   * NetXen,
@@@ -137,8 -137,6 +137,8 @@@ int netxen_init_firmware(struct netxen_
                return err;
        }
        /* 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));
  
@@@ -186,12 -184,15 +186,12 @@@ void netxen_initialize_adapter_sw(struc
                        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++;
                        }
                }
        }
 -      DPRINTK(INFO, "initialized buffers for %s and %s\n",
 -              "adapter->free_cmd_buf_list", "adapter->free_rxbuf");
  }
  
  void netxen_initialize_adapter_hw(struct netxen_adapter *adapter)
  
  void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
  {
 -      struct netxen_drvops *ops = adapter->ops;
        switch (adapter->ahw.board_type) {
        case NETXEN_NIC_GBE:
 -              ops->enable_phy_interrupts =
 +              adapter->enable_phy_interrupts =
                    netxen_niu_gbe_enable_phy_interrupts;
 -              ops->disable_phy_interrupts =
 +              adapter->disable_phy_interrupts =
                    netxen_niu_gbe_disable_phy_interrupts;
 -              ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
 -              ops->macaddr_set = netxen_niu_macaddr_set;
 -              ops->set_mtu = netxen_nic_set_mtu_gb;
 -              ops->set_promisc = netxen_niu_set_promiscuous_mode;
 -              ops->unset_promisc = netxen_niu_set_promiscuous_mode;
 -              ops->phy_read = netxen_niu_gbe_phy_read;
 -              ops->phy_write = netxen_niu_gbe_phy_write;
 -              ops->init_port = netxen_niu_gbe_init_port;
 -              ops->init_niu = netxen_nic_init_niu_gb;
 -              ops->stop_port = netxen_niu_disable_gbe_port;
 +              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;
  
        case NETXEN_NIC_XGBE:
 -              ops->enable_phy_interrupts =
 +              adapter->enable_phy_interrupts =
                    netxen_niu_xgbe_enable_phy_interrupts;
 -              ops->disable_phy_interrupts =
 +              adapter->disable_phy_interrupts =
                    netxen_niu_xgbe_disable_phy_interrupts;
 -              ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
 -              ops->macaddr_set = netxen_niu_xg_macaddr_set;
 -              ops->set_mtu = netxen_nic_set_mtu_xgb;
 -              ops->init_port = netxen_niu_xg_init_port;
 -              ops->set_promisc = netxen_niu_xg_set_promiscuous_mode;
 -              ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
 -              ops->stop_port = netxen_niu_disable_xg_port;
 +              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:
@@@ -381,8 -383,8 +381,8 @@@ int netxen_rom_wip_poll(struct netxen_a
        return 0;
  }
  
 -static inline int do_rom_fast_write(struct netxen_adapter *adapter,
 -                                  int addr, int data)
 +static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
 +                                  int data)
  {
        if (netxen_rom_wren(adapter)) {
                return -1;
@@@ -620,43 -622,6 +620,43 @@@ int netxen_pinit_from_rom(struct netxen
        return 0;
  }
  
 +int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 +{
 +      uint64_t addr;
 +      uint32_t hi;
 +      uint32_t lo;
 +
 +      adapter->dummy_dma.addr =
 +          pci_alloc_consistent(adapter->ahw.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__);
 +              return -ENOMEM;
 +      }
 +
 +      addr = (uint64_t) adapter->dummy_dma.phys_addr;
 +      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));
 +
 +      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);
 +              adapter->dummy_dma.addr = NULL;
 +      }
 +}
 +
  void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
  {
        u32 val = 0;
@@@ -691,8 -656,7 +691,8 @@@ int netxen_nic_rx_has_work(struct netxe
                desc_head = recv_ctx->rcv_status_desc_head;
                desc = &desc_head[consumer];
  
 -              if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST))
 +              if (((le16_to_cpu(netxen_get_sts_owner(desc)))
 +                   & STATUS_OWNER_HOST))
                        return 1;
        }
  
@@@ -746,12 -710,13 +746,13 @@@ static inline int netxen_nic_check_temp
        return rv;
  }
  
- void netxen_watchdog_task(unsigned long v)
+ void netxen_watchdog_task(struct work_struct *work)
  {
        int port_num;
        struct netxen_port *port;
        struct net_device *netdev;
-       struct netxen_adapter *adapter = (struct netxen_adapter *)v;
+       struct netxen_adapter *adapter =
+               container_of(work, struct netxen_adapter, watchdog_task);
  
        if (netxen_nic_check_temp(adapter))
                return;
                        netif_wake_queue(netdev);
        }
  
 -      if (adapter->ops->handle_phy_intr)
 -              adapter->ops->handle_phy_intr(adapter);
 +      if (adapter->handle_phy_intr)
 +              adapter->handle_phy_intr(adapter);
        mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
  }
  
@@@ -784,19 -749,19 +785,19 @@@ voi
  netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
                   struct status_desc *desc)
  {
 -      struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)];
 +      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(desc->reference_handle);
 +      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(desc->total_length);
 +      u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
        u32 desc_ctx;
        struct netxen_rcv_desc_ctx *rcv_desc;
        int ret;
  
 -      desc_ctx = STATUS_DESC_TYPE(desc);
 +      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);
        }
  
        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;
 +              }
 +      }
  
        pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
                         PCI_DMA_FROMDEVICE);
  
        skb = (struct sk_buff *)buffer->skb;
  
 -      if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) {
 +      if (likely(netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) {
                port->stats.csummed++;
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 -      } else
 -              skb->ip_summed = CHECKSUM_NONE;
 +      }
        skb->dev = netdev;
 -      skb_put(skb, length);
 +      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);
 +      }
 +
        skb->protocol = eth_type_trans(skb, netdev);
  
        ret = netif_receive_skb(skb);
        adapter->stats.post_called++;
        buffer->skb = NULL;
        buffer->state = NETXEN_BUFFER_FREE;
 +      buffer->lro_current_frags = 0;
 +      buffer->lro_expected_frags = 0;
  
        port->stats.no_rcv++;
        port->stats.rxbytes += length;
@@@ -906,7 -840,6 +907,7 @@@ u32 netxen_process_rcv_ring(struct netx
        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");
         */
        while (count < max) {
                desc = &desc_head[consumer];
 -              if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) {
 -                      DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner);
 +              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));
                        break;
                }
                netxen_process_rcv(adapter, ctxid, desc);
 -              desc->owner = STATUS_OWNER_PHANTOM;
 +              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(adapter, ctxid, ring);
 +                      netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
                }
        }
  
        if (count) {
                adapter->stats.process_rcv++;
                recv_ctx->status_rx_consumer = consumer;
 +              recv_ctx->status_rx_producer = producer;
  
                /* Window = 1 */
                writel(consumer,
  }
  
  /* Process Command status ring */
 -void netxen_process_cmd_ring(unsigned long data)
 +int netxen_process_cmd_ring(unsigned long data)
  {
        u32 last_consumer;
        u32 consumer;
        struct netxen_adapter *adapter = (struct netxen_adapter *)data;
 -      int count = 0;
 +      int count1 = 0;
 +      int count2 = 0;
        struct netxen_cmd_buffer *buffer;
        struct netxen_port *port;       /* port #1 */
        struct netxen_port *nport;
        u32 i;
        struct sk_buff *skb = NULL;
        int p;
 +      int done;
  
        spin_lock(&adapter->tx_lock);
        last_consumer = adapter->last_cmd_consumer;
         * number as part of the descriptor. This way we will be able to get
         * the netdev which is associated with that device.
         */
 -      consumer =
 -          readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
  
 +      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);
 -              return;
 +              return 1;
        }
  
        adapter->proc_cmd_buf_counter++;
         */
        spin_unlock(&adapter->tx_lock);
  
 -      while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) {
 +      while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) {
                buffer = &adapter->cmd_buf_arr[last_consumer];
                port = adapter->port[buffer->port];
                pdev = port->pdev;
                             && netif_carrier_ok(port->netdev))
                    && ((jiffies - port->netdev->trans_start) >
                        port->netdev->watchdog_timeo)) {
 -                      schedule_work(&port->adapter->tx_timeout_task);
 +                      SCHEDULE_WORK(port->adapter->tx_timeout_task
 +                                    + port->portnum);
                }
  
                last_consumer = get_next_index(last_consumer,
                                               adapter->max_tx_desc_count);
 -              count++;
 +              count1++;
        }
 -      adapter->stats.noxmitdone += count;
 +      adapter->stats.noxmitdone += count1;
  
 -      count = 0;
 +      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)
 -                     && (count < MAX_STATUS_HANDLE)) {
 +                     && (count2 < MAX_STATUS_HANDLE)) {
                        buffer =
                            &adapter->cmd_buf_arr[adapter->last_cmd_consumer];
 -                      count++;
 +                      count2++;
                        if (buffer->skb)
                                break;
                        else
                                                   adapter->max_tx_desc_count);
                }
        }
 -      if (count) {
 +      if (count1 || count2) {
                for (p = 0; p < adapter->ahw.max_ports; p++) {
                        nport = adapter->port[p];
                        if (netif_queue_stopped(nport->netdev)
                        }
                }
        }
 +      /*
 +       * If everything is freed up to consumer then check if the ring is full
 +       * If the ring is full then check if more needs to be freed and
 +       * schedule the call back again.
 +       *
 +       * This happens when there are 2 CPUs. One could be freeing and the
 +       * other filling it. If the ring is full when we get out of here and
 +       * the card has already interrupted the host then the host can miss the
 +       * interrupt.
 +       *
 +       * 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);
  
        spin_unlock(&adapter->tx_lock);
        DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
                __FUNCTION__);
 +      return (done);
  }
  
  /*
@@@ -1094,16 -1000,17 +1095,16 @@@ void netxen_post_rx_buffers(struct netx
        struct sk_buff *skb;
        struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
        struct netxen_rcv_desc_ctx *rcv_desc = NULL;
 -      struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx];
 -      struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
 -      u32 producer;
 +      uint producer;
        struct rcv_desc *pdesc;
        struct netxen_rx_buffer *buffer;
        int count = 0;
        int index = 0;
 +      netxen_ctx_msg msg = 0;
 +      dma_addr_t dma;
  
        adapter->stats.post_called++;
        rcv_desc = &recv_ctx->rcv_desc[ringid];
 -      rcv_desc_crb = &crbarea->rcv_desc_crb[ringid];
  
        producer = rcv_desc->producer;
        index = rcv_desc->begin_alloc;
                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;
                                " allocated only %d buffers\n", count);
                        break;
                }
 +
                count++;        /* now there should be no failure */
                pdesc = &rcv_desc->desc_head[producer];
 -              skb_reserve(skb, NET_IP_ALIGN);
 +
 +#if defined(XGB_DEBUG)
 +              *(unsigned long *)(skb->head) = 0xc0debabe;
 +              if (skb_is_nonlinear(skb)) {
 +                      printk("Allocated SKB @%p is nonlinear\n");
 +              }
 +#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;
 +              /* 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];
 +      }
 +      /* 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));
 +                      /*
 +                       * Write a doorbell msg to tell phanmon of change in
 +                       * receive ring producer
 +                       */
 +                      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);
 +                      netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
 +                      writel(msg,
 +                             DB_NORMALIZE(adapter,
 +                                          NETXEN_RCV_PRODUCER_OFFSET));
 +              }
 +      }
 +}
 +
 +void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx,
 +                               uint32_t ringid)
 +{
 +      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;
 +              }
 +              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
                buffer->dma = pci_map_single(pdev, skb->data,
                                             rcv_desc->dma_size,
                                             PCI_DMA_FROMDEVICE);
 +
                /* make a rcv descriptor  */
                pdesc->reference_handle = le16_to_cpu(buffer->ref_handle);
                pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size);
                        writel((producer - 1) &
                               (rcv_desc->max_rx_desc_count - 1),
                               NETXEN_CRB_NORMALIZE(adapter,
 -                                                  rcv_desc_crb->
 +                                                  recv_crb_registers[0].
 +                                                  rcv_desc_crb[ringid].
                                                    crb_rcv_producer_offset));
                        wmb();
                }
@@@ -1389,8 -1197,8 +1390,8 @@@ netxen_nic_do_ioctl(struct netxen_adapt
  
        switch (data.cmd) {
        case netxen_nic_cmd_pci_read:
 -              if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
 -                                                  &(data.u), data.size)))
 +              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)) {
                break;
  
        case netxen_nic_cmd_pci_write:
 -              data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
 -                                               data.size);
 +              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:
                retval = -EOPNOTSUPP;
                goto error_out;
        }
 -      put_user(data.rv, (u16 __user *) (&(up_data->rv)));
 +      put_user(data.rv, (&(up_data->rv)));
        DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
  
        error_out:
@@@ -1,25 -1,25 +1,25 @@@
  /*
   * Copyright (C) 2003 - 2006 NetXen, Inc.
   * All rights reserved.
 - * 
 + *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
 - *                            
 + *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
 - *                                   
 + *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   * MA  02111-1307, USA.
 - * 
 + *
   * The full GNU General Public License is included in this distribution
   * in the file called LICENSE.
 - * 
 + *
   * Contact Information:
   *    info@netxen.com
   * NetXen,
@@@ -32,7 -32,6 +32,7 @@@
   */
  
  #include <linux/vmalloc.h>
 +#include <linux/highmem.h>
  #include "netxen_nic_hw.h"
  
  #include "netxen_nic.h"
@@@ -49,21 -48,14 +49,21 @@@ MODULE_DESCRIPTION("NetXen Multi port (
  MODULE_LICENSE("GPL");
  MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
  
 -char netxen_nic_driver_name[] = "netxen";
 +char netxen_nic_driver_name[] = "netxen-nic";
  static char netxen_nic_driver_string[] = "NetXen Network Driver version "
      NETXEN_NIC_LINUX_VERSIONID;
  
 +struct netxen_adapter *g_adapter = NULL;
 +
  #define NETXEN_NETDEV_WEIGHT 120
  #define NETXEN_ADAPTER_UP_MAGIC 777
  #define NETXEN_NIC_PEG_TUNE 0
  
 +u8 nx_p2_id = NX_P2_C0;
 +
 +#define DMA_32BIT_MASK        0x00000000ffffffffULL
 +#define DMA_35BIT_MASK        0x00000007ffffffffULL
 +
  /* Local functions to NetXen NIC driver */
  static int __devinit netxen_nic_probe(struct pci_dev *pdev,
                                      const struct pci_device_id *ent);
@@@ -72,7 -64,7 +72,7 @@@ static int netxen_nic_open(struct net_d
  static int netxen_nic_close(struct net_device *netdev);
  static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
  static void netxen_tx_timeout(struct net_device *netdev);
- static void netxen_tx_timeout_task(struct net_device *netdev);
+ static void netxen_tx_timeout_task(struct work_struct *work);
  static void netxen_watchdog(unsigned long);
  static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
  static int netxen_nic_ioctl(struct net_device *netdev,
@@@ -95,9 -87,6 +95,9 @@@ static struct pci_device_id netxen_pci_
  
  MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
  
 +struct workqueue_struct *netxen_workq;
 +static void netxen_watchdog(unsigned long);
 +
  /*
   * netxen_nic_probe()
   *
@@@ -116,28 -105,20 +116,28 @@@ netxen_nic_probe(struct pci_dev *pdev, 
        struct net_device *netdev = NULL;
        struct netxen_adapter *adapter = NULL;
        struct netxen_port *port = NULL;
 -      u8 *mem_ptr0 = NULL;
 -      u8 *mem_ptr1 = NULL;
 -      u8 *mem_ptr2 = NULL;
 +      void __iomem *mem_ptr0 = NULL;
 +      void __iomem *mem_ptr1 = NULL;
 +      void __iomem *mem_ptr2 = NULL;
  
 -      unsigned long mem_base, mem_len;
 +      u8 *db_ptr = NULL;
 +      unsigned long mem_base, mem_len, db_base, db_len;
        int pci_using_dac, i, err;
        int ring;
        struct netxen_recv_context *recv_ctx = NULL;
        struct netxen_rcv_desc_ctx *rcv_desc = NULL;
        struct netxen_cmd_buffer *cmd_buf_arr = NULL;
        u64 mac_addr[FLASH_NUM_PORTS + 1];
 -      int valid_mac;
 +      int valid_mac = 0;
 +      static int netxen_cards_found = 0;
  
        printk(KERN_INFO "%s \n", netxen_nic_driver_string);
 +      /* In current scheme, we use only PCI function 0 */
 +      if (PCI_FUNC(pdev->devfn) != 0) {
 +              DPRINTK(ERR, "NetXen function %d will not be enabled.\n",
 +                      PCI_FUNC(pdev->devfn));
 +              return -ENODEV;
 +      }
        if ((err = pci_enable_device(pdev)))
                return err;
        if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
                goto err_out_disable_pdev;
  
        pci_set_master(pdev);
 -      if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) &&
 -          (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0))
 +      pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
 +      if (nx_p2_id == NX_P2_C1 &&
 +          (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
 +          (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
                pci_using_dac = 1;
 -      else {
 +      else {
                if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
                    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
                        goto err_out_free_res;
            ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
  
        if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) {
 -              DPRINTK(1, ERR,
 +              DPRINTK(ERR,
                        "Cannot remap adapter memory aborting.:"
                        "0 -> %p, 1 -> %p, 2 -> %p\n",
                        mem_ptr0, mem_ptr1, mem_ptr2);
  
                err = -EIO;
 -              if (mem_ptr0)
 -                      iounmap(mem_ptr0);
 -              if (mem_ptr1)
 -                      iounmap(mem_ptr1);
 -              if (mem_ptr2)
 -                      iounmap(mem_ptr2);
 -
 -              goto err_out_free_res;
 +              goto err_out_iounmap;
 +      }
 +      db_base = pci_resource_start(pdev, 4);  /* doorbell is on bar 4 */
 +      db_len = pci_resource_len(pdev, 4);
 +
 +      if (db_len == 0) {
 +              printk(KERN_ERR "%s: doorbell is disabled\n",
 +                     netxen_nic_driver_name);
 +              err = -EIO;
 +              goto err_out_iounmap;
 +      }
 +      DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base,
 +              db_len);
 +
 +      db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
 +      if (db_ptr == 0UL) {
 +              printk(KERN_ERR "%s: Failed to allocate doorbell map.",
 +                     netxen_nic_driver_name);
 +              err = -EIO;
 +              goto err_out_iounmap;
        }
 +      DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
  
  /*
   *      Allocate a adapter structure which will manage all the initialization
                       netxen_nic_driver_name,
                       (int)sizeof(struct netxen_adapter));
                err = -ENOMEM;
 -              goto err_out_iounmap;
 +              goto err_out_dbunmap;
        }
  
 +      if (netxen_cards_found == 0) {
 +              g_adapter = adapter;
 +      }
        adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS;
        adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
        adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
 +      adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
  
        pci_set_drvdata(pdev, adapter);
  
        cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
        if (cmd_buf_arr == NULL) {
 +              printk(KERN_ERR
 +                     "%s: Could not allocate cmd_buf_arr memory:%d\n",
 +                     netxen_nic_driver_name, (int)TX_RINGSIZE);
                err = -ENOMEM;
                goto err_out_free_adapter;
        }
                                rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
                                break;
  
 +                      case RCV_RING_LRO:
 +                              rcv_desc->max_rx_desc_count =
 +                                  adapter->max_lro_rx_desc_count;
 +                              rcv_desc->flags = RCV_DESC_LRO;
 +                              rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
 +                              rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
 +                              break;
 +
                        }
                        rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
                            vmalloc(RCV_BUFFSIZE);
  
                        if (rcv_desc->rx_buf_arr == NULL) {
 +                              printk(KERN_ERR "%s: Could not allocate"
 +                                     "rcv_desc->rx_buf_arr memory:%d\n",
 +                                     netxen_nic_driver_name,
 +                                     (int)RCV_BUFFSIZE);
                                err = -ENOMEM;
                                goto err_out_free_rx_buffer;
                        }
  
        }
  
 -      adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL);
 -      if (adapter->ops == NULL) {
 -              printk(KERN_ERR
 -                     "%s: Could not allocate memory for adapter->ops:%d\n",
 -                     netxen_nic_driver_name,
 -                     (int)sizeof(struct netxen_adapter));
 -              err = -ENOMEM;
 -              goto err_out_free_rx_buffer;
 -      }
 -
        adapter->cmd_buf_arr = cmd_buf_arr;
        adapter->ahw.pci_base0 = mem_ptr0;
        adapter->ahw.pci_base1 = mem_ptr1;
        adapter->ahw.pci_base2 = mem_ptr2;
 +      adapter->ahw.db_base = db_ptr;
 +      adapter->ahw.db_len = db_len;
        spin_lock_init(&adapter->tx_lock);
        spin_lock_init(&adapter->lock);
 +      netxen_initialize_adapter_sw(adapter);  /* initialize the buffers in adapter */
  #ifdef CONFIG_IA64
        netxen_pinit_from_rom(adapter, 0);
        udelay(500);
        netxen_load_firmware(adapter);
  #endif
  
 -      /* initialize the buffers in adapter */
 -      netxen_initialize_adapter_sw(adapter);
        /*
         * Set the CRB window to invalid. If any register in window 0 is
         * accessed it should set the window to 0 and then reset it to 1.
        adapter->ahw.xg_linkup = 0;
        adapter->watchdog_timer.function = &netxen_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
-       INIT_WORK(&adapter->watchdog_task,
-                 (void (*)(void *))netxen_watchdog_task, adapter);
+       INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
        adapter->ahw.pdev = pdev;
        adapter->proc_cmd_buf_counter = 0;
 -      pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id);
 +      adapter->ahw.revision_id = nx_p2_id;
  
        if (pci_enable_msi(pdev)) {
                adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET));
        writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
  
 +      /* do this before waking up pegs so that we have valid dummy dma addr */
 +      err = netxen_initialize_adapter_offload(adapter);
 +      if (err) {
 +              goto err_out_free_dev;
 +      }
 +
        /* Unlock the HW, prompting the boot sequence */
        writel(1,
               NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
        netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
  
        /* initialize the all the ports */
 +      adapter->active_ports = 0;
  
        for (i = 0; i < adapter->ahw.max_ports; i++) {
                netdev = alloc_etherdev(sizeof(struct netxen_port));
                                       netdev->dev_addr[4],
                                       netdev->dev_addr[5]);
                        } else {
 -                              if (adapter->ops->macaddr_set)
 -                                      adapter->ops->macaddr_set(port,
 -                                                                netdev->
 -                                                                dev_addr);
 +                              if (adapter->macaddr_set)
 +                                      adapter->macaddr_set(port,
 +                                                           netdev->dev_addr);
                        }
                }
-               INIT_WORK(adapter->tx_timeout_task + i,
-                         (void (*)(void *))netxen_tx_timeout_task, netdev);
+               adapter->netdev = netdev;
+               INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
                netif_carrier_off(netdev);
                netif_stop_queue(netdev);
  
                        goto err_out_free_dev;
                }
                adapter->port_count++;
 -              adapter->active_ports = 0;
                adapter->port[i] = port;
        }
  
                break;
        }
  
 +      adapter->number = netxen_cards_found;
        adapter->driver_mismatch = 0;
  
        return 0;
                        free_netdev(port->netdev);
                }
        }
 -      kfree(adapter->ops);
 +
 +      netxen_free_adapter_offload(adapter);
  
        err_out_free_rx_buffer:
        for (i = 0; i < MAX_RCV_CTX; ++i) {
                        }
                }
        }
 -
        vfree(cmd_buf_arr);
  
 -      kfree(adapter->port);
 -
        err_out_free_adapter:
        pci_set_drvdata(pdev, NULL);
        kfree(adapter);
  
 +      err_out_dbunmap:
 +      if (db_ptr)
 +              iounmap(db_ptr);
 +
        err_out_iounmap:
 -      iounmap(mem_ptr0);
 -      iounmap(mem_ptr1);
 -      iounmap(mem_ptr2);
 +      if (mem_ptr0)
 +              iounmap(mem_ptr0);
 +      if (mem_ptr1)
 +              iounmap(mem_ptr1);
 +      if (mem_ptr2)
 +              iounmap(mem_ptr2);
  
        err_out_free_res:
        pci_release_regions(pdev);
@@@ -532,8 -476,12 +531,8 @@@ static void __devexit netxen_nic_remove
  
        netxen_nic_stop_all_ports(adapter);
        /* leave the hw in the same state as reboot */
 -      netxen_pinit_from_rom(adapter, 0);
 -      udelay(500);
        netxen_load_firmware(adapter);
 -
 -      if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
 -              netxen_nic_disable_int(adapter);
 +      netxen_free_adapter_offload(adapter);
  
        udelay(500);            /* Delay for a while to drain the DMA engines */
        for (i = 0; i < adapter->port_count; i++) {
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                netxen_free_hw_resources(adapter);
  
 +      iounmap(adapter->ahw.db_base);
        iounmap(adapter->ahw.pci_base0);
        iounmap(adapter->ahw.pci_base1);
        iounmap(adapter->ahw.pci_base2);
        }
  
        vfree(adapter->cmd_buf_arr);
 -      kfree(adapter->ops);
        kfree(adapter);
  }
  
@@@ -598,8 -546,6 +597,8 @@@ static int netxen_nic_open(struct net_d
                        return -EIO;
                }
                netxen_nic_flash_print(adapter);
 +              if (adapter->init_niu)
 +                      adapter->init_niu(adapter);
  
                /* setup all the resources for the Phantom... */
                /* this include the descriptors for rcv, tx, and status */
                               err);
                        return err;
                }
 -              if (adapter->ops->init_port
 -                  && adapter->ops->init_port(adapter, port->portnum) != 0) {
 +              if (adapter->init_port
 +                  && adapter->init_port(adapter, port->portnum) != 0) {
                        printk(KERN_ERR "%s: Failed to initialize port %d\n",
                               netxen_nic_driver_name, port->portnum);
                        netxen_free_hw_resources(adapter);
                        return -EIO;
                }
 -              if (adapter->ops->init_niu)
 -                      adapter->ops->init_niu(adapter);
                for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
                        for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
                                netxen_post_rx_buffers(adapter, ctx, ring);
                }
 -              adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
 -      }
 -      adapter->active_ports++;
 -      if (adapter->active_ports == 1) {
 +              adapter->irq = adapter->ahw.pdev->irq;
                err = request_irq(adapter->ahw.pdev->irq, &netxen_intr,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name,
                                  adapter);
                if (err) {
                        printk(KERN_ERR "request_irq failed with: %d\n", err);
 -                      adapter->active_ports--;
 +                      netxen_free_hw_resources(adapter);
                        return err;
                }
 -              adapter->irq = adapter->ahw.pdev->irq;
 +
 +              adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
 +      }
 +      adapter->active_ports++;
 +      if (adapter->active_ports == 1) {
                if (!adapter->driver_mismatch)
                        mod_timer(&adapter->watchdog_timer, jiffies);
  
  
        /* Done here again so that even if phantom sw overwrote it,
         * we set it */
 -      if (adapter->ops->macaddr_set)
 -              adapter->ops->macaddr_set(port, netdev->dev_addr);
 +      if (adapter->macaddr_set)
 +              adapter->macaddr_set(port, netdev->dev_addr);
        netxen_nic_set_link_parameters(port);
  
        netxen_nic_set_multi(netdev);
 +      if (adapter->set_mtu)
 +              adapter->set_mtu(port, netdev->mtu);
 +
        if (!adapter->driver_mismatch)
                netif_start_queue(netdev);
  
@@@ -703,7 -647,6 +702,7 @@@ static int netxen_nic_close(struct net_
                        }
                        cmd_buff++;
                }
 +              FLUSH_SCHEDULED_WORK();
                del_timer_sync(&adapter->watchdog_timer);
        }
  
@@@ -724,6 -667,7 +723,6 @@@ static int netxen_nic_xmit_frame(struc
        struct cmd_desc_type0 *hwdesc;
        int k;
        struct netxen_cmd_buffer *pbuf = NULL;
 -      unsigned int tries = 0;
        static int dropped_packet = 0;
        int frag_count;
        u32 local_producer = 0;
                        if (((skb->nh.iph)->ihl * sizeof(u32)) +
                            ((skb->h.th)->doff * sizeof(u32)) +
                            sizeof(struct ethhdr) >
 -                          (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
 +                          (sizeof(struct cmd_desc_type0) - 2)) {
                                no_of_desc++;
                        }
                }
        if ((k + no_of_desc) >=
            ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
             last_cmd_consumer)) {
 +              port->stats.nocmddescriptor++;
 +              DPRINTK(ERR, "No command descriptors available,"
 +                      " producer = %d, consumer = %d count=%llu,"
 +                      " dropping packet\n", producer,
 +                      adapter->last_cmd_consumer,
 +                      port->stats.nocmddescriptor);
 +
 +              netif_stop_queue(netdev);
 +              port->flags |= NETXEN_NETDEV_STATUS;
                spin_unlock_bh(&adapter->tx_lock);
 -              if (tries == 0) {
 -                      local_bh_disable();
 -                      netxen_process_cmd_ring((unsigned long)adapter);
 -                      local_bh_enable();
 -                      ++tries;
 -                      goto retry_getting_window;
 -              } else {
 -                      port->stats.nocmddescriptor++;
 -                      DPRINTK(ERR, "No command descriptors available,"
 -                              " producer = %d, consumer = %d count=%llu,"
 -                              " dropping packet\n", producer,
 -                              adapter->last_cmd_consumer,
 -                              port->stats.nocmddescriptor);
 -
 -                      spin_lock_bh(&adapter->tx_lock);
 -                      netif_stop_queue(netdev);
 -                      port->flags |= NETXEN_NETDEV_STATUS;
 -                      spin_unlock_bh(&adapter->tx_lock);
 -                      return NETDEV_TX_BUSY;
 -              }
 +              return NETDEV_TX_BUSY;
        }
        k = get_index_range(k, max_tx_desc_count, no_of_desc);
        adapter->cmd_producer = k;
                pbuf->mss = 0;
                hwdesc->mss = 0;
        }
 -      pbuf->no_of_descriptors = no_of_desc;
        pbuf->total_length = skb->len;
        pbuf->skb = skb;
        pbuf->cmd = TX_ETHER_PKT;
        buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len,
                                      PCI_DMA_TODEVICE);
        buffrag->length = first_seg_len;
 -      CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len);
 -      hwdesc->num_of_buffers = frag_count;
 -      hwdesc->opcode = TX_ETHER_PKT;
 +      netxen_set_cmd_desc_totallength(hwdesc, skb->len);
 +      netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
 +      netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
  
 -      CMD_DESC_PORT_WRT(hwdesc, port->portnum);
 +      netxen_set_cmd_desc_port(hwdesc, port->portnum);
        hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
        hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
  
        /* For LSO, we need to copy the MAC/IP/TCP headers into
         * the descriptor ring
         */
 -      if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) {
 +      if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
 +          == TX_TCP_LSO) {
                int hdr_len, first_hdr_len, more_hdr;
                hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
 -              if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) {
 -                      first_hdr_len =
 -                          sizeof(struct cmd_desc_type0) - NET_IP_ALIGN;
 +              if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
 +                      first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
                        more_hdr = 1;
                } else {
                        first_hdr_len = hdr_len;
                hwdesc = &hw->cmd_desc_head[producer];
  
                /* copy the first 64 bytes */
 -              memcpy(((void *)hwdesc) + NET_IP_ALIGN,
 +              memcpy(((void *)hwdesc) + 2,
                       (void *)(skb->data), first_hdr_len);
                producer = get_next_index(producer, max_tx_desc_count);
  
        }
        spin_lock_bh(&adapter->tx_lock);
        port->stats.txbytes +=
 -          CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]);
 +          netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]);
        /* Code to update the adapter considering how many producer threads
           are currently working */
        if ((--adapter->num_threads) == 0) {
                       NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET));
                wmb();
                adapter->total_threads = 0;
 -      } else {
 -              u32 crb_producer = 0;
 -              crb_producer =
 -                  readl(NETXEN_CRB_NORMALIZE
 -                        (adapter, CRB_CMD_PRODUCER_OFFSET));
 -              if (crb_producer == local_producer) {
 -                      crb_producer = get_index_range(crb_producer,
 -                                                     max_tx_desc_count,
 -                                                     no_of_desc);
 -                      writel(crb_producer,
 -                             NETXEN_CRB_NORMALIZE(adapter,
 -                                                  CRB_CMD_PRODUCER_OFFSET));
 -                      wmb();
 -              }
        }
  
        port->stats.xmitfinished++;
  static void netxen_watchdog(unsigned long v)
  {
        struct netxen_adapter *adapter = (struct netxen_adapter *)v;
 -      schedule_work(&adapter->watchdog_task);
 +      if (adapter != g_adapter) {
 +              printk("%s: ***BUG*** adapter[%p] != g_adapter[%p]\n",
 +                     __FUNCTION__, adapter, g_adapter);
 +              return;
 +      }
 +
 +      SCHEDULE_WORK(&adapter->watchdog_task);
  }
  
  static void netxen_tx_timeout(struct net_device *netdev)
  {
        struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
 -      struct netxen_adapter *adapter = port->adapter;
  
 -      schedule_work(&adapter->tx_timeout_task);
 +      SCHEDULE_WORK(port->adapter->tx_timeout_task + port->portnum);
  }
  
- static void netxen_tx_timeout_task(struct net_device *netdev)
+ static void netxen_tx_timeout_task(struct work_struct *work)
  {
-       struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev);
+       struct netxen_adapter *adapter =
+               container_of(work, struct netxen_adapter, tx_timeout_task);
+       struct net_device *netdev = adapter->netdev;
        unsigned long flags;
  
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
               netxen_nic_driver_name, netdev->name);
  
-       spin_lock_irqsave(&port->adapter->lock, flags);
+       spin_lock_irqsave(&adapter->lock, flags);
        netxen_nic_close(netdev);
        netxen_nic_open(netdev);
-       spin_unlock_irqrestore(&port->adapter->lock, flags);
+       spin_unlock_irqrestore(&adapter->lock, flags);
        netdev->trans_start = jiffies;
        netif_wake_queue(netdev);
  }
@@@ -1001,11 -967,6 +1002,11 @@@ netxen_handle_int(struct netxen_adapte
        if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
                int count = 0;
                u32 mask;
 +              mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
 +              if ((mask & 0x80) == 0) {
 +                      /* not our interrupt */
 +                      return ret;
 +              }
                netxen_nic_disable_int(adapter);
                /* Window = 0 or 1 */
                do {
@@@ -1065,10 -1026,7 +1066,10 @@@ irqreturn_t netxen_intr(int irq, void *
                netdev = port->netdev;
  
                /* process our status queue (for all 4 ports) */
 -              netxen_handle_int(adapter, netdev);
 +              if (netif_running(netdev)) {
 +                      netxen_handle_int(adapter, netdev);
 +                      break;
 +              }
        }
  
        return IRQ_HANDLED;
@@@ -1082,12 -1040,11 +1083,12 @@@ static int netxen_nic_poll(struct net_d
        int done = 1;
        int ctx;
        int this_work_done;
 +      int work_done = 0;
  
        DPRINTK(INFO, "polling for %d descriptors\n", *budget);
        port->stats.polled++;
  
 -      adapter->work_done = 0;
 +      work_done = 0;
        for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
                /*
                 * Fairness issue. This will give undue weight to the
                this_work_done = netxen_process_rcv_ring(adapter, ctx,
                                                         work_to_do /
                                                         MAX_RCV_CTX);
 -              adapter->work_done += this_work_done;
 +              work_done += this_work_done;
        }
  
 -      netdev->quota -= adapter->work_done;
 -      *budget -= adapter->work_done;
 +      netdev->quota -= work_done;
 +      *budget -= work_done;
  
 -      if (adapter->work_done >= work_to_do
 -          && netxen_nic_rx_has_work(adapter) != 0)
 +      if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
                done = 0;
  
 -      netxen_process_cmd_ring((unsigned long)adapter);
 +      if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
 +              done = 0;
  
        DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
 -              adapter->work_done, work_to_do);
 +              work_done, work_to_do);
        if (done) {
                netif_rx_complete(netdev);
                netxen_nic_enable_int(adapter);
@@@ -1160,9 -1117,8 +1161,9 @@@ netxen_nic_ioctl(struct net_device *net
                if (ifr->ifr_data) {
                        sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP,
                                port->portnum);
 -                      nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name,
 -                                              NETXEN_NIC_NAME_LEN);
 +                      nr_bytes =
 +                          copy_to_user((char __user *)ifr->ifr_data, dev_name,
 +                                       NETXEN_NIC_NAME_LEN);
                        if (nr_bytes)
                                err = -EIO;
  
@@@ -1189,9 -1145,6 +1190,9 @@@ static struct pci_driver netxen_driver 
  
  static int __init netxen_init_module(void)
  {
 +      if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
 +              return -ENOMEM;
 +
        return pci_module_init(&netxen_driver);
  }
  
@@@ -1202,7 -1155,7 +1203,7 @@@ static void __exit netxen_exit_module(v
        /*
         * Wait for some time to allow the dma to drain, if any.
         */
 -      mdelay(5);
 +      destroy_workqueue(netxen_workq);
        pci_unregister_driver(&netxen_driver);
  }
  
diff --combined drivers/net/ns83820.c
@@@ -414,10 -414,10 +414,10 @@@ struct rx_info 
  
        struct sk_buff  *skbs[NR_RX_DESC];
  
 -      u32             *next_rx_desc;
 +      __le32          *next_rx_desc;
        u16             next_rx, next_empty;
  
 -      u32             *descs;
 +      __le32          *descs;
        dma_addr_t      phy_descs;
  };
  
@@@ -427,6 -427,7 +427,7 @@@ struct ns83820 
        u8                      __iomem *base;
  
        struct pci_dev          *pci_dev;
+       struct net_device       *ndev;
  
  #ifdef NS83820_VLAN_ACCEL_SUPPORT
        struct vlan_group       *vlgrp;
        struct sk_buff  *tx_skbs[NR_TX_DESC];
  
        char            pad[16] __attribute__((aligned(16)));
 -      u32             *tx_descs;
 +      __le32          *tx_descs;
        dma_addr_t      tx_phy_descs;
  
        struct timer_list       tx_watchdog;
@@@ -533,7 -534,7 +534,7 @@@ static void ns83820_vlan_rx_kill_vid(st
   * conditions, still route realtime traffic with as low jitter as
   * possible.
   */
 -static inline void build_rx_desc(struct ns83820 *dev, u32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts)
 +static inline void build_rx_desc(struct ns83820 *dev, __le32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts)
  {
        desc_addr_set(desc + DESC_LINK, link);
        desc_addr_set(desc + DESC_BUFPTR, buf);
@@@ -547,7 -548,7 +548,7 @@@ static inline int ns83820_add_rx_skb(st
  {
        unsigned next_empty;
        u32 cmdsts;
 -      u32 *sg;
 +      __le32 *sg;
        dma_addr_t buf;
  
        next_empty = dev->rx_info.next_empty;
@@@ -631,10 -632,10 +632,10 @@@ static void fastcall rx_refill_atomic(s
  }
  
  /* REFILL */
- static inline void queue_refill(void *_dev)
+ static inline void queue_refill(struct work_struct *work)
  {
-       struct net_device *ndev = _dev;
-       struct ns83820 *dev = PRIV(ndev);
+       struct ns83820 *dev = container_of(work, struct ns83820, tq_refill);
+       struct net_device *ndev = dev->ndev;
  
        rx_refill(ndev, GFP_KERNEL);
        if (dev->rx_info.up)
@@@ -874,8 -875,7 +875,8 @@@ static void fastcall rx_irq(struct net_
        struct rx_info *info = &dev->rx_info;
        unsigned next_rx;
        int rx_rc, len;
 -      u32 cmdsts, *desc;
 +      u32 cmdsts;
 +      __le32 *desc;
        unsigned long flags;
        int nr = 0;
  
@@@ -1011,8 -1011,7 +1012,8 @@@ static inline void kick_tx(struct ns838
  static void do_tx_done(struct net_device *ndev)
  {
        struct ns83820 *dev = PRIV(ndev);
 -      u32 cmdsts, tx_done_idx, *desc;
 +      u32 cmdsts, tx_done_idx;
 +      __le32 *desc;
  
        dprintk("do_tx_done(%p)\n", ndev);
        tx_done_idx = dev->tx_done_idx;
@@@ -1079,7 -1078,7 +1080,7 @@@ static void ns83820_cleanup_tx(struct n
                struct sk_buff *skb = dev->tx_skbs[i];
                dev->tx_skbs[i] = NULL;
                if (skb) {
 -                      u32 *desc = dev->tx_descs + (i * DESC_SIZE);
 +                      __le32 *desc = dev->tx_descs + (i * DESC_SIZE);
                        pci_unmap_single(dev->pci_dev,
                                        desc_addr_get(desc + DESC_BUFPTR),
                                        le32_to_cpu(desc[DESC_CMDSTS]) & CMDSTS_LEN_MASK,
@@@ -1109,7 -1108,7 +1110,7 @@@ static int ns83820_hard_start_xmit(stru
        skb_frag_t *frag;
        int stopped = 0;
        int do_intr = 0;
 -      volatile u32 *first_desc;
 +      volatile __le32 *first_desc;
  
        dprintk("ns83820_hard_start_xmit\n");
  
@@@ -1182,7 -1181,7 +1183,7 @@@ again
        first_desc = dev->tx_descs + (free_idx * DESC_SIZE);
  
        for (;;) {
 -              volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
 +              volatile __le32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
  
                dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,
                        (unsigned long long)buf);
@@@ -1457,8 -1456,7 +1458,8 @@@ static int ns83820_stop(struct net_devi
  static void ns83820_tx_timeout(struct net_device *ndev)
  {
        struct ns83820 *dev = PRIV(ndev);
 -        u32 tx_done_idx, *desc;
 +        u32 tx_done_idx;
 +      __le32 *desc;
        unsigned long flags;
  
        spin_lock_irqsave(&dev->tx_lock, flags);
@@@ -1844,6 -1842,7 +1845,7 @@@ static int __devinit ns83820_init_one(s
  
        ndev = alloc_etherdev(sizeof(struct ns83820));
        dev = PRIV(ndev);
+       dev->ndev = ndev;
        err = -ENOMEM;
        if (!dev)
                goto out;
        SET_MODULE_OWNER(ndev);
        SET_NETDEV_DEV(ndev, &pci_dev->dev);
  
-       INIT_WORK(&dev->tq_refill, queue_refill, ndev);
+       INIT_WORK(&dev->tq_refill, queue_refill);
        tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev);
  
        err = pci_enable_device(pci_dev);