Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
[safe/jmp/linux-2.6] / drivers / infiniband / hw / nes / nes_hw.c
index e9db6ef..5d139db 100644 (file)
 
 #include "nes.h"
 
+static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
+module_param(nes_lro_max_aggr, uint, 0444);
+MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation");
+
 static u32 crit_err_count;
 u32 int_mod_timer_init;
 u32 int_mod_cq_depth_256;
@@ -51,18 +55,19 @@ u32 int_mod_cq_depth_24;
 u32 int_mod_cq_depth_16;
 u32 int_mod_cq_depth_4;
 u32 int_mod_cq_depth_1;
-
+static const u8 nes_max_critical_error_count = 100;
 #include "nes_cm.h"
 
 static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq);
 static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count);
 static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
-                          u8 OneG_Mode);
+                               struct nes_adapter *nesadapter, u8  OneG_Mode);
 static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
 static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq);
 static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq);
 static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                   struct nes_hw_aeqe *aeqe);
+static void process_critical_error(struct nes_device *nesdev);
 static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number);
 static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode);
 
@@ -218,11 +223,10 @@ static void nes_nic_tune_timer(struct nes_device *nesdev)
        }
 
        /* boundary checking */
-       if (shared_timer->timer_in_use > NES_NIC_FAST_TIMER_HIGH)
-               shared_timer->timer_in_use = NES_NIC_FAST_TIMER_HIGH;
-       else if (shared_timer->timer_in_use < NES_NIC_FAST_TIMER_LOW) {
-               shared_timer->timer_in_use = NES_NIC_FAST_TIMER_LOW;
-       }
+       if (shared_timer->timer_in_use > shared_timer->threshold_high)
+               shared_timer->timer_in_use = shared_timer->threshold_high;
+       else if (shared_timer->timer_in_use < shared_timer->threshold_low)
+               shared_timer->timer_in_use = shared_timer->threshold_low;
 
        nesdev->currcq_count = 0;
 
@@ -288,9 +292,6 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
 
        if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)
                return NULL;
-       if (nes_init_serdes(nesdev, hw_rev, port_count, OneG_Mode))
-               return NULL;
-       nes_init_csr_ne020(nesdev, hw_rev, port_count);
 
        max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);
        nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);
@@ -349,6 +350,22 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
        nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
                        nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
 
+       if (nes_read_eeprom_values(nesdev, nesadapter)) {
+               printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
+               kfree(nesadapter);
+               return NULL;
+       }
+
+       if (nes_init_serdes(nesdev, hw_rev, port_count, nesadapter,
+                                                       OneG_Mode)) {
+               kfree(nesadapter);
+               return NULL;
+       }
+       nes_init_csr_ne020(nesdev, hw_rev, port_count);
+
+       memset(nesadapter->pft_mcast_map, 255,
+              sizeof nesadapter->pft_mcast_map);
+
        /* populate the new nesadapter */
        nesadapter->devfn = nesdev->pcidev->devfn;
        nesadapter->bus_number = nesdev->pcidev->bus->number;
@@ -394,7 +411,7 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
        nesadapter->base_pd = 1;
 
        nesadapter->device_cap_flags =
-               IB_DEVICE_ZERO_STAG | IB_DEVICE_MEM_WINDOW;
+               IB_DEVICE_LOCAL_DMA_LKEY | IB_DEVICE_MEM_WINDOW;
 
        nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
                        [(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
@@ -464,20 +481,25 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
 
        /* setup port configuration */
        if (nesadapter->port_count == 1) {
-               u32temp = 0x00000000;
+               nesadapter->log_port = 0x00000000;
                if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)
                        nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);
                else
                        nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
        } else {
-               if (nesadapter->port_count == 2)
-                       u32temp = 0x00000044;
-               else
-                       u32temp = 0x000000e4;
+               if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+                       nesadapter->log_port = 0x000000D8;
+               } else {
+                       if (nesadapter->port_count == 2)
+                               nesadapter->log_port = 0x00000044;
+                       else
+                               nesadapter->log_port = 0x000000e4;
+               }
                nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
        }
 
