summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cm.c
diff options
context:
space:
mode:
authorParav Pandit <parav@mellanox.com>2018-05-14 10:11:07 +0200
committerJason Gunthorpe <jgg@mellanox.com>2018-05-16 22:11:46 +0200
commita5c57d327272bdf3a8b19686eaca2ec683449e67 (patch)
tree1d64b3c5249c514fbb0596ea47660cd255a730c2 /drivers/infiniband/core/cm.c
parenti40iw: Extend port reuse support for listeners (diff)
downloadlinux-a5c57d327272bdf3a8b19686eaca2ec683449e67.tar.xz
linux-a5c57d327272bdf3a8b19686eaca2ec683449e67.zip
IB/cm: Avoid AV ah_attr overwriting during LAP message handling
AH attribute of the cm_id can be overwritten if LAP message is received on CM request which is in progress. This bug got introduced to avoid sleeping when spin lock is held as part of commit in Fixes tag. Therefore validate the cm_id state first and continue to perform AV ah_attr initialization. Given that Aleternative path related messages are not supported for RoCE, init_av_from_response/path is such messages are ok to be called from blocking context. Fixes: 33f93e1ebcf5 ("IB/cm: Fix sleeping while spin lock is held") 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.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index a92e1a5c202b..34b4defc3d1f 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3189,12 +3189,6 @@ static int cm_lap_handler(struct cm_work *work)
if (!cm_id_priv)
return -EINVAL;
- ret = cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
- work->mad_recv_wc->recv_buf.grh,
- &cm_id_priv->av);
- if (ret)
- goto deref;
-
param = &work->cm_event.param.lap_rcvd;
memset(&work->path[0], 0, sizeof(work->path[1]));
cm_path_set_rec_type(work->port->cm_dev->ib_device,
@@ -3239,10 +3233,16 @@ static int cm_lap_handler(struct cm_work *work)
goto unlock;
}
- cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
- cm_id_priv->tid = lap_msg->hdr.tid;
+ ret = cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+ work->mad_recv_wc->recv_buf.grh,
+ &cm_id_priv->av);
+ if (ret)
+ goto unlock;
+
cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av,
cm_id_priv);
+ cm_id_priv->id.lap_state = IB_CM_LAP_RCVD;
+ cm_id_priv->tid = lap_msg->hdr.tid;
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);