Merge branch 'nvmf-4.8-rc' of git://git.infradead.org/nvme-fabrics into for-linus
authorJens Axboe <axboe@fb.com>
Tue, 13 Sep 2016 13:58:34 +0000 (07:58 -0600)
committerJens Axboe <axboe@fb.com>
Tue, 13 Sep 2016 13:58:34 +0000 (07:58 -0600)
Sagi writes:

Here we have:
- Kconfig dependencies fix from Arnd
- nvme-rdma device removal fixes from Steve
- possible bad deref fix from Colin

1  2 
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h

index b6a953aed7e83d6058164ca66af2516ab0981e23,5621270664f4949bca4a7153402145f597ff39b2..80f988984f4448ca42d53c1b9e2bba890948ec78
@@@ -294,25 -294,6 +294,25 @@@ static void state_set(struct c4iw_ep_co
        return;
  }
  
 +static int alloc_ep_skb_list(struct sk_buff_head *ep_skb_list, int size)
 +{
 +      struct sk_buff *skb;
 +      unsigned int i;
 +      size_t len;
 +
 +      len = roundup(sizeof(union cpl_wr_size), 16);
 +      for (i = 0; i < size; i++) {
 +              skb = alloc_skb(len, GFP_KERNEL);
 +              if (!skb)
 +                      goto fail;
 +              skb_queue_tail(ep_skb_list, skb);
 +      }
 +      return 0;
 +fail:
 +      skb_queue_purge(ep_skb_list);
 +      return -ENOMEM;
 +}
 +
  static void *alloc_ep(int size, gfp_t gfp)
  {
        struct c4iw_ep_common *epc;
@@@ -333,6 -314,8 +333,8 @@@ static void remove_ep_tid(struct c4iw_e
  
        spin_lock_irqsave(&ep->com.dev->lock, flags);
        _remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid, 0);
+       if (idr_is_empty(&ep->com.dev->hwtid_idr))
+               wake_up(&ep->com.dev->wait);
        spin_unlock_irqrestore(&ep->com.dev->lock, flags);
  }
  
@@@ -403,8 -386,6 +405,8 @@@ void _c4iw_free_ep(struct kref *kref
                if (ep->mpa_skb)
                        kfree_skb(ep->mpa_skb);
        }
 +      if (!skb_queue_empty(&ep->com.ep_skb_list))
 +              skb_queue_purge(&ep->com.ep_skb_list);
        kfree(ep);
  }
  
