aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/i40iw/i40iw_hw.c
diff options
context:
space:
mode:
authorShiraz Saleem <shiraz.saleem@intel.com>2016-12-06 15:49:31 -0600
committerDoug Ledford <dledford@redhat.com>2016-12-12 17:20:27 -0500
commit1cda28bb5b503bab734072d97a41b2e7eda6b6b9 (patch)
treeea0369d13cead018e0dd94d0b9bbd7bf30a58513 /drivers/infiniband/hw/i40iw/i40iw_hw.c
parenti40iw: Fix double free of QP (diff)
downloadlinux-dev-1cda28bb5b503bab734072d97a41b2e7eda6b6b9.tar.xz
linux-dev-1cda28bb5b503bab734072d97a41b2e7eda6b6b9.zip
i40iw: Fix QP flush to not hang on empty queues or failure
When flush QP and there are no pending work requests, signal completion to unblock i40iw_drain_sq and i40iw_drain_rq which are waiting on completion for iwqp->sq_drained and iwqp->sq_drained respectively. Also, signal completion if flush QP fails to prevent the drain SQ or RQ from being blocked indefintely. Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/hw/i40iw/i40iw_hw.c')
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_hw.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/i40iw/i40iw_hw.c b/drivers/infiniband/hw/i40iw/i40iw_hw.c
index b2854b11a240..4394a6713bdf 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_hw.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_hw.c
@@ -622,6 +622,7 @@ enum i40iw_status_code i40iw_hw_flush_wqes(struct i40iw_device *iwdev,
struct i40iw_qp_flush_info *hw_info;
struct i40iw_cqp_request *cqp_request;
struct cqp_commands_info *cqp_info;
+ struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
cqp_request = i40iw_get_cqp_request(&iwdev->cqp, wait);
if (!cqp_request)
@@ -636,9 +637,30 @@ enum i40iw_status_code i40iw_hw_flush_wqes(struct i40iw_device *iwdev,
cqp_info->in.u.qp_flush_wqes.qp = qp;
cqp_info->in.u.qp_flush_wqes.scratch = (uintptr_t)cqp_request;
status = i40iw_handle_cqp_op(iwdev, cqp_request);
- if (status)
+ if (status) {
i40iw_pr_err("CQP-OP Flush WQE's fail");
- return status;
+ complete(&iwqp->sq_drained);
+ complete(&iwqp->rq_drained);
+ return status;
+ }
+ if (!cqp_request->compl_info.maj_err_code) {
+ switch (cqp_request->compl_info.min_err_code) {
+ case I40IW_CQP_COMPL_RQ_WQE_FLUSHED:
+ complete(&iwqp->sq_drained);
+ break;
+ case I40IW_CQP_COMPL_SQ_WQE_FLUSHED:
+ complete(&iwqp->rq_drained);
+ break;
+ case I40IW_CQP_COMPL_RQ_SQ_WQE_FLUSHED:
+ break;
+ default:
+ complete(&iwqp->sq_drained);
+ complete(&iwqp->rq_drained);
+ break;
+ }
+ }
+
+ return 0;
}
/**