-       nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, u32temp);
+       nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT,
+                                               nesadapter->log_port);
        nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",
                        nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));
 
@@ -702,23 +724,43 @@ static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_
  * nes_init_serdes
  */
 static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count,
-                          u8 OneG_Mode)
+                               struct nes_adapter *nesadapter, u8  OneG_Mode)
 {
        int i;
        u32 u32temp;
+       u32 serdes_common_control;
 
        if (hw_rev != NE020_REV) {
                /* init serdes 0 */
 
                nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
-               if (!OneG_Mode)
+               if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+                       serdes_common_control = nes_read_indexed(nesdev,
+                                       NES_IDX_ETH_SERDES_COMMON_CONTROL0);
+                       serdes_common_control |= 0x000000100;
+                       nes_write_indexed(nesdev,
+                                       NES_IDX_ETH_SERDES_COMMON_CONTROL0,
+                                       serdes_common_control);
+               } else if (!OneG_Mode) {
                        nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
-               if (port_count > 1) {
+               }
+               if (((port_count > 1) &&
+                       (nesadapter->phy_type[0] != NES_PHY_TYPE_PUMA_1G)) ||
+                       ((port_count > 2) &&
+                       (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G))) {
                        /* init serdes 1 */
                        nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
-                       if (!OneG_Mode)
+                       if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+                               serdes_common_control = nes_read_indexed(nesdev,
+                                       NES_IDX_ETH_SERDES_COMMON_CONTROL1);
+                               serdes_common_control |= 0x000000100;
+                               nes_write_indexed(nesdev,
+                                       NES_IDX_ETH_SERDES_COMMON_CONTROL1,
+                                       serdes_common_control);
+                       } else if (!OneG_Mode) {
                                nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
                        }
+               }
        } else {
                /* init serdes 0 */
                nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
@@ -822,7 +864,8 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou
 
        nes_write_indexed(nesdev, 0x00005000, 0x00018000);
        /* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
-       nes_write_indexed(nesdev, 0x00005004, 0x00020001);
+       nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, (wqm_quanta << 1) |
+                                                        0x00000001);
        nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
        nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
        nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
@@ -833,7 +876,7 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou
        nes_write_indexed(nesdev, 0x00000900, 0x20000001);
        nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
        nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
-                                                                                                               //
+
        nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
        /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
 
@@ -1222,6 +1265,7 @@ int nes_init_phy(struct nes_device *nesdev)
                if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
                        printk(PFX "%s: Programming mdc config for 1G\n", __func__);
                        tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+                       tx_config &= 0xFFFFFFE3;
                        tx_config |= 0x04;
                        nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
                }
@@ -1229,7 +1273,7 @@ int nes_init_phy(struct nes_device *nesdev)
                nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data);
                nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n",
                                nesadapter->phy_index[mac_index], phy_data);
-               nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index],  0xb000);
+               nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000);
 
                /* Reset the PHY */
                nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], 0x8000);
@@ -1287,7 +1331,8 @@ int nes_init_phy(struct nes_device *nesdev)
                    (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
                        /* setup 10G MDIO operation */
                        tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
-                       tx_config |= 0x14;
+                       tx_config &= 0xFFFFFFE3;
+                       tx_config |= 0x15;
                        nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
                }
                if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
@@ -1311,7 +1356,7 @@ int nes_init_phy(struct nes_device *nesdev)
                                nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008);
                                nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098);
                                nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00);
-                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0000);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0001);
                                nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528);
 
                                /*
@@ -1373,7 +1418,7 @@ int nes_init_phy(struct nes_device *nesdev)
                                 * the amcc phy is stable
                                 */
 
-                               sds_common_control0 = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
+                               sds_common_control0  = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
                                sds_common_control0 |= 0x1;
                                nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
 
