aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_ruc.c
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2008-05-13 14:40:25 -0400
committerRoland Dreier <rolandd@cisco.com>2008-05-13 14:40:25 -0400
commit53dc1ca194c062aa9771e194047f27ec1ca592df (patch)
tree4cf0fe73ea76f02f871d5e6def040a869b224f00 /drivers/infiniband/hw/ipath/ipath_ruc.c
parentdd37818dbdf8e51d0288c0197c351c005ffcdbdb (diff)
IB/ipath: Fix RC and UC error handling
When errors are detected in RC, the QP should transition to the IB_QPS_ERR state, not the IB_QPS_SQE state. Also, when the error is on the responder side, the receive work completion error was incorrect (remote vs. local). Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_ruc.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c165
1 files changed, 79 insertions, 86 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index 9e3fe61cbd08..c716a03dd399 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. 2 * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
3 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. 3 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
4 * 4 *
5 * This software is available to you under a choice of one of two 5 * This software is available to you under a choice of one of two
@@ -140,20 +140,11 @@ int ipath_init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe,
140 goto bail; 140 goto bail;
141 141
142bad_lkey: 142bad_lkey:
143 memset(&wc, 0, sizeof(wc));
143 wc.wr_id = wqe->wr_id; 144 wc.wr_id = wqe->wr_id;
144 wc.status = IB_WC_LOC_PROT_ERR; 145 wc.status = IB_WC_LOC_PROT_ERR;
145 wc.opcode = IB_WC_RECV; 146 wc.opcode = IB_WC_RECV;
146 wc.vendor_err = 0;
147 wc.byte_len = 0;
148 wc.imm_data = 0;
149 wc.qp = &qp->ibqp; 147 wc.qp = &qp->ibqp;
150 wc.src_qp = 0;
151 wc.wc_flags = 0;
152 wc.pkey_index = 0;
153 wc.slid = 0;
154 wc.sl = 0;
155 wc.dlid_path_bits = 0;
156 wc.port_num = 0;
157 /* Signal solicited completion event. */ 148 /* Signal solicited completion event. */
158 ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); 149 ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
159 ret = 0; 150 ret = 0;
@@ -270,6 +261,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp)
270 struct ib_wc wc; 261 struct ib_wc wc;
271 u64 sdata; 262 u64 sdata;
272 atomic64_t *maddr; 263 atomic64_t *maddr;
264 enum ib_wc_status send_status;
273 265
274 qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); 266 qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
275 if (!qp) { 267 if (!qp) {
@@ -300,8 +292,8 @@ again:
300 wqe = get_swqe_ptr(sqp, sqp->s_last); 292 wqe = get_swqe_ptr(sqp, sqp->s_last);
301 spin_unlock_irqrestore(&sqp->s_lock, flags); 293 spin_unlock_irqrestore(&sqp->s_lock, flags);
302 294
303 wc.wc_flags = 0; 295 memset(&wc, 0, sizeof wc);
304 wc.imm_data = 0; 296 send_status = IB_WC_SUCCESS;
305 297
306 sqp->s_sge.sge = wqe->sg_list[0]; 298 sqp->s_sge.sge = wqe->sg_list[0];
307 sqp->s_sge.sg_list = wqe->sg_list + 1; 299 sqp->s_sge.sg_list = wqe->sg_list + 1;
@@ -313,75 +305,33 @@ again:
313 wc.imm_data = wqe->wr.ex.imm_data; 305 wc.imm_data = wqe->wr.ex.imm_data;
314 /* FALLTHROUGH */ 306 /* FALLTHROUGH */
315 case IB_WR_SEND: 307 case IB_WR_SEND:
316 if (!ipath_get_rwqe(qp, 0)) { 308 if (!ipath_get_rwqe(qp, 0))
317 rnr_nak: 309 goto rnr_nak;
318 /* Handle RNR NAK */
319 if (qp->ibqp.qp_type == IB_QPT_UC)
320 goto send_comp;
321 if (sqp->s_rnr_retry == 0) {
322 wc.status = IB_WC_RNR_RETRY_EXC_ERR;
323 goto err;
324 }
325 if (sqp->s_rnr_retry_cnt < 7)
326 sqp->s_rnr_retry--;
327 dev->n_rnr_naks++;
328 sqp->s_rnr_timeout =
329 ib_ipath_rnr_table[qp->r_min_rnr_timer];
330 ipath_insert_rnr_queue(sqp);
331 goto done;
332 }
333 break; 310 break;
334 311
335 case IB_WR_RDMA_WRITE_WITH_IMM: 312 case IB_WR_RDMA_WRITE_WITH_IMM:
336 if (unlikely(!(qp->qp_access_flags & 313 if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE)))
337 IB_ACCESS_REMOTE_WRITE))) { 314 goto inv_err;
338 wc.status = IB_WC_REM_INV_REQ_ERR;
339 goto err;
340 }
341 wc.wc_flags = IB_WC_WITH_IMM; 315 wc.wc_flags = IB_WC_WITH_IMM;
342 wc.imm_data = wqe->wr.ex.imm_data; 316 wc.imm_data = wqe->wr.ex.imm_data;
343 if (!ipath_get_rwqe(qp, 1)) 317 if (!ipath_get_rwqe(qp, 1))
344 goto rnr_nak; 318 goto rnr_nak;
345 /* FALLTHROUGH */ 319 /* FALLTHROUGH */
346 case IB_WR_RDMA_WRITE: 320 case IB_WR_RDMA_WRITE:
347 if (unlikely(!(qp->qp_access_flags & 321 if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE)))
348 IB_ACCESS_REMOTE_WRITE))) { 322 goto inv_err;
349 wc.status = IB_WC_REM_INV_REQ_ERR;
350 goto err;
351 }
352 if (wqe->length == 0) 323 if (wqe->length == 0)
353 break; 324 break;
354 if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length, 325 if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
355 wqe->wr.wr.rdma.remote_addr, 326 wqe->wr.wr.rdma.remote_addr,
356 wqe->wr.wr.rdma.rkey, 327 wqe->wr.wr.rdma.rkey,
357 IB_ACCESS_REMOTE_WRITE))) { 328 IB_ACCESS_REMOTE_WRITE)))
358 acc_err: 329 goto acc_err;
359 wc.status = IB_WC_REM_ACCESS_ERR;
360 err:
361 wc.wr_id = wqe->wr.wr_id;
362 wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
363 wc.vendor_err = 0;
364 wc.byte_len = 0;
365 wc.qp = &sqp->ibqp;
366 wc.src_qp = sqp->remote_qpn;
367 wc.pkey_index = 0;
368 wc.slid = sqp->remote_ah_attr.dlid;
369 wc.sl = sqp->remote_ah_attr.sl;
370 wc.dlid_path_bits = 0;
371 wc.port_num = 0;
372 spin_lock_irqsave(&sqp->s_lock, flags);
373 ipath_sqerror_qp(sqp, &wc);
374 spin_unlock_irqrestore(&sqp->s_lock, flags);
375 goto done;
376 }
377 break; 330 break;
378 331
379 case IB_WR_RDMA_READ: 332 case IB_WR_RDMA_READ:
380 if (unlikely(!(qp->qp_access_flags & 333 if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
381 IB_ACCESS_REMOTE_READ))) { 334 goto inv_err;
382 wc.status = IB_WC_REM_INV_REQ_ERR;
383 goto err;
384 }
385 if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length, 335 if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
386 wqe->wr.wr.rdma.remote_addr, 336 wqe->wr.wr.rdma.remote_addr,
387 wqe->wr.wr.rdma.rkey, 337 wqe->wr.wr.rdma.rkey,
@@ -394,11 +344,8 @@ again:
394 344
395 case IB_WR_ATOMIC_CMP_AND_SWP: 345 case IB_WR_ATOMIC_CMP_AND_SWP:
396 case IB_WR_ATOMIC_FETCH_AND_ADD: 346 case IB_WR_ATOMIC_FETCH_AND_ADD:
397 if (unlikely(!(qp->qp_access_flags & 347 if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC)))
398 IB_ACCESS_REMOTE_ATOMIC))) { 348 goto inv_err;
399 wc.status = IB_WC_REM_INV_REQ_ERR;
400 goto err;
401 }
402 if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64), 349 if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
403 wqe->wr.wr.atomic.remote_addr, 350 wqe->wr.wr.atomic.remote_addr,
404 wqe->wr.wr.atomic.rkey, 351 wqe->wr.wr.atomic.rkey,
@@ -415,7 +362,8 @@ again:
415 goto send_comp; 362 goto send_comp;
416 363
417 default: 364 default:
418 goto done; 365 send_status = IB_WC_LOC_QP_OP_ERR;
366 goto serr;
419 } 367 }
420 368
421 sge = &sqp->s_sge.sge; 369 sge = &sqp->s_sge.sge;
@@ -458,14 +406,11 @@ again:
458 wc.opcode = IB_WC_RECV; 406 wc.opcode = IB_WC_RECV;
459 wc.wr_id = qp->r_wr_id; 407 wc.wr_id = qp->r_wr_id;
460 wc.status = IB_WC_SUCCESS; 408 wc.status = IB_WC_SUCCESS;
461 wc.vendor_err = 0;
462 wc.byte_len = wqe->length; 409 wc.byte_len = wqe->length;
463 wc.qp = &qp->ibqp; 410 wc.qp = &qp->ibqp;
464 wc.src_qp = qp->remote_qpn; 411 wc.src_qp = qp->remote_qpn;
465 wc.pkey_index = 0;
466 wc.slid = qp->remote_ah_attr.dlid; 412 wc.slid = qp->remote_ah_attr.dlid;
467 wc.sl = qp->remote_ah_attr.sl; 413 wc.sl = qp->remote_ah_attr.sl;
468 wc.dlid_path_bits = 0;
469 wc.port_num = 1; 414 wc.port_num = 1;
470 /* Signal completion event if the solicited bit is set. */ 415 /* Signal completion event if the solicited bit is set. */
471 ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 416 ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
@@ -473,9 +418,63 @@ again:
473 418
474send_comp: 419send_comp:
475 sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; 420 sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
476 ipath_send_complete(sqp, wqe, IB_WC_SUCCESS); 421 ipath_send_complete(sqp, wqe, send_status);
477 goto again; 422 goto again;
478 423
424rnr_nak:
425 /* Handle RNR NAK */
426 if (qp->ibqp.qp_type == IB_QPT_UC)
427 goto send_comp;
428 /*
429 * Note: we don't need the s_lock held since the BUSY flag
430 * makes this single threaded.
431 */
432 if (sqp->s_rnr_retry == 0) {
433 send_status = IB_WC_RNR_RETRY_EXC_ERR;
434 goto serr;
435 }
436 if (sqp->s_rnr_retry_cnt < 7)
437 sqp->s_rnr_retry--;
438 spin_lock_irqsave(&sqp->s_lock, flags);
439 if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_RECV_OK))
440 goto unlock;
441 dev->n_rnr_naks++;
442 sqp->s_rnr_timeout = ib_ipath_rnr_table[qp->r_min_rnr_timer];
443 ipath_insert_rnr_queue(sqp);
444 goto unlock;
445
446inv_err:
447 send_status = IB_WC_REM_INV_REQ_ERR;
448 wc.status = IB_WC_LOC_QP_OP_ERR;
449 goto err;
450
451acc_err:
452 send_status = IB_WC_REM_ACCESS_ERR;
453 wc.status = IB_WC_LOC_PROT_ERR;
454err:
455 /* responder goes to error state */
456 ipath_rc_error(qp, wc.status);
457
458serr:
459 spin_lock_irqsave(&sqp->s_lock, flags);
460 ipath_send_complete(sqp, wqe, send_status);
461 if (sqp->ibqp.qp_type == IB_QPT_RC) {
462 int lastwqe = ipath_error_qp(sqp, IB_WC_WR_FLUSH_ERR);
463
464 sqp->s_flags &= ~IPATH_S_BUSY;
465 spin_unlock_irqrestore(&sqp->s_lock, flags);
466 if (lastwqe) {
467 struct ib_event ev;
468
469 ev.device = sqp->ibqp.device;
470 ev.element.qp = &sqp->ibqp;
471 ev.event = IB_EVENT_QP_LAST_WQE_REACHED;
472 sqp->ibqp.event_handler(&ev, sqp->ibqp.qp_context);
473 }
474 goto done;
475 }
476unlock:
477 spin_unlock_irqrestore(&sqp->s_lock, flags);
479done: 478done:
480 if (atomic_dec_and_test(&qp->refcount)) 479 if (atomic_dec_and_test(&qp->refcount))
481 wake_up(&qp->wait); 480 wake_up(&qp->wait);
@@ -651,21 +650,15 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
651 status != IB_WC_SUCCESS) { 650 status != IB_WC_SUCCESS) {
652 struct ib_wc wc; 651 struct ib_wc wc;
653 652
653 memset(&wc, 0, sizeof wc);
654 wc.wr_id = wqe->wr.wr_id; 654 wc.wr_id = wqe->wr.wr_id;
655 wc.status = status; 655 wc.status = status;
656 wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; 656 wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
657 wc.vendor_err = 0;
658 wc.byte_len = wqe->length;
659 wc.imm_data = 0;
660 wc.qp = &qp->ibqp; 657 wc.qp = &qp->ibqp;
661 wc.src_qp = 0; 658 if (status == IB_WC_SUCCESS)
662 wc.wc_flags = 0; 659 wc.byte_len = wqe->length;
663 wc.pkey_index = 0; 660 ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc,
664 wc.slid = 0; 661 status != IB_WC_SUCCESS);
665 wc.sl = 0;
666 wc.dlid_path_bits = 0;
667 wc.port_num = 0;
668 ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
669 } 662 }
670 663
671 spin_lock_irqsave(&qp->s_lock, flags); 664 spin_lock_irqsave(&qp->s_lock, flags);