diff options
| -rw-r--r-- | drivers/infiniband/hw/nes/nes.c | 11 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes.h | 4 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 81 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.h | 4 |
4 files changed, 100 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index e17f52c21947..3b4ec3238ceb 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
| @@ -674,6 +674,8 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i | |||
| 674 | } | 674 | } |
| 675 | nes_notifiers_registered++; | 675 | nes_notifiers_registered++; |
| 676 | 676 | ||
| 677 | INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status); | ||
| 678 | |||
| 677 | /* Initialize network devices */ | 679 | /* Initialize network devices */ |
| 678 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) | 680 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) |
| 679 | goto bail7; | 681 | goto bail7; |
| @@ -756,6 +758,7 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
| 756 | struct nes_device *nesdev = pci_get_drvdata(pcidev); | 758 | struct nes_device *nesdev = pci_get_drvdata(pcidev); |
| 757 | struct net_device *netdev; | 759 | struct net_device *netdev; |
| 758 | int netdev_index = 0; | 760 | int netdev_index = 0; |
| 761 | unsigned long flags; | ||
| 759 | 762 | ||
| 760 | if (nesdev->netdev_count) { | 763 | if (nesdev->netdev_count) { |
| 761 | netdev = nesdev->netdev[netdev_index]; | 764 | netdev = nesdev->netdev[netdev_index]; |
| @@ -782,6 +785,14 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
| 782 | free_irq(pcidev->irq, nesdev); | 785 | free_irq(pcidev->irq, nesdev); |
| 783 | tasklet_kill(&nesdev->dpc_tasklet); | 786 | tasklet_kill(&nesdev->dpc_tasklet); |
| 784 | 787 | ||
| 788 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
| 789 | if (nesdev->link_recheck) { | ||
| 790 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
| 791 | cancel_delayed_work_sync(&nesdev->work); | ||
| 792 | } else { | ||
| 793 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
| 794 | } | ||
| 795 | |||
| 785 | /* Deallocate the Adapter Structure */ | 796 | /* Deallocate the Adapter Structure */ |
| 786 | nes_destroy_adapter(nesdev->nesadapter); | 797 | nes_destroy_adapter(nesdev->nesadapter); |
| 787 | 798 | ||
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index b3d145e82b4c..6fe79876009e 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
| @@ -268,6 +268,9 @@ struct nes_device { | |||
| 268 | u8 napi_isr_ran; | 268 | u8 napi_isr_ran; |
| 269 | u8 disable_rx_flow_control; | 269 | u8 disable_rx_flow_control; |
| 270 | u8 disable_tx_flow_control; | 270 | u8 disable_tx_flow_control; |
| 271 | |||
| 272 | struct delayed_work work; | ||
| 273 | u8 link_recheck; | ||
| 271 | }; | 274 | }; |
| 272 | 275 | ||
| 273 | 276 | ||
| @@ -507,6 +510,7 @@ void nes_nic_ce_handler(struct nes_device *, struct nes_hw_nic_cq *); | |||
| 507 | void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); | 510 | void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); |
| 508 | int nes_destroy_cqp(struct nes_device *); | 511 | int nes_destroy_cqp(struct nes_device *); |
| 509 | int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); | 512 | int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); |
| 513 | void nes_recheck_link_status(struct work_struct *work); | ||
| 510 | 514 | ||
| 511 | /* nes_nic.c */ | 515 | /* nes_nic.c */ |
| 512 | struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); | 516 | struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 2b89b06ca7c3..8b606fd64022 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
| @@ -2650,6 +2650,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
| 2650 | } | 2650 | } |
| 2651 | } | 2651 | } |
| 2652 | } | 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 | } | ||
| 2653 | } | 2660 | } |
| 2654 | 2661 | ||
| 2655 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); | 2662 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); |
| @@ -2657,6 +2664,80 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
| 2657 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; | 2664 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; |
| 2658 | } | 2665 | } |
| 2659 | 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 | } | ||
| 2660 | 2741 | ||
| 2661 | 2742 | ||
| 2662 | 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) |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 8a9ea9a4dc5d..d2abe07133a5 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
| @@ -1354,6 +1354,10 @@ struct nes_terminate_hdr { | |||
| 1354 | #define BAD_FRAME_OFFSET 64 | 1354 | #define BAD_FRAME_OFFSET 64 |
| 1355 | #define CQE_MAJOR_DRV 0x8000 | 1355 | #define CQE_MAJOR_DRV 0x8000 |
| 1356 | 1356 | ||
| 1357 | /* Used for link status recheck after interrupt processing */ | ||
| 1358 | #define NES_LINK_RECHECK_DELAY msecs_to_jiffies(50) | ||
| 1359 | #define NES_LINK_RECHECK_MAX 60 | ||
| 1360 | |||
| 1357 | #define nes_vlan_rx vlan_hwaccel_receive_skb | 1361 | #define nes_vlan_rx vlan_hwaccel_receive_skb |
| 1358 | #define nes_netif_rx netif_receive_skb | 1362 | #define nes_netif_rx netif_receive_skb |
| 1359 | 1363 | ||
