aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJianxin Xiong <[email protected]>2016-05-19 05:21:57 -0700
committerDoug Ledford <[email protected]>2016-05-26 11:23:11 -0400
commitb583faf4dc6eaa64895c37b81983e75a8c3c1e4e (patch)
tree3b94997fa2b5f7c5c91e8351b9d917b9d28e02ed
parentf70f5f6af36bce29fe2c4bc733a223b5746eb65f (diff)
IB/hfi1: Fix bug that blocks process on exit after port bounce
During the processing of a user SDMA request, if there was an error before the request counter was increased, the state of the packet queue could be updated incorrectly, causing the counter to underflow. As the result, the process could get stuck later since the counter could never get back to 0. This patch adds a condition to guard the packet queue update so that the counter is only decreased if it has been increased before the error happens. Reviewed-by: Mitko Haralanov <[email protected]> Signed-off-by: Jianxin Xiong <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
-rw-r--r--drivers/staging/rdma/hfi1/user_sdma.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c
index aed2878c97f1..29f4795f866c 100644
--- a/drivers/staging/rdma/hfi1/user_sdma.c
+++ b/drivers/staging/rdma/hfi1/user_sdma.c
@@ -510,6 +510,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
struct sdma_req_info info;
struct user_sdma_request *req;
u8 opcode, sc, vl;
+ int req_queued = 0;
if (iovec[idx].iov_len < sizeof(info) + sizeof(req->hdr)) {
hfi1_cdbg(
@@ -706,6 +707,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
set_comp_state(pq, cq, info.comp_idx, QUEUED, 0);
atomic_inc(&pq->n_reqs);
+ req_queued = 1;
/* Send the first N packets in the request to buy us some time */
ret = user_sdma_send_pkts(req, pcount);
if (unlikely(ret < 0 && ret != -EBUSY)) {
@@ -750,7 +752,8 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
return 0;
free_req:
user_sdma_free_request(req, true);
- pq_update(pq);
+ if (req_queued)
+ pq_update(pq);
set_comp_state(pq, cq, info.comp_idx, ERROR, req->status);
return ret;
}