Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-block.git] / drivers / infiniband / hw / cxgb4 / cm.c
index 768a0fb67dd6d5995545f40037aa2c5157548ce1..c2fb71c182a8f0a2a968446813898c42b9e476a7 100644 (file)
@@ -79,9 +79,10 @@ static int dack_mode = 1;
 module_param(dack_mode, int, 0644);
 MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
 
-int c4iw_max_read_depth = 8;
+uint c4iw_max_read_depth = 32;
 module_param(c4iw_max_read_depth, int, 0644);
-MODULE_PARM_DESC(c4iw_max_read_depth, "Per-connection max ORD/IRD (default=8)");
+MODULE_PARM_DESC(c4iw_max_read_depth,
+                "Per-connection max ORD/IRD (default=32)");
 
 static int enable_tcp_timestamps;
 module_param(enable_tcp_timestamps, int, 0644);
@@ -474,7 +475,8 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
                                          16)) | FW_WR_FLOWID(ep->hwtid));
 
        flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
-       flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
+       flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN
+                                           (ep->com.dev->rdev.lldi.pf));
        flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
        flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
        flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
@@ -821,6 +823,8 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
        if (mpa_rev_to_use == 2) {
                mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
                                               sizeof (struct mpa_v2_conn_params));
+               PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+                    ep->ord);
                mpa_v2_params.ird = htons((u16)ep->ird);
                mpa_v2_params.ord = htons((u16)ep->ord);
 
@@ -1190,8 +1194,8 @@ static int connect_request_upcall(struct c4iw_ep *ep)
                        sizeof(struct mpa_v2_conn_params);
        } else {
                /* this means MPA_v1 is used. Send max supported */
-               event.ord = c4iw_max_read_depth;
-               event.ird = c4iw_max_read_depth;
+               event.ord = cur_max_read_depth(ep->com.dev);
+               event.ird = cur_max_read_depth(ep->com.dev);
                event.private_data_len = ep->plen;
                event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
        }
@@ -1255,6 +1259,8 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
        return credits;
 }
 
+#define RELAXED_IRD_NEGOTIATION 1
+
 static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
        struct mpa_message *mpa;
@@ -1366,17 +1372,33 @@ static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
                                MPA_V2_IRD_ORD_MASK;
                        resp_ord = ntohs(mpa_v2_params->ord) &
                                MPA_V2_IRD_ORD_MASK;
+                       PDBG("%s responder ird %u ord %u ep ird %u ord %u\n",
+                            __func__, resp_ird, resp_ord, ep->ird, ep->ord);
 
                        /*
                         * This is a double-check. Ideally, below checks are
                         * not required since ird/ord stuff has been taken
                         * care of in c4iw_accept_cr
                         */
-                       if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+                       if (ep->ird < resp_ord) {
+                               if (RELAXED_IRD_NEGOTIATION && resp_ord <=
+                                   ep->com.dev->rdev.lldi.max_ordird_qp)
+                                       ep->ird = resp_ord;
+                               else
+                                       insuff_ird = 1;
+                       } else if (ep->ird > resp_ord) {
+                               ep->ird = resp_ord;
+                       }
+                       if (ep->ord > resp_ird) {
+                               if (RELAXED_IRD_NEGOTIATION)
+                                       ep->ord = resp_ird;
+                               else
+                                       insuff_ird = 1;
+                       }
+                       if (insuff_ird) {
                                err = -ENOMEM;
                                ep->ird = resp_ord;
                                ep->ord = resp_ird;
-                               insuff_ird = 1;
                        }
 
                        if (ntohs(mpa_v2_params->ird) &
@@ -1579,6 +1601,8 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
                                MPA_V2_IRD_ORD_MASK;
                        ep->ord = ntohs(mpa_v2_params->ord) &
                                MPA_V2_IRD_ORD_MASK;
+                       PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+                            ep->ord);
                        if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
                                if (peer2peer) {
                                        if (ntohs(mpa_v2_params->ord) &
@@ -1798,6 +1822,20 @@ static int is_neg_adv(unsigned int status)
               status == CPL_ERR_KEEPALV_NEG_ADVICE;
 }
 
+static char *neg_adv_str(unsigned int status)
+{
+       switch (status) {
+       case CPL_ERR_RTX_NEG_ADVICE:
+               return "Retransmit timeout";
+       case CPL_ERR_PERSIST_NEG_ADVICE:
+               return "Persist timeout";
+       case CPL_ERR_KEEPALV_NEG_ADVICE:
+               return "Keepalive timeout";
+       default:
+               return "Unknown";
+       }
+}
+
 static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
 {
        ep->snd_win = snd_win;
@@ -1996,8 +2034,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
             status, status2errno(status));
 
        if (is_neg_adv(status)) {
-               printk(KERN_WARNING MOD "Connection problems for atid %u\n",
-                       atid);
+               dev_warn(&dev->rdev.lldi.pdev->dev,
+                        "Connection problems for atid %u status %u (%s)\n",
+                        atid, status, neg_adv_str(status));
                return 0;
        }
 
@@ -2472,8 +2511,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 
        ep = lookup_tid(t, tid);
        if (is_neg_adv(req->status)) {
-               PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
-                    ep->hwtid);
+               dev_warn(&dev->rdev.lldi.pdev->dev,
+                        "Negative advice on abort - tid %u status %d (%s)\n",
+                        ep->hwtid, req->status, neg_adv_str(req->status));
                return 0;
        }
        PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