@@ -1382,7 +1427,7 @@ int nes_init_phy(struct nes_device *nesdev)
                                nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
 
                                i = 0;
-                               while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
+                               while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
                                                && (i++ < 5000)) {
                                        /* mdelay(1); */
                                }
@@ -1659,10 +1704,10 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
        }
 
        u64temp = (u64)nesvnic->nic.sq_pbase;
-       nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+       nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX]  = cpu_to_le32((u32)u64temp);
        nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
        u64temp = (u64)nesvnic->nic.rq_pbase;
-       nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+       nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX]  = cpu_to_le32((u32)u64temp);
        nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
 
        cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
@@ -1714,7 +1759,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
                nic_rqe = &nesvnic->nic.rq_vbase[counter];
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
-               nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+               nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]  = cpu_to_le32((u32)pmem);
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
                nesvnic->nic.rx_skb[counter] = skb;
        }
@@ -1738,13 +1783,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
                        jumbomode = 1;
                nes_nic_init_timer_defaults(nesdev, jumbomode);
        }
-       nesvnic->lro_mgr.max_aggr = NES_LRO_MAX_AGGR;
-       nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
-       nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
+       nesvnic->lro_mgr.max_aggr       = nes_lro_max_aggr;
+       nesvnic->lro_mgr.max_desc       = NES_MAX_LRO_DESCRIPTORS;
+       nesvnic->lro_mgr.lro_arr        = nesvnic->lro_desc;
        nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
-       nesvnic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
-       nesvnic->lro_mgr.dev = netdev;
-       nesvnic->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
+       nesvnic->lro_mgr.features       = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
+       nesvnic->lro_mgr.dev            = netdev;
+       nesvnic->lro_mgr.ip_summed      = CHECKSUM_UNNECESSARY;
        nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
        return 0;
 }
@@ -1755,9 +1800,14 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
  */
 void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
 {
+       u64 u64temp;
+       dma_addr_t bus_address;
        struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_hw_cqp_wqe *cqp_wqe;
+       struct nes_hw_nic_sq_wqe *nic_sqe;
        struct nes_hw_nic_rq_wqe *nic_rqe;
+       __le16 *wqe_fragment_length;
+       u16  wqe_fragment_index;
        u64 wqe_frag;
        u32 cqp_head;
        unsigned long flags;
@@ -1765,15 +1815,70 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
 
        /* Free remaining NIC receive buffers */
        while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
-               nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
-               wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
-               wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
+               nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
+               wqe_frag  = (u64)le32_to_cpu(
+                       nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
+               wqe_frag |= ((u64)le32_to_cpu(
+                       nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
                pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
                                nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
                dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
                nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
        }
 
+       /* Free remaining NIC transmit buffers */
+       while (nesvnic->nic.sq_head != nesvnic->nic.sq_tail) {
+               nic_sqe = &nesvnic->nic.sq_vbase[nesvnic->nic.sq_tail];
+               wqe_fragment_index = 1;
+               wqe_fragment_length = (__le16 *)
+                       &nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
+               /* bump past the vlan tag */
+               wqe_fragment_length++;
+               if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
+                       u64temp = (u64)le32_to_cpu(
+                               nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
+                               wqe_fragment_index*2]);
+                       u64temp += ((u64)le32_to_cpu(
+                               nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
+                               + wqe_fragment_index*2]))<<32;
+                       bus_address = (dma_addr_t)u64temp;
+                       if (test_and_clear_bit(nesvnic->nic.sq_tail,
+                                       nesvnic->nic.first_frag_overflow)) {
+                               pci_unmap_single(nesdev->pcidev,
+                                               bus_address,
+                                               le16_to_cpu(wqe_fragment_length[
+                                                       wqe_fragment_index++]),
+                                               PCI_DMA_TODEVICE);
+                       }
+                       for (; wqe_fragment_index < 5; wqe_fragment_index++) {
+                               if (wqe_fragment_length[wqe_fragment_index]) {
+                                       u64temp = le32_to_cpu(
+                                               nic_sqe->wqe_words[
+                                               NES_NIC_SQ_WQE_FRAG0_LOW_IDX+
+                                               wqe_fragment_index*2]);
+                                       u64temp += ((u64)le32_to_cpu(
+                                               nic_sqe->wqe_words[
+                                               NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+
+                                               wqe_fragment_index*2]))<<32;
+                                       bus_address = (dma_addr_t)u64temp;
+                                       pci_unmap_page(nesdev->pcidev,
+                                                       bus_address,
+                                                       le16_to_cpu(
+                                                       wqe_fragment_length[
+                                                       wqe_fragment_index]),
+                                                       PCI_DMA_TODEVICE);
+                               } else
+                                       break;
+                       }
+               }
+               if (nesvnic->nic.tx_skb[nesvnic->nic.sq_tail])
+                       dev_kfree_skb(
+                               nesvnic->nic.tx_skb[nesvnic->nic.sq_tail]);
+
+               nesvnic->nic.sq_tail = (++nesvnic->nic.sq_tail)
+                                       & (nesvnic->nic.sq_size - 1);
+       }
+
        spin_lock_irqsave(&nesdev->cqp.lock, flags);
 
        /* Destroy NIC QP */
