Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Aug 2010 00:08:02 +0000 (17:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Aug 2010 00:08:02 +0000 (17:08 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (42 commits)
  IB/qib: Add missing <linux/slab.h> include
  IB/ehca: Drop unnecessary NULL test
  RDMA/nes: Fix confusing if statement indentation
  IB/ehca: Init irq tasklet before irq can happen
  RDMA/nes: Fix misindented code
  RDMA/nes: Fix showing wqm_quanta
  RDMA/nes: Get rid of "set but not used" variables
  RDMA/nes: Read firmware version from correct place
  IB/srp: Export req_lim via sysfs
  IB/srp: Make receive buffer handling more robust
  IB/srp: Use print_hex_dump()
  IB: Rename RAW_ETY to RAW_ETHERTYPE
  RDMA/nes: Fix two sparse warnings
  RDMA/cxgb3: Make needlessly global iwch_l2t_send() static
  IB/iser: Make needlessly global iser_alloc_rx_descriptors() static
  RDMA/cxgb4: Add timeouts when waiting for FW responses
  IB/qib: Fix race between qib_error_qp() and receive packet processing
  IB/qib: Limit the number of packets processed per interrupt
  IB/qib: Allow writes to the diag_counters to be able to clear them
  IB/qib: Set cfgctxts to number of CPUs by default
  ...

1  2 
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_nic.c

@@@ -137,7 -137,7 +137,7 @@@ static void stop_ep_timer(struct iwch_e
        put_ep(&ep->com);
  }
  
- int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2e)
static int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2e)
  {
        int     error = 0;
        struct cxio_rdev *rdev;
@@@ -1364,7 -1364,7 +1364,7 @@@ static int pass_accept_req(struct t3cde
                       __func__);
                goto reject;
        }
 -      dst = &rt->u.dst;
 +      dst = &rt->dst;
        l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
@@@ -1932,7 -1932,7 +1932,7 @@@ int iwch_connect(struct iw_cm_id *cm_id
                err = -EHOSTUNREACH;
                goto fail3;
        }
 -      ep->dst = &rt->u.dst;
 +      ep->dst = &rt->dst;
  
        /* get a l2t entry */
        ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
@@@ -371,7 -371,7 +371,7 @@@ int iwch_post_send(struct ib_qp *ibqp, 
        }
        num_wrs = Q_FREECNT(qhp->wq.sq_rptr, qhp->wq.sq_wptr,
                  qhp->wq.sq_size_log2);
-       if (num_wrs <= 0) {
+       if (num_wrs == 0) {
                spin_unlock_irqrestore(&qhp->lock, flag);
                err = -ENOMEM;
                goto out;
@@@ -554,7 -554,7 +554,7 @@@ int iwch_bind_mw(struct ib_qp *qp
        }
        num_wrs = Q_FREECNT(qhp->wq.sq_rptr, qhp->wq.sq_wptr,
                            qhp->wq.sq_size_log2);
-       if ((num_wrs) <= 0) {
+       if (num_wrs == 0) {
                spin_unlock_irqrestore(&qhp->lock, flag);
                return -ENOMEM;
        }
@@@ -816,7 -816,7 +816,7 @@@ static void __flush_qp(struct iwch_qp *
        atomic_inc(&qhp->refcnt);
        spin_unlock_irqrestore(&qhp->lock, *flag);
  
 -      /* locking heirarchy: cq lock first, then qp lock. */
 +      /* locking hierarchy: cq lock first, then qp lock. */
        spin_lock_irqsave(&rchp->lock, *flag);
        spin_lock(&qhp->lock);
        cxio_flush_hw_cq(&rchp->cq);
        if (flushed)
                (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
  
 -      /* locking heirarchy: cq lock first, then qp lock. */
 +      /* locking hierarchy: cq lock first, then qp lock. */
        spin_lock_irqsave(&schp->lock, *flag);
        spin_lock(&qhp->lock);
        cxio_flush_hw_cq(&schp->cq);
@@@ -61,6 -61,10 +61,10 @@@ static char *states[] = 
        NULL,
  };
  
+ static int dack_mode;
+ module_param(dack_mode, int, 0644);
+ MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=0)");
  int c4iw_max_read_depth = 8;
  module_param(c4iw_max_read_depth, int, 0644);
  MODULE_PARM_DESC(c4iw_max_read_depth, "Per-connection max ORD/IRD (default=8)");
@@@ -469,11 -473,12 +473,12 @@@ static int send_connect(struct c4iw_ep 
                       __func__);
                return -ENOMEM;
        }
-       set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->txq_idx);
+       set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
  
        cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
        wscale = compute_wscale(rcv_win);
        opt0 = KEEP_ALIVE(1) |
+              DELACK(1) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
               L2T_IDX(ep->l2t->idx) |
@@@ -780,11 -785,11 +785,11 @@@ static void connect_reply_upcall(struc
                event.private_data_len = ep->plen;
                event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
        }
-       if (ep->com.cm_id) {
-               PDBG("%s ep %p tid %u status %d\n", __func__, ep,
-                    ep->hwtid, status);
-               ep->com.cm_id->event_handler(ep->com.cm_id, &event);
-       }
+       PDBG("%s ep %p tid %u status %d\n", __func__, ep,
+            ep->hwtid, status);
+       ep->com.cm_id->event_handler(ep->com.cm_id, &event);
        if (status < 0) {
                ep->com.cm_id->rem_ref(ep->com.cm_id);
                ep->com.cm_id = NULL;
@@@ -845,8 -850,10 +850,10 @@@ static int update_rx_credits(struct c4i
        INIT_TP_WR(req, ep->hwtid);
        OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
                                                    ep->hwtid));
-       req->credit_dack = cpu_to_be32(credits);
-       set_wr_txq(skb, CPL_PRIORITY_ACK, ep->txq_idx);
+       req->credit_dack = cpu_to_be32(credits | RX_FORCE_ACK(1) |
+                                      F_RX_DACK_CHANGE |
+                                      V_RX_DACK_MODE(dack_mode));
+       set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx);
        c4iw_ofld_send(&ep->com.dev->rdev, skb);
        return credits;
  }
