diff options
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_cq.c | 26 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 36 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_tools.h | 1 |
5 files changed, 29 insertions, 39 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 3550047c1375..8580f2a0ea57 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -174,8 +174,8 @@ struct ehca_cq { | |||
174 | spinlock_t cb_lock; | 174 | spinlock_t cb_lock; |
175 | struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; | 175 | struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; |
176 | struct list_head entry; | 176 | struct list_head entry; |
177 | u32 nr_callbacks; /* #events assigned to cpu by scaling code */ | 177 | u32 nr_callbacks; /* #events assigned to cpu by scaling code */ |
178 | u32 nr_events; /* #events seen */ | 178 | atomic_t nr_events; /* #events seen */ |
179 | wait_queue_head_t wait_completion; | 179 | wait_queue_head_t wait_completion; |
180 | spinlock_t task_lock; | 180 | spinlock_t task_lock; |
181 | u32 ownpid; | 181 | u32 ownpid; |
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 94bad273b34c..3729997457ca 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c | |||
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, | |||
146 | spin_lock_init(&my_cq->spinlock); | 146 | spin_lock_init(&my_cq->spinlock); |
147 | spin_lock_init(&my_cq->cb_lock); | 147 | spin_lock_init(&my_cq->cb_lock); |
148 | spin_lock_init(&my_cq->task_lock); | 148 | spin_lock_init(&my_cq->task_lock); |
149 | atomic_set(&my_cq->nr_events, 0); | ||
149 | init_waitqueue_head(&my_cq->wait_completion); | 150 | init_waitqueue_head(&my_cq->wait_completion); |
150 | my_cq->ownpid = current->tgid; | 151 | my_cq->ownpid = current->tgid; |
151 | 152 | ||
@@ -303,16 +304,6 @@ create_cq_exit1: | |||
303 | return cq; | 304 | return cq; |
304 | } | 305 | } |
305 | 306 | ||
306 | static int get_cq_nr_events(struct ehca_cq *my_cq) | ||
307 | { | ||
308 | int ret; | ||
309 | unsigned long flags; | ||
310 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | ||
311 | ret = my_cq->nr_events; | ||
312 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | int ehca_destroy_cq(struct ib_cq *cq) | 307 | int ehca_destroy_cq(struct ib_cq *cq) |
317 | { | 308 | { |
318 | u64 h_ret; | 309 | u64 h_ret; |
@@ -339,17 +330,18 @@ int ehca_destroy_cq(struct ib_cq *cq) | |||
339 | } | 330 | } |
340 | } | 331 | } |
341 | 332 | ||
333 | /* | ||
334 | * remove the CQ from the idr first to make sure | ||
335 | * no more interrupt tasklets will touch this CQ | ||
336 | */ | ||
342 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 337 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); |
343 | while (my_cq->nr_events) { | ||
344 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
345 | wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq)); | ||
346 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | ||
347 | /* recheck nr_events to assure no cqe has just arrived */ | ||
348 | } | ||
349 | |||
350 | idr_remove(&ehca_cq_idr, my_cq->token); | 338 | idr_remove(&ehca_cq_idr, my_cq->token); |
351 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | 339 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); |
352 | 340 | ||
341 | /* now wait until all pending events have completed */ | ||
342 | wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events)); | ||
343 | |||
344 | /* nobody's using our CQ any longer -- we can destroy it */ | ||
353 | h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); | 345 | h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); |
354 | if (h_ret == H_R_STATE) { | 346 | if (h_ret == H_R_STATE) { |
355 | /* cq in err: read err data and destroy it forcibly */ | 347 | /* cq in err: read err data and destroy it forcibly */ |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 100329ba3343..3e790a326d97 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * | 5 | * |
6 | * Authors: Heiko J Schick <schickhj@de.ibm.com> | 6 | * Authors: Heiko J Schick <schickhj@de.ibm.com> |
7 | * Khadija Souissi <souissi@de.ibm.com> | 7 | * Khadija Souissi <souissi@de.ibm.com> |
8 | * Hoang-Nam Nguyen <hnguyen@de.ibm.com> | ||
9 | * Joachim Fenkes <fenkes@de.ibm.com> | ||
8 | * | 10 | * |
9 | * Copyright (c) 2005 IBM Corporation | 11 | * Copyright (c) 2005 IBM Corporation |
10 | * | 12 | * |
@@ -212,6 +214,8 @@ static void cq_event_callback(struct ehca_shca *shca, | |||
212 | 214 | ||
213 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 215 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); |
214 | cq = idr_find(&ehca_cq_idr, token); | 216 | cq = idr_find(&ehca_cq_idr, token); |
217 | if (cq) | ||
218 | atomic_inc(&cq->nr_events); | ||
215 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | 219 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); |
216 | 220 | ||
217 | if (!cq) | 221 | if (!cq) |
@@ -219,6 +223,9 @@ static void cq_event_callback(struct ehca_shca *shca, | |||
219 | 223 | ||
220 | ehca_error_data(shca, cq, cq->ipz_cq_handle.handle); | 224 | ehca_error_data(shca, cq, cq->ipz_cq_handle.handle); |
221 | 225 | ||
226 | if (atomic_dec_and_test(&cq->nr_events)) | ||
227 | wake_up(&cq->wait_completion); | ||
228 | |||
222 | return; | 229 | return; |
223 | } | 230 | } |
224 | 231 | ||
@@ -414,25 +421,22 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe) | |||
414 | token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); | 421 | token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); |
415 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 422 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); |
416 | cq = idr_find(&ehca_cq_idr, token); | 423 | cq = idr_find(&ehca_cq_idr, token); |
424 | if (cq) | ||
425 | atomic_inc(&cq->nr_events); | ||
426 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
417 | if (cq == NULL) { | 427 | if (cq == NULL) { |
418 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
419 | ehca_err(&shca->ib_device, | 428 | ehca_err(&shca->ib_device, |
420 | "Invalid eqe for non-existing cq token=%x", | 429 | "Invalid eqe for non-existing cq token=%x", |
421 | token); | 430 | token); |
422 | return; | 431 | return; |
423 | } | 432 | } |
424 | reset_eq_pending(cq); | 433 | reset_eq_pending(cq); |
425 | cq->nr_events++; | ||
426 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
427 | if (ehca_scaling_code) | 434 | if (ehca_scaling_code) |
428 | queue_comp_task(cq); | 435 | queue_comp_task(cq); |
429 | else { | 436 | else { |
430 | comp_event_callback(cq); | 437 | comp_event_callback(cq); |
431 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 438 | if (atomic_dec_and_test(&cq->nr_events)) |
432 | cq->nr_events--; | ||
433 | if (!cq->nr_events) | ||
434 | wake_up(&cq->wait_completion); | 439 | wake_up(&cq->wait_completion); |
435 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
436 | } | 440 | } |
437 | } else { | 441 | } else { |
438 | ehca_dbg(&shca->ib_device, "Got non completion event"); | 442 | ehca_dbg(&shca->ib_device, "Got non completion event"); |
@@ -478,15 +482,15 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) | |||
478 | token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); | 482 | token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value); |
479 | spin_lock(&ehca_cq_idr_lock); | 483 | spin_lock(&ehca_cq_idr_lock); |
480 | eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token); | 484 | eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token); |
485 | if (eqe_cache[eqe_cnt].cq) | ||
486 | atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events); | ||
487 | spin_unlock(&ehca_cq_idr_lock); | ||
481 | if (!eqe_cache[eqe_cnt].cq) { | 488 | if (!eqe_cache[eqe_cnt].cq) { |
482 | spin_unlock(&ehca_cq_idr_lock); | ||
483 | ehca_err(&shca->ib_device, | 489 | ehca_err(&shca->ib_device, |
484 | "Invalid eqe for non-existing cq " | 490 | "Invalid eqe for non-existing cq " |
485 | "token=%x", token); | 491 | "token=%x", token); |
486 | continue; | 492 | continue; |
487 | } | 493 | } |
488 | eqe_cache[eqe_cnt].cq->nr_events++; | ||
489 | spin_unlock(&ehca_cq_idr_lock); | ||
490 | } else | 494 | } else |
491 | eqe_cache[eqe_cnt].cq = NULL; | 495 | eqe_cache[eqe_cnt].cq = NULL; |
492 | eqe_cnt++; | 496 | eqe_cnt++; |
@@ -517,11 +521,8 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq) | |||
517 | else { | 521 | else { |
518 | struct ehca_cq *cq = eq->eqe_cache[i].cq; | 522 | struct ehca_cq *cq = eq->eqe_cache[i].cq; |
519 | comp_event_callback(cq); | 523 | comp_event_callback(cq); |
520 | spin_lock(&ehca_cq_idr_lock); | 524 | if (atomic_dec_and_test(&cq->nr_events)) |
521 | cq->nr_events--; | ||
522 | if (!cq->nr_events) | ||
523 | wake_up(&cq->wait_completion); | 525 | wake_up(&cq->wait_completion); |
524 | spin_unlock(&ehca_cq_idr_lock); | ||
525 | } | 526 | } |
526 | } else { | 527 | } else { |
527 | ehca_dbg(&shca->ib_device, "Got non completion event"); | 528 | ehca_dbg(&shca->ib_device, "Got non completion event"); |
@@ -621,13 +622,10 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct) | |||
621 | while (!list_empty(&cct->cq_list)) { | 622 | while (!list_empty(&cct->cq_list)) { |
622 | cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); | 623 | cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); |
623 | spin_unlock_irqrestore(&cct->task_lock, flags); | 624 | spin_unlock_irqrestore(&cct->task_lock, flags); |
624 | comp_event_callback(cq); | ||
625 | 625 | ||
626 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 626 | comp_event_callback(cq); |
627 | cq->nr_events--; | 627 | if (atomic_dec_and_test(&cq->nr_events)) |
628 | if (!cq->nr_events) | ||
629 | wake_up(&cq->wait_completion); | 628 | wake_up(&cq->wait_completion); |
630 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | ||
631 | 629 | ||
632 | spin_lock_irqsave(&cct->task_lock, flags); | 630 | spin_lock_irqsave(&cct->task_lock, flags); |
633 | spin_lock(&cq->task_lock); | 631 | spin_lock(&cq->task_lock); |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h index 6ed06ee033ed..3346cb06cea6 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.h +++ b/drivers/infiniband/hw/ehca/ehca_irq.h | |||
@@ -47,7 +47,6 @@ struct ehca_shca; | |||
47 | 47 | ||
48 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
49 | #include <linux/types.h> | 49 | #include <linux/types.h> |
50 | #include <asm/atomic.h> | ||
51 | 50 | ||
52 | int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource); | 51 | int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource); |
53 | 52 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index 973c4b591545..03b185f873da 100644 --- a/drivers/infiniband/hw/ehca/ehca_tools.h +++ b/drivers/infiniband/hw/ehca/ehca_tools.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/cpu.h> | 59 | #include <linux/cpu.h> |
60 | #include <linux/device.h> | 60 | #include <linux/device.h> |
61 | 61 | ||
62 | #include <asm/atomic.h> | ||
62 | #include <asm/abs_addr.h> | 63 | #include <asm/abs_addr.h> |
63 | #include <asm/ibmebus.h> | 64 | #include <asm/ibmebus.h> |
64 | #include <asm/io.h> | 65 | #include <asm/io.h> |