aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4/cm.c
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2013-01-07 08:11:53 -0500
committerRoland Dreier <roland@purestorage.com>2013-02-14 18:51:56 -0500
commit325abead6cc7ef50572c53b1adc4d2442234b50f (patch)
tree59f77611c4b59024635f7c03128e828b2af03192 /drivers/infiniband/hw/cxgb4/cm.c
parent1557967bf921e787f0c9236c2899603d85f44d31 (diff)
RDMA/cxgb4: Keep QP referenced until TID released
The driver is currently releasing the last ref on the QP too early. This can cause bus errors due to HW still fetching WRs from the HW queue. The fix is to keep a qp ref until we release the HW TID. Signed-off-by: Vipul Pandya <vipul@chelsio.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/cm.c')
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31d1fac605d3..ebcdb3ff0cf4 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -143,6 +143,18 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status);
143static LIST_HEAD(timeout_list); 143static LIST_HEAD(timeout_list);
144static spinlock_t timeout_lock; 144static spinlock_t timeout_lock;
145 145
146static void deref_qp(struct c4iw_ep *ep)
147{
148 c4iw_qp_rem_ref(&ep->com.qp->ibqp);
149 clear_bit(QP_REFERENCED, &ep->com.flags);
150}
151
152static void ref_qp(struct c4iw_ep *ep)
153{
154 set_bit(QP_REFERENCED, &ep->com.flags);
155 c4iw_qp_add_ref(&ep->com.qp->ibqp);
156}
157
146static void start_ep_timer(struct c4iw_ep *ep) 158static void start_ep_timer(struct c4iw_ep *ep)
147{ 159{
148 PDBG("%s ep %p\n", __func__, ep); 160 PDBG("%s ep %p\n", __func__, ep);
@@ -271,6 +283,8 @@ void _c4iw_free_ep(struct kref *kref)
271 283
272 ep = container_of(kref, struct c4iw_ep, com.kref); 284 ep = container_of(kref, struct c4iw_ep, com.kref);
273 PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]); 285 PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
286 if (test_bit(QP_REFERENCED, &ep->com.flags))
287 deref_qp(ep);
274 if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) { 288 if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
275 cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); 289 cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
276 dst_release(ep->dst); 290 dst_release(ep->dst);
@@ -863,7 +877,6 @@ static void close_complete_upcall(struct c4iw_ep *ep)
863 ep->com.cm_id->event_handler(ep->com.cm_id, &event); 877 ep->com.cm_id->event_handler(ep->com.cm_id, &event);
864 ep->com.cm_id->rem_ref(ep->com.cm_id); 878 ep->com.cm_id->rem_ref(ep->com.cm_id);
865 ep->com.cm_id = NULL; 879 ep->com.cm_id = NULL;
866 ep->com.qp = NULL;
867 set_bit(CLOSE_UPCALL, &ep->com.history); 880 set_bit(CLOSE_UPCALL, &ep->com.history);
868 } 881 }
869} 882}
@@ -906,7 +919,6 @@ static void peer_abort_upcall(struct c4iw_ep *ep)
906 ep->com.cm_id->event_handler(ep->com.cm_id, &event); 919 ep->com.cm_id->event_handler(ep->com.cm_id, &event);
907 ep->com.cm_id->rem_ref(ep->com.cm_id); 920 ep->com.cm_id->rem_ref(ep->com.cm_id);
908 ep->com.cm_id = NULL; 921 ep->com.cm_id = NULL;
909 ep->com.qp = NULL;
910 set_bit(ABORT_UPCALL, &ep->com.history); 922 set_bit(ABORT_UPCALL, &ep->com.history);
911 } 923 }
912} 924}
@@ -946,7 +958,6 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
946 if (status < 0) { 958 if (status < 0) {
947 ep->com.cm_id->rem_ref(ep->com.cm_id); 959 ep->com.cm_id->rem_ref(ep->com.cm_id);
948 ep->com.cm_id = NULL; 960 ep->com.cm_id = NULL;
949 ep->com.qp = NULL;
950 } 961 }
951} 962}
952 963
@@ -2434,6 +2445,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2434 cm_id->add_ref(cm_id); 2445 cm_id->add_ref(cm_id);
2435 ep->com.cm_id = cm_id; 2446 ep->com.cm_id = cm_id;
2436 ep->com.qp = qp; 2447 ep->com.qp = qp;
2448 ref_qp(ep);
2437 2449
2438 /* bind QP to EP and move to RTS */ 2450 /* bind QP to EP and move to RTS */
2439 attrs.mpa_attr = ep->mpa_attr; 2451 attrs.mpa_attr = ep->mpa_attr;
@@ -2464,7 +2476,6 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2464 return 0; 2476 return 0;
2465err1: 2477err1:
2466 ep->com.cm_id = NULL; 2478 ep->com.cm_id = NULL;
2467 ep->com.qp = NULL;
2468 cm_id->rem_ref(cm_id); 2479 cm_id->rem_ref(cm_id);
2469err: 2480err:
2470 c4iw_put_ep(&ep->com); 2481 c4iw_put_ep(&ep->com);
@@ -2505,6 +2516,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
2505 ep->com.cm_id = cm_id; 2516 ep->com.cm_id = cm_id;
2506 ep->com.qp = get_qhp(dev, conn_param->qpn); 2517 ep->com.qp = get_qhp(dev, conn_param->qpn);
2507 BUG_ON(!ep->com.qp); 2518 BUG_ON(!ep->com.qp);
2519 ref_qp(ep);
2508 PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn, 2520 PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
2509 ep->com.qp, cm_id); 2521 ep->com.qp, cm_id);
2510 2522