diff options
| -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 " |
