diff options
Diffstat (limited to 'drivers/infiniband/sw/rdmavt/qp.c')
| -rw-r--r-- | drivers/infiniband/sw/rdmavt/qp.c | 84 | 
1 files changed, 51 insertions, 33 deletions
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 3cdf75d0c7a4..7858d499db03 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -61,6 +61,8 @@  #define RVT_RWQ_COUNT_THRESHOLD 16  static void rvt_rc_timeout(struct timer_list *t); +static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, +			 enum ib_qp_type type);  /*   * Convert the AETH RNR timeout code into the number of microseconds. @@ -452,40 +454,41 @@ no_qp_table:  }  /** - * free_all_qps - check for QPs still in use + * rvt_free_qp_cb - callback function to reset a qp + * @qp: the qp to reset + * @v: a 64-bit value + * + * This function resets the qp and removes it from the + * qp hash table. + */ +static void rvt_free_qp_cb(struct rvt_qp *qp, u64 v) +{ +	unsigned int *qp_inuse = (unsigned int *)v; +	struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); + +	/* Reset the qp and remove it from the qp hash list */ +	rvt_reset_qp(rdi, qp, qp->ibqp.qp_type); + +	/* Increment the qp_inuse count */ +	(*qp_inuse)++; +} + +/** + * rvt_free_all_qps - check for QPs still in use   * @rdi: rvt device info structure   *   * There should not be any QPs still in use.   * Free memory for table. + * Return the number of QPs still in use.   */  static unsigned rvt_free_all_qps(struct rvt_dev_info *rdi)  { -	unsigned long flags; -	struct rvt_qp *qp; -	unsigned n, qp_inuse = 0; -	spinlock_t *ql; /* work around too long line below */ - -	if (rdi->driver_f.free_all_qps) -		qp_inuse = rdi->driver_f.free_all_qps(rdi); +	unsigned int qp_inuse = 0;  	qp_inuse += rvt_mcast_tree_empty(rdi); -	if (!rdi->qp_dev) -		return qp_inuse; - -	ql = &rdi->qp_dev->qpt_lock; -	spin_lock_irqsave(ql, flags); -	for (n = 0; n < rdi->qp_dev->qp_table_size; n++) { -		qp = rcu_dereference_protected(rdi->qp_dev->qp_table[n], -					       lockdep_is_held(ql)); -		RCU_INIT_POINTER(rdi->qp_dev->qp_table[n], NULL); +	rvt_qp_iter(rdi, (u64)&qp_inuse, rvt_free_qp_cb); -		for (; qp; qp = rcu_dereference_protected(qp->next, -							  lockdep_is_held(ql))) -			qp_inuse++; -	} -	spin_unlock_irqrestore(ql, flags); -	synchronize_rcu();  	return qp_inuse;  } @@ -902,14 +905,14 @@ static void rvt_init_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,  }  /** - * rvt_reset_qp - initialize the QP state to the reset state + * _rvt_reset_qp - initialize the QP state to the reset state   * @qp: the QP to reset   * @type: the QP type   *   * r_lock, s_hlock, and s_lock are required to be held by the caller   */ -static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, -			 enum ib_qp_type type) +static void _rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, +			  enum ib_qp_type type)  	__must_hold(&qp->s_lock)  	__must_hold(&qp->s_hlock)  	__must_hold(&qp->r_lock) @@ -955,6 +958,27 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,  	lockdep_assert_held(&qp->s_lock);  } +/** + * rvt_reset_qp - initialize the QP state to the reset state + * @rdi: the device info + * @qp: the QP to reset + * @type: the QP type + * + * This is the wrapper function to acquire the r_lock, s_hlock, and s_lock + * before calling _rvt_reset_qp(). + */ +static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, +			 enum ib_qp_type type) +{ +	spin_lock_irq(&qp->r_lock); +	spin_lock(&qp->s_hlock); +	spin_lock(&qp->s_lock); +	_rvt_reset_qp(rdi, qp, type); +	spin_unlock(&qp->s_lock); +	spin_unlock(&qp->s_hlock); +	spin_unlock_irq(&qp->r_lock); +} +  /** rvt_free_qpn - Free a qpn from the bit map   * @qpt: QP table   * @qpn: queue pair number to free @@ -1546,7 +1570,7 @@ int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,  	switch (new_state) {  	case IB_QPS_RESET:  		if (qp->state != IB_QPS_RESET) -			rvt_reset_qp(rdi, qp, ibqp->qp_type); +			_rvt_reset_qp(rdi, qp, ibqp->qp_type);  		break;  	case IB_QPS_RTR: @@ -1695,13 +1719,7 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)  	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);  	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); -	spin_lock_irq(&qp->r_lock); -	spin_lock(&qp->s_hlock); -	spin_lock(&qp->s_lock);  	rvt_reset_qp(rdi, qp, ibqp->qp_type); -	spin_unlock(&qp->s_lock); -	spin_unlock(&qp->s_hlock); -	spin_unlock_irq(&qp->r_lock);  	wait_event(qp->wait, !atomic_read(&qp->refcount));  	/* qpn is now available for use again */  |