diff options
Diffstat (limited to 'drivers/infiniband/hw/irdma/utils.c')
| -rw-r--r-- | drivers/infiniband/hw/irdma/utils.c | 112 | 
1 files changed, 107 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c index b510ef747399..8b94d87b0192 100644 --- a/drivers/infiniband/hw/irdma/utils.c +++ b/drivers/infiniband/hw/irdma/utils.c @@ -481,6 +481,7 @@ void irdma_free_cqp_request(struct irdma_cqp *cqp,  		WRITE_ONCE(cqp_request->request_done, false);  		cqp_request->callback_fcn = NULL;  		cqp_request->waiting = false; +		cqp_request->pending = false;  		spin_lock_irqsave(&cqp->req_lock, flags);  		list_add_tail(&cqp_request->list, &cqp->cqp_avail_reqs); @@ -521,6 +522,22 @@ irdma_free_pending_cqp_request(struct irdma_cqp *cqp,  }  /** + * irdma_cleanup_deferred_cqp_ops - clean-up cqp with no completions + * @dev: sc_dev + * @cqp: cqp + */ +static void irdma_cleanup_deferred_cqp_ops(struct irdma_sc_dev *dev, +					   struct irdma_cqp *cqp) +{ +	u64 scratch; + +	/* process all CQP requests with deferred/pending completions */ +	while ((scratch = irdma_sc_cqp_cleanup_handler(dev))) +		irdma_free_pending_cqp_request(cqp, (struct irdma_cqp_request *) +						    (uintptr_t)scratch); +} + +/**   * irdma_cleanup_pending_cqp_op - clean-up cqp with no   * completions   * @rf: RDMA PCI function @@ -533,6 +550,8 @@ void irdma_cleanup_pending_cqp_op(struct irdma_pci_f *rf)  	struct cqp_cmds_info *pcmdinfo = NULL;  	u32 i, pending_work, wqe_idx; +	if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_3) +		irdma_cleanup_deferred_cqp_ops(dev, cqp);  	pending_work = IRDMA_RING_USED_QUANTA(cqp->sc_cqp.sq_ring);  	wqe_idx = IRDMA_RING_CURRENT_TAIL(cqp->sc_cqp.sq_ring);  	for (i = 0; i < pending_work; i++) { @@ -552,6 +571,26 @@ void irdma_cleanup_pending_cqp_op(struct irdma_pci_f *rf)  	}  } +static int irdma_get_timeout_threshold(struct irdma_sc_dev *dev) +{ +	u16 time_s = dev->vc_caps.cqp_timeout_s; + +	if (!time_s) +		return CQP_TIMEOUT_THRESHOLD; + +	return time_s * 1000 / dev->hw_attrs.max_cqp_compl_wait_time_ms; +} + +static int irdma_get_def_timeout_threshold(struct irdma_sc_dev *dev) +{ +	u16 time_s = dev->vc_caps.cqp_def_timeout_s; + +	if (!time_s) +		return CQP_DEF_CMPL_TIMEOUT_THRESHOLD; + +	return time_s * 1000 / dev->hw_attrs.max_cqp_compl_wait_time_ms; +} +  /**   * irdma_wait_event - wait for completion   * @rf: RDMA PCI function @@ -561,6 +600,7 @@ static int irdma_wait_event(struct irdma_pci_f *rf,  			    struct irdma_cqp_request *cqp_request)  {  	struct irdma_cqp_timeout cqp_timeout = {}; +	int timeout_threshold = irdma_get_timeout_threshold(&rf->sc_dev);  	bool cqp_error = false;  	int err_code = 0; @@ -572,9 +612,17 @@ static int irdma_wait_event(struct irdma_pci_f *rf,  				       msecs_to_jiffies(CQP_COMPL_WAIT_TIME_MS)))  			break; +		if (cqp_request->pending) +			/* There was a deferred or pending completion +			 * received for this CQP request, so we need +			 * to wait longer than usual. +			 */ +			timeout_threshold = +				irdma_get_def_timeout_threshold(&rf->sc_dev); +  		irdma_check_cqp_progress(&cqp_timeout, &rf->sc_dev); -		if (cqp_timeout.count < CQP_TIMEOUT_THRESHOLD) +		if (cqp_timeout.count < timeout_threshold)  			continue;  		if (!rf->reset) { @@ -649,6 +697,9 @@ static const char *const irdma_cqp_cmd_names[IRDMA_MAX_CQP_OPS] = {  	[IRDMA_OP_ADD_LOCAL_MAC_ENTRY] = "Add Local MAC Entry Cmd",  	[IRDMA_OP_DELETE_LOCAL_MAC_ENTRY] = "Delete Local MAC Entry Cmd",  	[IRDMA_OP_CQ_MODIFY] = "CQ Modify Cmd", +	[IRDMA_OP_SRQ_CREATE] = "Create SRQ Cmd", +	[IRDMA_OP_SRQ_MODIFY] = "Modify SRQ Cmd", +	[IRDMA_OP_SRQ_DESTROY] = "Destroy SRQ Cmd",  };  static const struct irdma_cqp_err_info irdma_noncrit_err_list[] = { @@ -1065,6 +1116,26 @@ static void irdma_dealloc_push_page(struct irdma_pci_f *rf,  	irdma_put_cqp_request(&rf->cqp, cqp_request);  } +static void irdma_free_gsi_qp_rsrc(struct irdma_qp *iwqp, u32 qp_num) +{ +	struct irdma_device *iwdev = iwqp->iwdev; +	struct irdma_pci_f *rf = iwdev->rf; +	unsigned long flags; + +	if (rf->sc_dev.hw_attrs.uk_attrs.hw_rev < IRDMA_GEN_3) +		return; + +	irdma_vchnl_req_del_vport(&rf->sc_dev, iwdev->vport_id, qp_num); + +	if (qp_num == 1) { +		spin_lock_irqsave(&rf->rsrc_lock, flags); +		rf->hwqp1_rsvd = false; +		spin_unlock_irqrestore(&rf->rsrc_lock, flags); +	} else if (qp_num > 2) { +		irdma_free_rsrc(rf, rf->allocated_qps, qp_num); +	} +} +  /**   * irdma_free_qp_rsrc - free up memory resources for qp   * @iwqp: qp ptr (user or kernel) @@ -1073,7 +1144,7 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)  {  	struct irdma_device *iwdev = iwqp->iwdev;  	struct irdma_pci_f *rf = iwdev->rf; -	u32 qp_num = iwqp->ibqp.qp_num; +	u32 qp_num = iwqp->sc_qp.qp_uk.qp_id;  	irdma_ieq_cleanup_qp(iwdev->vsi.ieq, &iwqp->sc_qp);  	irdma_dealloc_push_page(rf, &iwqp->sc_qp); @@ -1083,8 +1154,12 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)  					   iwqp->sc_qp.user_pri);  	} -	if (qp_num > 2) -		irdma_free_rsrc(rf, rf->allocated_qps, qp_num); +	if (iwqp->ibqp.qp_type == IB_QPT_GSI) { +		irdma_free_gsi_qp_rsrc(iwqp, qp_num); +	} else { +		if (qp_num > 2) +			irdma_free_rsrc(rf, rf->allocated_qps, qp_num); +	}  	dma_free_coherent(rf->sc_dev.hw->device, iwqp->q2_ctx_mem.size,  			  iwqp->q2_ctx_mem.va, iwqp->q2_ctx_mem.pa);  	iwqp->q2_ctx_mem.va = NULL; @@ -1096,6 +1171,30 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)  }  /** + * irdma_srq_wq_destroy - send srq destroy cqp + * @rf: RDMA PCI function + * @srq: hardware control srq + */ +void irdma_srq_wq_destroy(struct irdma_pci_f *rf, struct irdma_sc_srq *srq) +{ +	struct irdma_cqp_request *cqp_request; +	struct cqp_cmds_info *cqp_info; + +	cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); +	if (!cqp_request) +		return; + +	cqp_info = &cqp_request->info; +	cqp_info->cqp_cmd = IRDMA_OP_SRQ_DESTROY; +	cqp_info->post_sq = 1; +	cqp_info->in.u.srq_destroy.srq = srq; +	cqp_info->in.u.srq_destroy.scratch = (uintptr_t)cqp_request; + +	irdma_handle_cqp_op(rf, cqp_request); +	irdma_put_cqp_request(&rf->cqp, cqp_request); +} + +/**   * irdma_cq_wq_destroy - send cq destroy cqp   * @rf: RDMA PCI function   * @cq: hardware control cq @@ -2266,7 +2365,10 @@ bool irdma_cq_empty(struct irdma_cq *iwcq)  	u8 polarity;  	ukcq  = &iwcq->sc_cq.cq_uk; -	cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); +	if (ukcq->avoid_mem_cflct) +		cqe = IRDMA_GET_CURRENT_EXTENDED_CQ_ELEM(ukcq); +	else +		cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq);  	get_64bit_val(cqe, 24, &qword3);  	polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3);  | 
