From: Andy Gospodarek <gospo@redhat.com> Date: Fri, 14 Nov 2008 11:14:29 -0500 Subject: [net] ixgbe: add support for 82598AT Message-id: 20081114161429.GE20392@gospo.rdu.redhat.com O-Subject: [RHEL5.3 PATCH] ixgbe: add support for 82598AT Bugzilla: 454910 RH-Acked-by: John W. Linville <linville@redhat.com> RH-Acked-by: Neil Horman <nhorman@redhat.com> RH-Acked-by: Prarit Bhargava <prarit@redhat.com> This patch adds support for the new 82595AT adapters. Though we previously removed support for this adapter by dropping the pci-id, this adds it back and includes the support needed to make it work properly. This is mostly a backport of the following upstream commit with a small recursion fix during initialization as well: commit 0befdb3e0a26a8949063915274e1bec8873c526b Author: Jesse Brandeburg <jesse.brandeburg@intel.com> Date: Fri Oct 31 00:46:40 2008 -0700 ixgbe: add device support for 82598AT (copper 10GbE) adapters Intel is currently shipping support for adapters with a phy that does 10GBase-T (copper), which is 10 Gigabit ethernet over standard Category 6 cabling. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com> This should completely satisfy the request in RHBZ 454910. diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ff7615d..7ff9bb3 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -260,6 +260,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3) #define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4) #define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 5) +#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) #define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 6) #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 7) diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index f96358b..34869bf 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -193,7 +193,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: media_type = ixgbe_media_type_fiber; break; - case IXGBE_DEV_ID_82598AT_DUAL_PORT: + case IXGBE_DEV_ID_82598AT: media_type = ixgbe_media_type_copper; break; default: @@ -365,7 +365,7 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN; /* Set up MAC */ - hw->mac.ops.setup_link(hw); + ixgbe_setup_mac_link_82598(hw); return status; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 69c45c3..35688bd 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -147,6 +147,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: @@ -155,6 +157,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 02762fd..30939da 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -71,6 +71,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), @@ -768,6 +770,18 @@ 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 irqreturn_t ixgbe_msix_lsc(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; @@ -781,6 +795,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data, struct pt_regs *regs) mod_timer(&adapter->watchdog_timer, jiffies); } + ixgbe_check_fan_failure(adapter, eicr); + if (!test_bit(__IXGBE_DOWN, &adapter->state)) IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); @@ -1110,6 +1126,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data, struct pt_regs *regs) } + ixgbe_check_fan_failure(adapter, eicr); + if (netif_rx_schedule_prep(adapter->q_vector[0].dummy_netdev)) { adapter->tx_ring[0].total_packets = 0; adapter->tx_ring[0].total_bytes = 0; @@ -1212,6 +1230,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); } @@ -1619,6 +1639,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; @@ -2299,6 +2326,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; /* Enable Dynamic interrupt throttling by default */ adapter->rx_eitr = 1; @@ -3238,6 +3268,26 @@ static void ixgbe_netpoll(struct net_device *netdev) #endif /** + * ixgbe_link_config - set up initial link with default speed and duplex + * @hw: pointer to private hardware struct + * + * Returns 0 on success, negative on failure + */ +static int ixgbe_link_config(struct ixgbe_hw *hw) +{ + u32 autoneg = IXGBE_LINK_SPEED_10GB_FULL; + + /* 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); +} + +/** * ixgbe_napi_add_all - prep napi structs for use * @adapter: private struct * helper function to napi_add each possible q_vector->napi @@ -3494,6 +3544,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, /* reset the hardware with the new settings */ ixgbe_start_hw(hw); + /* link_config depends on start_hw being called at least once */ + err = ixgbe_link_config(hw); + if (err) { + dev_err(&pdev->dev, "setup_link_speed FAILED %d\n", err); + goto err_register; + } + netif_carrier_off(netdev); netif_stop_queue(netdev); diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 8002931..e1e82f4 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -492,3 +492,21 @@ s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, return 0; } + +/** + * 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 = ixgbe_read_phy_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 aa3ea72..6d9cd07 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -46,4 +46,8 @@ s32 ixgbe_check_tnx_phy_link(struct ixgbe_hw *hw, u32 *speed, bool *link_up); s32 ixgbe_setup_tnx_phy_link_speed(struct ixgbe_hw *hw, u32 speed, bool autoneg, bool autoneg_wait_to_complete); +/* PHY specific */ +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 0a32b17..05a3698 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -38,7 +38,7 @@ /* Device IDs */ #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 -#define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 +#define IXGBE_DEV_ID_82598AT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC @@ -466,14 +466,17 @@ /* PHY IDs*/ #define TN1010_PHY_ID 0x00A19410 +#define TNX_FW_REV 0xB #define QT2022_PHY_ID 0x0043A400 /* General purpose Interrupt Enable */ -#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ -#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ -#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ -#define IXGBE_GPIE_EIAME 0x40000000 -#define IXGBE_GPIE_PBA_SUPPORT 0x80000000 +#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ +#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */ +#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ +#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ +#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ +#define IXGBE_GPIE_EIAME 0x40000000 +#define IXGBE_GPIE_PBA_SUPPORT 0x80000000 /* Transmit Flow Control status */ #define IXGBE_TFCS_TXOFF 0x00000001 @@ -547,18 +550,23 @@ /* Extended Interrupt Cause Read */ #define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ #define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */ -#define IXGBE_EICR_MNG 0x00400000 /* Managability Event Interrupt */ +#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */ +#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ +#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */ #define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */ #define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */ #define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define IXGBE_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ + /* Extended Interrupt Cause Set */ #define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ #define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ -#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Error */ +#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ +#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ +#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */ #define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ @@ -1126,7 +1134,8 @@ struct ixgbe_adv_tx_context_desc { #define IXGBE_LINK_SPEED_100_FULL 0x0008 #define IXGBE_LINK_SPEED_1GB_FULL 0x0020 #define IXGBE_LINK_SPEED_10GB_FULL 0x0080 - +#define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \ + IXGBE_LINK_SPEED_10GB_FULL) enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, @@ -1248,6 +1257,7 @@ struct ixgbe_mac_operations { enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); s32 (*setup_link)(struct ixgbe_hw *); s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *); + s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *); s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool); s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *); }; @@ -1270,6 +1280,7 @@ struct ixgbe_mac_info { u32 link_attach_type; u32 link_mode_select; bool link_settings_loaded; + bool autoneg; }; struct ixgbe_eeprom_info {