@@@ -1264,6 -1271,7 +1271,7 @@@ static void accept_cr(struct c4iw_ep *e
        cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx);
        wscale = compute_wscale(rcv_win);
        opt0 = KEEP_ALIVE(1) |
+              DELACK(1) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
               L2T_IDX(ep->l2t->idx) |
                                      ep->hwtid));
        rpl->opt0 = cpu_to_be64(opt0);
        rpl->opt2 = cpu_to_be32(opt2);
-       set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->txq_idx);
+       set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
        c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
  
        return;
@@@ -1344,7 -1352,7 +1352,7 @@@ static int pass_accept_req(struct c4iw_
        u16 rss_qid;
        u32 mtu;
        int step;
-       int txq_idx;
+       int txq_idx, ctrlq_idx;
  
        parent_ep = lookup_stid(t, stid);
        PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
                       __func__);
                goto reject;
        }
 -      dst = &rt->u.dst;
 +      dst = &rt->dst;
        if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
                pdev = ip_dev_find(&init_net, peer_ip);
                BUG_ON(!pdev);
                smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
                step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
                txq_idx = cxgb4_port_idx(pdev) * step;
+               ctrlq_idx = cxgb4_port_idx(pdev);
                step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
                rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
                dev_put(pdev);
                smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
                step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
                txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
+               ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
                step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
                rss_qid = dev->rdev.lldi.rxq_ids[
                          cxgb4_port_idx(dst->neighbour->dev) * step];
        child_ep->rss_qid = rss_qid;
        child_ep->mtu = mtu;
        child_ep->txq_idx = txq_idx;
+       child_ep->ctrlq_idx = ctrlq_idx;
  
        PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__,
             tx_chan, smac_idx, rss_qid);
