aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core
diff options
context:
space:
mode:
authorAnimesh K Trivedi <ATR@zurich.ibm.com>2010-09-28 10:44:02 -0400
committerRoland Dreier <rolandd@cisco.com>2010-10-11 23:24:04 -0400
commit26012f0750dd73348b0a0a680a4bee2715d4a334 (patch)
tree5e180250d46e74f9116c15503830b1b9a0b1ac50 /drivers/infiniband/core
parent557d0540b96176dc42943e84c88c288f523388ca (diff)
RDMA/iwcm: Fix hang in uninterruptible wait on cm_id destroy
A process can get stuck in an uninterruptible wait in the kernel while destroying a cm_id when iw_cm_connect() fails: For example, When creation of a PD fails but the user continues with an attempt to connect to the server without checking the return value, in iw_cm_connect() a NULL qp is found so the call fails. However the IWCM_F_CONNECT_WAIT bit is not cleared. destroy_cm_id() then waits forever for IWCM_F_CONNECT_WAIT to be cleared. The same problem exists on the passive side with the accept call. Fix this by clearing the bit and waking up any waiters in the appropriate spots. Signed-off-by: Animesh Trivedi <atr@zurich.ibm.com> Acked-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r--drivers/infiniband/core/iwcm.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index bfead5bc25f6..2a1e9ae134b4 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -506,6 +506,8 @@ int iw_cm_accept(struct iw_cm_id *cm_id,
506 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn); 506 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
507 if (!qp) { 507 if (!qp) {
508 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 508 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
509 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
510 wake_up_all(&cm_id_priv->connect_wait);
509 return -EINVAL; 511 return -EINVAL;
510 } 512 }
511 cm_id->device->iwcm->add_ref(qp); 513 cm_id->device->iwcm->add_ref(qp);
@@ -565,6 +567,8 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
565 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn); 567 qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
566 if (!qp) { 568 if (!qp) {
567 spin_unlock_irqrestore(&cm_id_priv->lock, flags); 569 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
570 clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
571 wake_up_all(&cm_id_priv->connect_wait);
568 return -EINVAL; 572 return -EINVAL;
569 } 573 }
570 cm_id->device->iwcm->add_ref(qp); 574 cm_id->device->iwcm->add_ref(qp);