@@ -1849,17 +1954,17 @@ int nes_napi_isr(struct nes_device *nesdev)
        /* iff NIC, process here, else wait for DPC */
        if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
                nesdev->napi_isr_ran = 0;
-               nes_write32(nesdev->regs+NES_INT_STAT,
-                               (int_stat &
-                               ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
+               nes_write32(nesdev->regs + NES_INT_STAT,
+                       (int_stat &
+                       ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 | NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
 
                /* Process the CEQs */
                nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
 
                if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
-                                          (!nesadapter->et_use_adaptive_rx_coalesce)) ||
-                                         ((nesadapter->et_use_adaptive_rx_coalesce) &&
-                                          (nesdev->deepcq_count > nesadapter->et_pkt_rate_low)))) ) {
+                                       (!nesadapter->et_use_adaptive_rx_coalesce)) ||
+                                       ((nesadapter->et_use_adaptive_rx_coalesce) &&
+                                        (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
                        if ((nesdev->int_req & NES_INT_TIMER) == 0) {
                                /* Enable Periodic timer interrupts */
                                nesdev->int_req |= NES_INT_TIMER;
@@ -1890,7 +1995,30 @@ int nes_napi_isr(struct nes_device *nesdev)
        }
 }
 
-
+static void process_critical_error(struct nes_device *nesdev)
+{
+       u32 debug_error;
+       u32 nes_idx_debug_error_masks0 = 0;
+       u16 error_module = 0;
+
+       debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
+       printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
+                       (u16)debug_error);
+       nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
+                       0x01010000 | (debug_error & 0x0000ffff));
+       if (crit_err_count++ > 10)
+               nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
+       error_module = (u16) (debug_error & 0x1F00) >> 8;
+       if (++nesdev->nesadapter->crit_error_count[error_module-1] >=
+                       nes_max_critical_error_count) {
+               printk(KERN_ERR PFX "Masking off critical error for module "
+                       "0x%02X\n", (u16)error_module);
+               nes_idx_debug_error_masks0 = nes_read_indexed(nesdev,
+                       NES_IDX_DEBUG_ERROR_MASKS0);
+               nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0,
+                       nes_idx_debug_error_masks0 | (1 << error_module));
+       }
+}
 /**
  * nes_dpc
  */
@@ -1905,7 +2033,6 @@ void nes_dpc(unsigned long param)
        u32 timer_stat;
        u32 temp_int_stat;
        u32 intf_int_stat;
-       u32 debug_error;
        u32 processed_intf_int = 0;
        u16 processed_timer_int = 0;
        u16 completion_ints = 0;
