diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_qp.c | 20 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_rc.c | 12 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_verbs.h | 2 |
3 files changed, 29 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index a8c4a6b03d7a..6a41fdbc8e57 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c | |||
@@ -377,13 +377,15 @@ static void ipath_reset_qp(struct ipath_qp *qp) | |||
377 | * @err: the receive completion error to signal if a RWQE is active | 377 | * @err: the receive completion error to signal if a RWQE is active |
378 | * | 378 | * |
379 | * Flushes both send and receive work queues. | 379 | * Flushes both send and receive work queues. |
380 | * Returns true if last WQE event should be generated. | ||
380 | * The QP s_lock should be held and interrupts disabled. | 381 | * The QP s_lock should be held and interrupts disabled. |
381 | */ | 382 | */ |
382 | 383 | ||
383 | void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) | 384 | int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) |
384 | { | 385 | { |
385 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); | 386 | struct ipath_ibdev *dev = to_idev(qp->ibqp.device); |
386 | struct ib_wc wc; | 387 | struct ib_wc wc; |
388 | int ret = 0; | ||
387 | 389 | ||
388 | ipath_dbg("QP%d/%d in error state\n", | 390 | ipath_dbg("QP%d/%d in error state\n", |
389 | qp->ibqp.qp_num, qp->remote_qpn); | 391 | qp->ibqp.qp_num, qp->remote_qpn); |
@@ -454,7 +456,10 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) | |||
454 | wq->tail = tail; | 456 | wq->tail = tail; |
455 | 457 | ||
456 | spin_unlock(&qp->r_rq.lock); | 458 | spin_unlock(&qp->r_rq.lock); |
457 | } | 459 | } else if (qp->ibqp.event_handler) |
460 | ret = 1; | ||
461 | |||
462 | return ret; | ||
458 | } | 463 | } |
459 | 464 | ||
460 | /** | 465 | /** |
@@ -473,6 +478,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
473 | struct ipath_qp *qp = to_iqp(ibqp); | 478 | struct ipath_qp *qp = to_iqp(ibqp); |
474 | enum ib_qp_state cur_state, new_state; | 479 | enum ib_qp_state cur_state, new_state; |
475 | unsigned long flags; | 480 | unsigned long flags; |
481 | int lastwqe = 0; | ||
476 | int ret; | 482 | int ret; |
477 | 483 | ||
478 | spin_lock_irqsave(&qp->s_lock, flags); | 484 | spin_lock_irqsave(&qp->s_lock, flags); |
@@ -532,7 +538,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
532 | break; | 538 | break; |
533 | 539 | ||
534 | case IB_QPS_ERR: | 540 | case IB_QPS_ERR: |
535 | ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); | 541 | lastwqe = ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); |
536 | break; | 542 | break; |
537 | 543 | ||
538 | default: | 544 | default: |
@@ -591,6 +597,14 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
591 | qp->state = new_state; | 597 | qp->state = new_state; |
592 | spin_unlock_irqrestore(&qp->s_lock, flags); | 598 | spin_unlock_irqrestore(&qp->s_lock, flags); |
593 | 599 | ||
600 | if (lastwqe) { | ||
601 | struct ib_event ev; | ||
602 | |||
603 | ev.device = qp->ibqp.device; | ||
604 | ev.element.qp = &qp->ibqp; | ||
605 | ev.event = IB_EVENT_QP_LAST_WQE_REACHED; | ||
606 | qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); | ||
607 | } | ||
594 | ret = 0; | 608 | ret = 0; |
595 | goto bail; | 609 | goto bail; |
596 | 610 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 53259daeb4f8..5c29b2bfea17 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -1497,11 +1497,21 @@ send_ack: | |||
1497 | static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) | 1497 | static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) |
1498 | { | 1498 | { |
1499 | unsigned long flags; | 1499 | unsigned long flags; |
1500 | int lastwqe; | ||
1500 | 1501 | ||
1501 | spin_lock_irqsave(&qp->s_lock, flags); | 1502 | spin_lock_irqsave(&qp->s_lock, flags); |
1502 | qp->state = IB_QPS_ERR; | 1503 | qp->state = IB_QPS_ERR; |
1503 | ipath_error_qp(qp, err); | 1504 | lastwqe = ipath_error_qp(qp, err); |
1504 | spin_unlock_irqrestore(&qp->s_lock, flags); | 1505 | spin_unlock_irqrestore(&qp->s_lock, flags); |
1506 | |||
1507 | if (lastwqe) { | ||
1508 | struct ib_event ev; | ||
1509 | |||
1510 | ev.device = qp->ibqp.device; | ||
1511 | ev.element.qp = &qp->ibqp; | ||
1512 | ev.event = IB_EVENT_QP_LAST_WQE_REACHED; | ||
1513 | qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); | ||
1514 | } | ||
1505 | } | 1515 | } |
1506 | 1516 | ||
1507 | static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) | 1517 | static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 619ad728b07b..a1972295bffd 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
@@ -672,7 +672,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
672 | 672 | ||
673 | int ipath_destroy_qp(struct ib_qp *ibqp); | 673 | int ipath_destroy_qp(struct ib_qp *ibqp); |
674 | 674 | ||
675 | void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err); | 675 | int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err); |
676 | 676 | ||
677 | int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | 677 | int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, |
678 | int attr_mask, struct ib_udata *udata); | 678 | int attr_mask, struct ib_udata *udata); |