Skip to content

Commit 9be1959

Browse files
jgunthorpejfvogel
authored andcommitted
RDMA/cm: Allow ib_send_cm_sidr_rep() to be done under lock
The first thing ib_send_cm_sidr_rep() does is obtain the lock, so use the usual unlocked wrapper, locked actor pattern here. Get rid of the cm_reject_sidr_req() wrapper so each call site can call the locked or unlocked version as required. This avoids a sketchy lock/unlock sequence (which could allow state to change) during cm_destroy_id(). Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Orabug: 31483278 (cherry picked from commit 6a8824a) cherry-pick-repo=linux/kernel/git/torvalds/linux.git Conflicts: drivers/infiniband/core/cm.c Conflicts due to context issues because of missing commits in UEK. Signed-off-by: Ka-Cheong Poon <[email protected]> Tested-by: June Wang <[email protected]> Reviewed-by: Sharath Srinivasan <[email protected]>
1 parent e502124 commit 9be1959

File tree

1 file changed

+28
-30
lines changed
  • drivers/infiniband/core

1 file changed

+28
-30
lines changed

drivers/infiniband/core/cm.c

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ EXPORT_SYMBOL(ibcm_reject_msg);
109109
struct cm_id_private;
110110
static void cm_add_one(struct ib_device *device);
111111
static void cm_remove_one(struct ib_device *device, void *client_data);
112+
static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
113+
struct ib_cm_sidr_rep_param *param);
112114
static int cm_send_dreq_locked(struct cm_id_private *cm_id_priv,
113115
const void *private_data, u8 private_data_len);
114116
static int cm_send_drep_locked(struct cm_id_private *cm_id_priv,
@@ -856,16 +858,6 @@ static struct cm_id_private * cm_insert_remote_sidr(struct cm_id_private
856858
return NULL;
857859
}
858860

859-
static void cm_reject_sidr_req(struct cm_id_private *cm_id_priv,
860-
enum ib_cm_sidr_status status)
861-
{
862-
struct ib_cm_sidr_rep_param param;
863-
864-
memset(&param, 0, sizeof param);
865-
param.status = status;
866-
ib_send_cm_sidr_rep(&cm_id_priv->id, &param);
867-
}
868-
869861
struct ib_cm_id *ib_create_cm_id(struct ib_device *device,
870862
ib_cm_handler cm_handler,
871863
void *context)
@@ -1055,8 +1047,10 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
10551047
spin_unlock_irq(&cm_id_priv->lock);
10561048
break;
10571049
case IB_CM_SIDR_REQ_RCVD:
1050+
cm_send_sidr_rep_locked(cm_id_priv,
1051+
&(struct ib_cm_sidr_rep_param){
1052+
.status = IB_SIDR_REJECT });
10581053
spin_unlock_irq(&cm_id_priv->lock);
1059-
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
10601054
break;
10611055
case IB_CM_REQ_SENT:
10621056
case IB_CM_MRA_REQ_RCVD:
@@ -3648,7 +3642,9 @@ static int cm_sidr_req_handler(struct cm_work *work)
36483642
sidr_req_msg->service_id);
36493643
if (!cur_cm_id_priv) {
36503644
spin_unlock_irq(&cm.lock);
3651-
cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
3645+
ib_send_cm_sidr_rep(&cm_id_priv->id,
3646+
&(struct ib_cm_sidr_rep_param){
3647+
.status = IB_SIDR_UNSUPPORTED });
36523648
goto out; /* No match. */
36533649
}
36543650
refcount_inc(&cur_cm_id_priv->refcount);
@@ -3689,50 +3685,52 @@ static void cm_format_sidr_rep(struct cm_sidr_rep_msg *sidr_rep_msg,
36893685
param->private_data_len);
36903686
}
36913687

3692-
int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
3693-
struct ib_cm_sidr_rep_param *param)
3688+
static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv,
3689+
struct ib_cm_sidr_rep_param *param)
36943690
{
3695-
struct cm_id_private *cm_id_priv;
36963691
struct ib_mad_send_buf *msg;
3697-
unsigned long flags;
36983692
int ret;
36993693

3694+
lockdep_assert_held(&cm_id_priv->lock);
3695+
37003696
if ((param->info && param->info_length > IB_CM_SIDR_REP_INFO_LENGTH) ||
37013697
(param->private_data &&
37023698
param->private_data_len > IB_CM_SIDR_REP_PRIVATE_DATA_SIZE))
37033699
return -EINVAL;
37043700

3705-
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
3706-
spin_lock_irqsave(&cm_id_priv->lock, flags);
3707-
if (cm_id->state != IB_CM_SIDR_REQ_RCVD) {
3708-
ret = -EINVAL;
3709-
goto error;
3710-
}
3701+
if (cm_id_priv->id.state != IB_CM_SIDR_REQ_RCVD)
3702+
return -EINVAL;
37113703

37123704
ret = cm_alloc_msg(cm_id_priv, &msg);
37133705
if (ret)
3714-
goto error;
3706+
return ret;
37153707

37163708
cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,
37173709
param);
37183710
ret = ib_post_send_mad(msg, NULL);
37193711
if (ret) {
3720-
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
37213712
cm_free_msg(msg);
37223713
return ret;
37233714
}
3724-
cm_id->state = IB_CM_IDLE;
3725-
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3726-
3727-
spin_lock_irqsave(&cm.lock, flags);
3715+
cm_id_priv->id.state = IB_CM_IDLE;
37283716
if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
37293717
rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
37303718
RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
37313719
}
3732-
spin_unlock_irqrestore(&cm.lock, flags);
37333720
return 0;
3721+
}
37343722

3735-
error: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
3723+
int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
3724+
struct ib_cm_sidr_rep_param *param)
3725+
{
3726+
struct cm_id_private *cm_id_priv =
3727+
container_of(cm_id, struct cm_id_private, id);
3728+
unsigned long flags;
3729+
int ret;
3730+
3731+
spin_lock_irqsave(&cm_id_priv->lock, flags);
3732+
ret = cm_send_sidr_rep_locked(cm_id_priv, param);
3733+
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
37363734
return ret;
37373735
}
37383736
EXPORT_SYMBOL(ib_send_cm_sidr_rep);

0 commit comments

Comments
 (0)