@@@ -1473,8 -1484,6 +1484,6 @@@ static int peer_close(struct c4iw_dev *
        int closing = 0;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(hdr);
-       int start_timer = 0;
-       int stop_timer = 0;
  
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
                wake_up(&ep->com.waitq);
                break;
        case FPDU_MODE:
-               start_timer = 1;
+               start_ep_timer(ep);
                __state_set(&ep->com, CLOSING);
                closing = 1;
                peer_close_upcall(ep);
                disconnect = 0;
                break;
        case MORIBUND:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                if (ep->com.cm_id && ep->com.qp) {
                        attrs.next_state = C4IW_QP_STATE_IDLE;
                        c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
                c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
        }
-       if (start_timer)
-               start_ep_timer(ep);
-       if (stop_timer)
-               stop_ep_timer(ep);
        if (disconnect)
                c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
        if (release)
@@@ -1579,7 -1584,6 +1584,6 @@@ static int peer_abort(struct c4iw_dev *
        unsigned long flags;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(req);
-       int stop_timer = 0;
  
        ep = lookup_tid(t, tid);
        if (is_neg_adv_abort(req->status)) {
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                break;
        case MPA_REQ_SENT:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                connect_reply_upcall(ep, -ECONNRESET);
                break;
        case MPA_REP_SENT:
                break;
        case MORIBUND:
        case CLOSING:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                /*FALLTHROUGH*/
        case FPDU_MODE:
                if (ep->com.cm_id && ep->com.qp) {
        rpl->cmd = CPL_ABORT_NO_RST;
        c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb);
  out:
-       if (stop_timer)
-               stop_ep_timer(ep);
        if (release)
                release_ep_resources(ep);
        return 0;
@@@ -1683,7 -1685,6 +1685,6 @@@ static int close_con_rpl(struct c4iw_de
        int release = 0;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(rpl);
-       int stop_timer = 0;
  
        ep = lookup_tid(t, tid);
  
                __state_set(&ep->com, MORIBUND);
                break;
        case MORIBUND:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                if ((ep->com.cm_id) && (ep->com.qp)) {
                        attrs.next_state = C4IW_QP_STATE_IDLE;
                        c4iw_modify_qp(ep->com.qp->rhp,
                break;
        }
        spin_unlock_irqrestore(&ep->com.lock, flags);
-       if (stop_timer)
-               stop_ep_timer(ep);
        if (release)
                release_ep_resources(ep);
        return 0;
@@@ -1939,7 -1938,7 +1938,7 @@@ int c4iw_connect(struct iw_cm_id *cm_id
                err = -EHOSTUNREACH;
                goto fail3;
        }
 -      ep->dst = &rt->u.dst;
 +      ep->dst = &rt->dst;
  
        /* get a l2t entry */
        if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
                ep->txq_idx = cxgb4_port_idx(pdev) * step;
                step = ep->com.dev->rdev.lldi.nrxq /
                       ep->com.dev->rdev.lldi.nchan;
+               ep->ctrlq_idx = cxgb4_port_idx(pdev);
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
                              cxgb4_port_idx(pdev) * step];
                dev_put(pdev);
                step = ep->com.dev->rdev.lldi.ntxq /
                       ep->com.dev->rdev.lldi.nchan;
                ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
+               ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
                step = ep->com.dev->rdev.lldi.nrxq /
                       ep->com.dev->rdev.lldi.nchan;
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
@@@ -2049,8 -2050,15 +2050,15 @@@ int c4iw_create_listen(struct iw_cm_id 
                goto fail3;
  
        /* wait for pass_open_rpl */
-       wait_event(ep->com.waitq, ep->com.rpl_done);
-       err = ep->com.rpl_err;
+       wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
+       if (ep->com.rpl_done)
+               err = ep->com.rpl_err;
+       else {
+               printk(KERN_ERR MOD "Device %s not responding!\n",
+                      pci_name(ep->com.dev->rdev.lldi.pdev));
+               ep->com.dev->rdev.flags = T4_FATAL_ERROR;
+               err = -EIO;
+       }
        if (!err) {
                cm_id->provider_data = ep;
                goto out;
@@@ -2079,10 -2087,17 +2087,17 @@@ int c4iw_destroy_listen(struct iw_cm_i
        err = listen_stop(ep);
        if (err)
                goto done;
-       wait_event(ep->com.waitq, ep->com.rpl_done);
+       wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
+       if (ep->com.rpl_done)
+               err = ep->com.rpl_err;
+       else {
+               printk(KERN_ERR MOD "Device %s not responding!\n",
+                      pci_name(ep->com.dev->rdev.lldi.pdev));
+               ep->com.dev->rdev.flags = T4_FATAL_ERROR;
+               err = -EIO;
+       }
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET);
  done:
-       err = ep->com.rpl_err;
        cm_id->rem_ref(cm_id);
        c4iw_put_ep(&ep->com);
        return err;
@@@ -2095,8 -2110,6 +2110,6 @@@ int c4iw_ep_disconnect(struct c4iw_ep *
        int close = 0;
        int fatal = 0;
        struct c4iw_rdev *rdev;
-       int start_timer = 0;
-       int stop_timer = 0;
  
        spin_lock_irqsave(&ep->com.lock, flags);
  
                        ep->com.state = ABORTING;
                else {
                        ep->com.state = CLOSING;
-                       start_timer = 1;
+                       start_ep_timer(ep);
                }
                set_bit(CLOSE_SENT, &ep->com.flags);
                break;
                if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
                        close = 1;
                        if (abrupt) {
-                               stop_timer = 1;
+                               stop_ep_timer(ep);
                                ep->com.state = ABORTING;
                        } else
                                ep->com.state = MORIBUND;
        }
  
        spin_unlock_irqrestore(&ep->com.lock, flags);
-       if (start_timer)
-               start_ep_timer(ep);
-       if (stop_timer)
-               stop_ep_timer(ep);
        if (close) {
                if (abrupt)
                        ret = abort_connection(ep, NULL, gfp);
@@@ -2244,7 -2253,7 +2253,7 @@@ static void process_work(struct work_st
  {
        struct sk_buff *skb = NULL;
        struct c4iw_dev *dev;
-       struct cpl_act_establish *rpl = cplhdr(skb);
+       struct cpl_act_establish *rpl;
        unsigned int opcode;
        int ret;
  
@@@ -130,7 -130,7 +130,7 @@@ static int create_qp(struct c4iw_rdev *
        /* build fw_ri_res_wr */
        wr_len = sizeof *res_wr + 2 * sizeof *res;
  
-       skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL);
+       skb = alloc_skb(wr_len, GFP_KERNEL);
        if (!skb) {
                ret = -ENOMEM;
                goto err7;
        res->u.sqrq.dcaen_to_eqsize = cpu_to_be32(
                V_FW_RI_RES_WR_DCAEN(0) |
                V_FW_RI_RES_WR_DCACPU(0) |
-               V_FW_RI_RES_WR_FBMIN(3) |
+               V_FW_RI_RES_WR_FBMIN(2) |
                V_FW_RI_RES_WR_FBMAX(3) |
                V_FW_RI_RES_WR_CIDXFTHRESHO(0) |
                V_FW_RI_RES_WR_CIDXFTHRESH(0) |
        res->u.sqrq.dcaen_to_eqsize = cpu_to_be32(
                V_FW_RI_RES_WR_DCAEN(0) |
                V_FW_RI_RES_WR_DCACPU(0) |
-               V_FW_RI_RES_WR_FBMIN(3) |
+               V_FW_RI_RES_WR_FBMIN(2) |
                V_FW_RI_RES_WR_FBMAX(3) |
                V_FW_RI_RES_WR_CIDXFTHRESHO(0) |
                V_FW_RI_RES_WR_CIDXFTHRESH(0) |
@@@ -235,12 -235,78 +235,78 @@@ err1
        return -ENOMEM;
  }
  
- static int build_rdma_send(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
+ static int build_immd(struct t4_sq *sq, struct fw_ri_immd *immdp,
+                     struct ib_send_wr *wr, int max, u32 *plenp)
  {
+       u8 *dstp, *srcp;
+       u32 plen = 0;
        int i;
+       int rem, len;
+       dstp = (u8 *)immdp->data;
+       for (i = 0; i < wr->num_sge; i++) {
+               if ((plen + wr->sg_list[i].length) > max)
+                       return -EMSGSIZE;
+               srcp = (u8 *)(unsigned long)wr->sg_list[i].addr;
+               plen += wr->sg_list[i].length;
+               rem = wr->sg_list[i].length;
+               while (rem) {
+                       if (dstp == (u8 *)&sq->queue[sq->size])
+                               dstp = (u8 *)sq->queue;
+                       if (rem <= (u8 *)&sq->queue[sq->size] - dstp)
+                               len = rem;
+                       else
+                               len = (u8 *)&sq->queue[sq->size] - dstp;
+                       memcpy(dstp, srcp, len);
+                       dstp += len;
+                       srcp += len;
+                       rem -= len;
+               }
+       }
+       immdp->op = FW_RI_DATA_IMMD;
+       immdp->r1 = 0;
+       immdp->r2 = 0;
+       immdp->immdlen = cpu_to_be32(plen);
+       *plenp = plen;
+       return 0;
+ }
+ static int build_isgl(__be64 *queue_start, __be64 *queue_end,
+                     struct fw_ri_isgl *isglp, struct ib_sge *sg_list,
+                     int num_sge, u32 *plenp)
+ {
+       int i;
+       u32 plen = 0;
+       __be64 *flitp = (__be64 *)isglp->sge;
+       for (i = 0; i < num_sge; i++) {
+               if ((plen + sg_list[i].length) < plen)
+                       return -EMSGSIZE;
+               plen += sg_list[i].length;
+               *flitp = cpu_to_be64(((u64)sg_list[i].lkey << 32) |
+                                    sg_list[i].length);
+               if (++flitp == queue_end)
+                       flitp = queue_start;
+               *flitp = cpu_to_be64(sg_list[i].addr);
+               if (++flitp == queue_end)
+                       flitp = queue_start;
+       }
+       isglp->op = FW_RI_DATA_ISGL;
+       isglp->r1 = 0;
+       isglp->nsge = cpu_to_be16(num_sge);
+       isglp->r2 = 0;
+       if (plenp)
+               *plenp = plen;
+       return 0;
+ }
+ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe,
+                          struct ib_send_wr *wr, u8 *len16)
+ {
        u32 plen;
        int size;
-       u8 *datap;
+       int ret;
  
        if (wr->num_sge > T4_MAX_SEND_SGE)
                return -EINVAL;
        default:
                return -EINVAL;
        }
        plen = 0;
        if (wr->num_sge) {
                if (wr->send_flags & IB_SEND_INLINE) {
-                       datap = (u8 *)wqe->send.u.immd_src[0].data;
-                       for (i = 0; i < wr->num_sge; i++) {
-                               if ((plen + wr->sg_list[i].length) >
-                                   T4_MAX_SEND_INLINE) {
-                                       return -EMSGSIZE;
-                               }
-                               plen += wr->sg_list[i].length;
-                               memcpy(datap,
-                                    (void *)(unsigned long)wr->sg_list[i].addr,
-                                    wr->sg_list[i].length);
-                               datap += wr->sg_list[i].length;
-                       }
-                       wqe->send.u.immd_src[0].op = FW_RI_DATA_IMMD;
-                       wqe->send.u.immd_src[0].r1 = 0;
-                       wqe->send.u.immd_src[0].r2 = 0;
-                       wqe->send.u.immd_src[0].immdlen = cpu_to_be32(plen);
+                       ret = build_immd(sq, wqe->send.u.immd_src, wr,
+                                        T4_MAX_SEND_INLINE, &plen);
+                       if (ret)
+                               return ret;
                        size = sizeof wqe->send + sizeof(struct fw_ri_immd) +
                               plen;
                } else {
-                       for (i = 0; i < wr->num_sge; i++) {
-                               if ((plen + wr->sg_list[i].length) < plen)
-                                       return -EMSGSIZE;
-                               plen += wr->sg_list[i].length;
-                               wqe->send.u.isgl_src[0].sge[i].stag =
-                                       cpu_to_be32(wr->sg_list[i].lkey);
-                               wqe->send.u.isgl_src[0].sge[i].len =
-                                       cpu_to_be32(wr->sg_list[i].length);
-                               wqe->send.u.isgl_src[0].sge[i].to =
-                                       cpu_to_be64(wr->sg_list[i].addr);
-                       }
-                       wqe->send.u.isgl_src[0].op = FW_RI_DATA_ISGL;
-                       wqe->send.u.isgl_src[0].r1 = 0;
-                       wqe->send.u.isgl_src[0].nsge = cpu_to_be16(wr->num_sge);
-                       wqe->send.u.isgl_src[0].r2 = 0;
+                       ret = build_isgl((__be64 *)sq->queue,
+                                        (__be64 *)&sq->queue[sq->size],
+                                        wqe->send.u.isgl_src,
+                                        wr->sg_list, wr->num_sge, &plen);
+                       if (ret)
+                               return ret;
                        size = sizeof wqe->send + sizeof(struct fw_ri_isgl) +
                               wr->num_sge * sizeof(struct fw_ri_sge);
                }
                wqe->send.u.immd_src[0].r2 = 0;
                wqe->send.u.immd_src[0].immdlen = 0;
                size = sizeof wqe->send + sizeof(struct fw_ri_immd);
+               plen = 0;
        }
        *len16 = DIV_ROUND_UP(size, 16);
        wqe->send.plen = cpu_to_be32(plen);
        return 0;
  }
  
- static int build_rdma_write(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
+ static int build_rdma_write(struct t4_sq *sq, union t4_wr *wqe,
+                           struct ib_send_wr *wr, u8 *len16)
  {
-       int i;
        u32 plen;
        int size;
-       u8 *datap;
+       int ret;
  
-       if (wr->num_sge > T4_MAX_WRITE_SGE)
+       if (wr->num_sge > T4_MAX_SEND_SGE)
                return -EINVAL;
        wqe->write.r2 = 0;
        wqe->write.stag_sink = cpu_to_be32(wr->wr.rdma.rkey);
        wqe->write.to_sink = cpu_to_be64(wr->wr.rdma.remote_addr);
-       plen = 0;
        if (wr->num_sge) {
                if (wr->send_flags & IB_SEND_INLINE) {
-                       datap = (u8 *)wqe->write.u.immd_src[0].data;
-                       for (i = 0; i < wr->num_sge; i++) {
-                               if ((plen + wr->sg_list[i].length) >
-                                   T4_MAX_WRITE_INLINE) {
-                                       return -EMSGSIZE;
-                               }
-                               plen += wr->sg_list[i].length;
-                               memcpy(datap,
-                                    (void *)(unsigned long)wr->sg_list[i].addr,
-                                    wr->sg_list[i].length);
-                               datap += wr->sg_list[i].length;
-                       }
-                       wqe->write.u.immd_src[0].op = FW_RI_DATA_IMMD;
-                       wqe->write.u.immd_src[0].r1 = 0;
-                       wqe->write.u.immd_src[0].r2 = 0;
-                       wqe->write.u.immd_src[0].immdlen = cpu_to_be32(plen);
+                       ret = build_immd(sq, wqe->write.u.immd_src, wr,
+                                        T4_MAX_WRITE_INLINE, &plen);
+                       if (ret)
+                               return ret;
                        size = sizeof wqe->write + sizeof(struct fw_ri_immd) +
                               plen;
                } else {
-                       for (i = 0; i < wr->num_sge; i++) {
-                               if ((plen + wr->sg_list[i].length) < plen)
-                                       return -EMSGSIZE;
-                               plen += wr->sg_list[i].length;
-                               wqe->write.u.isgl_src[0].sge[i].stag =
-                                       cpu_to_be32(wr->sg_list[i].lkey);
-                               wqe->write.u.isgl_src[0].sge[i].len =
-                                       cpu_to_be32(wr->sg_list[i].length);
-                               wqe->write.u.isgl_src[0].sge[i].to =
-                                       cpu_to_be64(wr->sg_list[i].addr);
-                       }
-                       wqe->write.u.isgl_src[0].op = FW_RI_DATA_ISGL;
-                       wqe->write.u.isgl_src[0].r1 = 0;
-                       wqe->write.u.isgl_src[0].nsge =
-                                                      cpu_to_be16(wr->num_sge);
-                       wqe->write.u.isgl_src[0].r2 = 0;
+                       ret = build_isgl((__be64 *)sq->queue,
+                                        (__be64 *)&sq->queue[sq->size],
+                                        wqe->write.u.isgl_src,
+                                        wr->sg_list, wr->num_sge, &plen);
+                       if (ret)
+                               return ret;
                        size = sizeof wqe->write + sizeof(struct fw_ri_isgl) +
                               wr->num_sge * sizeof(struct fw_ri_sge);
                }
                wqe->write.u.immd_src[0].r2 = 0;
                wqe->write.u.immd_src[0].immdlen = 0;
                size = sizeof wqe->write + sizeof(struct fw_ri_immd);
+               plen = 0;
        }
        *len16 = DIV_ROUND_UP(size, 16);
        wqe->write.plen = cpu_to_be32(plen);
@@@ -416,29 -441,13 +441,13 @@@ static int build_rdma_read(union t4_wr 
  static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,
                           struct ib_recv_wr *wr, u8 *len16)
  {
-       int i;
-       int plen = 0;
+       int ret;
  
-       for (i = 0; i < wr->num_sge; i++) {
-               if ((plen + wr->sg_list[i].length) < plen)
-                       return -EMSGSIZE;
-               plen += wr->sg_list[i].length;
-               wqe->recv.isgl.sge[i].stag =
-                       cpu_to_be32(wr->sg_list[i].lkey);
-               wqe->recv.isgl.sge[i].len =
-                       cpu_to_be32(wr->sg_list[i].length);
-               wqe->recv.isgl.sge[i].to =
-                       cpu_to_be64(wr->sg_list[i].addr);
-       }
-       for (; i < T4_MAX_RECV_SGE; i++) {
-               wqe->recv.isgl.sge[i].stag = 0;
-               wqe->recv.isgl.sge[i].len = 0;
-               wqe->recv.isgl.sge[i].to = 0;
-       }
-       wqe->recv.isgl.op = FW_RI_DATA_ISGL;
-       wqe->recv.isgl.r1 = 0;
-       wqe->recv.isgl.nsge = cpu_to_be16(wr->num_sge);
-       wqe->recv.isgl.r2 = 0;
+       ret = build_isgl((__be64 *)qhp->wq.rq.queue,
+                        (__be64 *)&qhp->wq.rq.queue[qhp->wq.rq.size],
+                        &wqe->recv.isgl, wr->sg_list, wr->num_sge, NULL);
+       if (ret)
+               return ret;
        *len16 = DIV_ROUND_UP(sizeof wqe->recv +
                              wr->num_sge * sizeof(struct fw_ri_sge), 16);
        return 0;
@@@ -547,7 -556,9 +556,9 @@@ int c4iw_post_send(struct ib_qp *ibqp, 
                        *bad_wr = wr;
                        break;
                }
-               wqe = &qhp->wq.sq.queue[qhp->wq.sq.pidx];
+               wqe = (union t4_wr *)((u8 *)qhp->wq.sq.queue +
+                     qhp->wq.sq.wq_pidx * T4_EQ_ENTRY_SIZE);
                fw_flags = 0;
                if (wr->send_flags & IB_SEND_SOLICITED)
                        fw_flags |= FW_RI_SOLICITED_EVENT_FLAG;
                                swsqe->opcode = FW_RI_SEND;
                        else
                                swsqe->opcode = FW_RI_SEND_WITH_INV;
-                       err = build_rdma_send(wqe, wr, &len16);
+                       err = build_rdma_send(&qhp->wq.sq, wqe, wr, &len16);
                        break;
                case IB_WR_RDMA_WRITE:
                        fw_opcode = FW_RI_RDMA_WRITE_WR;
                        swsqe->opcode = FW_RI_RDMA_WRITE;
-                       err = build_rdma_write(wqe, wr, &len16);
+                       err = build_rdma_write(&qhp->wq.sq, wqe, wr, &len16);
                        break;
                case IB_WR_RDMA_READ:
                case IB_WR_RDMA_READ_WITH_INV:
                     swsqe->opcode, swsqe->read_len);
                wr = wr->next;
                num_wrs--;
-               t4_sq_produce(&qhp->wq);
-               idx++;
+               t4_sq_produce(&qhp->wq, len16);
+               idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
        }
        if (t4_wq_db_enabled(&qhp->wq))
                t4_ring_sq_db(&qhp->wq, idx);
@@@ -656,7 -667,9 +667,9 @@@ int c4iw_post_receive(struct ib_qp *ibq
                        *bad_wr = wr;
                        break;
                }
-               wqe = &qhp->wq.rq.queue[qhp->wq.rq.pidx];
+               wqe = (union t4_recv_wr *)((u8 *)qhp->wq.rq.queue +
+                                          qhp->wq.rq.wq_pidx *
+                                          T4_EQ_ENTRY_SIZE);
                if (num_wrs)
                        err = build_rdma_recv(qhp, wqe, wr, &len16);
                else
                wqe->recv.r2[1] = 0;
                wqe->recv.r2[2] = 0;
                wqe->recv.len16 = len16;
-               if (len16 < 5)
-                       wqe->flits[8] = 0;
                PDBG("%s cookie 0x%llx pidx %u\n", __func__,
                     (unsigned long long) wr->wr_id, qhp->wq.rq.pidx);
-               t4_rq_produce(&qhp->wq);
+               t4_rq_produce(&qhp->wq, len16);
+               idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE);
                wr = wr->next;
                num_wrs--;
-               idx++;
        }
        if (t4_wq_db_enabled(&qhp->wq))
                t4_ring_rq_db(&qhp->wq, idx);
@@@ -905,7 -915,7 +915,7 @@@ static void __flush_qp(struct c4iw_qp *
        atomic_inc(&qhp->refcnt);
        spin_unlock_irqrestore(&qhp->lock, *flag);
  
 -      /* locking heirarchy: cq lock first, then qp lock. */
 +      /* locking hierarchy: cq lock first, then qp lock. */
        spin_lock_irqsave(&rchp->lock, *flag);
        spin_lock(&qhp->lock);
        c4iw_flush_hw_cq(&rchp->cq);
        if (flushed)
                (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
  
 -      /* locking heirarchy: cq lock first, then qp lock. */
 +      /* locking hierarchy: cq lock first, then qp lock. */
        spin_lock_irqsave(&schp->lock, *flag);
        spin_lock(&qhp->lock);
        c4iw_flush_hw_cq(&schp->cq);
@@@ -951,7 -961,8 +961,8 @@@ static void flush_qp(struct c4iw_qp *qh
        __flush_qp(qhp, rchp, schp, flag);
  }
  
- static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
+ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
+                    struct c4iw_ep *ep)
  {
        struct fw_ri_wr *wqe;
        int ret;
        struct sk_buff *skb;
  
        PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
-            qhp->ep->hwtid);
+            ep->hwtid);
  
-       skb = alloc_skb(sizeof *wqe, GFP_KERNEL | __GFP_NOFAIL);
+       skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
-       set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
+       set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
  
        wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
        memset(wqe, 0, sizeof *wqe);
                FW_WR_OP(FW_RI_INIT_WR) |
                FW_WR_COMPL(1));
        wqe->flowid_len16 = cpu_to_be32(
-               FW_WR_FLOWID(qhp->ep->hwtid) |
+               FW_WR_FLOWID(ep->hwtid) |
                FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
        wqe->cookie = (u64)&wr_wait;
  
@@@ -1035,7 -1046,7 +1046,7 @@@ static int rdma_init(struct c4iw_dev *r
        PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
             qhp->ep->hwtid);
  
-       skb = alloc_skb(sizeof *wqe, GFP_KERNEL | __GFP_NOFAIL);
+       skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
        set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
@@@ -1202,17 -1213,16 +1213,16 @@@ int c4iw_modify_qp(struct c4iw_dev *rhp
                case C4IW_QP_STATE_CLOSING:
                        BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
                        qhp->attr.state = C4IW_QP_STATE_CLOSING;
+                       ep = qhp->ep;
                        if (!internal) {
                                abort = 0;
                                disconnect = 1;
-                               ep = qhp->ep;
                                c4iw_get_ep(&ep->com);
                        }
                        spin_unlock_irqrestore(&qhp->lock, flag);
-                       ret = rdma_fini(rhp, qhp);
+                       ret = rdma_fini(rhp, qhp, ep);
                        spin_lock_irqsave(&qhp->lock, flag);
                        if (ret) {
-                               ep = qhp->ep;
                                c4iw_get_ep(&ep->com);
                                disconnect = abort = 1;
                                goto err;
@@@ -1146,7 -1146,7 +1146,7 @@@ static int nes_addr_resolve_neigh(struc
        }
  
        if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
 -              neigh_event_send(rt->u.dst.neighbour, NULL);
 +              neigh_event_send(rt->dst.neighbour, NULL);
  
        ip_rt_put(rt);
        return rc;
@@@ -1719,8 -1719,6 +1719,6 @@@ static int handle_ack_pkt(struct nes_cm
  {
        int datasize = 0;
        u32 inc_sequence;
-       u32 rem_seq_ack;
-       u32 rem_seq;
        int ret = 0;
        int optionsize;
        optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
  
        skb_pull(skb, tcph->doff << 2);
        inc_sequence = ntohl(tcph->seq);
-       rem_seq = ntohl(tcph->seq);
-       rem_seq_ack =  ntohl(tcph->ack_seq);
        datasize = skb->len;
        switch (cm_node->state) {
        case NES_CM_STATE_SYN_RCVD:
@@@ -2565,7 -2561,7 +2561,7 @@@ static int nes_cm_disconn_true(struct n
        u16 last_ae;
        u8 original_hw_tcp_state;
        u8 original_ibqp_state;
-       enum iw_cm_event_type disconn_status = IW_CM_EVENT_STATUS_OK;
+       enum iw_cm_event_status disconn_status = IW_CM_EVENT_STATUS_OK;
        int issue_disconn = 0;
        int issue_close = 0;
        int issue_flush = 0;
@@@ -3128,17 -3124,15 +3124,15 @@@ int nes_create_listen(struct iw_cm_id *
        struct nes_vnic *nesvnic;
        struct nes_cm_listener *cm_node;
        struct nes_cm_info cm_info;
-       struct nes_adapter *adapter;
        int err;
  
        nes_debug(NES_DBG_CM, "cm_id = %p, local port = 0x%04X.\n",
                        cm_id, ntohs(cm_id->local_addr.sin_port));
  
        nesvnic = to_nesvnic(cm_id->device);
        if (!nesvnic)
                return -EINVAL;
-       adapter = nesvnic->nesdev->nesadapter;
        nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n",
                        nesvnic, nesvnic->netdev, nesvnic->netdev->name);
  
@@@ -232,6 -232,13 +232,13 @@@ static int nes_netdev_open(struct net_d
                                NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
                first_nesvnic = nesvnic;
        }
+       if (nesvnic->of_device_registered) {
+               nesdev->iw_status = 1;
+               nesdev->nesadapter->send_term_ok = 1;
+               nes_port_ibevent(nesvnic);
+       }
        if (first_nesvnic->linkup) {
                /* Enable network packets */
                nesvnic->linkup = 1;
@@@ -309,9 -316,9 +316,9 @@@ static int nes_netdev_stop(struct net_d
  
  
        if (nesvnic->of_device_registered) {
-               nes_destroy_ofa_device(nesvnic->nesibdev);
-               nesvnic->nesibdev = NULL;
-               nesvnic->of_device_registered = 0;
+               nesdev->nesadapter->send_term_ok = 0;
+               nesdev->iw_status = 0;
+               nes_port_ibevent(nesvnic);
        }
        nes_destroy_nic_qp(nesvnic);
  
@@@ -463,7 -470,6 +470,6 @@@ static int nes_netdev_start_xmit(struc
        u16 nhoffset;
        u16 wqes_needed;
        u16 wqes_available;
-       u32 old_head;
        u32 wqe_misc;
  
        /*
@@@ -503,7 -509,6 +509,6 @@@ sq_no_longer_full
                if (skb_is_gso(skb)) {
                        nesvnic->segmented_tso_requests++;
                        nesvnic->tso_requests++;
-                       old_head = nesnic->sq_head;
                        /* Basically 4 fragments available per WQE with extended fragments */
                        wqes_needed = nr_frags >> 2;
                        wqes_needed += (nr_frags&3)?1:0;
@@@ -1567,12 -1572,6 +1572,12 @@@ static int nes_netdev_set_settings(stru
  }
  
  
 +static int nes_netdev_set_flags(struct net_device *netdev, u32 flags)
 +{
 +      return ethtool_op_set_flags(netdev, flags, ETH_FLAG_LRO);
 +}
 +
 +
  static const struct ethtool_ops nes_ethtool_ops = {
        .get_link = ethtool_op_get_link,
        .get_settings = nes_netdev_get_settings,
        .get_tso = ethtool_op_get_tso,
        .set_tso = ethtool_op_set_tso,
        .get_flags = ethtool_op_get_flags,
 -      .set_flags = ethtool_op_set_flags,
 +      .set_flags = nes_netdev_set_flags,
  };