diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_common.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 188 |
1 files changed, 120 insertions, 68 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b5c434b617b1..4456c235a44a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. + Copyright(c) 1999 - 2014 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -114,7 +114,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) s32 ret_val = 0; u32 reg = 0, reg_bp = 0; u16 reg_cu = 0; - bool got_lock = false; + bool locked = false; /* * Validate the requested mode. Strict IEEE mode does not allow @@ -139,11 +139,17 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) * we link at 10G, the 1G advertisement is harmless and vice versa. */ switch (hw->phy.media_type) { + case ixgbe_media_type_backplane: + /* some MAC's need RMW protection on AUTOC */ + ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); + if (!ret_val) + goto out; + + /* only backplane uses autoc so fall though */ case ixgbe_media_type_fiber_fixed: case ixgbe_media_type_fiber: - case ixgbe_media_type_backplane: reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); - reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC); + break; case ixgbe_media_type_copper: hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, @@ -240,27 +246,12 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) * LESM is on, likewise reset_pipeline requries the lock as * it also writes AUTOC. */ - if ((hw->mac.type == ixgbe_mac_82599EB) && - ixgbe_verify_lesm_fw_enabled_82599(hw)) { - ret_val = hw->mac.ops.acquire_swfw_sync(hw, - IXGBE_GSSR_MAC_CSR_SM); - if (ret_val) - goto out; - - got_lock = true; - } - - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp); - - if (hw->mac.type == ixgbe_mac_82599EB) - ixgbe_reset_pipeline_82599(hw); - - if (got_lock) - hw->mac.ops.release_swfw_sync(hw, - IXGBE_GSSR_MAC_CSR_SM); + ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); + if (ret_val) + goto out; } else if ((hw->phy.media_type == ixgbe_media_type_copper) && - ixgbe_device_supports_autoneg_fc(hw)) { + ixgbe_device_supports_autoneg_fc(hw)) { hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, reg_cu); } @@ -2437,6 +2428,55 @@ out: } /** + * ixgbe_pcie_timeout_poll - Return number of times to poll for completion + * @hw: pointer to hardware structure + * + * System-wide timeout range is encoded in PCIe Device Control2 register. + * + * Add 10% to specified maximum and return the number of times to poll for + * completion timeout, in units of 100 microsec. Never return less than + * 800 = 80 millisec. + **/ +static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) +{ + struct ixgbe_adapter *adapter = hw->back; + s16 devctl2; + u32 pollcnt; + + pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_CONTROL2, + &devctl2); + devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; + + switch (devctl2) { + case IXGBE_PCIDEVCTRL2_65_130ms: + pollcnt = 1300; /* 130 millisec */ + break; + case IXGBE_PCIDEVCTRL2_260_520ms: + pollcnt = 5200; /* 520 millisec */ + break; + case IXGBE_PCIDEVCTRL2_1_2s: + pollcnt = 20000; /* 2 sec */ + break; + case IXGBE_PCIDEVCTRL2_4_8s: + pollcnt = 80000; /* 8 sec */ + break; + case IXGBE_PCIDEVCTRL2_17_34s: + pollcnt = 34000; /* 34 sec */ + break; + case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ + case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ + case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ + case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ + default: + pollcnt = 800; /* 80 millisec minimum */ + break; + } + + /* add 10% to spec maximum */ + return (pollcnt * 11) / 10; +} + +/** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure * @@ -2447,16 +2487,16 @@ out: **/ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { - struct ixgbe_adapter *adapter = hw->back; s32 status = 0; - u32 i; + u32 i, poll; u16 value; /* Always set this bit to ensure any future transactions are blocked */ IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); /* Exit if master requests are blocked */ - if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) + if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || + ixgbe_removed(hw->hw_addr)) goto out; /* Poll for master request bit to clear */ @@ -2481,10 +2521,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) * Before proceeding, make sure that the PCIe block does not have * transactions pending. */ - for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { + poll = ixgbe_pcie_timeout_poll(hw); + for (i = 0; i < poll; i++) { udelay(100); - pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS, - &value); + value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS); + if (ixgbe_removed(hw->hw_addr)) + goto out; if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) goto out; } @@ -2564,6 +2606,35 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) } /** + * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read + * @hw: pointer to hardware structure + * @reg_val: Value we read from AUTOC + * @locked: bool to indicate whether the SW/FW lock should be taken. Never + * true in this the generic case. + * + * The default case requires no protection so just to the register read. + **/ +s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) +{ + *locked = false; + *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); + return 0; +} + +/** + * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write + * @hw: pointer to hardware structure + * @reg_val: value to write to AUTOC + * @locked: bool to indicate whether the SW/FW lock was already taken by + * previous read. + **/ +s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) +{ + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); + return 0; +} + +/** * ixgbe_disable_rx_buff_generic - Stops the receive data path * @hw: pointer to hardware structure * @@ -2641,6 +2712,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); s32 ret_val = 0; + bool locked = false; /* * Link must be up to auto-blink the LEDs; @@ -2649,28 +2721,19 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { - /* Need the SW/FW semaphore around AUTOC writes if 82599 and - * LESM is on. - */ - bool got_lock = false; - - if ((hw->mac.type == ixgbe_mac_82599EB) && - ixgbe_verify_lesm_fw_enabled_82599(hw)) { - ret_val = hw->mac.ops.acquire_swfw_sync(hw, - IXGBE_GSSR_MAC_CSR_SM); - if (ret_val) - goto out; + ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); + if (!ret_val) + goto out; - got_lock = true; - } autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); + + ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); + if (!ret_val) + goto out; + IXGBE_WRITE_FLUSH(hw); - if (got_lock) - hw->mac.ops.release_swfw_sync(hw, - IXGBE_GSSR_MAC_CSR_SM); usleep_range(10000, 20000); } @@ -2690,33 +2753,21 @@ out: **/ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) { - u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + u32 autoc_reg = 0; u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); s32 ret_val = 0; - bool got_lock = false; + bool locked = false; - /* Need the SW/FW semaphore around AUTOC writes if 82599 and - * LESM is on. - */ - if ((hw->mac.type == ixgbe_mac_82599EB) && - ixgbe_verify_lesm_fw_enabled_82599(hw)) { - ret_val = hw->mac.ops.acquire_swfw_sync(hw, - IXGBE_GSSR_MAC_CSR_SM); - if (ret_val) - goto out; - - got_lock = true; - } + ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); + if (!ret_val) + goto out; autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; - IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); - - if (hw->mac.type == ixgbe_mac_82599EB) - ixgbe_reset_pipeline_82599(hw); - if (got_lock) - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); + ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); + if (!ret_val) + goto out; led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg &= ~IXGBE_LED_BLINK(index); @@ -2817,7 +2868,6 @@ san_mac_addr_clr: **/ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) { - struct ixgbe_adapter *adapter = hw->back; u16 msix_count = 1; u16 max_msix_count; u16 pcie_offset; @@ -2836,7 +2886,9 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) return msix_count; } - pci_read_config_word(adapter->pdev, pcie_offset, &msix_count); + msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset); + if (ixgbe_removed(hw->hw_addr)) + msix_count = 0; msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; /* MSI-X count is zero-based in HW */ |