aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIshai Rabinovitz <ishai@mellanox.co.il>2012-11-26 05:44:53 -0500
committerRoland Dreier <roland@purestorage.com>2012-11-30 20:40:32 -0500
commit73aa89ed9e2bebf0c3fff4504e6dff1421b5c819 (patch)
treef42868513f2d3532a1ca3e37445cf6eab7b410c4
parentef6c49d87c3418c442a22e55e3ce2f91b163d69e (diff)
IB/srp: destroy and recreate QP and CQs when reconnecting
HW QP FATAL errors persist over a reset operation, but we can recover from that by recreating the QP and associated CQs for each connection. Creating a new QP/CQ also completely forecloses any possibility of getting stale completions or packets on the new connection. Signed-off-by: Ishai Rabinovitz <ishai@mellanox.co.il> Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> [ updated to current code from OFED, cleaned up commit message ] Signed-off-by: David Dillow <dillowda@ornl.gov> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c66
1 files changed, 35 insertions, 31 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 95590a38e88..85771eba9c8 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -222,27 +222,29 @@ static int srp_new_cm_id(struct srp_target_port *target)
222static int srp_create_target_ib(struct srp_target_port *target) 222static int srp_create_target_ib(struct srp_target_port *target)
223{ 223{
224 struct ib_qp_init_attr *init_attr; 224 struct ib_qp_init_attr *init_attr;
225 struct ib_cq *recv_cq, *send_cq;
226 struct ib_qp *qp;
225 int ret; 227 int ret;
226 228
227 init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL); 229 init_attr = kzalloc(sizeof *init_attr, GFP_KERNEL);
228 if (!init_attr) 230 if (!init_attr)
229 return -ENOMEM; 231 return -ENOMEM;
230 232
231 target->recv_cq = ib_create_cq(target->srp_host->srp_dev->dev, 233 recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
232 srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0); 234 srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
233 if (IS_ERR(target->recv_cq)) { 235 if (IS_ERR(recv_cq)) {
234 ret = PTR_ERR(target->recv_cq); 236 ret = PTR_ERR(recv_cq);
235 goto err; 237 goto err;
236 } 238 }
237 239
238 target->send_cq = ib_create_cq(target->srp_host->srp_dev->dev, 240 send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
239 srp_send_completion, NULL, target, SRP_SQ_SIZE, 0); 241 srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
240 if (IS_ERR(target->send_cq)) { 242 if (IS_ERR(send_cq)) {
241 ret = PTR_ERR(target->send_cq); 243 ret = PTR_ERR(send_cq);
242 goto err_recv_cq; 244 goto err_recv_cq;
243 } 245 }
244 246
245 ib_req_notify_cq(target->recv_cq, IB_CQ_NEXT_COMP); 247 ib_req_notify_cq(recv_cq, IB_CQ_NEXT_COMP);
246 248
247 init_attr->event_handler = srp_qp_event; 249 init_attr->event_handler = srp_qp_event;
248 init_attr->cap.max_send_wr = SRP_SQ_SIZE; 250 init_attr->cap.max_send_wr = SRP_SQ_SIZE;
@@ -251,30 +253,41 @@ static int srp_create_target_ib(struct srp_target_port *target)
251 init_attr->cap.max_send_sge = 1; 253 init_attr->cap.max_send_sge = 1;
252 init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; 254 init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
253 init_attr->qp_type = IB_QPT_RC; 255 init_attr->qp_type = IB_QPT_RC;
254 init_attr->send_cq = target->send_cq; 256 init_attr->send_cq = send_cq;
255 init_attr->recv_cq = target->recv_cq; 257 init_attr->recv_cq = recv_cq;
256 258
257 target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr); 259 qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
258 if (IS_ERR(target->qp)) { 260 if (IS_ERR(qp)) {
259 ret = PTR_ERR(target->qp); 261 ret = PTR_ERR(qp);
260 goto err_send_cq; 262 goto err_send_cq;
261 } 263 }
262 264
263 ret = srp_init_qp(target, target->qp); 265 ret = srp_init_qp(target, qp);
264 if (ret) 266 if (ret)
265 goto err_qp; 267 goto err_qp;
266 268
269 if (target->qp)
270 ib_destroy_qp(target->qp);
271 if (target->recv_cq)
272 ib_destroy_cq(target->recv_cq);
273 if (target->send_cq)
274 ib_destroy_cq(target->send_cq);
275
276 target->qp = qp;
277 target->recv_cq = recv_cq;
278 target->send_cq = send_cq;
279
267 kfree(init_attr); 280 kfree(init_attr);
268 return 0; 281 return 0;
269 282
270err_qp: 283err_qp:
271 ib_destroy_qp(target->qp); 284 ib_destroy_qp(qp);
272 285
273err_send_cq: 286err_send_cq:
274 ib_destroy_cq(target->send_cq); 287 ib_destroy_cq(send_cq);
275 288
276err_recv_cq: 289err_recv_cq:
277 ib_destroy_cq(target->recv_cq); 290 ib_destroy_cq(recv_cq);
278 291
279err: 292err:
280 kfree(init_attr); 293 kfree(init_attr);
@@ -289,6 +302,9 @@ static void srp_free_target_ib(struct srp_target_port *target)
289 ib_destroy_cq(target->send_cq); 302 ib_destroy_cq(target->send_cq);
290 ib_destroy_cq(target->recv_cq); 303 ib_destroy_cq(target->recv_cq);
291 304
305 target->qp = NULL;
306 target->send_cq = target->recv_cq = NULL;
307
292 for (i = 0; i < SRP_RQ_SIZE; ++i) 308 for (i = 0; i < SRP_RQ_SIZE; ++i)
293 srp_free_iu(target->srp_host, target->rx_ring[i]); 309 srp_free_iu(target->srp_host, target->rx_ring[i]);
294 for (i = 0; i < SRP_SQ_SIZE; ++i) 310 for (i = 0; i < SRP_SQ_SIZE; ++i)
@@ -678,8 +694,6 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
678static int srp_reconnect_target(struct srp_target_port *target) 694static int srp_reconnect_target(struct srp_target_port *target)
679{ 695{
680 struct Scsi_Host *shost = target->scsi_host; 696 struct Scsi_Host *shost = target->scsi_host;
681 struct ib_qp_attr qp_attr;
682 struct ib_wc wc;
683 int i, ret; 697 int i, ret;
684 698
685 if (target->state != SRP_TARGET_LIVE) 699 if (target->state != SRP_TARGET_LIVE)
@@ -696,20 +710,10 @@ static int srp_reconnect_target(struct srp_target_port *target)
696 if (ret) 710 if (ret)
697 goto unblock; 711 goto unblock;
698 712
699 qp_attr.qp_state = IB_QPS_RESET; 713 ret = srp_create_target_ib(target);
700 ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
701 if (ret)
702 goto unblock;
703
704 ret = srp_init_qp(target, target->qp);
705 if (ret) 714 if (ret)
706 goto unblock; 715 goto unblock;
707 716
708 while (ib_poll_cq(target->recv_cq, 1, &wc) > 0)
709 ; /* nothing */
710 while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
711 ; /* nothing */
712
713 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) { 717 for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
714 struct srp_request *req = &target->req_ring[i]; 718 struct srp_request *req = &target->req_ring[i];
715 if (req->scmnd) 719 if (req->scmnd)