aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c102
1 files changed, 52 insertions, 50 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index d89bdee0cf55..73473db19863 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2493,7 +2493,12 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2493 u16 last_ae; 2493 u16 last_ae;
2494 u8 original_hw_tcp_state; 2494 u8 original_hw_tcp_state;
2495 u8 original_ibqp_state; 2495 u8 original_ibqp_state;
2496 u8 issued_disconnect_reset = 0; 2496 enum iw_cm_event_type disconn_status = IW_CM_EVENT_STATUS_OK;
2497 int issue_disconn = 0;
2498 int issue_close = 0;
2499 int issue_flush = 0;
2500 u32 flush_q = NES_CQP_FLUSH_RQ;
2501 struct ib_event ibevent;
2497 2502
2498 if (!nesqp) { 2503 if (!nesqp) {
2499 nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n"); 2504 nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n");
@@ -2517,24 +2522,55 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2517 original_ibqp_state = nesqp->ibqp_state; 2522 original_ibqp_state = nesqp->ibqp_state;
2518 last_ae = nesqp->last_aeq; 2523 last_ae = nesqp->last_aeq;
2519 2524
2525 if (nesqp->term_flags) {
2526 issue_disconn = 1;
2527 issue_close = 1;
2528 nesqp->cm_id = NULL;
2529 if (nesqp->flush_issued == 0) {
2530 nesqp->flush_issued = 1;
2531 issue_flush = 1;
2532 }
2533 } else if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
2534 ((original_ibqp_state == IB_QPS_RTS) &&
2535 (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
2536 issue_disconn = 1;
2537 if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET)
2538 disconn_status = IW_CM_EVENT_STATUS_RESET;
2539 }
2540
2541 if (((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
2542 (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) ||
2543 (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) ||
2544 (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
2545 issue_close = 1;
2546 nesqp->cm_id = NULL;
2547 if (nesqp->flush_issued == 0) {
2548 nesqp->flush_issued = 1;
2549 issue_flush = 1;
2550 }
2551 }
2552
2553 spin_unlock_irqrestore(&nesqp->lock, flags);
2520 2554
2521 nes_debug(NES_DBG_CM, "set ibqp_state=%u\n", nesqp->ibqp_state); 2555 if ((issue_flush) && (nesqp->destroyed == 0)) {
2556 /* Flush the queue(s) */
2557 if (nesqp->hw_iwarp_state >= NES_AEQE_IWARP_STATE_TERMINATE)
2558 flush_q |= NES_CQP_FLUSH_SQ;
2559 flush_wqes(nesvnic->nesdev, nesqp, flush_q, 1);
2522 2560
2523 if ((nesqp->cm_id) && (cm_id->event_handler)) { 2561 if (nesqp->term_flags) {
2524 if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) || 2562 ibevent.device = nesqp->ibqp.device;
2525 ((original_ibqp_state == IB_QPS_RTS) && 2563 ibevent.event = nesqp->terminate_eventtype;
2526 (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) { 2564 ibevent.element.qp = &nesqp->ibqp;
2565 nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
2566 }
2567 }
2568
2569 if ((cm_id) && (cm_id->event_handler)) {
2570 if (issue_disconn) {
2527 atomic_inc(&cm_disconnects); 2571 atomic_inc(&cm_disconnects);
2528 cm_event.event = IW_CM_EVENT_DISCONNECT; 2572 cm_event.event = IW_CM_EVENT_DISCONNECT;
2529 if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { 2573 cm_event.status = disconn_status;
2530 cm_event.status = IW_CM_EVENT_STATUS_RESET;
2531 nes_debug(NES_DBG_CM, "Generating a CM "
2532 "Disconnect Event (status reset) for "
2533 "QP%u, cm_id = %p. \n",
2534 nesqp->hwqp.qp_id, cm_id);
2535 } else
2536 cm_event.status = IW_CM_EVENT_STATUS_OK;
2537
2538 cm_event.local_addr = cm_id->local_addr; 2574 cm_event.local_addr = cm_id->local_addr;
2539 cm_event.remote_addr = cm_id->remote_addr; 2575 cm_event.remote_addr = cm_id->remote_addr;
2540 cm_event.private_data = NULL; 2576 cm_event.private_data = NULL;
@@ -2547,28 +2583,14 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2547 nesqp->hwqp.sq_tail, cm_id, 2583 nesqp->hwqp.sq_tail, cm_id,
2548 atomic_read(&nesqp->refcount)); 2584 atomic_read(&nesqp->refcount));
2549 2585
2550 spin_unlock_irqrestore(&nesqp->lock, flags);
2551 ret = cm_id->event_handler(cm_id, &cm_event); 2586 ret = cm_id->event_handler(cm_id, &cm_event);
2552 if (ret) 2587 if (ret)
2553 nes_debug(NES_DBG_CM, "OFA CM event_handler " 2588 nes_debug(NES_DBG_CM, "OFA CM event_handler "
2554 "returned, ret=%d\n", ret); 2589 "returned, ret=%d\n", ret);
2555 spin_lock_irqsave(&nesqp->lock, flags);
2556 } 2590 }
2557 2591
2558 /* There might have been another AE while the lock was released */ 2592 if (issue_close) {
2559 original_hw_tcp_state = nesqp->hw_tcp_state;
2560 original_ibqp_state = nesqp->ibqp_state;
2561 last_ae = nesqp->last_aeq;
2562
2563 if ((issued_disconnect_reset == 0) && (nesqp->cm_id) &&
2564 ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
2565 (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) ||
2566 (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) ||
2567 (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
2568 atomic_inc(&cm_closes); 2593 atomic_inc(&cm_closes);
2569 nesqp->cm_id = NULL;
2570 nesqp->in_disconnect = 0;
2571 spin_unlock_irqrestore(&nesqp->lock, flags);
2572 nes_disconnect(nesqp, 1); 2594 nes_disconnect(nesqp, 1);
2573 2595
2574 cm_id->provider_data = nesqp; 2596 cm_id->provider_data = nesqp;
@@ -2587,27 +2609,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2587 } 2609 }
2588 2610
2589 cm_id->rem_ref(cm_id); 2611 cm_id->rem_ref(cm_id);
2590
2591 spin_lock_irqsave(&nesqp->lock, flags);
2592 if (nesqp->flush_issued == 0) {
2593 nesqp->flush_issued = 1;
2594 spin_unlock_irqrestore(&nesqp->lock, flags);
2595 flush_wqes(nesvnic->nesdev, nesqp,
2596 NES_CQP_FLUSH_RQ, 1);
2597 } else
2598 spin_unlock_irqrestore(&nesqp->lock, flags);
2599 } else {
2600 cm_id = nesqp->cm_id;
2601 spin_unlock_irqrestore(&nesqp->lock, flags);
2602 /* check to see if the inbound reset beat the outbound reset */
2603 if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) {
2604 nes_debug(NES_DBG_CM, "QP%u: Decing refcount "
2605 "due to inbound reset beating the "
2606 "outbound reset.\n", nesqp->hwqp.qp_id);
2607 }
2608 } 2612 }
2609 } else {
2610 spin_unlock_irqrestore(&nesqp->lock, flags);
2611 } 2613 }
2612 2614
2613 return 0; 2615 return 0;