diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 102 |
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; |