|
61 | 61 | #define RVT_RWQ_COUNT_THRESHOLD 16
|
62 | 62 |
|
63 | 63 | static void rvt_rc_timeout(struct timer_list *t);
|
| 64 | +static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
| 65 | + enum ib_qp_type type); |
64 | 66 |
|
65 | 67 | /*
|
66 | 68 | * Convert the AETH RNR timeout code into the number of microseconds.
|
@@ -452,40 +454,41 @@ int rvt_driver_qp_init(struct rvt_dev_info *rdi)
|
452 | 454 | }
|
453 | 455 |
|
454 | 456 | /**
|
455 |
| - * free_all_qps - check for QPs still in use |
| 457 | + * rvt_free_qp_cb - callback function to reset a qp |
| 458 | + * @qp: the qp to reset |
| 459 | + * @v: a 64-bit value |
| 460 | + * |
| 461 | + * This function resets the qp and removes it from the |
| 462 | + * qp hash table. |
| 463 | + */ |
| 464 | +static void rvt_free_qp_cb(struct rvt_qp *qp, u64 v) |
| 465 | +{ |
| 466 | + unsigned int *qp_inuse = (unsigned int *)v; |
| 467 | + struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); |
| 468 | + |
| 469 | + /* Reset the qp and remove it from the qp hash list */ |
| 470 | + rvt_reset_qp(rdi, qp, qp->ibqp.qp_type); |
| 471 | + |
| 472 | + /* Increment the qp_inuse count */ |
| 473 | + (*qp_inuse)++; |
| 474 | +} |
| 475 | + |
| 476 | +/** |
| 477 | + * rvt_free_all_qps - check for QPs still in use |
456 | 478 | * @rdi: rvt device info structure
|
457 | 479 | *
|
458 | 480 | * There should not be any QPs still in use.
|
459 | 481 | * Free memory for table.
|
| 482 | + * Return the number of QPs still in use. |
460 | 483 | */
|
461 | 484 | static unsigned rvt_free_all_qps(struct rvt_dev_info *rdi)
|
462 | 485 | {
|
463 |
| - unsigned long flags; |
464 |
| - struct rvt_qp *qp; |
465 |
| - unsigned n, qp_inuse = 0; |
466 |
| - spinlock_t *ql; /* work around too long line below */ |
467 |
| - |
468 |
| - if (rdi->driver_f.free_all_qps) |
469 |
| - qp_inuse = rdi->driver_f.free_all_qps(rdi); |
| 486 | + unsigned int qp_inuse = 0; |
470 | 487 |
|
471 | 488 | qp_inuse += rvt_mcast_tree_empty(rdi);
|
472 | 489 |
|
473 |
| - if (!rdi->qp_dev) |
474 |
| - return qp_inuse; |
475 |
| - |
476 |
| - ql = &rdi->qp_dev->qpt_lock; |
477 |
| - spin_lock_irqsave(ql, flags); |
478 |
| - for (n = 0; n < rdi->qp_dev->qp_table_size; n++) { |
479 |
| - qp = rcu_dereference_protected(rdi->qp_dev->qp_table[n], |
480 |
| - lockdep_is_held(ql)); |
481 |
| - RCU_INIT_POINTER(rdi->qp_dev->qp_table[n], NULL); |
| 490 | + rvt_qp_iter(rdi, (u64)&qp_inuse, rvt_free_qp_cb); |
482 | 491 |
|
483 |
| - for (; qp; qp = rcu_dereference_protected(qp->next, |
484 |
| - lockdep_is_held(ql))) |
485 |
| - qp_inuse++; |
486 |
| - } |
487 |
| - spin_unlock_irqrestore(ql, flags); |
488 |
| - synchronize_rcu(); |
489 | 492 | return qp_inuse;
|
490 | 493 | }
|
491 | 494 |
|
@@ -902,14 +905,14 @@ static void rvt_init_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
|
902 | 905 | }
|
903 | 906 |
|
904 | 907 | /**
|
905 |
| - * rvt_reset_qp - initialize the QP state to the reset state |
| 908 | + * _rvt_reset_qp - initialize the QP state to the reset state |
906 | 909 | * @qp: the QP to reset
|
907 | 910 | * @type: the QP type
|
908 | 911 | *
|
909 | 912 | * r_lock, s_hlock, and s_lock are required to be held by the caller
|
910 | 913 | */
|
911 |
| -static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
912 |
| - enum ib_qp_type type) |
| 914 | +static void _rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
| 915 | + enum ib_qp_type type) |
913 | 916 | __must_hold(&qp->s_lock)
|
914 | 917 | __must_hold(&qp->s_hlock)
|
915 | 918 | __must_hold(&qp->r_lock)
|
@@ -955,6 +958,27 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
|
955 | 958 | lockdep_assert_held(&qp->s_lock);
|
956 | 959 | }
|
957 | 960 |
|
| 961 | +/** |
| 962 | + * rvt_reset_qp - initialize the QP state to the reset state |
| 963 | + * @rdi: the device info |
| 964 | + * @qp: the QP to reset |
| 965 | + * @type: the QP type |
| 966 | + * |
| 967 | + * This is the wrapper function to acquire the r_lock, s_hlock, and s_lock |
| 968 | + * before calling _rvt_reset_qp(). |
| 969 | + */ |
| 970 | +static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, |
| 971 | + enum ib_qp_type type) |
| 972 | +{ |
| 973 | + spin_lock_irq(&qp->r_lock); |
| 974 | + spin_lock(&qp->s_hlock); |
| 975 | + spin_lock(&qp->s_lock); |
| 976 | + _rvt_reset_qp(rdi, qp, type); |
| 977 | + spin_unlock(&qp->s_lock); |
| 978 | + spin_unlock(&qp->s_hlock); |
| 979 | + spin_unlock_irq(&qp->r_lock); |
| 980 | +} |
| 981 | + |
958 | 982 | /** rvt_free_qpn - Free a qpn from the bit map
|
959 | 983 | * @qpt: QP table
|
960 | 984 | * @qpn: queue pair number to free
|
@@ -1546,7 +1570,7 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
1546 | 1570 | switch (new_state) {
|
1547 | 1571 | case IB_QPS_RESET:
|
1548 | 1572 | if (qp->state != IB_QPS_RESET)
|
1549 |
| - rvt_reset_qp(rdi, qp, ibqp->qp_type); |
| 1573 | + _rvt_reset_qp(rdi, qp, ibqp->qp_type); |
1550 | 1574 | break;
|
1551 | 1575 |
|
1552 | 1576 | case IB_QPS_RTR:
|
@@ -1695,13 +1719,7 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
|
1695 | 1719 | struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
|
1696 | 1720 | struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
|
1697 | 1721 |
|
1698 |
| - spin_lock_irq(&qp->r_lock); |
1699 |
| - spin_lock(&qp->s_hlock); |
1700 |
| - spin_lock(&qp->s_lock); |
1701 | 1722 | rvt_reset_qp(rdi, qp, ibqp->qp_type);
|
1702 |
| - spin_unlock(&qp->s_lock); |
1703 |
| - spin_unlock(&qp->s_hlock); |
1704 |
| - spin_unlock_irq(&qp->r_lock); |
1705 | 1723 |
|
1706 | 1724 | wait_event(qp->wait, !atomic_read(&qp->refcount));
|
1707 | 1725 | /* qpn is now available for use again */
|
|
0 commit comments