diff options
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_82598.c | 12 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 33 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 84 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_phy.c | 68 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_phy.h | 7 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_type.h | 6 |
7 files changed, 183 insertions, 28 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index e116d340dcc6..132854f646ba 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -267,6 +267,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17) #define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18) #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19) +#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) #define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 7cddcfba809e..c2cdb042c481 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -59,6 +59,11 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) /* PHY Init */ switch (phy->type) { + case ixgbe_phy_tn: + phy->ops.check_link = &ixgbe_check_phy_link_tnx; + phy->ops.get_firmware_version = + &ixgbe_get_phy_firmware_version_tnx; + break; default: break; } @@ -189,6 +194,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598EB_XF_LR: media_type = ixgbe_media_type_fiber; break; + case IXGBE_DEV_ID_82598AT: + media_type = ixgbe_media_type_copper; + break; default: media_type = ixgbe_media_type_unknown; break; @@ -872,6 +880,10 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598EB_XF_LR: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; + case IXGBE_DEV_ID_82598AT: + physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T | + IXGBE_PHYSICAL_LAYER_1000BASE_T); + break; default: physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 81a9c4b86726..a610016a0172 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -94,9 +94,9 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = { }; #define IXGBE_QUEUE_STATS_LEN \ - ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \ - ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \ - (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) + ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \ + ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \ + (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) @@ -149,6 +149,8 @@ static int ixgbe_set_settings(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + u32 advertised, old; + s32 err; switch (hw->phy.media_type) { case ixgbe_media_type_fiber: @@ -157,6 +159,31 @@ static int ixgbe_set_settings(struct net_device *netdev, return -EINVAL; /* in this case we currently only support 10Gb/FULL */ break; + case ixgbe_media_type_copper: + /* 10000/copper and 1000/copper must autoneg + * this function does not support any duplex forcing, but can + * limit the advertising of the adapter to only 10000 or 1000 */ + if (ecmd->autoneg == AUTONEG_DISABLE) + return -EINVAL; + + old = hw->phy.autoneg_advertised; + advertised = 0; + if (ecmd->advertising & ADVERTISED_10000baseT_Full) + advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (ecmd->advertising & ADVERTISED_1000baseT_Full) + advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + if (old == advertised) + break; + /* this sets the link speed and restarts auto-neg */ + err = hw->mac.ops.setup_link_speed(hw, advertised, true, true); + if (err) { + DPRINTK(PROBE, INFO, + "setup link failed with code %d\n", err); + hw->mac.ops.setup_link_speed(hw, old, true, true); + } + break; default: break; } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 36f2bb666bf7..7ad07a00680a 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -68,6 +68,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT), + board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), @@ -666,7 +668,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->netdev); ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc); - adapter->netdev->last_rx = jiffies; next_desc: rx_desc->wb.upper.status_error = 0; @@ -904,6 +905,17 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) return; } +static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) +{ + struct ixgbe_hw *hw = &adapter->hw; + + if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) && + (eicr & IXGBE_EICR_GPI_SDP1)) { + DPRINTK(PROBE, CRIT, "Fan has stopped, replace the adapter\n"); + /* write to clear the interrupt */ + IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); + } +} static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) { @@ -928,6 +940,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); + ixgbe_check_fan_failure(adapter, eicr); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); @@ -1312,6 +1326,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) { u32 mask; mask = IXGBE_EIMS_ENABLE_MASK; + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) + mask |= IXGBE_EIMS_GPI_SDP1; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); IXGBE_WRITE_FLUSH(&adapter->hw); } @@ -1343,6 +1359,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); + ixgbe_check_fan_failure(adapter, eicr); + if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) { adapter->tx_ring[0].total_packets = 0; adapter->tx_ring[0].total_bytes = 0; @@ -1925,6 +1943,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); } + /* Enable fan failure interrupt if media type is copper */ + if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { + gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); + gpie |= IXGBE_SDP1_GPIEN; + IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); + } + mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD); if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) { mhadd &= ~IXGBE_MHADD_MFS_MASK; @@ -1970,6 +1995,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) ixgbe_irq_enable(adapter); + /* enable transmits */ + netif_tx_start_all_queues(netdev); + /* bring the link up in the watchdog, this could race with our first * link up interrupt but shouldn't be a problem */ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; @@ -2562,6 +2590,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus()); adapter->ring_feature[RING_F_RSS].indices = rss; adapter->flags |= IXGBE_FLAG_RSS_ENABLED; + if (hw->mac.ops.get_media_type && + (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)) + adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; /* default flow control settings */ hw->fc.original_type = ixgbe_fc_none; @@ -3217,7 +3248,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) (FLOW_TX ? "TX" : "None")))); netif_carrier_on(netdev); - netif_tx_wake_all_queues(netdev); } else { /* Force detection of hung controller */ adapter->detect_tx_hung = true; @@ -3228,7 +3258,6 @@ static void ixgbe_watchdog_task(struct work_struct *work) if (netif_carrier_ok(netdev)) { DPRINTK(LINK, INFO, "NIC Link is Down\n"); netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); } } @@ -3689,9 +3718,30 @@ static int ixgbe_link_config(struct ixgbe_hw *hw) /* must always autoneg for both 1G and 10G link */ hw->mac.autoneg = true; + if ((hw->mac.type == ixgbe_mac_82598EB) && + (hw->phy.media_type == ixgbe_media_type_copper)) + autoneg = IXGBE_LINK_SPEED_82598_AUTONEG; + return hw->mac.ops.setup_link_speed(hw, autoneg, true, true); } +static const struct net_device_ops ixgbe_netdev_ops = { + .ndo_open = ixgbe_open, + .ndo_stop = ixgbe_close, + .ndo_get_stats = ixgbe_get_stats, + .ndo_set_multicast_list = ixgbe_set_rx_mode, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = ixgbe_set_mac, + .ndo_change_mtu = ixgbe_change_mtu, + .ndo_tx_timeout = ixgbe_tx_timeout, + .ndo_vlan_rx_register = ixgbe_vlan_rx_register, + .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ixgbe_netpoll, +#endif +}; + /** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -3773,23 +3823,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, continue; } - netdev->open = &ixgbe_open; - netdev->stop = &ixgbe_close; + netdev->netdev_ops = &ixgbe_netdev_ops; netdev->hard_start_xmit = &ixgbe_xmit_frame; - netdev->get_stats = &ixgbe_get_stats; - netdev->set_rx_mode = &ixgbe_set_rx_mode; - netdev->set_multicast_list = &ixgbe_set_rx_mode; - netdev->set_mac_address = &ixgbe_set_mac; - netdev->change_mtu = &ixgbe_change_mtu; ixgbe_set_ethtool_ops(netdev); - netdev->tx_timeout = &ixgbe_tx_timeout; netdev->watchdog_timeo = 5 * HZ; - netdev->vlan_rx_register = ixgbe_vlan_rx_register; - netdev->vlan_rx_add_vid = ixgbe_vlan_rx_add_vid; - netdev->vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = ixgbe_netpoll; -#endif strcpy(netdev->name, pci_name(pdev)); adapter->bd_number = cards_found; @@ -3875,8 +3912,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status); link_speed = link_status & IXGBE_PCI_LINK_SPEED; link_width = link_status & IXGBE_PCI_LINK_WIDTH; - dev_info(&pdev->dev, "(PCI Express:%s:%s) " - "%02x:%02x:%02x:%02x:%02x:%02x\n", + dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n", ((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" : (link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" : "Unknown"), @@ -3885,8 +3921,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, (link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" : (link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" : "Unknown"), - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + netdev->dev_addr); ixgbe_read_pba_num_generic(hw, &part_num); dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n", hw->mac.type, hw->phy.type, @@ -3911,7 +3946,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); ixgbe_napi_add_all(adapter); @@ -4009,7 +4043,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev->priv; + struct ixgbe_adapter *adapter = netdev_priv(netdev); netif_device_detach(netdev); @@ -4030,7 +4064,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev->priv; + struct ixgbe_adapter *adapter = netdev_priv(netdev); if (pci_enable_device(pdev)) { DPRINTK(PROBE, ERR, @@ -4058,7 +4092,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) static void ixgbe_io_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct ixgbe_adapter *adapter = netdev->priv; + struct ixgbe_adapter *adapter = netdev_priv(netdev); if (netif_running(netdev)) { if (ixgbe_up(adapter)) { diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 764035a8c9a1..981e6d849592 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -121,6 +121,9 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) enum ixgbe_phy_type phy_type; switch (phy_id) { + case TN1010_PHY_ID: + phy_type = ixgbe_phy_tn; + break; case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; @@ -426,3 +429,68 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, return 0; } +/** + * ixgbe_check_phy_link_tnx - Determine link and speed status + * @hw: pointer to hardware structure + * + * Reads the VS1 register to determine if link is up and the current speed for + * the PHY. + **/ +s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *link_up) +{ + s32 status = 0; + u32 time_out; + u32 max_time_out = 10; + u16 phy_link = 0; + u16 phy_speed = 0; + u16 phy_data = 0; + + /* Initialize speed and link to default case */ + *link_up = false; + *speed = IXGBE_LINK_SPEED_10GB_FULL; + + /* + * Check current speed and link status of the PHY register. + * This is a vendor specific register and may have to + * be changed for other copper PHYs. + */ + for (time_out = 0; time_out < max_time_out; time_out++) { + udelay(10); + status = hw->phy.ops.read_reg(hw, + IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + &phy_data); + phy_link = phy_data & + IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; + phy_speed = phy_data & + IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; + if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { + *link_up = true; + if (phy_speed == + IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) + *speed = IXGBE_LINK_SPEED_1GB_FULL; + break; + } + } + + return status; +} + +/** + * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version + * @hw: pointer to hardware structure + * @firmware_version: pointer to the PHY Firmware Version + **/ +s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, + u16 *firmware_version) +{ + s32 status = 0; + + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + firmware_version); + + return status; +} + diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index 9bfe3f2b1d8f..5cc063d02770 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -77,4 +77,11 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, bool autoneg, bool autoneg_wait_to_complete); +/* PHY specific */ +s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *link_up); +s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, + u16 *firmware_version); + #endif /* _IXGBE_PHY_H_ */ diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index c6f8fa1c4e59..51df39dae816 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -36,6 +36,7 @@ /* Device IDs */ #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 +#define IXGBE_DEV_ID_82598AT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 @@ -488,6 +489,8 @@ #define IXGBE_MAX_PHY_ADDR 32 /* PHY IDs*/ +#define TN1010_PHY_ID 0x00A19410 +#define TNX_FW_REV 0xB #define QT2022_PHY_ID 0x0043A400 /* PHY Types */ @@ -1202,6 +1205,7 @@ enum ixgbe_mac_type { enum ixgbe_phy_type { ixgbe_phy_unknown = 0, + ixgbe_phy_tn, ixgbe_phy_qt, ixgbe_phy_xaui, ixgbe_phy_tw_tyco, @@ -1396,6 +1400,8 @@ struct ixgbe_phy_operations { s32 (*setup_link)(struct ixgbe_hw *); s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); + s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); + s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *); s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *); s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); |