@@ -1937,12 +2064,12 @@ void nes_dpc(unsigned long param)
                }
 
                if (int_stat) {
-                       if (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                                       NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)) {
+                       if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
+                                       NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
                                /* Ack the interrupts */
                                nes_write32(nesdev->regs+NES_INT_STAT,
-                                               (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                                               NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
+                                       (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
+                                       NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
                        }
 
                        temp_int_stat = int_stat;
@@ -1983,14 +2110,7 @@ void nes_dpc(unsigned long param)
                                intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
                                intf_int_stat &= nesdev->intf_int_req;
                                if (NES_INTF_INT_CRITERR & intf_int_stat) {
-                                       debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
-                                       printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
-                                                       (u16)debug_error);
-                                       nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
-                                                       0x01010000 | (debug_error & 0x0000ffff));
-                                       /* BUG(); */
-                                       if (crit_err_count++ > 10)
-                                               nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
+                                       process_critical_error(nesdev);
                                }
                                if (NES_INTF_INT_PCIERR & intf_int_stat) {
                                        printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
@@ -2007,8 +2127,8 @@ void nes_dpc(unsigned long param)
                        }
                }
                /* Don't use the interface interrupt bit stay in loop */
-               int_stat &= ~NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                               NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3;
+               int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
+                               NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
        } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
 
        if (timer_ints == 1) {
@@ -2019,9 +2139,9 @@ void nes_dpc(unsigned long param)
                                        nesdev->timer_only_int_count = 0;
                                        nesdev->int_req &= ~NES_INT_TIMER;
                                        nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
-                                       nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
+                                       nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
                                } else {
-                                       nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
+                                       nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
                                }
                        } else {
                                if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
@@ -2029,7 +2149,7 @@ void nes_dpc(unsigned long param)
                                        nes_nic_init_timer(nesdev);
                                }
                                nesdev->timer_only_int_count = 0;
-                               nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
+                               nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
                        }
                } else {
                        nesdev->timer_only_int_count = 0;
@@ -2078,7 +2198,7 @@ static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
        do {
                if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
                                NES_CEQE_VALID) {
-                       u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX])))<<32) |
+                       u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]))) << 32) |
                                                ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
                        u64temp <<= 1;
                        cq = *((struct nes_hw_cq **)&u64temp);
