diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:32:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:32:31 -0500 |
commit | e69381b4175ba162229646f6753ff1d87c24d468 (patch) | |
tree | ac4c03f6a0a1a0426832aa4f5c3b7732080c51cc /drivers/infiniband/hw/ehca | |
parent | 238ccbb050a243e935bb3fc679c2e4bbff7004aa (diff) | |
parent | 14f369d1d61e7ac6578c54ca9ce3caaf4072412c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (45 commits)
RDMA/cxgb3: Fix error paths in post_send and post_recv
RDMA/nes: Fix stale ARP issue
RDMA/nes: FIN during MPA startup causes timeout
RDMA/nes: Free kmap() resources
RDMA/nes: Check for zero STag
RDMA/nes: Fix Xansation test crash on cm_node ref_count
RDMA/nes: Abnormal listener exit causes loopback node crash
RDMA/nes: Fix crash in nes_accept()
RDMA/nes: Resource not freed for REJECTed connections
RDMA/nes: MPA request/response error checking
RDMA/nes: Fix query of ORD values
RDMA/nes: Fix MAX_CM_BUFFER define
RDMA/nes: Pass correct size to ioremap_nocache()
RDMA/nes: Update copyright and branding string
RDMA/nes: Add max_cqe check to nes_create_cq()
RDMA/nes: Clean up struct nes_qp
RDMA/nes: Implement IB_SIGNAL_ALL_WR as an iWARP extension
RDMA/nes: Add additional SFP+ PHY uC status check and PHY reset
RDMA/nes: Correct fast memory registration implementation
IB/ehca: Fix error paths in post_send and post_recv
...
Diffstat (limited to 'drivers/infiniband/hw/ehca')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_eq.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_reqs.c | 67 |
4 files changed, 39 insertions, 40 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index c825142a2fb..0136abd50dd 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -375,6 +375,7 @@ extern rwlock_t ehca_qp_idr_lock; | |||
375 | extern rwlock_t ehca_cq_idr_lock; | 375 | extern rwlock_t ehca_cq_idr_lock; |
376 | extern struct idr ehca_qp_idr; | 376 | extern struct idr ehca_qp_idr; |
377 | extern struct idr ehca_cq_idr; | 377 | extern struct idr ehca_cq_idr; |
378 | extern spinlock_t shca_list_lock; | ||
378 | 379 | ||
379 | extern int ehca_static_rate; | 380 | extern int ehca_static_rate; |
380 | extern int ehca_port_act_time; | 381 | extern int ehca_port_act_time; |
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c index 523e733c630..3b87589b8ea 100644 --- a/drivers/infiniband/hw/ehca/ehca_eq.c +++ b/drivers/infiniband/hw/ehca/ehca_eq.c | |||
@@ -169,12 +169,15 @@ int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) | |||
169 | unsigned long flags; | 169 | unsigned long flags; |
170 | u64 h_ret; | 170 | u64 h_ret; |
171 | 171 | ||
172 | spin_lock_irqsave(&eq->spinlock, flags); | ||
173 | ibmebus_free_irq(eq->ist, (void *)shca); | 172 | ibmebus_free_irq(eq->ist, (void *)shca); |
174 | 173 | ||
175 | h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); | 174 | spin_lock_irqsave(&shca_list_lock, flags); |
175 | eq->is_initialized = 0; | ||
176 | spin_unlock_irqrestore(&shca_list_lock, flags); | ||
176 | 177 | ||
177 | spin_unlock_irqrestore(&eq->spinlock, flags); | 178 | tasklet_kill(&eq->interrupt_task); |
179 | |||
180 | h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); | ||
178 | 181 | ||
179 | if (h_ret != H_SUCCESS) { | 182 | if (h_ret != H_SUCCESS) { |
180 | ehca_err(&shca->ib_device, "Can't free EQ resources."); | 183 | ehca_err(&shca->ib_device, "Can't free EQ resources."); |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index fb2d83c5bf0..129a6bebd6e 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -123,7 +123,7 @@ DEFINE_IDR(ehca_qp_idr); | |||
123 | DEFINE_IDR(ehca_cq_idr); | 123 | DEFINE_IDR(ehca_cq_idr); |
124 | 124 | ||
125 | static LIST_HEAD(shca_list); /* list of all registered ehcas */ | 125 | static LIST_HEAD(shca_list); /* list of all registered ehcas */ |
126 | static DEFINE_SPINLOCK(shca_list_lock); | 126 | DEFINE_SPINLOCK(shca_list_lock); |
127 | 127 | ||
128 | static struct timer_list poll_eqs_timer; | 128 | static struct timer_list poll_eqs_timer; |
129 | 129 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 8fd88cd828f..e3ec7fdd67b 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c | |||
@@ -400,7 +400,6 @@ static inline void map_ib_wc_status(u32 cqe_status, | |||
400 | 400 | ||
401 | static inline int post_one_send(struct ehca_qp *my_qp, | 401 | static inline int post_one_send(struct ehca_qp *my_qp, |
402 | struct ib_send_wr *cur_send_wr, | 402 | struct ib_send_wr *cur_send_wr, |
403 | struct ib_send_wr **bad_send_wr, | ||
404 | int hidden) | 403 | int hidden) |
405 | { | 404 | { |
406 | struct ehca_wqe *wqe_p; | 405 | struct ehca_wqe *wqe_p; |
@@ -412,8 +411,6 @@ static inline int post_one_send(struct ehca_qp *my_qp, | |||
412 | wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue); | 411 | wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue); |
413 | if (unlikely(!wqe_p)) { | 412 | if (unlikely(!wqe_p)) { |
414 | /* too many posted work requests: queue overflow */ | 413 | /* too many posted work requests: queue overflow */ |
415 | if (bad_send_wr) | ||
416 | *bad_send_wr = cur_send_wr; | ||
417 | ehca_err(my_qp->ib_qp.device, "Too many posted WQEs " | 414 | ehca_err(my_qp->ib_qp.device, "Too many posted WQEs " |
418 | "qp_num=%x", my_qp->ib_qp.qp_num); | 415 | "qp_num=%x", my_qp->ib_qp.qp_num); |
419 | return -ENOMEM; | 416 | return -ENOMEM; |
@@ -433,8 +430,6 @@ static inline int post_one_send(struct ehca_qp *my_qp, | |||
433 | */ | 430 | */ |
434 | if (unlikely(ret)) { | 431 | if (unlikely(ret)) { |
435 | my_qp->ipz_squeue.current_q_offset = start_offset; | 432 | my_qp->ipz_squeue.current_q_offset = start_offset; |
436 | if (bad_send_wr) | ||
437 | *bad_send_wr = cur_send_wr; | ||
438 | ehca_err(my_qp->ib_qp.device, "Could not write WQE " | 433 | ehca_err(my_qp->ib_qp.device, "Could not write WQE " |
439 | "qp_num=%x", my_qp->ib_qp.qp_num); | 434 | "qp_num=%x", my_qp->ib_qp.qp_num); |
440 | return -EINVAL; | 435 | return -EINVAL; |
@@ -448,7 +443,6 @@ int ehca_post_send(struct ib_qp *qp, | |||
448 | struct ib_send_wr **bad_send_wr) | 443 | struct ib_send_wr **bad_send_wr) |
449 | { | 444 | { |
450 | struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); | 445 | struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); |
451 | struct ib_send_wr *cur_send_wr; | ||
452 | int wqe_cnt = 0; | 446 | int wqe_cnt = 0; |
453 | int ret = 0; | 447 | int ret = 0; |
454 | unsigned long flags; | 448 | unsigned long flags; |
@@ -457,7 +451,8 @@ int ehca_post_send(struct ib_qp *qp, | |||
457 | if (unlikely(my_qp->state < IB_QPS_RTS)) { | 451 | if (unlikely(my_qp->state < IB_QPS_RTS)) { |
458 | ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", | 452 | ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", |
459 | my_qp->state, qp->qp_num); | 453 | my_qp->state, qp->qp_num); |
460 | return -EINVAL; | 454 | ret = -EINVAL; |
455 | goto out; | ||
461 | } | 456 | } |
462 | 457 | ||
463 | /* LOCK the QUEUE */ | 458 | /* LOCK the QUEUE */ |
@@ -476,24 +471,21 @@ int ehca_post_send(struct ib_qp *qp, | |||
476 | struct ib_send_wr circ_wr; | 471 | struct ib_send_wr circ_wr; |
477 | memset(&circ_wr, 0, sizeof(circ_wr)); | 472 | memset(&circ_wr, 0, sizeof(circ_wr)); |
478 | circ_wr.opcode = IB_WR_RDMA_READ; | 473 | circ_wr.opcode = IB_WR_RDMA_READ; |
479 | post_one_send(my_qp, &circ_wr, NULL, 1); /* ignore retcode */ | 474 | post_one_send(my_qp, &circ_wr, 1); /* ignore retcode */ |
480 | wqe_cnt++; | 475 | wqe_cnt++; |
481 | ehca_dbg(qp->device, "posted circ wr qp_num=%x", qp->qp_num); | 476 | ehca_dbg(qp->device, "posted circ wr qp_num=%x", qp->qp_num); |
482 | my_qp->message_count = my_qp->packet_count = 0; | 477 | my_qp->message_count = my_qp->packet_count = 0; |
483 | } | 478 | } |
484 | 479 | ||
485 | /* loop processes list of send reqs */ | 480 | /* loop processes list of send reqs */ |
486 | for (cur_send_wr = send_wr; cur_send_wr != NULL; | 481 | while (send_wr) { |
487 | cur_send_wr = cur_send_wr->next) { | 482 | ret = post_one_send(my_qp, send_wr, 0); |
488 | ret = post_one_send(my_qp, cur_send_wr, bad_send_wr, 0); | ||
489 | if (unlikely(ret)) { | 483 | if (unlikely(ret)) { |
490 | /* if one or more WQEs were successful, don't fail */ | ||
491 | if (wqe_cnt) | ||
492 | ret = 0; | ||
493 | goto post_send_exit0; | 484 | goto post_send_exit0; |
494 | } | 485 | } |
495 | wqe_cnt++; | 486 | wqe_cnt++; |
496 | } /* eof for cur_send_wr */ | 487 | send_wr = send_wr->next; |
488 | } | ||
497 | 489 | ||
498 | post_send_exit0: | 490 | post_send_exit0: |
499 | iosync(); /* serialize GAL register access */ | 491 | iosync(); /* serialize GAL register access */ |
@@ -503,6 +495,10 @@ post_send_exit0: | |||
503 | my_qp, qp->qp_num, wqe_cnt, ret); | 495 | my_qp, qp->qp_num, wqe_cnt, ret); |
504 | my_qp->message_count += wqe_cnt; | 496 | my_qp->message_count += wqe_cnt; |
505 | spin_unlock_irqrestore(&my_qp->spinlock_s, flags); | 497 | spin_unlock_irqrestore(&my_qp->spinlock_s, flags); |
498 | |||
499 | out: | ||
500 | if (ret) | ||
501 | *bad_send_wr = send_wr; | ||
506 | return ret; | 502 | return ret; |
507 | } | 503 | } |
508 | 504 | ||
@@ -511,7 +507,6 @@ static int internal_post_recv(struct ehca_qp *my_qp, | |||
511 | struct ib_recv_wr *recv_wr, | 507 | struct ib_recv_wr *recv_wr, |
512 | struct ib_recv_wr **bad_recv_wr) | 508 | struct ib_recv_wr **bad_recv_wr) |
513 | { | 509 | { |
514 | struct ib_recv_wr *cur_recv_wr; | ||
515 | struct ehca_wqe *wqe_p; | 510 | struct ehca_wqe *wqe_p; |
516 | int wqe_cnt = 0; | 511 | int wqe_cnt = 0; |
517 | int ret = 0; | 512 | int ret = 0; |
@@ -522,27 +517,23 @@ static int internal_post_recv(struct ehca_qp *my_qp, | |||
522 | if (unlikely(!HAS_RQ(my_qp))) { | 517 | if (unlikely(!HAS_RQ(my_qp))) { |
523 | ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d", | 518 | ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d", |
524 | my_qp, my_qp->real_qp_num, my_qp->ext_type); | 519 | my_qp, my_qp->real_qp_num, my_qp->ext_type); |
525 | return -ENODEV; | 520 | ret = -ENODEV; |
521 | goto out; | ||
526 | } | 522 | } |
527 | 523 | ||
528 | /* LOCK the QUEUE */ | 524 | /* LOCK the QUEUE */ |
529 | spin_lock_irqsave(&my_qp->spinlock_r, flags); | 525 | spin_lock_irqsave(&my_qp->spinlock_r, flags); |
530 | 526 | ||
531 | /* loop processes list of send reqs */ | 527 | /* loop processes list of recv reqs */ |
532 | for (cur_recv_wr = recv_wr; cur_recv_wr != NULL; | 528 | while (recv_wr) { |
533 | cur_recv_wr = cur_recv_wr->next) { | ||
534 | u64 start_offset = my_qp->ipz_rqueue.current_q_offset; | 529 | u64 start_offset = my_qp->ipz_rqueue.current_q_offset; |
535 | /* get pointer next to free WQE */ | 530 | /* get pointer next to free WQE */ |
536 | wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue); | 531 | wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue); |
537 | if (unlikely(!wqe_p)) { | 532 | if (unlikely(!wqe_p)) { |
538 | /* too many posted work requests: queue overflow */ | 533 | /* too many posted work requests: queue overflow */ |
539 | if (bad_recv_wr) | 534 | ret = -ENOMEM; |
540 | *bad_recv_wr = cur_recv_wr; | 535 | ehca_err(dev, "Too many posted WQEs " |
541 | if (wqe_cnt == 0) { | 536 | "qp_num=%x", my_qp->real_qp_num); |
542 | ret = -ENOMEM; | ||
543 | ehca_err(dev, "Too many posted WQEs " | ||
544 | "qp_num=%x", my_qp->real_qp_num); | ||
545 | } | ||
546 | goto post_recv_exit0; | 537 | goto post_recv_exit0; |
547 | } | 538 | } |
548 | /* | 539 | /* |
@@ -552,7 +543,7 @@ static int internal_post_recv(struct ehca_qp *my_qp, | |||
552 | rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size; | 543 | rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size; |
553 | 544 | ||
554 | /* write a RECV WQE into the QUEUE */ | 545 | /* write a RECV WQE into the QUEUE */ |
555 | ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr, | 546 | ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, recv_wr, |
556 | rq_map_idx); | 547 | rq_map_idx); |
557 | /* | 548 | /* |
558 | * if something failed, | 549 | * if something failed, |
@@ -560,22 +551,20 @@ static int internal_post_recv(struct ehca_qp *my_qp, | |||
560 | */ | 551 | */ |
561 | if (unlikely(ret)) { | 552 | if (unlikely(ret)) { |
562 | my_qp->ipz_rqueue.current_q_offset = start_offset; | 553 | my_qp->ipz_rqueue.current_q_offset = start_offset; |
563 | *bad_recv_wr = cur_recv_wr; | 554 | ret = -EINVAL; |
564 | if (wqe_cnt == 0) { | 555 | ehca_err(dev, "Could not write WQE " |
565 | ret = -EINVAL; | 556 | "qp_num=%x", my_qp->real_qp_num); |
566 | ehca_err(dev, "Could not write WQE " | ||
567 | "qp_num=%x", my_qp->real_qp_num); | ||
568 | } | ||
569 | goto post_recv_exit0; | 557 | goto post_recv_exit0; |
570 | } | 558 | } |
571 | 559 | ||
572 | qmap_entry = &my_qp->rq_map.map[rq_map_idx]; | 560 | qmap_entry = &my_qp->rq_map.map[rq_map_idx]; |
573 | qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); | 561 | qmap_entry->app_wr_id = get_app_wr_id(recv_wr->wr_id); |
574 | qmap_entry->reported = 0; | 562 | qmap_entry->reported = 0; |
575 | qmap_entry->cqe_req = 1; | 563 | qmap_entry->cqe_req = 1; |
576 | 564 | ||
577 | wqe_cnt++; | 565 | wqe_cnt++; |
578 | } /* eof for cur_recv_wr */ | 566 | recv_wr = recv_wr->next; |
567 | } /* eof for recv_wr */ | ||
579 | 568 | ||
580 | post_recv_exit0: | 569 | post_recv_exit0: |
581 | iosync(); /* serialize GAL register access */ | 570 | iosync(); /* serialize GAL register access */ |
@@ -584,6 +573,11 @@ post_recv_exit0: | |||
584 | ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i", | 573 | ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i", |
585 | my_qp, my_qp->real_qp_num, wqe_cnt, ret); | 574 | my_qp, my_qp->real_qp_num, wqe_cnt, ret); |
586 | spin_unlock_irqrestore(&my_qp->spinlock_r, flags); | 575 | spin_unlock_irqrestore(&my_qp->spinlock_r, flags); |
576 | |||
577 | out: | ||
578 | if (ret) | ||
579 | *bad_recv_wr = recv_wr; | ||
580 | |||
587 | return ret; | 581 | return ret; |
588 | } | 582 | } |
589 | 583 | ||
@@ -597,6 +591,7 @@ int ehca_post_recv(struct ib_qp *qp, | |||
597 | if (unlikely(my_qp->state == IB_QPS_RESET)) { | 591 | if (unlikely(my_qp->state == IB_QPS_RESET)) { |
598 | ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", | 592 | ehca_err(qp->device, "Invalid QP state qp_state=%d qpn=%x", |
599 | my_qp->state, qp->qp_num); | 593 | my_qp->state, qp->qp_num); |
594 | *bad_recv_wr = recv_wr; | ||
600 | return -EINVAL; | 595 | return -EINVAL; |
601 | } | 596 | } |
602 | 597 | ||