summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2016-06-14 20:58:05 +0000
committernp <np@FreeBSD.org>2016-06-14 20:58:05 +0000
commit1610db9e87ef0c31f19e71dad471b39bc0b09bfa (patch)
treed94f82ab9e03b4f5aafcc4b7f281f107d3f2a6b5
parenta048478c507785f68e86db1a32431aa36773ee06 (diff)
downloadFreeBSD-src-1610db9e87ef0c31f19e71dad471b39bc0b09bfa.zip
FreeBSD-src-1610db9e87ef0c31f19e71dad471b39bc0b09bfa.tar.gz
Fix bug in iwcm that caused a panic in iw_cm_wq when krping is run
repeatedly in a tight loop. Approved by: re (gjb@) Obtained from: hselasky@ (part of larger changes in D5791)
-rw-r--r--sys/ofed/drivers/infiniband/core/iwcm.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sys/ofed/drivers/infiniband/core/iwcm.c b/sys/ofed/drivers/infiniband/core/iwcm.c
index 7e27584..5a1cc72 100644
--- a/sys/ofed/drivers/infiniband/core/iwcm.c
+++ b/sys/ofed/drivers/infiniband/core/iwcm.c
@@ -266,9 +266,16 @@ static void add_ref(struct iw_cm_id *cm_id)
static void rem_ref(struct iw_cm_id *cm_id)
{
struct iwcm_id_private *cm_id_priv;
+ int cb_destroy;
+
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
- if (iwcm_deref_id(cm_id_priv) &&
- test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+
+ /*
+ * Test bit before deref in case the cm_id gets freed on another
+ * thread.
+ */
+ cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+ if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
free_cm_id(cm_id_priv);
}
@@ -1157,6 +1164,8 @@ static void cm_work_handler(struct work_struct *_work)
}
return;
}
+ if (empty)
+ return;
spin_lock_irqsave(&cm_id_priv->lock, flags);
}
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
OpenPOWER on IntegriCloud