@@ -2106,7 +2226,7 @@ static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
  */
 static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
 {
-//     u64 u64temp;
+       /* u64 u64temp; */
        u32 head;
        u32 aeq_size;
        u32 aeqe_misc;
@@ -2125,8 +2245,10 @@ static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
                if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
                        if (aeqe_cq_id >= NES_FIRST_QPN) {
                                /* dealing with an accelerated QP related AE */
-//                             u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])))<<32) |
-//                                     ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
+                               /*
+                                * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
+                                *           ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
+                                */
                                nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
                        } else {
                                /* TODO: dealing with a CQP related AE */
@@ -2252,7 +2374,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
                        spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
                }
                /* read the PHY interrupt status register */
-               if (nesadapter->OneG_Mode) {
+               if ((nesadapter->OneG_Mode) &&
+               (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
                        do {
                                nes_read_1G_phy_reg(nesdev, 0x1a,
                                                nesadapter->phy_index[mac_index], &phy_data);
@@ -2418,7 +2541,7 @@ static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic
 {
        struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
 
-       netif_rx_schedule(nesdev->netdev[nesvnic->netdev_index], &nesvnic->napi);
+       netif_rx_schedule(&nesvnic->napi);
 }
 
 
@@ -2474,8 +2597,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                /* bump past the vlan tag */
                                wqe_fragment_length++;
                                if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
-                                       u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
-                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
+                                       u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
+                                                       wqe_fragment_index * 2]);
+                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
+                                                       wqe_fragment_index * 2])) << 32;
                                        bus_address = (dma_addr_t)u64temp;
                                        if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
                                                pci_unmap_single(nesdev->pcidev,
@@ -2485,8 +2610,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                        }
                                        for (; wqe_fragment_index < 5; wqe_fragment_index++) {
                                                if (wqe_fragment_length[wqe_fragment_index]) {
-                                                       u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
-                                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
+                                                       u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
+                                                                               wqe_fragment_index * 2]);
+                                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
+                                                                               + wqe_fragment_index * 2])) <<32;
                                                        bus_address = (dma_addr_t)u64temp;
                                                        pci_unmap_page(nesdev->pcidev,
                                                                        bus_address,
@@ -2533,7 +2660,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
                                        nes_write32(nesdev->regs+NES_CQE_ALLOC,
                                                        cq->cq_number | (cqe_count << 16));
-//                                     nesadapter->tune_timer.cq_count += cqe_count;
+                                       /* nesadapter->tune_timer.cq_count += cqe_count; */
                                        nesdev->currcq_count += cqe_count;
                                        cqe_count = 0;
                                        nes_replenish_nic_rq(nesvnic);
@@ -2573,27 +2700,33 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                                        pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */
 
                                if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
-                                       nes_cm_recv(rx_skb, nesvnic->netdev);
+                                       if (nes_cm_recv(rx_skb, nesvnic->netdev))
+                                               rx_skb = NULL;
+                               }
+                               if (rx_skb == NULL)
+                                       goto skip_rx_indicate0;
+
+
+                               if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
+                                   (nesvnic->vlan_grp != NULL)) {
+                                       vlan_tag = (u16)(le32_to_cpu(
+                                                       cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
+                                                       >> 16);
+                                       nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
+                                                       nesvnic->netdev->name, vlan_tag);
+                                       if (nes_use_lro)
+                                               lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
+                                                               nesvnic->vlan_grp, vlan_tag, NULL);
+                                       else
+                                               nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
                                } else {
-                                       if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) {
-                                               vlan_tag = (u16)(le32_to_cpu(
-                                                               cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
-                                                               >> 16);
-                                               nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
-                                                               nesvnic->netdev->name, vlan_tag);
-                                               if (nes_use_lro)
-                                                       lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
-                                                                       nesvnic->vlan_grp, vlan_tag, NULL);
-                                               else
-                                                       nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
-                                       } else {
-                                               if (nes_use_lro)
-                                                       lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
-                                               else
-                                                       nes_netif_rx(rx_skb);
-                                       }
+                                       if (nes_use_lro)
+                                               lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
+                                       else
+                                               nes_netif_rx(rx_skb);
                                }
 
+skip_rx_indicate0:
                                nesvnic->netdev->last_rx = jiffies;
                                /* nesvnic->netstats.rx_packets++; */
                                /* nesvnic->netstats.rx_bytes += rx_pkt_size; */
@@ -2608,7 +2741,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                /* Replenish Nic CQ */
                                nes_write32(nesdev->regs+NES_CQE_ALLOC,
                                                cq->cq_number | (cqe_count << 16));
-//                             nesdev->nesadapter->tune_timer.cq_count += cqe_count;
+                               /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
                                nesdev->currcq_count += cqe_count;
                                cqe_count = 0;
                        }
@@ -2636,7 +2769,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
        cq->cqe_allocs_pending = cqe_count;
        if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
        {
-//             nesdev->nesadapter->tune_timer.cq_count += cqe_count;
+               /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
                nesdev->currcq_count += cqe_count;
                nes_nic_tune_timer(nesdev);
        }
@@ -2671,7 +2804,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 
                if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
                        u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
-                                       cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
+                                       cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
                                        ((u64)(le32_to_cpu(cq->cq_vbase[head].
                                        cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
                        cqp = *((struct nes_hw_cqp **)&u64temp);
@@ -2688,7 +2821,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
                        }
 
                        u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-                                       wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX])))<<32) |
+                                       wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
                                        ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
                                        wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
                        cqp_request = *((struct nes_cqp_request **)&u64temp);
@@ -2700,46 +2833,18 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
                                        barrier();
                                        cqp_request->request_done = 1;
                                        wake_up(&cqp_request->waitq);
