Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[sfrench/cifs-2.6.git] / drivers / infiniband / hw / cxgb4 / cm.c
index 8c9b483a0d93064dc7ae7dc55ea511fcd98c1532..32d352a88d50fba3e4526608b6ca345af630ab16 100644 (file)
@@ -61,6 +61,10 @@ static char *states[] = {
        NULL,
 };
 
        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)");
 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 @@ static int send_connect(struct c4iw_ep *ep)
                       __func__);
                return -ENOMEM;
        }
                       __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) |
 
        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) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
               L2T_IDX(ep->l2t->idx) |
@@ -780,11 +785,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);
        }
                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;
        if (status < 0) {
                ep->com.cm_id->rem_ref(ep->com.cm_id);
                ep->com.cm_id = NULL;
@@ -845,8 +850,10 @@ 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));
        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;
 }
        c4iw_ofld_send(&ep->com.dev->rdev, skb);
        return credits;
 }
@@ -1264,6 +1271,7 @@ 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) |
        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) |
               WND_SCALE(wscale) |
               MSS_IDX(mtu_idx) |
               L2T_IDX(ep->l2t->idx) |
@@ -1287,7 +1295,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);
                                      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;
        c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 
        return;
@@ -1344,7 +1352,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
        u16 rss_qid;
        u32 mtu;
        int step;
        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);
 
        parent_ep = lookup_stid(t, stid);
        PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid);
@@ -1376,6 +1384,7 @@ 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;
                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);
                step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
                rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
                dev_put(pdev);
@@ -1387,6 +1396,7 @@ 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;
                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];
                step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
                rss_qid = dev->rdev.lldi.rxq_ids[
                          cxgb4_port_idx(dst->neighbour->dev) * step];
@@ -1426,6 +1436,7 @@ 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->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);
 
        PDBG("%s tx_chan %u smac_idx %u rss_qid %u\n", __func__,
             tx_chan, smac_idx, rss_qid);
@@ -1473,8 +1484,6 @@ 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 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);
 
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1511,7 +1520,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                wake_up(&ep->com.waitq);
                break;
        case FPDU_MODE:
                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);
                __state_set(&ep->com, CLOSING);
                closing = 1;
                peer_close_upcall(ep);
@@ -1524,7 +1533,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                disconnect = 0;
                break;
        case MORIBUND:
                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,
                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,
@@ -1547,10 +1556,6 @@ 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);
        }
                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)
        if (disconnect)
                c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
        if (release)
@@ -1579,7 +1584,6 @@ 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);
        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)) {
 
        ep = lookup_tid(t, tid);
        if (is_neg_adv_abort(req->status)) {
@@ -1594,10 +1598,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                break;
        case MPA_REQ_SENT:
                break;
        case MPA_REQ_SENT:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                connect_reply_upcall(ep, -ECONNRESET);
                break;
        case MPA_REP_SENT:
                connect_reply_upcall(ep, -ECONNRESET);
                break;
        case MPA_REP_SENT:
@@ -1621,7 +1625,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
                break;
        case MORIBUND:
        case CLOSING:
                break;
        case MORIBUND:
        case CLOSING:
-               stop_timer = 1;
+               stop_ep_timer(ep);
                /*FALLTHROUGH*/
        case FPDU_MODE:
                if (ep->com.cm_id && ep->com.qp) {
                /*FALLTHROUGH*/
        case FPDU_MODE:
                if (ep->com.cm_id && ep->com.qp) {
@@ -1667,8 +1671,6 @@ 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:
        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;
        if (release)
                release_ep_resources(ep);
        return 0;
@@ -1683,7 +1685,6 @@ 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 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);
 
 
        ep = lookup_tid(t, tid);
 
@@ -1697,7 +1698,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                __state_set(&ep->com, MORIBUND);
                break;
        case MORIBUND:
                __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,
                if ((ep->com.cm_id) && (ep->com.qp)) {
                        attrs.next_state = C4IW_QP_STATE_IDLE;
                        c4iw_modify_qp(ep->com.qp->rhp,
@@ -1717,8 +1718,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                break;
        }
        spin_unlock_irqrestore(&ep->com.lock, flags);
                break;
        }
        spin_unlock_irqrestore(&ep->com.lock, flags);
-       if (stop_timer)
-               stop_ep_timer(ep);
        if (release)
                release_ep_resources(ep);
        return 0;
        if (release)
                release_ep_resources(ep);
        return 0;
@@ -1957,6 +1956,7 @@ 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->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);
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
                              cxgb4_port_idx(pdev) * step];
                dev_put(pdev);
@@ -1971,6 +1971,7 @@ 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;
                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[
                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 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
                goto fail3;
 
        /* wait for pass_open_rpl */
                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;
        if (!err) {
                cm_id->provider_data = ep;
                goto out;
@@ -2079,10 +2087,17 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id)
        err = listen_stop(ep);
        if (err)
                goto done;
        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:
        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;
        cm_id->rem_ref(cm_id);
        c4iw_put_ep(&ep->com);
        return err;
@@ -2095,8 +2110,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
        int close = 0;
        int fatal = 0;
        struct c4iw_rdev *rdev;
        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);
 
 
        spin_lock_irqsave(&ep->com.lock, flags);
 
@@ -2120,7 +2133,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
                        ep->com.state = ABORTING;
                else {
                        ep->com.state = CLOSING;
                        ep->com.state = ABORTING;
                else {
                        ep->com.state = CLOSING;
-                       start_timer = 1;
+                       start_ep_timer(ep);
                }
                set_bit(CLOSE_SENT, &ep->com.flags);
                break;
                }
                set_bit(CLOSE_SENT, &ep->com.flags);
                break;
@@ -2128,7 +2141,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) {
                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;
                                ep->com.state = ABORTING;
                        } else
                                ep->com.state = MORIBUND;
@@ -2146,10 +2159,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
        }
 
        spin_unlock_irqrestore(&ep->com.lock, flags);
        }
 
        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);
        if (close) {
                if (abrupt)
                        ret = abort_connection(ep, NULL, gfp);
@@ -2244,7 +2253,7 @@ static void process_work(struct work_struct *work)
 {
        struct sk_buff *skb = NULL;
        struct c4iw_dev *dev;
 {
        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;
 
        unsigned int opcode;
        int ret;