aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4/qp.c
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2010-09-10 12:15:36 -0400
committerRoland Dreier <rolandd@cisco.com>2010-09-28 13:53:48 -0400
commit2f5b48c3ad84fda9efe35122b058ccffc0c2c7cf (patch)
tree11d3a830803748d83c132ee402ed3376a58f6aed /drivers/infiniband/hw/cxgb4/qp.c
parentc6d7b26791a2aefdf97f2af1e93161ed05acd631 (diff)
RDMA/cxgb4: Use a mutex for QP and EP state transitions
Move the connection setup/teardown paths to the workq thread removing spin lock/irq disable requirements for these paths. This allows calls down to the LLD for EP and QP state transition actions to be atomic with respect to processing CPL messages coming up from the HW. Namely, calls to rdma_init() and rdma_fini() can now be called with the mutex held avoiding many race conditions with the abort path. The QP spinlock is still used but only to manipulate the qp state. This allows the fastpaths, poll, post_send, and pos_recv, to run in the irq context. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/qp.c')
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c90
1 files changed, 42 insertions, 48 deletions
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 7e45f7334282..76a286f88edd 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -35,6 +35,14 @@ static int ocqp_support;
35module_param(ocqp_support, int, 0644); 35module_param(ocqp_support, int, 0644);
36MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)"); 36MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)");
37 37
38static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
39{
40 unsigned long flag;
41 spin_lock_irqsave(&qhp->lock, flag);
42 qhp->attr.state = state;
43 spin_unlock_irqrestore(&qhp->lock, flag);
44}
45
38static void dealloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq) 46static void dealloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
39{ 47{
40 c4iw_ocqp_pool_free(rdev, sq->dma_addr, sq->memsize); 48 c4iw_ocqp_pool_free(rdev, sq->dma_addr, sq->memsize);
@@ -949,46 +957,38 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
949 * Assumes qhp lock is held. 957 * Assumes qhp lock is held.
950 */ 958 */
951static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, 959static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
952 struct c4iw_cq *schp, unsigned long *flag) 960 struct c4iw_cq *schp)
953{ 961{
954 int count; 962 int count;
955 int flushed; 963 int flushed;
964 unsigned long flag;
956 965
957 PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp); 966 PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
958 /* take a ref on the qhp since we must release the lock */
959 atomic_inc(&qhp->refcnt);
960 spin_unlock_irqrestore(&qhp->lock, *flag);
961 967
962 /* locking hierarchy: cq lock first, then qp lock. */ 968 /* locking hierarchy: cq lock first, then qp lock. */
963 spin_lock_irqsave(&rchp->lock, *flag); 969 spin_lock_irqsave(&rchp->lock, flag);
964 spin_lock(&qhp->lock); 970 spin_lock(&qhp->lock);
965 c4iw_flush_hw_cq(&rchp->cq); 971 c4iw_flush_hw_cq(&rchp->cq);
966 c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count); 972 c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
967 flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); 973 flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
968 spin_unlock(&qhp->lock); 974 spin_unlock(&qhp->lock);
969 spin_unlock_irqrestore(&rchp->lock, *flag); 975 spin_unlock_irqrestore(&rchp->lock, flag);
970 if (flushed) 976 if (flushed)
971 (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); 977 (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
972 978
973 /* locking hierarchy: cq lock first, then qp lock. */ 979 /* locking hierarchy: cq lock first, then qp lock. */
974 spin_lock_irqsave(&schp->lock, *flag); 980 spin_lock_irqsave(&schp->lock, flag);
975 spin_lock(&qhp->lock); 981 spin_lock(&qhp->lock);
976 c4iw_flush_hw_cq(&schp->cq); 982 c4iw_flush_hw_cq(&schp->cq);
977 c4iw_count_scqes(&schp->cq, &qhp->wq, &count); 983 c4iw_count_scqes(&schp->cq, &qhp->wq, &count);
978 flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count); 984 flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
979 spin_unlock(&qhp->lock); 985 spin_unlock(&qhp->lock);
980 spin_unlock_irqrestore(&schp->lock, *flag); 986 spin_unlock_irqrestore(&schp->lock, flag);
981 if (flushed) 987 if (flushed)
982 (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); 988 (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
983
984 /* deref */
985 if (atomic_dec_and_test(&qhp->refcnt))
986 wake_up(&qhp->wait);
987
988 spin_lock_irqsave(&qhp->lock, *flag);
989} 989}
990 990
991static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag) 991static void flush_qp(struct c4iw_qp *qhp)
992{ 992{
993 struct c4iw_cq *rchp, *schp; 993 struct c4iw_cq *rchp, *schp;
994 994
@@ -1002,7 +1002,7 @@ static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag)
1002 t4_set_cq_in_error(&schp->cq); 1002 t4_set_cq_in_error(&schp->cq);
1003 return; 1003 return;
1004 } 1004 }
1005 __flush_qp(qhp, rchp, schp, flag); 1005 __flush_qp(qhp, rchp, schp);
1006} 1006}
1007 1007
1008static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, 1008static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
@@ -1010,7 +1010,6 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1010{ 1010{
1011 struct fw_ri_wr *wqe; 1011 struct fw_ri_wr *wqe;
1012 int ret; 1012 int ret;
1013 struct c4iw_wr_wait wr_wait;
1014 struct sk_buff *skb; 1013 struct sk_buff *skb;
1015 1014
1016 PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid, 1015 PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -1029,15 +1028,15 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1029 wqe->flowid_len16 = cpu_to_be32( 1028 wqe->flowid_len16 = cpu_to_be32(
1030 FW_WR_FLOWID(ep->hwtid) | 1029 FW_WR_FLOWID(ep->hwtid) |
1031 FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16))); 1030 FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
1032 wqe->cookie = (unsigned long) &wr_wait; 1031 wqe->cookie = (unsigned long) &ep->com.wr_wait;
1033 1032
1034 wqe->u.fini.type = FW_RI_TYPE_FINI; 1033 wqe->u.fini.type = FW_RI_TYPE_FINI;
1035 c4iw_init_wr_wait(&wr_wait); 1034 c4iw_init_wr_wait(&ep->com.wr_wait);
1036 ret = c4iw_ofld_send(&rhp->rdev, skb); 1035 ret = c4iw_ofld_send(&rhp->rdev, skb);
1037 if (ret) 1036 if (ret)
1038 goto out; 1037 goto out;
1039 1038
1040 ret = c4iw_wait_for_reply(&rhp->rdev, &wr_wait, qhp->ep->hwtid, 1039 ret = c4iw_wait_for_reply(&rhp->rdev, &ep->com.wr_wait, qhp->ep->hwtid,
1041 qhp->wq.sq.qid, __func__); 1040 qhp->wq.sq.qid, __func__);
1042out: 1041out:
1043 PDBG("%s ret %d\n", __func__, ret); 1042 PDBG("%s ret %d\n", __func__, ret);
@@ -1072,7 +1071,6 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
1072{ 1071{
1073 struct fw_ri_wr *wqe; 1072 struct fw_ri_wr *wqe;
1074 int ret; 1073 int ret;
1075 struct c4iw_wr_wait wr_wait;
1076 struct sk_buff *skb; 1074 struct sk_buff *skb;
1077 1075
1078 PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid, 1076 PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -1092,7 +1090,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
1092 FW_WR_FLOWID(qhp->ep->hwtid) | 1090 FW_WR_FLOWID(qhp->ep->hwtid) |
1093 FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16))); 1091 FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
1094 1092
1095 wqe->cookie = (unsigned long) &wr_wait; 1093 wqe->cookie = (unsigned long) &qhp->ep->com.wr_wait;
1096 1094
1097 wqe->u.init.type = FW_RI_TYPE_INIT; 1095 wqe->u.init.type = FW_RI_TYPE_INIT;
1098 wqe->u.init.mpareqbit_p2ptype = 1096 wqe->u.init.mpareqbit_p2ptype =
@@ -1129,13 +1127,13 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
1129 if (qhp->attr.mpa_attr.initiator) 1127 if (qhp->attr.mpa_attr.initiator)
1130 build_rtr_msg(qhp->attr.mpa_attr.p2p_type, &wqe->u.init); 1128 build_rtr_msg(qhp->attr.mpa_attr.p2p_type, &wqe->u.init);
1131 1129
1132 c4iw_init_wr_wait(&wr_wait); 1130 c4iw_init_wr_wait(&qhp->ep->com.wr_wait);
1133 ret = c4iw_ofld_send(&rhp->rdev, skb); 1131 ret = c4iw_ofld_send(&rhp->rdev, skb);
1134 if (ret) 1132 if (ret)
1135 goto out; 1133 goto out;
1136 1134
1137 ret = c4iw_wait_for_reply(&rhp->rdev, &wr_wait, qhp->ep->hwtid, 1135 ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
1138 qhp->wq.sq.qid, __func__); 1136 qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
1139out: 1137out:
1140 PDBG("%s ret %d\n", __func__, ret); 1138 PDBG("%s ret %d\n", __func__, ret);
1141 return ret; 1139 return ret;
@@ -1148,7 +1146,6 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1148{ 1146{
1149 int ret = 0; 1147 int ret = 0;
1150 struct c4iw_qp_attributes newattr = qhp->attr; 1148 struct c4iw_qp_attributes newattr = qhp->attr;
1151 unsigned long flag;
1152 int disconnect = 0; 1149 int disconnect = 0;
1153 int terminate = 0; 1150 int terminate = 0;
1154 int abort = 0; 1151 int abort = 0;
@@ -1159,7 +1156,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1159 qhp, qhp->wq.sq.qid, qhp->wq.rq.qid, qhp->ep, qhp->attr.state, 1156 qhp, qhp->wq.sq.qid, qhp->wq.rq.qid, qhp->ep, qhp->attr.state,
1160 (mask & C4IW_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1); 1157 (mask & C4IW_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
1161 1158
1162 spin_lock_irqsave(&qhp->lock, flag); 1159 mutex_lock(&qhp->mutex);
1163 1160
1164 /* Process attr changes if in IDLE */ 1161 /* Process attr changes if in IDLE */
1165 if (mask & C4IW_QP_ATTR_VALID_MODIFY) { 1162 if (mask & C4IW_QP_ATTR_VALID_MODIFY) {
@@ -1210,7 +1207,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1210 qhp->attr.mpa_attr = attrs->mpa_attr; 1207 qhp->attr.mpa_attr = attrs->mpa_attr;
1211 qhp->attr.llp_stream_handle = attrs->llp_stream_handle; 1208 qhp->attr.llp_stream_handle = attrs->llp_stream_handle;
1212 qhp->ep = qhp->attr.llp_stream_handle; 1209 qhp->ep = qhp->attr.llp_stream_handle;
1213 qhp->attr.state = C4IW_QP_STATE_RTS; 1210 set_state(qhp, C4IW_QP_STATE_RTS);
1214 1211
1215 /* 1212 /*
1216 * Ref the endpoint here and deref when we 1213 * Ref the endpoint here and deref when we
@@ -1219,15 +1216,13 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1219 * transition. 1216 * transition.
1220 */ 1217 */
1221 c4iw_get_ep(&qhp->ep->com); 1218 c4iw_get_ep(&qhp->ep->com);
1222 spin_unlock_irqrestore(&qhp->lock, flag);
1223 ret = rdma_init(rhp, qhp); 1219 ret = rdma_init(rhp, qhp);
1224 spin_lock_irqsave(&qhp->lock, flag);
1225 if (ret) 1220 if (ret)
1226 goto err; 1221 goto err;
1227 break; 1222 break;
1228 case C4IW_QP_STATE_ERROR: 1223 case C4IW_QP_STATE_ERROR:
1229 qhp->attr.state = C4IW_QP_STATE_ERROR; 1224 set_state(qhp, C4IW_QP_STATE_ERROR);
1230 flush_qp(qhp, &flag); 1225 flush_qp(qhp);
1231 break; 1226 break;
1232 default: 1227 default:
1233 ret = -EINVAL; 1228 ret = -EINVAL;
@@ -1238,39 +1233,38 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1238 switch (attrs->next_state) { 1233 switch (attrs->next_state) {
1239 case C4IW_QP_STATE_CLOSING: 1234 case C4IW_QP_STATE_CLOSING:
1240 BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2); 1235 BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
1241 qhp->attr.state = C4IW_QP_STATE_CLOSING; 1236 set_state(qhp, C4IW_QP_STATE_CLOSING);
1242 ep = qhp->ep; 1237 ep = qhp->ep;
1243 if (!internal) { 1238 if (!internal) {
1244 abort = 0; 1239 abort = 0;
1245 disconnect = 1; 1240 disconnect = 1;
1246 c4iw_get_ep(&ep->com); 1241 c4iw_get_ep(&qhp->ep->com);
1247 } 1242 }
1248 spin_unlock_irqrestore(&qhp->lock, flag);
1249 ret = rdma_fini(rhp, qhp, ep); 1243 ret = rdma_fini(rhp, qhp, ep);
1250 spin_lock_irqsave(&qhp->lock, flag);
1251 if (ret) { 1244 if (ret) {
1252 c4iw_get_ep(&ep->com); 1245 if (internal)
1246 c4iw_get_ep(&qhp->ep->com);
1253 disconnect = abort = 1; 1247 disconnect = abort = 1;
1254 goto err; 1248 goto err;
1255 } 1249 }
1256 break; 1250 break;
1257 case C4IW_QP_STATE_TERMINATE: 1251 case C4IW_QP_STATE_TERMINATE:
1258 qhp->attr.state = C4IW_QP_STATE_TERMINATE; 1252 set_state(qhp, C4IW_QP_STATE_TERMINATE);
1259 if (qhp->ibqp.uobject) 1253 if (qhp->ibqp.uobject)
1260 t4_set_wq_in_error(&qhp->wq); 1254 t4_set_wq_in_error(&qhp->wq);
1261 ep = qhp->ep; 1255 ep = qhp->ep;
1262 c4iw_get_ep(&ep->com);
1263 if (!internal) 1256 if (!internal)
1264 terminate = 1; 1257 terminate = 1;
1265 disconnect = 1; 1258 disconnect = 1;
1259 c4iw_get_ep(&qhp->ep->com);
1266 break; 1260 break;
1267 case C4IW_QP_STATE_ERROR: 1261 case C4IW_QP_STATE_ERROR:
1268 qhp->attr.state = C4IW_QP_STATE_ERROR; 1262 set_state(qhp, C4IW_QP_STATE_ERROR);
1269 if (!internal) { 1263 if (!internal) {
1270 abort = 1; 1264 abort = 1;
1271 disconnect = 1; 1265 disconnect = 1;
1272 ep = qhp->ep; 1266 ep = qhp->ep;
1273 c4iw_get_ep(&ep->com); 1267 c4iw_get_ep(&qhp->ep->com);
1274 } 1268 }
1275 goto err; 1269 goto err;
1276 break; 1270 break;
@@ -1286,8 +1280,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1286 } 1280 }
1287 switch (attrs->next_state) { 1281 switch (attrs->next_state) {
1288 case C4IW_QP_STATE_IDLE: 1282 case C4IW_QP_STATE_IDLE:
1289 flush_qp(qhp, &flag); 1283 flush_qp(qhp);
1290 qhp->attr.state = C4IW_QP_STATE_IDLE; 1284 set_state(qhp, C4IW_QP_STATE_IDLE);
1291 qhp->attr.llp_stream_handle = NULL; 1285 qhp->attr.llp_stream_handle = NULL;
1292 c4iw_put_ep(&qhp->ep->com); 1286 c4iw_put_ep(&qhp->ep->com);
1293 qhp->ep = NULL; 1287 qhp->ep = NULL;
@@ -1309,7 +1303,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
1309 ret = -EINVAL; 1303 ret = -EINVAL;
1310 goto out; 1304 goto out;
1311 } 1305 }
1312 qhp->attr.state = C4IW_QP_STATE_IDLE; 1306 set_state(qhp, C4IW_QP_STATE_IDLE);
1313 break; 1307 break;
1314 case C4IW_QP_STATE_TERMINATE: 1308 case C4IW_QP_STATE_TERMINATE:
1315 if (!internal) { 1309 if (!internal) {
@@ -1335,13 +1329,13 @@ err:
1335 if (!ep) 1329 if (!ep)
1336 ep = qhp->ep; 1330 ep = qhp->ep;
1337 qhp->ep = NULL; 1331 qhp->ep = NULL;
1338 qhp->attr.state = C4IW_QP_STATE_ERROR; 1332 set_state(qhp, C4IW_QP_STATE_ERROR);
1339 free = 1; 1333 free = 1;
1340 wake_up(&qhp->wait); 1334 wake_up(&qhp->wait);
1341 BUG_ON(!ep); 1335 BUG_ON(!ep);
1342 flush_qp(qhp, &flag); 1336 flush_qp(qhp);
1343out: 1337out:
1344 spin_unlock_irqrestore(&qhp->lock, flag); 1338 mutex_unlock(&qhp->mutex);
1345 1339
1346 if (terminate) 1340 if (terminate)
1347 post_terminate(qhp, NULL, internal ? GFP_ATOMIC : GFP_KERNEL); 1341 post_terminate(qhp, NULL, internal ? GFP_ATOMIC : GFP_KERNEL);
@@ -1363,7 +1357,6 @@ out:
1363 */ 1357 */
1364 if (free) 1358 if (free)
1365 c4iw_put_ep(&ep->com); 1359 c4iw_put_ep(&ep->com);
1366
1367 PDBG("%s exit state %d\n", __func__, qhp->attr.state); 1360 PDBG("%s exit state %d\n", __func__, qhp->attr.state);
1368 return ret; 1361 return ret;
1369} 1362}
@@ -1478,6 +1471,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
1478 qhp->attr.max_ord = 1; 1471 qhp->attr.max_ord = 1;
1479 qhp->attr.max_ird = 1; 1472 qhp->attr.max_ird = 1;
1480 spin_lock_init(&qhp->lock); 1473 spin_lock_init(&qhp->lock);
1474 mutex_init(&qhp->mutex);
1481 init_waitqueue_head(&qhp->wait); 1475 init_waitqueue_head(&qhp->wait);
1482 atomic_set(&qhp->refcnt, 1); 1476 atomic_set(&qhp->refcnt, 1);
1483 1477