From 2a6db2d00c8af2714c0f0921b5538e470e7c2ff5 Mon Sep 17 00:00:00 2001 From: Alexander Schmidt Date: Thu, 10 Jun 2010 09:06:53 +0000 Subject: [PATCH] --- yaml --- r: 206714 b: refs/heads/master c: 91fb0dd9cb71ab1a90ab1f48c34b935fdbca55b9 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/infiniband/hw/cxgb4/cm.c | 91 +++---- trunk/drivers/infiniband/hw/cxgb4/cq.c | 4 +- trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 1 - trunk/drivers/infiniband/hw/cxgb4/mem.c | 2 +- trunk/drivers/infiniband/hw/cxgb4/qp.c | 240 +++++++++--------- trunk/drivers/infiniband/hw/cxgb4/t4.h | 32 +-- .../drivers/infiniband/hw/cxgb4/t4fw_ri_api.h | 10 - trunk/drivers/infiniband/hw/ehca/ehca_main.c | 3 +- 9 files changed, 179 insertions(+), 206 deletions(-) diff --git a/[refs] b/[refs] index 930eabd418b5..a5293ad13853 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a5f4a07820ebc60b21c984d893f48402c4b4a4a2 +refs/heads/master: 91fb0dd9cb71ab1a90ab1f48c34b935fdbca55b9 diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index 6c40779b62f4..855ee44fdb52 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -61,10 +61,6 @@ 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)"); @@ -473,12 +469,11 @@ static int send_connect(struct c4iw_ep *ep) __func__); return -ENOMEM; } - set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); + set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->txq_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) | @@ -785,11 +780,11 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status) event.private_data_len = ep->plen; event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); } - - 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 (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); + } if (status < 0) { ep->com.cm_id->rem_ref(ep->com.cm_id); ep->com.cm_id = NULL; @@ -850,10 +845,8 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits) 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 | RX_FORCE_ACK(1) | - F_RX_DACK_CHANGE | - V_RX_DACK_MODE(dack_mode)); - set_wr_txq(skb, CPL_PRIORITY_ACK, ep->ctrlq_idx); + req->credit_dack = cpu_to_be32(credits); + set_wr_txq(skb, CPL_PRIORITY_ACK, ep->txq_idx); c4iw_ofld_send(&ep->com.dev->rdev, skb); return credits; } @@ -1271,7 +1264,6 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, 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) | @@ -1295,7 +1287,7 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, ep->hwtid)); rpl->opt0 = cpu_to_be64(opt0); rpl->opt2 = cpu_to_be32(opt2); - set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx); + set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->txq_idx); c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); return; @@ -1352,7 +1344,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) u16 rss_qid; u32 mtu; int step; - int txq_idx, ctrlq_idx; + int txq_idx; parent_ep = lookup_stid(t, stid); PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid); @@ -1384,7 +1376,6 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 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); @@ -1396,7 +1387,6 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 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]; @@ -1436,7 +1426,6 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) 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); @@ -1484,6 +1473,8 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 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); @@ -1520,7 +1511,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) wake_up(&ep->com.waitq); break; case FPDU_MODE: - start_ep_timer(ep); + start_timer = 1; __state_set(&ep->com, CLOSING); closing = 1; peer_close_upcall(ep); @@ -1533,7 +1524,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) disconnect = 0; break; case MORIBUND: - stop_ep_timer(ep); + stop_timer = 1; 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, @@ -1556,6 +1547,10 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) 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) @@ -1584,6 +1579,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 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)) { @@ -1598,10 +1594,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) case CONNECTING: break; case MPA_REQ_WAIT: - stop_ep_timer(ep); + stop_timer = 1; break; case MPA_REQ_SENT: - stop_ep_timer(ep); + stop_timer = 1; connect_reply_upcall(ep, -ECONNRESET); break; case MPA_REP_SENT: @@ -1625,7 +1621,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) break; case MORIBUND: case CLOSING: - stop_ep_timer(ep); + stop_timer = 1; /*FALLTHROUGH*/ case FPDU_MODE: if (ep->com.cm_id && ep->com.qp) { @@ -1671,6 +1667,8 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) 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; @@ -1685,6 +1683,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) 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); @@ -1698,7 +1697,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) __state_set(&ep->com, MORIBUND); break; case MORIBUND: - stop_ep_timer(ep); + stop_timer = 1; if ((ep->com.cm_id) && (ep->com.qp)) { attrs.next_state = C4IW_QP_STATE_IDLE; c4iw_modify_qp(ep->com.qp->rhp, @@ -1718,6 +1717,8 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) break; } spin_unlock_irqrestore(&ep->com.lock, flags); + if (stop_timer) + stop_ep_timer(ep); if (release) release_ep_resources(ep); return 0; @@ -1956,7 +1957,6 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 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); @@ -1971,7 +1971,6 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 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[ @@ -2050,15 +2049,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) goto fail3; /* wait for pass_open_rpl */ - 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; - } + wait_event(ep->com.waitq, ep->com.rpl_done); + err = ep->com.rpl_err; if (!err) { cm_id->provider_data = ep; goto out; @@ -2087,17 +2079,10 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) err = listen_stop(ep); if (err) goto 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; - } + wait_event(ep->com.waitq, ep->com.rpl_done); 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; @@ -2110,6 +2095,8 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) 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); @@ -2133,7 +2120,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) ep->com.state = ABORTING; else { ep->com.state = CLOSING; - start_ep_timer(ep); + start_timer = 1; } set_bit(CLOSE_SENT, &ep->com.flags); break; @@ -2141,7 +2128,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { close = 1; if (abrupt) { - stop_ep_timer(ep); + stop_timer = 1; ep->com.state = ABORTING; } else ep->com.state = MORIBUND; @@ -2159,6 +2146,10 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) } 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); @@ -2253,7 +2244,7 @@ static void process_work(struct work_struct *work) { struct sk_buff *skb = NULL; struct c4iw_dev *dev; - struct cpl_act_establish *rpl; + struct cpl_act_establish *rpl = cplhdr(skb); unsigned int opcode; int ret; diff --git a/trunk/drivers/infiniband/hw/cxgb4/cq.c b/trunk/drivers/infiniband/hw/cxgb4/cq.c index b3daf39eed4a..fac5c6e68011 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cq.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cq.c @@ -43,7 +43,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq, int ret; wr_len = sizeof *res_wr + sizeof *res; - skb = alloc_skb(wr_len, GFP_KERNEL); + skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL); if (!skb) return -ENOMEM; set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); @@ -118,7 +118,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq, /* build fw_ri_res_wr */ wr_len = sizeof *res_wr + sizeof *res; - skb = alloc_skb(wr_len, GFP_KERNEL); + skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL); if (!skb) { ret = -ENOMEM; goto err4; diff --git a/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index ed459b8f800f..d33e1a668811 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/trunk/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -619,7 +619,6 @@ struct c4iw_ep { u16 plen; u16 rss_qid; u16 txq_idx; - u16 ctrlq_idx; u8 tos; }; diff --git a/trunk/drivers/infiniband/hw/cxgb4/mem.c b/trunk/drivers/infiniband/hw/cxgb4/mem.c index 269373a62f22..82b5703b8947 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/mem.c +++ b/trunk/drivers/infiniband/hw/cxgb4/mem.c @@ -59,7 +59,7 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, wr_len = roundup(sizeof *req + sizeof *sc + roundup(copy_len, T4_ULPTX_MIN_IO), 16); - skb = alloc_skb(wr_len, GFP_KERNEL); + skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL); if (!skb) return -ENOMEM; set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0); diff --git a/trunk/drivers/infiniband/hw/cxgb4/qp.c b/trunk/drivers/infiniband/hw/cxgb4/qp.c index c9aaf24bf2b4..7065cb310553 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/qp.c +++ b/trunk/drivers/infiniband/hw/cxgb4/qp.c @@ -130,7 +130,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, /* build fw_ri_res_wr */ wr_len = sizeof *res_wr + 2 * sizeof *res; - skb = alloc_skb(wr_len, GFP_KERNEL); + skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL); if (!skb) { ret = -ENOMEM; goto err7; @@ -162,7 +162,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, 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(2) | + V_FW_RI_RES_WR_FBMIN(3) | V_FW_RI_RES_WR_FBMAX(3) | V_FW_RI_RES_WR_CIDXFTHRESHO(0) | V_FW_RI_RES_WR_CIDXFTHRESH(0) | @@ -185,7 +185,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, 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(2) | + V_FW_RI_RES_WR_FBMIN(3) | V_FW_RI_RES_WR_FBMAX(3) | V_FW_RI_RES_WR_CIDXFTHRESHO(0) | V_FW_RI_RES_WR_CIDXFTHRESH(0) | @@ -235,78 +235,12 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, return -ENOMEM; } -static int build_immd(struct t4_sq *sq, struct fw_ri_immd *immdp, - struct ib_send_wr *wr, int max, u32 *plenp) +static int build_rdma_send(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16) { - 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; - int ret; + u8 *datap; if (wr->num_sge > T4_MAX_SEND_SGE) return -EINVAL; @@ -333,23 +267,43 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe, default: return -EINVAL; } - plen = 0; if (wr->num_sge) { if (wr->send_flags & IB_SEND_INLINE) { - ret = build_immd(sq, wqe->send.u.immd_src, wr, - T4_MAX_SEND_INLINE, &plen); - if (ret) - return ret; + 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); size = sizeof wqe->send + sizeof(struct fw_ri_immd) + plen; } else { - 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; + 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; size = sizeof wqe->send + sizeof(struct fw_ri_isgl) + wr->num_sge * sizeof(struct fw_ri_sge); } @@ -359,40 +313,62 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe, 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(struct t4_sq *sq, union t4_wr *wqe, - struct ib_send_wr *wr, u8 *len16) +static int build_rdma_write(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16) { + int i; u32 plen; int size; - int ret; + u8 *datap; - if (wr->num_sge > T4_MAX_SEND_SGE) + if (wr->num_sge > T4_MAX_WRITE_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) { - ret = build_immd(sq, wqe->write.u.immd_src, wr, - T4_MAX_WRITE_INLINE, &plen); - if (ret) - return ret; + 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); size = sizeof wqe->write + sizeof(struct fw_ri_immd) + plen; } else { - 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; + 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; size = sizeof wqe->write + sizeof(struct fw_ri_isgl) + wr->num_sge * sizeof(struct fw_ri_sge); } @@ -402,7 +378,6 @@ static int build_rdma_write(struct t4_sq *sq, union t4_wr *wqe, 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); @@ -441,13 +416,29 @@ static int build_rdma_read(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16) static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe, struct ib_recv_wr *wr, u8 *len16) { - int ret; + int i; + int plen = 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; + 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; *len16 = DIV_ROUND_UP(sizeof wqe->recv + wr->num_sge * sizeof(struct fw_ri_sge), 16); return 0; @@ -556,9 +547,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, *bad_wr = wr; break; } - wqe = (union t4_wr *)((u8 *)qhp->wq.sq.queue + - qhp->wq.sq.wq_pidx * T4_EQ_ENTRY_SIZE); - + wqe = &qhp->wq.sq.queue[qhp->wq.sq.pidx]; fw_flags = 0; if (wr->send_flags & IB_SEND_SOLICITED) fw_flags |= FW_RI_SOLICITED_EVENT_FLAG; @@ -575,12 +564,12 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, swsqe->opcode = FW_RI_SEND; else swsqe->opcode = FW_RI_SEND_WITH_INV; - err = build_rdma_send(&qhp->wq.sq, wqe, wr, &len16); + err = build_rdma_send(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(&qhp->wq.sq, wqe, wr, &len16); + err = build_rdma_write(wqe, wr, &len16); break; case IB_WR_RDMA_READ: case IB_WR_RDMA_READ_WITH_INV: @@ -630,8 +619,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, swsqe->opcode, swsqe->read_len); wr = wr->next; num_wrs--; - t4_sq_produce(&qhp->wq, len16); - idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); + t4_sq_produce(&qhp->wq); + idx++; } if (t4_wq_db_enabled(&qhp->wq)) t4_ring_sq_db(&qhp->wq, idx); @@ -667,9 +656,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, *bad_wr = wr; break; } - wqe = (union t4_recv_wr *)((u8 *)qhp->wq.rq.queue + - qhp->wq.rq.wq_pidx * - T4_EQ_ENTRY_SIZE); + wqe = &qhp->wq.rq.queue[qhp->wq.rq.pidx]; if (num_wrs) err = build_rdma_recv(qhp, wqe, wr, &len16); else @@ -688,12 +675,15 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, 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, len16); - idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); + t4_rq_produce(&qhp->wq); wr = wr->next; num_wrs--; + idx++; } if (t4_wq_db_enabled(&qhp->wq)) t4_ring_rq_db(&qhp->wq, idx); @@ -961,8 +951,7 @@ static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag) __flush_qp(qhp, rchp, schp, flag); } -static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, - struct c4iw_ep *ep) +static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp) { struct fw_ri_wr *wqe; int ret; @@ -970,12 +959,12 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, struct sk_buff *skb; PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid, - ep->hwtid); + qhp->ep->hwtid); - skb = alloc_skb(sizeof *wqe, GFP_KERNEL); + skb = alloc_skb(sizeof *wqe, GFP_KERNEL | __GFP_NOFAIL); if (!skb) return -ENOMEM; - set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx); + set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx); wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe)); memset(wqe, 0, sizeof *wqe); @@ -983,7 +972,7 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, FW_WR_OP(FW_RI_INIT_WR) | FW_WR_COMPL(1)); wqe->flowid_len16 = cpu_to_be32( - FW_WR_FLOWID(ep->hwtid) | + FW_WR_FLOWID(qhp->ep->hwtid) | FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16))); wqe->cookie = (u64)&wr_wait; @@ -1046,7 +1035,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp) 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); + skb = alloc_skb(sizeof *wqe, GFP_KERNEL | __GFP_NOFAIL); if (!skb) return -ENOMEM; set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx); @@ -1213,16 +1202,17 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, 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, ep); + ret = rdma_fini(rhp, qhp); spin_lock_irqsave(&qhp->lock, flag); if (ret) { + ep = qhp->ep; c4iw_get_ep(&ep->com); disconnect = abort = 1; goto err; diff --git a/trunk/drivers/infiniband/hw/cxgb4/t4.h b/trunk/drivers/infiniband/hw/cxgb4/t4.h index aef55f42bea4..9cf8d85bfcff 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/t4.h +++ b/trunk/drivers/infiniband/hw/cxgb4/t4.h @@ -65,10 +65,10 @@ struct t4_status_page { u8 db_off; }; -#define T4_EQ_ENTRY_SIZE 64 +#define T4_EQ_SIZE 64 #define T4_SQ_NUM_SLOTS 4 -#define T4_SQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_SQ_NUM_SLOTS) +#define T4_SQ_NUM_BYTES (T4_EQ_SIZE * T4_SQ_NUM_SLOTS) #define T4_MAX_SEND_SGE ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_send_wr) - \ sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge)) #define T4_MAX_SEND_INLINE ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_send_wr) - \ @@ -84,7 +84,7 @@ struct t4_status_page { #define T4_MAX_FR_DEPTH (T4_MAX_FR_IMMD / sizeof(u64)) #define T4_RQ_NUM_SLOTS 2 -#define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS) +#define T4_RQ_NUM_BYTES (T4_EQ_SIZE * T4_RQ_NUM_SLOTS) #define T4_MAX_RECV_SGE 4 union t4_wr { @@ -97,18 +97,20 @@ union t4_wr { struct fw_ri_fr_nsmr_wr fr; struct fw_ri_inv_lstag_wr inv; struct t4_status_page status; - __be64 flits[T4_EQ_ENTRY_SIZE / sizeof(__be64) * T4_SQ_NUM_SLOTS]; + __be64 flits[T4_EQ_SIZE / sizeof(__be64) * T4_SQ_NUM_SLOTS]; }; union t4_recv_wr { struct fw_ri_recv_wr recv; struct t4_status_page status; - __be64 flits[T4_EQ_ENTRY_SIZE / sizeof(__be64) * T4_RQ_NUM_SLOTS]; + __be64 flits[T4_EQ_SIZE / sizeof(__be64) * T4_RQ_NUM_SLOTS]; }; static inline void init_wr_hdr(union t4_wr *wqe, u16 wrid, enum fw_wr_opcodes opcode, u8 flags, u8 len16) { + int slots_used; + wqe->send.opcode = (u8)opcode; wqe->send.flags = flags; wqe->send.wrid = wrid; @@ -116,6 +118,12 @@ static inline void init_wr_hdr(union t4_wr *wqe, u16 wrid, wqe->send.r1[1] = 0; wqe->send.r1[2] = 0; wqe->send.len16 = len16; + + slots_used = DIV_ROUND_UP(len16*16, T4_EQ_SIZE); + while (slots_used < T4_SQ_NUM_SLOTS) { + wqe->flits[slots_used * T4_EQ_SIZE / sizeof(__be64)] = 0; + slots_used++; + } } /* CQE/AE status codes */ @@ -281,7 +289,6 @@ struct t4_sq { u16 size; u16 cidx; u16 pidx; - u16 wq_pidx; }; struct t4_swrqe { @@ -303,7 +310,6 @@ struct t4_rq { u16 size; u16 cidx; u16 pidx; - u16 wq_pidx; }; struct t4_wq { @@ -334,14 +340,11 @@ static inline u32 t4_rq_avail(struct t4_wq *wq) return wq->rq.size - 1 - wq->rq.in_use; } -static inline void t4_rq_produce(struct t4_wq *wq, u8 len16) +static inline void t4_rq_produce(struct t4_wq *wq) { wq->rq.in_use++; if (++wq->rq.pidx == wq->rq.size) wq->rq.pidx = 0; - wq->rq.wq_pidx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); - if (wq->rq.wq_pidx >= wq->rq.size * T4_RQ_NUM_SLOTS) - wq->rq.wq_pidx %= wq->rq.size * T4_RQ_NUM_SLOTS; } static inline void t4_rq_consume(struct t4_wq *wq) @@ -367,14 +370,11 @@ static inline u32 t4_sq_avail(struct t4_wq *wq) return wq->sq.size - 1 - wq->sq.in_use; } -static inline void t4_sq_produce(struct t4_wq *wq, u8 len16) +static inline void t4_sq_produce(struct t4_wq *wq) { wq->sq.in_use++; if (++wq->sq.pidx == wq->sq.size) wq->sq.pidx = 0; - wq->sq.wq_pidx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); - if (wq->sq.wq_pidx >= wq->sq.size * T4_SQ_NUM_SLOTS) - wq->sq.wq_pidx %= wq->sq.size * T4_SQ_NUM_SLOTS; } static inline void t4_sq_consume(struct t4_wq *wq) @@ -386,12 +386,14 @@ static inline void t4_sq_consume(struct t4_wq *wq) static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc) { + inc *= T4_SQ_NUM_SLOTS; wmb(); writel(QID(wq->sq.qid) | PIDX(inc), wq->db); } static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc) { + inc *= T4_RQ_NUM_SLOTS; wmb(); writel(QID(wq->rq.qid) | PIDX(inc), wq->db); } diff --git a/trunk/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/trunk/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h index dc193c292671..fc706bd07fae 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h +++ b/trunk/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h @@ -826,14 +826,4 @@ struct ulptx_idata { #define S_ULPTX_NSGE 0 #define M_ULPTX_NSGE 0xFFFF #define V_ULPTX_NSGE(x) ((x) << S_ULPTX_NSGE) - -#define S_RX_DACK_MODE 29 -#define M_RX_DACK_MODE 0x3 -#define V_RX_DACK_MODE(x) ((x) << S_RX_DACK_MODE) -#define G_RX_DACK_MODE(x) (((x) >> S_RX_DACK_MODE) & M_RX_DACK_MODE) - -#define S_RX_DACK_CHANGE 31 -#define V_RX_DACK_CHANGE(x) ((x) << S_RX_DACK_CHANGE) -#define F_RX_DACK_CHANGE V_RX_DACK_CHANGE(1U) - #endif /* _T4FW_RI_API_H_ */ diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index ecb51b396c42..cfc4de7a5da4 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -360,7 +360,8 @@ static int ehca_sense_attributes(struct ehca_shca *shca) * a firmware property, so it's valid across all adapters */ if (ehca_lock_hcalls == -1) - ehca_lock_hcalls = !(shca->hca_cap & HCA_CAP_H_ALLOC_RES_SYNC); + ehca_lock_hcalls = !EHCA_BMASK_GET(HCA_CAP_H_ALLOC_RES_SYNC, + shca->hca_cap); /* translate supported MR page sizes; always support 4K */ shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;