@@@ -641,27 -622,25 +643,27 @@@ static void abort_arp_failure(void *han
        }
  }
  
 -static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
 +static int send_flowc(struct c4iw_ep *ep)
  {
 -      unsigned int flowclen = 80;
        struct fw_flowc_wr *flowc;
 +      struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list);
        int i;
        u16 vlan = ep->l2t->vlan;
        int nparams;
  
 +      if (WARN_ON(!skb))
 +              return -ENOMEM;
 +
        if (vlan == CPL_L2T_VLAN_NONE)
                nparams = 8;
        else
                nparams = 9;
  
 -      skb = get_skb(skb, flowclen, GFP_KERNEL);
 -      flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen);
 +      flowc = (struct fw_flowc_wr *)__skb_put(skb, FLOWC_LEN);
  
        flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) |
                                           FW_FLOWC_WR_NPARAMS_V(nparams));
 -      flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen,
 +      flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(FLOWC_LEN,
                                          16)) | FW_WR_FLOWID_V(ep->hwtid));
  
        flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
        return c4iw_ofld_send(&ep->com.dev->rdev, skb);
  }
  
 -static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp)
 +static int send_halfclose(struct c4iw_ep *ep)
  {
        struct cpl_close_con_req *req;
 -      struct sk_buff *skb;
 +      struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list);
        int wrlen = roundup(sizeof *req, 16);
  
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 -      skb = get_skb(NULL, wrlen, gfp);
 -      if (!skb) {
 -              printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
 +      if (WARN_ON(!skb))
                return -ENOMEM;
 -      }
 +
        set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
        t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
        req = (struct cpl_close_con_req *) skb_put(skb, wrlen);
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
  }
  
 -static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
 +static int send_abort(struct c4iw_ep *ep)
  {
        struct cpl_abort_req *req;
        int wrlen = roundup(sizeof *req, 16);
 +      struct sk_buff *req_skb = skb_dequeue(&ep->com.ep_skb_list);
  
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 -      skb = get_skb(skb, wrlen, gfp);
 -      if (!skb) {
 -              printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
 -                     __func__);
 +      if (WARN_ON(!req_skb))
                return -ENOMEM;
 -      }
 -      set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
 -      t4_set_arp_err_handler(skb, ep, abort_arp_failure);
 -      req = (struct cpl_abort_req *) skb_put(skb, wrlen);
 +
 +      set_wr_txq(req_skb, CPL_PRIORITY_DATA, ep->txq_idx);
 +      t4_set_arp_err_handler(req_skb, ep, abort_arp_failure);
 +      req = (struct cpl_abort_req *)skb_put(req_skb, wrlen);
        memset(req, 0, wrlen);
        INIT_TP_WR(req, ep->hwtid);
        OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid));
        req->cmd = CPL_ABORT_SEND_RST;
 -      return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 +      return c4iw_l2t_send(&ep->com.dev->rdev, req_skb, ep->l2t);
  }
  
  static void best_mtu(const unsigned short *mtus, unsigned short mtu,
@@@ -1011,19 -994,9 +1013,19 @@@ static int send_mpa_req(struct c4iw_ep 
  
        mpa = (struct mpa_message *)(req + 1);
        memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
 -      mpa->flags = (crc_enabled ? MPA_CRC : 0) |
 -                   (markers_enabled ? MPA_MARKERS : 0) |
 -                   (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
 +
 +      mpa->flags = 0;
 +      if (crc_enabled)
 +              mpa->flags |= MPA_CRC;
 +      if (markers_enabled) {
 +              mpa->flags |= MPA_MARKERS;
 +              ep->mpa_attr.recv_marker_enabled = 1;
 +      } else {
 +              ep->mpa_attr.recv_marker_enabled = 0;
 +      }
 +      if (mpa_rev_to_use == 2)
 +              mpa->flags |= MPA_ENHANCED_RDMA_CONN;
 +
        mpa->private_data_size = htons(ep->plen);
        mpa->revision = mpa_rev_to_use;
        if (mpa_rev_to_use == 1) {
@@@ -1198,11 -1171,8 +1200,11 @@@ static int send_mpa_reply(struct c4iw_e
        mpa = (struct mpa_message *)(req + 1);
        memset(mpa, 0, sizeof(*mpa));
        memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
 -      mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
 -                   (markers_enabled ? MPA_MARKERS : 0);
 +      mpa->flags = 0;
 +      if (ep->mpa_attr.crc_enabled)
 +              mpa->flags |= MPA_CRC;
 +      if (ep->mpa_attr.recv_marker_enabled)
 +              mpa->flags |= MPA_MARKERS;
        mpa->revision = ep->mpa_attr.version;
        mpa->private_data_size = htons(plen);
  
@@@ -1280,7 -1250,7 +1282,7 @@@ static int act_establish(struct c4iw_de
        set_bit(ACT_ESTAB, &ep->com.history);
  
        /* start MPA negotiation */
 -      ret = send_flowc(ep, NULL);
 +      ret = send_flowc(ep);
        if (ret)
                goto err;
        if (ep->retry_with_mpa_v1)
@@@ -1587,6 -1557,7 +1589,6 @@@ static int process_mpa_reply(struct c4i
         */
        __state_set(&ep->com, FPDU_MODE);
        ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
 -      ep->mpa_attr.recv_marker_enabled = markers_enabled;
        ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
        ep->mpa_attr.version = mpa->revision;
        ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
@@@ -1827,12 -1798,8 +1829,12 @@@ static int process_mpa_request(struct c
                                (ep->mpa_pkt + sizeof(*mpa));
                        ep->ird = ntohs(mpa_v2_params->ird) &
                                MPA_V2_IRD_ORD_MASK;
 +                      ep->ird = min_t(u32, ep->ird,
 +                                      cur_max_read_depth(ep->com.dev));
                        ep->ord = ntohs(mpa_v2_params->ord) &
                                MPA_V2_IRD_ORD_MASK;
 +                      ep->ord = min_t(u32, ep->ord,
 +                                      cur_max_read_depth(ep->com.dev));
                        PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
                             ep->ord);
                        if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
@@@ -2039,17 -2006,12 +2041,17 @@@ static int send_fw_act_open_req(struct 
  }
  
  /*
 - * Return whether a failed active open has allocated a TID
 + * Some of the error codes above implicitly indicate that there is no TID
 + * allocated with the result of an ACT_OPEN.  We use this predicate to make
 + * that explicit.
   */
  static inline int act_open_has_tid(int status)
  {
 -      return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
 -             status != CPL_ERR_ARP_MISS;
 +      return (status != CPL_ERR_TCAM_PARITY &&
 +              status != CPL_ERR_TCAM_MISS &&
 +              status != CPL_ERR_TCAM_FULL &&
 +              status != CPL_ERR_CONN_EXIST_SYNRECV &&
 +              status != CPL_ERR_CONN_EXIST);
  }
  
  /* Returns whether a CPL status conveys negative advice.
@@@ -2117,8 -2079,10 +2119,10 @@@ static int import_ep(struct c4iw_ep *ep
                }
                ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
                                        n, pdev, rt_tos2priority(tos));
-               if (!ep->l2t)
+               if (!ep->l2t) {
+                       dev_put(pdev);
                        goto out;
+               }
                ep->mtu = pdev->mtu;
                ep->tx_chan = cxgb4_port_chan(pdev);
                ep->smac_idx = cxgb4_tp_smt_idx(adapter_type,
@@@ -2170,7 -2134,6 +2174,7 @@@ out
  static int c4iw_reconnect(struct c4iw_ep *ep)
  {
        int err = 0;
 +      int size = 0;
        struct sockaddr_in *laddr = (struct sockaddr_in *)
                                    &ep->com.cm_id->m_local_addr;
        struct sockaddr_in *raddr = (struct sockaddr_in *)
        init_timer(&ep->timer);
        c4iw_init_wr_wait(&ep->com.wr_wait);
  
 +      /* When MPA revision is different on nodes, the node with MPA_rev=2
 +       * tries to reconnect with MPA_rev 1 for the same EP through
 +       * c4iw_reconnect(), where the same EP is assigned with new tid for
 +       * further connection establishment. As we are using the same EP pointer
 +       * for reconnect, few skbs are used during the previous c4iw_connect(),
 +       * which leaves the EP with inadequate skbs for further
 +       * c4iw_reconnect(), Further causing an assert BUG_ON() due to empty
 +       * skb_list() during peer_abort(). Allocate skbs which is already used.
 +       */
 +      size = (CN_MAX_CON_BUF - skb_queue_len(&ep->com.ep_skb_list));
 +      if (alloc_ep_skb_list(&ep->com.ep_skb_list, size)) {
 +              err = -ENOMEM;
 +              goto fail1;
 +      }
 +
        /*
         * Allocate an active TID to initiate a TCP connection.
         */
@@@ -2266,7 -2214,6 +2270,7 @@@ fail2
         * response of 1st connect request.
         */
        connect_reply_upcall(ep, -ECONNRESET);
 +fail1:
        c4iw_put_ep(&ep->com);
  out:
        return err;
@@@ -2633,10 -2580,6 +2637,10 @@@ static int pass_accept_req(struct c4iw_
        if (peer_mss && child_ep->mtu > (peer_mss + hdrs))
                child_ep->mtu = peer_mss + hdrs;
  
 +      skb_queue_head_init(&child_ep->com.ep_skb_list);
 +      if (alloc_ep_skb_list(&child_ep->com.ep_skb_list, CN_MAX_CON_BUF))
 +              goto fail;
 +
        state_set(&child_ep->com, CONNECTING);
        child_ep->com.dev = dev;
        child_ep->com.cm_id = NULL;
                               (const u32 *)&sin6->sin6_addr.s6_addr, 1);
        }
        goto out;
 +fail:
 +      c4iw_put_ep(&child_ep->com);
  reject:
        reject_cr(dev, hwtid, skb);
        if (parent_ep)
@@@ -2733,7 -2674,7 +2737,7 @@@ static int pass_establish(struct c4iw_d
        ep->com.state = MPA_REQ_WAIT;
        start_ep_timer(ep);
        set_bit(PASS_ESTAB, &ep->com.history);
 -      ret = send_flowc(ep, skb);
 +      ret = send_flowc(ep);
        mutex_unlock(&ep->com.mutex);
        if (ret)
                c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
@@@ -2934,8 -2875,10 +2938,8 @@@ static int peer_abort(struct c4iw_dev *
        }
        mutex_unlock(&ep->com.mutex);
  
 -      rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
 -      if (!rpl_skb) {
 -              printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
 -                     __func__);
 +      rpl_skb = skb_dequeue(&ep->com.ep_skb_list);
 +      if (WARN_ON(!rpl_skb)) {
                release = 1;
                goto out;
        }
@@@ -3072,9 -3015,9 +3076,9 @@@ static int fw4_ack(struct c4iw_dev *dev
                PDBG("%s last streaming msg ack ep %p tid %u state %u "
                     "initiator %u freeing skb\n", __func__, ep, ep->hwtid,
                     state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0);
 +              mutex_lock(&ep->com.mutex);
                kfree_skb(ep->mpa_skb);
                ep->mpa_skb = NULL;
 -              mutex_lock(&ep->com.mutex);
                if (test_bit(STOP_MPA_TIMER, &ep->com.flags))
                        stop_ep_timer(ep);
                mutex_unlock(&ep->com.mutex);
@@@ -3086,9 -3029,9 +3090,9 @@@ out
  
  int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
  {
 -      int err = 0;
 -      int disconnect = 0;
 +      int abort;
        struct c4iw_ep *ep = to_ep(cm_id);
 +
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
  
        mutex_lock(&ep->com.mutex);
        }
        set_bit(ULP_REJECT, &ep->com.history);
        if (mpa_rev == 0)
 -              disconnect = 2;
 -      else {
 -              err = send_mpa_reject(ep, pdata, pdata_len);
 -              disconnect = 1;
 -      }
 +              abort = 1;
 +      else
 +              abort = send_mpa_reject(ep, pdata, pdata_len);
        mutex_unlock(&ep->com.mutex);
 -      if (disconnect) {
 -              stop_ep_timer(ep);
 -              err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
 -      }
 +
 +      stop_ep_timer(ep);
 +      c4iw_ep_disconnect(ep, abort != 0, GFP_KERNEL);
        c4iw_put_ep(&ep->com);
        return 0;
  }
@@@ -3140,7 -3086,7 +3144,7 @@@ int c4iw_accept_cr(struct iw_cm_id *cm_
        if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
                if (conn_param->ord > ep->ird) {
                        if (RELAXED_IRD_NEGOTIATION) {
 -                              ep->ord = ep->ird;
 +                              conn_param->ord = ep->ird;
                        } else {
                                ep->ird = conn_param->ird;
                                ep->ord = conn_param->ord;
@@@ -3306,13 -3252,6 +3310,13 @@@ int c4iw_connect(struct iw_cm_id *cm_id
                err = -ENOMEM;
                goto out;
        }
 +
 +      skb_queue_head_init(&ep->com.ep_skb_list);
 +      if (alloc_ep_skb_list(&ep->com.ep_skb_list, CN_MAX_CON_BUF)) {
 +              err = -ENOMEM;
 +              goto fail1;
 +      }
 +
        init_timer(&ep->timer);
        ep->plen = conn_param->private_data_len;
        if (ep->plen)
        if (!ep->com.qp) {
                PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn);
                err = -EINVAL;
 -              goto fail1;
 +              goto fail2;
        }
        ref_qp(ep);
        PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
        if (ep->atid == -1) {
                printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
                err = -ENOMEM;
 -              goto fail1;
 +              goto fail2;
        }
        insert_handle(dev, &dev->atid_idr, ep, ep->atid);
  
                if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) {
                        err = pick_local_ipaddrs(dev, cm_id);
                        if (err)
 -                              goto fail1;
 +                              goto fail2;
                }
  
                /* find a route */
                if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) {
                        err = pick_local_ip6addrs(dev, cm_id);
                        if (err)
 -                              goto fail1;
 +                              goto fail2;
                }
  
                /* find a route */
        if (!ep->dst) {
                printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
                err = -EHOSTUNREACH;
 -              goto fail2;
 +              goto fail3;
        }
  
        err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true,
                        ep->com.dev->rdev.lldi.adapter_type, cm_id->tos);
        if (err) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
 -              goto fail3;
 +              goto fail4;
        }
  
        PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
                goto out;
  
        cxgb4_l2t_release(ep->l2t);
 -fail3:
 +fail4:
        dst_release(ep->dst);
 -fail2:
 +fail3:
        remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
        cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
 -fail1:
 +fail2:
 +      skb_queue_purge(&ep->com.ep_skb_list);
        deref_cm_id(&ep->com);
 +fail1:
        c4iw_put_ep(&ep->com);
  out:
        return err;
@@@ -3528,7 -3465,6 +3532,7 @@@ int c4iw_create_listen(struct iw_cm_id 
                err = -ENOMEM;
                goto fail1;
        }
 +      skb_queue_head_init(&ep->com.ep_skb_list);
        PDBG("%s ep %p\n", __func__, ep);
        ep->com.cm_id = cm_id;
        ref_cm_id(&ep->com);
@@@ -3645,22 -3581,11 +3649,22 @@@ int c4iw_ep_disconnect(struct c4iw_ep *
        case MPA_REQ_RCVD:
        case MPA_REP_SENT:
        case FPDU_MODE:
 +      case CONNECTING:
                close = 1;
                if (abrupt)
                        ep->com.state = ABORTING;
                else {
                        ep->com.state = CLOSING;
 +
 +                      /*
 +                       * if we close before we see the fw4_ack() then we fix
 +                       * up the timer state since we're reusing it.
 +                       */
 +                      if (ep->mpa_skb &&
 +                          test_bit(STOP_MPA_TIMER, &ep->com.flags)) {
 +                              clear_bit(STOP_MPA_TIMER, &ep->com.flags);
 +                              stop_ep_timer(ep);
 +                      }
                        start_ep_timer(ep);
                }
                set_bit(CLOSE_SENT, &ep->com.flags);
                if (abrupt) {
                        set_bit(EP_DISC_ABORT, &ep->com.history);
                        close_complete_upcall(ep, -ECONNRESET);
 -                      ret = send_abort(ep, NULL, gfp);
 +                      ret = send_abort(ep);
                } else {
                        set_bit(EP_DISC_CLOSE, &ep->com.history);
 -                      ret = send_halfclose(ep, gfp);
 +                      ret = send_halfclose(ep);
                }
                if (ret) {
                        set_bit(EP_DISC_FAIL, &ep->com.history);
index 071d7332ec061489080a9ef55c1a6cbd9622af4d,63561aa9c69e7218e5972e47be9e84a99fbd2e97..3c4b2126e0d12e319a7779505673a651af689211
@@@ -317,7 -317,7 +317,7 @@@ static int qp_open(struct inode *inode
        idr_for_each(&qpd->devp->qpidr, count_idrs, &count);
        spin_unlock_irq(&qpd->devp->lock);
  
 -      qpd->bufsize = count * 128;
 +      qpd->bufsize = count * 180;
        qpd->buf = vmalloc(qpd->bufsize);
        if (!qpd->buf) {
                kfree(qpd);
@@@ -872,9 -872,13 +872,13 @@@ static void c4iw_rdev_close(struct c4iw
  static void c4iw_dealloc(struct uld_ctx *ctx)
  {
        c4iw_rdev_close(&ctx->dev->rdev);
+       WARN_ON_ONCE(!idr_is_empty(&ctx->dev->cqidr));
        idr_destroy(&ctx->dev->cqidr);
+       WARN_ON_ONCE(!idr_is_empty(&ctx->dev->qpidr));
        idr_destroy(&ctx->dev->qpidr);
+       WARN_ON_ONCE(!idr_is_empty(&ctx->dev->mmidr));
        idr_destroy(&ctx->dev->mmidr);
+       wait_event(ctx->dev->wait, idr_is_empty(&ctx->dev->hwtid_idr));
        idr_destroy(&ctx->dev->hwtid_idr);
        idr_destroy(&ctx->dev->stid_idr);
        idr_destroy(&ctx->dev->atid_idr);
@@@ -992,6 -996,7 +996,7 @@@ static struct c4iw_dev *c4iw_alloc(cons
        mutex_init(&devp->rdev.stats.lock);
        mutex_init(&devp->db_mutex);
        INIT_LIST_HEAD(&devp->db_fc_list);
+       init_waitqueue_head(&devp->wait);
        devp->avail_ird = devp->rdev.lldi.max_ird_adapter;
  
        if (c4iw_debugfs_root) {
index aa47e0ae80bc4c42d7a0009714a26be8e0ff7bbb,0e9cd4479bb3fcf833699116bf7c760a68226837..4b83b84f7ddf4fe56f6c9d573b0a7f00a629db74
@@@ -263,6 -263,7 +263,7 @@@ struct c4iw_dev 
        struct idr stid_idr;
        struct list_head db_fc_list;
        u32 avail_ird;
+       wait_queue_head_t wait;
  };
  
  static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
@@@ -384,7 -385,6 +385,7 @@@ struct c4iw_mr 
        struct ib_mr ibmr;
        struct ib_umem *umem;
        struct c4iw_dev *rhp;
 +      struct sk_buff *dereg_skb;
        u64 kva;
        struct tpt_attributes attr;
        u64 *mpl;
@@@ -401,7 -401,6 +402,7 @@@ static inline struct c4iw_mr *to_c4iw_m
  struct c4iw_mw {
        struct ib_mw ibmw;
        struct c4iw_dev *rhp;
 +      struct sk_buff *dereg_skb;
        u64 kva;
        struct tpt_attributes attr;
  };
@@@ -414,7 -413,6 +415,7 @@@ static inline struct c4iw_mw *to_c4iw_m
  struct c4iw_cq {
        struct ib_cq ibcq;
        struct c4iw_dev *rhp;
 +      struct sk_buff *destroy_skb;
        struct t4_cq cq;
        spinlock_t lock;
        spinlock_t comp_handler_lock;
@@@ -475,7 -473,7 +476,7 @@@ struct c4iw_qp 
        struct t4_wq wq;
        spinlock_t lock;
        struct mutex mutex;
 -      atomic_t refcnt;
 +      struct kref kref;
        wait_queue_head_t wait;
        struct timer_list timer;
        int sq_sig_all;
@@@ -792,29 -790,10 +793,29 @@@ enum c4iw_ep_history 
        CM_ID_DEREFED           = 28,
  };
  
 +enum conn_pre_alloc_buffers {
 +      CN_ABORT_REQ_BUF,
 +      CN_ABORT_RPL_BUF,
 +      CN_CLOSE_CON_REQ_BUF,
 +      CN_DESTROY_BUF,
 +      CN_FLOWC_BUF,
 +      CN_MAX_CON_BUF
 +};
 +
 +#define FLOWC_LEN 80
 +union cpl_wr_size {
 +      struct cpl_abort_req abrt_req;
 +      struct cpl_abort_rpl abrt_rpl;
 +      struct fw_ri_wr ri_req;
 +      struct cpl_close_con_req close_req;
 +      char flowc_buf[FLOWC_LEN];
 +};
 +
  struct c4iw_ep_common {
        struct iw_cm_id *cm_id;
        struct c4iw_qp *qp;
        struct c4iw_dev *dev;
 +      struct sk_buff_head ep_skb_list;
        enum c4iw_ep_state state;
        struct kref kref;
        struct mutex mutex;