-                                       if (atomic_dec_and_test(&cqp_request->refcount)) {
-                                               nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
-                                                               cqp_request,
-                                                               le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
-                                               if (cqp_request->dynamic) {
-                                                       kfree(cqp_request);
-                                               } else {
-                                                       spin_lock_irqsave(&nesdev->cqp.lock, flags);
-                                                       list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
-                                                       spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
-                                               }
-                                       }
-                               } else if (cqp_request->callback) {
-                                       /* Envoke the callback routine */
-                                       cqp_request->cqp_callback(nesdev, cqp_request);
-                                       if (cqp_request->dynamic) {
-                                               kfree(cqp_request);
-                                       } else {
-                                               spin_lock_irqsave(&nesdev->cqp.lock, flags);
-                                               list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
-                                               spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
-                                       }
+                                       nes_put_cqp_request(nesdev, cqp_request);
                                } else {
-                                       nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
-                                                       cqp_request,
-                                                       le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
-                                       if (cqp_request->dynamic) {
-                                               kfree(cqp_request);
-                                       } else {
-                                               spin_lock_irqsave(&nesdev->cqp.lock, flags);
-                                               list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
-                                               spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
-                                       }
+                                       if (cqp_request->callback)
+                                               cqp_request->cqp_callback(nesdev, cqp_request);
+                                       nes_free_cqp_request(nesdev, cqp_request);
                                }
                        } else {
                                wake_up(&nesdev->cqp.waitq);
                        }
 
                        cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
-                       nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16));
+                       nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
                        if (++cqp->sq_tail >= cqp->sq_size)
                                cqp->sq_tail = 0;
 
@@ -2808,13 +2913,13 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
        nes_debug(NES_DBG_AEQ, "\n");
        aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
        if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
-               context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
+               context  = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
                context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
        } else {
                aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
                aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
                context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
-                                               aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
+                                               aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
                BUG_ON(!context);
        }
 
@@ -2827,13 +2932,11 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
                        nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
 
-
        switch (async_event_id) {
                case NES_AEQE_AEID_LLP_FIN_RECEIVED:
                        nesqp = *((struct nes_qp **)&context);
                        if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
                                nesqp->cm_id->add_ref(nesqp->cm_id);
-                               nes_add_ref(&nesqp->ibqp);
                                schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
                                                NES_TIMER_TYPE_CLOSE, 1, 0);
                                nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
@@ -2857,7 +2960,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
                                tcp_state = NES_AEQE_TCP_STATE_CLOSED;
                        }
-                       nes_add_ref(&nesqp->ibqp);
                        spin_lock_irqsave(&nesqp->lock, flags);
                        nesqp->hw_iwarp_state = iwarp_state;
                        nesqp->hw_tcp_state = tcp_state;
@@ -2895,7 +2997,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                }
                                spin_unlock_irqrestore(&nesqp->lock, flags);
                                if (next_iwarp_state) {
-                                       nes_add_ref(&nesqp->ibqp);
                                        nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
                                                        " also added another reference\n",
                                                        nesqp->hwqp.qp_id, next_iwarp_state);
@@ -2907,7 +3008,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                        /* FIN Received but ib state not RTS,
                                                        close complete will be on its way */
                                        spin_unlock_irqrestore(&nesqp->lock, flags);
-                                       nes_rem_ref(&nesqp->ibqp);
                                        return;
                                }
                                spin_unlock_irqrestore(&nesqp->lock, flags);
