diff options
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_hw.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 1980a461c499..8b606fd64022 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2608 | netif_start_queue(nesvnic->netdev); | 2608 | netif_start_queue(nesvnic->netdev); |
2609 | nesvnic->linkup = 1; | 2609 | nesvnic->linkup = 1; |
2610 | netif_carrier_on(nesvnic->netdev); | 2610 | netif_carrier_on(nesvnic->netdev); |
2611 | |||
2612 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2613 | if (nesdev->iw_status == 0) { | ||
2614 | nesdev->iw_status = 1; | ||
2615 | nes_port_ibevent(nesvnic); | ||
2616 | } | ||
2617 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2611 | } | 2618 | } |
2612 | } | 2619 | } |
2613 | } else { | 2620 | } else { |
@@ -2633,9 +2640,23 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2633 | netif_stop_queue(nesvnic->netdev); | 2640 | netif_stop_queue(nesvnic->netdev); |
2634 | nesvnic->linkup = 0; | 2641 | nesvnic->linkup = 0; |
2635 | netif_carrier_off(nesvnic->netdev); | 2642 | netif_carrier_off(nesvnic->netdev); |
2643 | |||
2644 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2645 | if (nesdev->iw_status == 1) { | ||
2646 | nesdev->iw_status = 0; | ||
2647 | nes_port_ibevent(nesvnic); | ||
2648 | } | ||
2649 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2636 | } | 2650 | } |
2637 | } | 2651 | } |
2638 | } | 2652 | } |
2653 | if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) { | ||
2654 | if (nesdev->link_recheck) | ||
2655 | cancel_delayed_work(&nesdev->work); | ||
2656 | nesdev->link_recheck = 1; | ||
2657 | schedule_delayed_work(&nesdev->work, | ||
2658 | NES_LINK_RECHECK_DELAY); | ||
2659 | } | ||
2639 | } | 2660 | } |
2640 | 2661 | ||
2641 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); | 2662 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); |
@@ -2643,6 +2664,80 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2643 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; | 2664 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; |
2644 | } | 2665 | } |
2645 | 2666 | ||
2667 | void nes_recheck_link_status(struct work_struct *work) | ||
2668 | { | ||
2669 | unsigned long flags; | ||
2670 | struct nes_device *nesdev = container_of(work, struct nes_device, work.work); | ||
2671 | struct nes_adapter *nesadapter = nesdev->nesadapter; | ||
2672 | struct nes_vnic *nesvnic; | ||
2673 | u32 mac_index = nesdev->mac_index; | ||
2674 | u16 phy_data; | ||
2675 | u16 temp_phy_data; | ||
2676 | |||
2677 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | ||
2678 | |||
2679 | /* check link status */ | ||
2680 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003); | ||
2681 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2682 | |||
2683 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); | ||
2684 | nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2685 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); | ||
2686 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2687 | |||
2688 | phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0; | ||
2689 | |||
2690 | nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n", | ||
2691 | __func__, phy_data, | ||
2692 | nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP"); | ||
2693 | |||
2694 | if (phy_data & 0x0004) { | ||
2695 | nesadapter->mac_link_down[mac_index] = 0; | ||
2696 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | ||
2697 | if (nesvnic->linkup == 0) { | ||
2698 | printk(PFX "The Link is now up for port %s, netdev %p.\n", | ||
2699 | nesvnic->netdev->name, nesvnic->netdev); | ||
2700 | if (netif_queue_stopped(nesvnic->netdev)) | ||
2701 | netif_start_queue(nesvnic->netdev); | ||
2702 | nesvnic->linkup = 1; | ||
2703 | netif_carrier_on(nesvnic->netdev); | ||
2704 | |||
2705 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2706 | if (nesdev->iw_status == 0) { | ||
2707 | nesdev->iw_status = 1; | ||
2708 | nes_port_ibevent(nesvnic); | ||
2709 | } | ||
2710 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2711 | } | ||
2712 | } | ||
2713 | |||
2714 | } else { | ||
2715 | nesadapter->mac_link_down[mac_index] = 1; | ||
2716 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | ||
2717 | if (nesvnic->linkup == 1) { | ||
2718 | printk(PFX "The Link is now down for port %s, netdev %p.\n", | ||
2719 | nesvnic->netdev->name, nesvnic->netdev); | ||
2720 | if (!(netif_queue_stopped(nesvnic->netdev))) | ||
2721 | netif_stop_queue(nesvnic->netdev); | ||
2722 | nesvnic->linkup = 0; | ||
2723 | netif_carrier_off(nesvnic->netdev); | ||
2724 | |||
2725 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2726 | if (nesdev->iw_status == 1) { | ||
2727 | nesdev->iw_status = 0; | ||
2728 | nes_port_ibevent(nesvnic); | ||
2729 | } | ||
2730 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2731 | } | ||
2732 | } | ||
2733 | } | ||
2734 | if (nesdev->link_recheck++ < NES_LINK_RECHECK_MAX) | ||
2735 | schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY); | ||
2736 | else | ||
2737 | nesdev->link_recheck = 0; | ||
2738 | |||
2739 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); | ||
2740 | } | ||
2646 | 2741 | ||
2647 | 2742 | ||
2648 | static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) | 2743 | static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) |