diff options
author | Stefan Roscher <ossrosch@linux.vnet.ibm.com> | 2008-05-07 14:35:06 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-05-07 14:35:06 -0400 |
commit | 12137c593d127c6c1a3eb050674da047682badaf (patch) | |
tree | f615c55e363b550c7489aa0aceeb8d62c201fcad /drivers/infiniband/hw | |
parent | ab69b3cf1219e0d07bb4ea373f36b1de38af531c (diff) |
IB/ehca: Wait for async events to finish before destroying QP
This is necessary because, in a multicore environment, a race between
uverbs async handler and destroy QP could occur.
Signed-off-by: Stefan Roscher <stefan.roscher at de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 5 |
3 files changed, 11 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 00bab60f6de4..1e9e99a13933 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -192,6 +192,8 @@ struct ehca_qp { | |||
192 | int mtu_shift; | 192 | int mtu_shift; |
193 | u32 message_count; | 193 | u32 message_count; |
194 | u32 packet_count; | 194 | u32 packet_count; |
195 | atomic_t nr_events; /* events seen */ | ||
196 | wait_queue_head_t wait_completion; | ||
195 | }; | 197 | }; |
196 | 198 | ||
197 | #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ) | 199 | #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ) |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index ca5eb0cb628c..ce1ab0571be3 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -204,6 +204,8 @@ static void qp_event_callback(struct ehca_shca *shca, u64 eqe, | |||
204 | 204 | ||
205 | read_lock(&ehca_qp_idr_lock); | 205 | read_lock(&ehca_qp_idr_lock); |
206 | qp = idr_find(&ehca_qp_idr, token); | 206 | qp = idr_find(&ehca_qp_idr, token); |
207 | if (qp) | ||
208 | atomic_inc(&qp->nr_events); | ||
207 | read_unlock(&ehca_qp_idr_lock); | 209 | read_unlock(&ehca_qp_idr_lock); |
208 | 210 | ||
209 | if (!qp) | 211 | if (!qp) |
@@ -223,6 +225,8 @@ static void qp_event_callback(struct ehca_shca *shca, u64 eqe, | |||
223 | if (fatal && qp->ext_type == EQPT_SRQBASE) | 225 | if (fatal && qp->ext_type == EQPT_SRQBASE) |
224 | dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED); | 226 | dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED); |
225 | 227 | ||
228 | if (atomic_dec_and_test(&qp->nr_events)) | ||
229 | wake_up(&qp->wait_completion); | ||
226 | return; | 230 | return; |
227 | } | 231 | } |
228 | 232 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 18fba92fa7ae..3f59587338ea 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -566,6 +566,8 @@ static struct ehca_qp *internal_create_qp( | |||
566 | return ERR_PTR(-ENOMEM); | 566 | return ERR_PTR(-ENOMEM); |
567 | } | 567 | } |
568 | 568 | ||
569 | atomic_set(&my_qp->nr_events, 0); | ||
570 | init_waitqueue_head(&my_qp->wait_completion); | ||
569 | spin_lock_init(&my_qp->spinlock_s); | 571 | spin_lock_init(&my_qp->spinlock_s); |
570 | spin_lock_init(&my_qp->spinlock_r); | 572 | spin_lock_init(&my_qp->spinlock_r); |
571 | my_qp->qp_type = qp_type; | 573 | my_qp->qp_type = qp_type; |
@@ -1934,6 +1936,9 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
1934 | idr_remove(&ehca_qp_idr, my_qp->token); | 1936 | idr_remove(&ehca_qp_idr, my_qp->token); |
1935 | write_unlock_irqrestore(&ehca_qp_idr_lock, flags); | 1937 | write_unlock_irqrestore(&ehca_qp_idr_lock, flags); |
1936 | 1938 | ||
1939 | /* now wait until all pending events have completed */ | ||
1940 | wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events)); | ||
1941 | |||
1937 | h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); | 1942 | h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); |
1938 | if (h_ret != H_SUCCESS) { | 1943 | if (h_ret != H_SUCCESS) { |
1939 | ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%li " | 1944 | ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%li " |