aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/qib/qib_verbs.c
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@intel.com>2012-06-27 18:33:12 -0400
committerRoland Dreier <roland@purestorage.com>2012-07-08 21:05:19 -0400
commit6a82649f217023863d6b1740017e6c3dd6685327 (patch)
treeb11e8bd8993d4db88a386336172faf0215ba724d /drivers/infiniband/hw/qib/qib_verbs.c
parent354dff1bd8ccd41b6e8421226d586d35e7fb8920 (diff)
IB/qib: Avoid returning EBUSY from MR deregister
A timing issue can occur where qib_mr_dereg can return -EBUSY if the MR use count is not zero. This can occur if the MR is de-registered while RDMA read response packets are being progressed from the SDMA ring. The suspicion is that the peer sent an RDMA read request, which has already been copied across to the peer. The peer sees the completion of his request and then communicates to the responder that the MR is not needed any longer. The responder tries to de-register the MR, catching some responses remaining in the SDMA ring holding the MR use count. The code now uses a get/put paradigm to track MR use counts and coordinates with the MR de-registration process using a completion when the count has reached zero. A timeout on the delay is in place to catch other EBUSY issues. The reference count protocol is as follows: - The return to the user counts as 1 - A reference from the lk_table or the qib_ibdev counts as 1. - Transient I/O operations increase/decrease as necessary A lot of code duplication has been folded into the new routines init_qib_mregion() and deinit_qib_mregion(). Additionally, explicit initialization of fields to zero is now handled by kzalloc(). Also, duplicated code 'while.*num_sge' that decrements reference counts have been consolidated in qib_put_ss(). Reviewed-by: Ramkrishna Vepa <ramkrishna.vepa@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_verbs.c')
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index 7b6c3bffa9d9..76d7ce8a8c6e 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -183,7 +183,7 @@ void qib_copy_sge(struct qib_sge_state *ss, void *data, u32 length, int release)
183 sge->sge_length -= len; 183 sge->sge_length -= len;
184 if (sge->sge_length == 0) { 184 if (sge->sge_length == 0) {
185 if (release) 185 if (release)
186 atomic_dec(&sge->mr->refcount); 186 qib_put_mr(sge->mr);
187 if (--ss->num_sge) 187 if (--ss->num_sge)
188 *sge = *ss->sg_list++; 188 *sge = *ss->sg_list++;
189 } else if (sge->length == 0 && sge->mr->lkey) { 189 } else if (sge->length == 0 && sge->mr->lkey) {
@@ -224,7 +224,7 @@ void qib_skip_sge(struct qib_sge_state *ss, u32 length, int release)
224 sge->sge_length -= len; 224 sge->sge_length -= len;
225 if (sge->sge_length == 0) { 225 if (sge->sge_length == 0) {
226 if (release) 226 if (release)
227 atomic_dec(&sge->mr->refcount); 227 qib_put_mr(sge->mr);
228 if (--ss->num_sge) 228 if (--ss->num_sge)
229 *sge = *ss->sg_list++; 229 *sge = *ss->sg_list++;
230 } else if (sge->length == 0 && sge->mr->lkey) { 230 } else if (sge->length == 0 && sge->mr->lkey) {
@@ -435,7 +435,7 @@ bail_inval_free:
435 while (j) { 435 while (j) {
436 struct qib_sge *sge = &wqe->sg_list[--j]; 436 struct qib_sge *sge = &wqe->sg_list[--j];
437 437
438 atomic_dec(&sge->mr->refcount); 438 qib_put_mr(sge->mr);
439 } 439 }
440bail_inval: 440bail_inval:
441 ret = -EINVAL; 441 ret = -EINVAL;
@@ -978,7 +978,7 @@ void qib_put_txreq(struct qib_verbs_txreq *tx)
978 if (atomic_dec_and_test(&qp->refcount)) 978 if (atomic_dec_and_test(&qp->refcount))
979 wake_up(&qp->wait); 979 wake_up(&qp->wait);
980 if (tx->mr) { 980 if (tx->mr) {
981 atomic_dec(&tx->mr->refcount); 981 qib_put_mr(tx->mr);
982 tx->mr = NULL; 982 tx->mr = NULL;
983 } 983 }
984 if (tx->txreq.flags & QIB_SDMA_TXREQ_F_FREEBUF) { 984 if (tx->txreq.flags & QIB_SDMA_TXREQ_F_FREEBUF) {
@@ -1336,7 +1336,7 @@ done:
1336 } 1336 }
1337 qib_sendbuf_done(dd, pbufn); 1337 qib_sendbuf_done(dd, pbufn);
1338 if (qp->s_rdma_mr) { 1338 if (qp->s_rdma_mr) {
1339 atomic_dec(&qp->s_rdma_mr->refcount); 1339 qib_put_mr(qp->s_rdma_mr);
1340 qp->s_rdma_mr = NULL; 1340 qp->s_rdma_mr = NULL;
1341 } 1341 }
1342 if (qp->s_wqe) { 1342 if (qp->s_wqe) {