aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cm.c
diff options
context:
space:
mode:
authorParav Pandit <parav@mellanox.com>2018-05-14 11:11:08 +0300
committerJason Gunthorpe <jgg@mellanox.com>2018-05-16 14:11:46 -0600
commit0e225dcb7681c0a8e52fb9dc68bd8ab973de4ca2 (patch)
tree24b3330a9794d08c1e477958c36c1a6e2d619f29 /drivers/infiniband/core/cm.c
parentIB/cm: Avoid AV ah_attr overwriting during LAP message handling (diff)
downloadlinux-dev-0e225dcb7681c0a8e52fb9dc68bd8ab973de4ca2.tar.xz
linux-dev-0e225dcb7681c0a8e52fb9dc68bd8ab973de4ca2.zip
IB/cm: Store and restore ah_attr during LAP msg processing
During CM LAP processing, ah_attr is reinitialized on receiving LAP request. First likely during CM request processing. ah_attr might get zero out if LAP processing fails. Therefore, attempt to create new ah_attr for the LAP message. If the initialization fails, continue with older ah_attr. If the initialization passes, consider the new ah_attr by overwriting the older one. Signed-off-by: Parav Pandit <parav@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/infiniband/core/cm.c')
-rw-r--r--drivers/infiniband/core/cm.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 34b4defc3d1f..8b640cb88f3a 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -452,6 +452,32 @@ static void cm_set_private_data(struct cm_id_private *cm_id_priv,
cm_id_priv->private_data_len = private_data_len;
}
+static int cm_init_av_for_lap(struct cm_port *port, struct ib_wc *wc,
+ struct ib_grh *grh, struct cm_av *av)
+{
+ struct rdma_ah_attr new_ah_attr;
+ int ret;
+
+ av->port = port;
+ av->pkey_index = wc->pkey_index;
+
+ /*
+ * av->ah_attr might be initialized based on past wc during incoming
+ * connect request or while sending out connect request. So initialize
+ * a new ah_attr on stack. If initialization fails, old ah_attr is
+ * used for sending any responses. If initialization is successful,
+ * than new ah_attr is used by overwriting old one.
+ */
+ ret = ib_init_ah_attr_from_wc(port->cm_dev->ib_device,
+ port->port_num, wc,
+ grh, &new_ah_attr);
+ if (ret)
+ return ret;
+
+ memcpy(&av->ah_attr, &new_ah_attr, sizeof(new_ah_attr));
+ return 0;
+}
+
static int cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
struct ib_grh *grh, struct cm_av *av)
{
@@ -3233,9 +3259,9 @@ static int cm_lap_handler(struct cm_work *work)
goto unlock;
}
- ret = cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
- work->mad_recv_wc->recv_buf.grh,
- &cm_id_priv->av);
+ ret = cm_init_av_for_lap(work->port, work->mad_recv_wc->wc,
+ work->mad_recv_wc->recv_buf.grh,
+ &cm_id_priv->av);
if (ret)
goto unlock;