@@ -2941,7 +3041,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
                                        ((nesqp->ibqp_state == IB_QPS_RTS)&&
                                        (async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
-                               nes_add_ref(&nesqp->ibqp);
                                nes_cm_disconn(nesqp);
                        } else {
                                nesqp->in_disconnect = 0;
@@ -2950,7 +3049,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        break;
                case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
                        nesqp = *((struct nes_qp **)&context);
-                       nes_add_ref(&nesqp->ibqp);
                        spin_lock_irqsave(&nesqp->lock, flags);
                        nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
                        nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
@@ -3061,7 +3159,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
@@ -3081,7 +3178,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
@@ -3101,10 +3197,25 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                                nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
                        }
                        /* tell cm to disconnect, cm will queue work to thread */
-                       nes_add_ref(&nesqp->ibqp);
                        nes_cm_disconn(nesqp);
                        break;
                        /* TODO: additional AEs need to be here */
+               case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
+                       nesqp = *((struct nes_qp **)&context);
+                       spin_lock_irqsave(&nesqp->lock, flags);
+                       nesqp->hw_iwarp_state = iwarp_state;
+                       nesqp->hw_tcp_state = tcp_state;
+                       nesqp->last_aeq = async_event_id;
+                       spin_unlock_irqrestore(&nesqp->lock, flags);
+                       if (nesqp->ibqp.event_handler) {
+                               ibevent.device = nesqp->ibqp.device;
+                               ibevent.element.qp = &nesqp->ibqp;
+                               ibevent.event = IB_EVENT_QP_ACCESS_ERR;
+                               nesqp->ibqp.event_handler(&ibevent,
+                                               nesqp->ibqp.qp_context);
+                       }
+                       nes_cm_disconn(nesqp);
+                       break;
                default:
                        nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
                                        async_event_id);
@@ -3140,7 +3251,6 @@ int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
 {
        struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_hw_cqp_wqe *cqp_wqe;
-       unsigned long flags;
        struct nes_cqp_request *cqp_request;
        int ret = 0;
        u16 major_code;
@@ -3167,7 +3277,7 @@ int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
        nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
 
        atomic_set(&cqp_request->refcount, 2);
-       nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
+       nes_post_cqp_request(nesdev, cqp_request);
 
        if (add_port == NES_MANAGE_APBVT_ADD)
                ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
@@ -3175,15 +3285,9 @@ int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
        nes_debug(NES_DBG_QP, "Completed, ret=%u,  CQP Major:Minor codes = 0x%04X:0x%04X\n",
                        ret, cqp_request->major_code, cqp_request->minor_code);
        major_code = cqp_request->major_code;
-       if (atomic_dec_and_test(&cqp_request->refcount)) {
-               if (cqp_request->dynamic) {
-                       kfree(cqp_request);
-               } else {
-                       spin_lock_irqsave(&nesdev->cqp.lock, flags);
-                       list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
-                       spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
-               }
-       }
+
+       nes_put_cqp_request(nesdev, cqp_request);
+
        if (!ret)
                return -ETIME;
        else if (major_code)
@@ -3231,7 +3335,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
                cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
                cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
                                (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
-                               (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
+                               (((u32)mac_addr[4]) << 8)  | (u32)mac_addr[5]);
                cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
                                (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
        } else {
@@ -3243,7 +3347,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
                        nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
 
        atomic_set(&cqp_request->refcount, 1);
-       nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
+       nes_post_cqp_request(nesdev, cqp_request);
 }
 
 
@@ -3253,7 +3357,6 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
 void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
                u32 which_wq, u32 wait_completion)
 {
-       unsigned long flags;
        struct nes_cqp_request *cqp_request;
        struct nes_hw_cqp_wqe *cqp_wqe;
        int ret;
@@ -3276,7 +3379,7 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
                        cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);
        cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);
 
-       nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
+       nes_post_cqp_request(nesdev, cqp_request);
 
        if (wait_completion) {
                /* Wait for CQP */
@@ -3285,14 +3388,6 @@ void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
                nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"
                                " CQP Major:Minor codes = 0x%04X:0x%04X\n",
                                ret, cqp_request->major_code, cqp_request->minor_code);
-               if (atomic_dec_and_test(&cqp_request->refcount)) {
-                       if (cqp_request->dynamic) {
-                               kfree(cqp_request);
-                       } else {
-                               spin_lock_irqsave(&nesdev->cqp.lock, flags);
-                               list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
-                               spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
-                       }
-               }
+               nes_put_cqp_request(nesdev, cqp_request);
        }
 }