i40iw: Fix the connection ORD value for loopback
authorTatyana Nikolova <tatyana.e.nikolova@intel.com>
Fri, 22 Dec 2017 15:47:02 +0000 (09:47 -0600)
committerJason Gunthorpe <jgg@mellanox.com>
Fri, 22 Dec 2017 20:46:11 +0000 (13:46 -0700)
The accepting QP ORD value should be adjusted not to
exceed the peer QP IRD value (RFC 6581). This is
skipped for loopback. After the ORD is validated
by i40iw_record_ird_ord(), adjust the ORD value of
the loopback accepting QP to prevent overrunning the
IRD space of the peer QP. Also move the ORD accounting
for 0-byte RDMA read to i40iw_record_ird_ord().

Fixes: f27b4746f378 ("i40iw: add connection management code")
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/i40iw/i40iw_cm.c

index 341f138..97b6203 100644 (file)
@@ -128,6 +128,8 @@ static void i40iw_record_ird_ord(struct i40iw_cm_node *cm_node, u32 conn_ird,
 
        if (conn_ord > I40IW_MAX_ORD_SIZE)
                conn_ord = I40IW_MAX_ORD_SIZE;
+       else if (!conn_ord && cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO)
+               conn_ord = 1;
 
        cm_node->ird_size = conn_ird;
        cm_node->ord_size = conn_ord;
@@ -2874,15 +2876,13 @@ static struct i40iw_cm_listener *i40iw_make_listen_node(
  * i40iw_create_cm_node - make a connection node with params
  * @cm_core: cm's core
  * @iwdev: iwarp device structure
- * @private_data_len: len to provate data for mpa request
- * @private_data: pointer to private data for connection
+ * @conn_param: upper layer connection parameters
  * @cm_info: quad info for connection
  */
 static struct i40iw_cm_node *i40iw_create_cm_node(
                                        struct i40iw_cm_core *cm_core,
                                        struct i40iw_device *iwdev,
-                                       u16 private_data_len,
-                                       void *private_data,
+                                       struct iw_cm_conn_param *conn_param,
                                        struct i40iw_cm_info *cm_info)
 {
        struct i40iw_cm_node *cm_node;
@@ -2890,6 +2890,9 @@ static struct i40iw_cm_node *i40iw_create_cm_node(
        struct i40iw_cm_node *loopback_remotenode;
        struct i40iw_cm_info loopback_cm_info;
 
+       u16 private_data_len = conn_param->private_data_len;
+       const void *private_data = conn_param->private_data;
+
        /* create a CM connection node */
        cm_node = i40iw_make_cm_node(cm_core, iwdev, cm_info, NULL);
        if (!cm_node)
@@ -2898,6 +2901,8 @@ static struct i40iw_cm_node *i40iw_create_cm_node(
        cm_node->tcp_cntxt.client = 1;
        cm_node->tcp_cntxt.rcv_wscale = I40IW_CM_DEFAULT_RCV_WND_SCALE;
 
+       i40iw_record_ird_ord(cm_node, conn_param->ird, conn_param->ord);
+
        if (!memcmp(cm_info->loc_addr, cm_info->rem_addr, sizeof(cm_info->loc_addr))) {
                loopback_remotelistener = i40iw_find_listener(
                                                cm_core,
@@ -2931,6 +2936,10 @@ static struct i40iw_cm_node *i40iw_create_cm_node(
                               private_data_len);
                        loopback_remotenode->pdata.size = private_data_len;
 
+                       if (loopback_remotenode->ord_size > cm_node->ird_size)
+                               loopback_remotenode->ord_size =
+                                       cm_node->ird_size;
+
                        cm_node->state = I40IW_CM_STATE_OFFLOADED;
                        cm_node->tcp_cntxt.rcv_nxt =
                                loopback_remotenode->tcp_cntxt.loc_seq_num;
@@ -3809,9 +3818,7 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                    __func__, cm_id->tos, cm_info.user_pri);
        cm_id->add_ref(cm_id);
        cm_node = i40iw_create_cm_node(&iwdev->cm_core, iwdev,
-                                      conn_param->private_data_len,
-                                      (void *)conn_param->private_data,
-                                      &cm_info);
+                                      conn_param, &cm_info);
 
        if (IS_ERR(cm_node)) {
                ret = PTR_ERR(cm_node);
@@ -3843,11 +3850,6 @@ int i40iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
 
        cm_node->apbvt_set = true;
-       i40iw_record_ird_ord(cm_node, conn_param->ird, conn_param->ord);
-       if (cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO &&
-           !cm_node->ord_size)
-               cm_node->ord_size = 1;
-
        iwqp->cm_node = cm_node;
        cm_node->iwqp = iwqp;
        iwqp->cm_id = cm_id;