diff options
| -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; |