@@ -2731,8 +2771,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        BUG_ON(!qp);
 
        set_bit(ULP_ACCEPT, &ep->com.history);
-       if ((conn_param->ord > c4iw_max_read_depth) ||
-           (conn_param->ird > c4iw_max_read_depth)) {
+       if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
+           (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
                abort_connection(ep, NULL, GFP_KERNEL);
                err = -EINVAL;
                goto err;
@@ -2740,31 +2780,41 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 
        if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
                if (conn_param->ord > ep->ird) {
-                       ep->ird = conn_param->ird;
-                       ep->ord = conn_param->ord;
-                       send_mpa_reject(ep, conn_param->private_data,
-                                       conn_param->private_data_len);
-                       abort_connection(ep, NULL, GFP_KERNEL);
-                       err = -ENOMEM;
-                       goto err;
+                       if (RELAXED_IRD_NEGOTIATION) {
+                               ep->ord = ep->ird;
+                       } else {
+                               ep->ird = conn_param->ird;
+                               ep->ord = conn_param->ord;
+                               send_mpa_reject(ep, conn_param->private_data,
+                                               conn_param->private_data_len);
+                               abort_connection(ep, NULL, GFP_KERNEL);
+                               err = -ENOMEM;
+                               goto err;
+                       }
                }
-               if (conn_param->ird > ep->ord) {
-                       if (!ep->ord)
-                               conn_param->ird = 1;
-                       else {
+               if (conn_param->ird < ep->ord) {
+                       if (RELAXED_IRD_NEGOTIATION &&
+                           ep->ord <= h->rdev.lldi.max_ordird_qp) {
+                               conn_param->ird = ep->ord;
+                       } else {
                                abort_connection(ep, NULL, GFP_KERNEL);
                                err = -ENOMEM;
                                goto err;
                        }
                }
-
        }
        ep->ird = conn_param->ird;
        ep->ord = conn_param->ord;
 
-       if (ep->mpa_attr.version != 2)
+       if (ep->mpa_attr.version == 1) {
                if (peer2peer && ep->ird == 0)
                        ep->ird = 1;
+       } else {
+               if (peer2peer &&
+                   (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
+                   (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+                       ep->ird = 1;
+       }
 
        PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
@@ -2803,6 +2853,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        return 0;
 err1:
        ep->com.cm_id = NULL;
+       abort_connection(ep, NULL, GFP_KERNEL);
        cm_id->rem_ref(cm_id);
 err:
        mutex_unlock(&ep->com.mutex);
@@ -2886,8 +2937,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        int iptype;
        int iwpm_err = 0;
 
-       if ((conn_param->ord > c4iw_max_read_depth) ||
-           (conn_param->ird > c4iw_max_read_depth)) {
+       if ((conn_param->ord > cur_max_read_depth(dev)) ||
+           (conn_param->ird > cur_max_read_depth(dev))) {
                err = -EINVAL;
                goto out;
        }
@@ -3867,8 +3918,9 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
                return 0;
        }
        if (is_neg_adv(req->status)) {
-               PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
-                    ep->hwtid);
+               dev_warn(&dev->rdev.lldi.pdev->dev,
+                        "Negative advice on abort - tid %u status %d (%s)\n",
+                        ep->hwtid, req->status, neg_adv_str(req->status));
                kfree_skb(skb);
                return 0;
        }