19ca4041bSJack F Vogel /****************************************************************************** 213705f88SJack F Vogel 3*758cc3dcSJack F Vogel Copyright (c) 2001-2014, Intel Corporation 413705f88SJack F Vogel All rights reserved. 513705f88SJack F Vogel 613705f88SJack F Vogel Redistribution and use in source and binary forms, with or without 713705f88SJack F Vogel modification, are permitted provided that the following conditions are met: 813705f88SJack F Vogel 913705f88SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 1013705f88SJack F Vogel this list of conditions and the following disclaimer. 1113705f88SJack F Vogel 1213705f88SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 1313705f88SJack F Vogel notice, this list of conditions and the following disclaimer in the 1413705f88SJack F Vogel documentation and/or other materials provided with the distribution. 1513705f88SJack F Vogel 1613705f88SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 1713705f88SJack F Vogel contributors may be used to endorse or promote products derived from 1813705f88SJack F Vogel this software without specific prior written permission. 1913705f88SJack F Vogel 2013705f88SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2113705f88SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213705f88SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2313705f88SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2413705f88SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2513705f88SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2613705f88SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2713705f88SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2813705f88SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2913705f88SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3013705f88SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 3113705f88SJack F Vogel 329ca4041bSJack F Vogel ******************************************************************************/ 3313705f88SJack F Vogel /*$FreeBSD$*/ 3413705f88SJack F Vogel 3513705f88SJack F Vogel #include "ixgbe_common.h" 361a4e3449SJack F Vogel #include "ixgbe_phy.h" 37fd75b91dSJack F Vogel #include "ixgbe_dcb.h" 38fd75b91dSJack F Vogel #include "ixgbe_dcb_82599.h" 3913705f88SJack F Vogel #include "ixgbe_api.h" 4013705f88SJack F Vogel 4113705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 4213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 4313705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 4413705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 4513705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 4613705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 4713705f88SJack F Vogel u16 count); 4813705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 4913705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5013705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5113705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 5213705f88SJack F Vogel 5313705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 542969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 552969bf0eSJack F Vogel u16 *san_mac_offset); 5685d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5785d0a26eSJack F Vogel u16 words, u16 *data); 5885d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5985d0a26eSJack F Vogel u16 words, u16 *data); 6085d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 6185d0a26eSJack F Vogel u16 offset); 6213705f88SJack F Vogel 6313705f88SJack F Vogel /** 649ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 659ca4041bSJack F Vogel * @hw: pointer to the hardware structure 6613705f88SJack F Vogel * 679ca4041bSJack F Vogel * Initialize the function pointers. 6813705f88SJack F Vogel **/ 699ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 7013705f88SJack F Vogel { 719ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 729ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 739ca4041bSJack F Vogel u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 7413705f88SJack F Vogel 752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_ops_generic"); 762969bf0eSJack F Vogel 7713705f88SJack F Vogel /* EEPROM */ 78*758cc3dcSJack F Vogel eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; 799ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 8085d0a26eSJack F Vogel if (eec & IXGBE_EEC_PRES) { 81*758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eerd_generic; 82*758cc3dcSJack F Vogel eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; 8385d0a26eSJack F Vogel } else { 84*758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; 8585d0a26eSJack F Vogel eeprom->ops.read_buffer = 86*758cc3dcSJack F Vogel ixgbe_read_eeprom_buffer_bit_bang_generic; 8785d0a26eSJack F Vogel } 88*758cc3dcSJack F Vogel eeprom->ops.write = ixgbe_write_eeprom_generic; 89*758cc3dcSJack F Vogel eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; 909ca4041bSJack F Vogel eeprom->ops.validate_checksum = 91*758cc3dcSJack F Vogel ixgbe_validate_eeprom_checksum_generic; 92*758cc3dcSJack F Vogel eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; 93*758cc3dcSJack F Vogel eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; 949ca4041bSJack F Vogel 959ca4041bSJack F Vogel /* MAC */ 96*758cc3dcSJack F Vogel mac->ops.init_hw = ixgbe_init_hw_generic; 979ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 98*758cc3dcSJack F Vogel mac->ops.start_hw = ixgbe_start_hw_generic; 99*758cc3dcSJack F Vogel mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; 1009ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 1011b6e0dbaSJack F Vogel mac->ops.get_supported_physical_layer = NULL; 102*758cc3dcSJack F Vogel mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; 103*758cc3dcSJack F Vogel mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; 104*758cc3dcSJack F Vogel mac->ops.stop_adapter = ixgbe_stop_adapter_generic; 105*758cc3dcSJack F Vogel mac->ops.get_bus_info = ixgbe_get_bus_info_generic; 106*758cc3dcSJack F Vogel mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; 107*758cc3dcSJack F Vogel mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; 108*758cc3dcSJack F Vogel mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; 109*758cc3dcSJack F Vogel mac->ops.prot_autoc_read = prot_autoc_read_generic; 110*758cc3dcSJack F Vogel mac->ops.prot_autoc_write = prot_autoc_write_generic; 1119ca4041bSJack F Vogel 1129ca4041bSJack F Vogel /* LEDs */ 113*758cc3dcSJack F Vogel mac->ops.led_on = ixgbe_led_on_generic; 114*758cc3dcSJack F Vogel mac->ops.led_off = ixgbe_led_off_generic; 115*758cc3dcSJack F Vogel mac->ops.blink_led_start = ixgbe_blink_led_start_generic; 116*758cc3dcSJack F Vogel mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; 1179ca4041bSJack F Vogel 11813705f88SJack F Vogel /* RAR, Multicast, VLAN */ 119*758cc3dcSJack F Vogel mac->ops.set_rar = ixgbe_set_rar_generic; 120*758cc3dcSJack F Vogel mac->ops.clear_rar = ixgbe_clear_rar_generic; 1210ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1229ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1235b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 124*758cc3dcSJack F Vogel mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; 125*758cc3dcSJack F Vogel mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; 126*758cc3dcSJack F Vogel mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; 127*758cc3dcSJack F Vogel mac->ops.enable_mc = ixgbe_enable_mc_generic; 128*758cc3dcSJack F Vogel mac->ops.disable_mc = ixgbe_disable_mc_generic; 1295b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1305b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 13185d0a26eSJack F Vogel mac->ops.set_vlvf = NULL; 1325b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 133*758cc3dcSJack F Vogel mac->ops.enable_rx = ixgbe_enable_rx_generic; 134*758cc3dcSJack F Vogel mac->ops.disable_rx = ixgbe_disable_rx_generic; 1359ca4041bSJack F Vogel 1360ac6dfecSJack F Vogel /* Flow Control */ 137*758cc3dcSJack F Vogel mac->ops.fc_enable = ixgbe_fc_enable_generic; 138*758cc3dcSJack F Vogel mac->ops.setup_fc = ixgbe_setup_fc_generic; 1399ca4041bSJack F Vogel 1409ca4041bSJack F Vogel /* Link */ 1419ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1429ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1439ca4041bSJack F Vogel mac->ops.check_link = NULL; 144fd75b91dSJack F Vogel mac->ops.dmac_config = NULL; 145fd75b91dSJack F Vogel mac->ops.dmac_update_tcs = NULL; 146fd75b91dSJack F Vogel mac->ops.dmac_config_tcs = NULL; 14713705f88SJack F Vogel 14813705f88SJack F Vogel return IXGBE_SUCCESS; 14913705f88SJack F Vogel } 15013705f88SJack F Vogel 15113705f88SJack F Vogel /** 152fd75b91dSJack F Vogel * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation 153fd75b91dSJack F Vogel * of flow control 154a621e3c8SJack F Vogel * @hw: pointer to hardware structure 155a621e3c8SJack F Vogel * 156fd75b91dSJack F Vogel * This function returns TRUE if the device supports flow control 157fd75b91dSJack F Vogel * autonegotiation, and FALSE if it does not. 158fd75b91dSJack F Vogel * 159a621e3c8SJack F Vogel **/ 160fd75b91dSJack F Vogel bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 161a621e3c8SJack F Vogel { 162fd75b91dSJack F Vogel bool supported = FALSE; 163fd75b91dSJack F Vogel ixgbe_link_speed speed; 164fd75b91dSJack F Vogel bool link_up; 165a621e3c8SJack F Vogel 166a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); 167a621e3c8SJack F Vogel 168fd75b91dSJack F Vogel switch (hw->phy.media_type) { 169fd75b91dSJack F Vogel case ixgbe_media_type_fiber_fixed: 170*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 171fd75b91dSJack F Vogel case ixgbe_media_type_fiber: 172fd75b91dSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 173fd75b91dSJack F Vogel /* if link is down, assume supported */ 174fd75b91dSJack F Vogel if (link_up) 175fd75b91dSJack F Vogel supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? 176fd75b91dSJack F Vogel TRUE : FALSE; 177fd75b91dSJack F Vogel else 178fd75b91dSJack F Vogel supported = TRUE; 179fd75b91dSJack F Vogel break; 180fd75b91dSJack F Vogel case ixgbe_media_type_backplane: 181fd75b91dSJack F Vogel supported = TRUE; 182fd75b91dSJack F Vogel break; 183fd75b91dSJack F Vogel case ixgbe_media_type_copper: 184fd75b91dSJack F Vogel /* only some copper devices support flow control autoneg */ 185a621e3c8SJack F Vogel switch (hw->device_id) { 186a621e3c8SJack F Vogel case IXGBE_DEV_ID_82599_T3_LOM: 1870ecc2ff0SJack F Vogel case IXGBE_DEV_ID_X540T: 188*758cc3dcSJack F Vogel case IXGBE_DEV_ID_X540T1: 189fd75b91dSJack F Vogel case IXGBE_DEV_ID_X540_BYPASS: 190*758cc3dcSJack F Vogel case IXGBE_DEV_ID_X550T: 191fd75b91dSJack F Vogel supported = TRUE; 192fd75b91dSJack F Vogel break; 193a621e3c8SJack F Vogel default: 194fd75b91dSJack F Vogel supported = FALSE; 195a621e3c8SJack F Vogel } 196fd75b91dSJack F Vogel default: 197fd75b91dSJack F Vogel break; 198fd75b91dSJack F Vogel } 199fd75b91dSJack F Vogel 200fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, 201fd75b91dSJack F Vogel "Device %x does not support flow control autoneg", 202fd75b91dSJack F Vogel hw->device_id); 203fd75b91dSJack F Vogel return supported; 204a621e3c8SJack F Vogel } 205a621e3c8SJack F Vogel 206a621e3c8SJack F Vogel /** 207*758cc3dcSJack F Vogel * ixgbe_setup_fc_generic - Set up flow control 208a621e3c8SJack F Vogel * @hw: pointer to hardware structure 209a621e3c8SJack F Vogel * 210a621e3c8SJack F Vogel * Called at init time to set up flow control. 211a621e3c8SJack F Vogel **/ 212*758cc3dcSJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 213a621e3c8SJack F Vogel { 214a621e3c8SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 215a621e3c8SJack F Vogel u32 reg = 0, reg_bp = 0; 216a621e3c8SJack F Vogel u16 reg_cu = 0; 217*758cc3dcSJack F Vogel bool locked = FALSE; 218a621e3c8SJack F Vogel 219*758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_fc_generic"); 220a621e3c8SJack F Vogel 221*758cc3dcSJack F Vogel /* Validate the requested mode */ 222a621e3c8SJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 223fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 224fd75b91dSJack F Vogel "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 225a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 226a621e3c8SJack F Vogel goto out; 227a621e3c8SJack F Vogel } 228a621e3c8SJack F Vogel 229a621e3c8SJack F Vogel /* 230a621e3c8SJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 231a621e3c8SJack F Vogel * default flow control setting, so we explicitly set it to full. 232a621e3c8SJack F Vogel */ 233a621e3c8SJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 234a621e3c8SJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 235a621e3c8SJack F Vogel 236a621e3c8SJack F Vogel /* 237a621e3c8SJack F Vogel * Set up the 1G and 10G flow control advertisement registers so the 238a621e3c8SJack F Vogel * HW will be able to do fc autoneg once the cable is plugged in. If 239a621e3c8SJack F Vogel * we link at 10G, the 1G advertisement is harmless and vice versa. 240a621e3c8SJack F Vogel */ 241a621e3c8SJack F Vogel switch (hw->phy.media_type) { 242a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 243*758cc3dcSJack F Vogel /* some MAC's need RMW protection on AUTOC */ 244*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 245*758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 246*758cc3dcSJack F Vogel goto out; 247*758cc3dcSJack F Vogel 248*758cc3dcSJack F Vogel /* only backplane uses autoc so fall though */ 249*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 250*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 251*758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 252a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 253*758cc3dcSJack F Vogel 254a621e3c8SJack F Vogel break; 255a621e3c8SJack F Vogel case ixgbe_media_type_copper: 256a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 257a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); 258a621e3c8SJack F Vogel break; 259a621e3c8SJack F Vogel default: 260a621e3c8SJack F Vogel break; 261a621e3c8SJack F Vogel } 262a621e3c8SJack F Vogel 263a621e3c8SJack F Vogel /* 264a621e3c8SJack F Vogel * The possible values of fc.requested_mode are: 265a621e3c8SJack F Vogel * 0: Flow control is completely disabled 266a621e3c8SJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 267a621e3c8SJack F Vogel * but not send pause frames). 268a621e3c8SJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 269a621e3c8SJack F Vogel * we do not support receiving pause frames). 270a621e3c8SJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 271a621e3c8SJack F Vogel * other: Invalid. 272a621e3c8SJack F Vogel */ 273a621e3c8SJack F Vogel switch (hw->fc.requested_mode) { 274a621e3c8SJack F Vogel case ixgbe_fc_none: 275a621e3c8SJack F Vogel /* Flow control completely disabled by software override. */ 276a621e3c8SJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 277a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 278a621e3c8SJack F Vogel reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 279a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE); 280a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 281a621e3c8SJack F Vogel reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 282a621e3c8SJack F Vogel break; 283a621e3c8SJack F Vogel case ixgbe_fc_tx_pause: 284a621e3c8SJack F Vogel /* 285a621e3c8SJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 286a621e3c8SJack F Vogel * disabled by software override. 287a621e3c8SJack F Vogel */ 288a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_ASM_PAUSE; 289a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 290a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 291a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 292a621e3c8SJack F Vogel reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 293a621e3c8SJack F Vogel } else if (hw->phy.media_type == ixgbe_media_type_copper) { 294a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_ASM_PAUSE; 295a621e3c8SJack F Vogel reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 296a621e3c8SJack F Vogel } 297a621e3c8SJack F Vogel break; 298a621e3c8SJack F Vogel case ixgbe_fc_rx_pause: 299a621e3c8SJack F Vogel /* 300a621e3c8SJack F Vogel * Rx Flow control is enabled and Tx Flow control is 301a621e3c8SJack F Vogel * disabled by software override. Since there really 302a621e3c8SJack F Vogel * isn't a way to advertise that we are capable of RX 303a621e3c8SJack F Vogel * Pause ONLY, we will advertise that we support both 304a621e3c8SJack F Vogel * symmetric and asymmetric Rx PAUSE, as such we fall 305a621e3c8SJack F Vogel * through to the fc_full statement. Later, we will 306a621e3c8SJack F Vogel * disable the adapter's ability to send PAUSE frames. 307a621e3c8SJack F Vogel */ 308a621e3c8SJack F Vogel case ixgbe_fc_full: 309a621e3c8SJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 310a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 311a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 312a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 313a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE; 314a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 315a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 316a621e3c8SJack F Vogel break; 317a621e3c8SJack F Vogel default: 318fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 319fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 320a621e3c8SJack F Vogel ret_val = IXGBE_ERR_CONFIG; 321a621e3c8SJack F Vogel goto out; 322a621e3c8SJack F Vogel break; 323a621e3c8SJack F Vogel } 324a621e3c8SJack F Vogel 325*758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_X540) { 326a621e3c8SJack F Vogel /* 327a621e3c8SJack F Vogel * Enable auto-negotiation between the MAC & PHY; 328a621e3c8SJack F Vogel * the MAC will advertise clause 37 flow control. 329a621e3c8SJack F Vogel */ 330a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 331a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 332a621e3c8SJack F Vogel 333a621e3c8SJack F Vogel /* Disable AN timeout */ 334a621e3c8SJack F Vogel if (hw->fc.strict_ieee) 335a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 336a621e3c8SJack F Vogel 337a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 338a621e3c8SJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 339a621e3c8SJack F Vogel } 340a621e3c8SJack F Vogel 341a621e3c8SJack F Vogel /* 342a621e3c8SJack F Vogel * AUTOC restart handles negotiation of 1G and 10G on backplane 343a621e3c8SJack F Vogel * and copper. There is no need to set the PCS1GCTL register. 344a621e3c8SJack F Vogel * 345a621e3c8SJack F Vogel */ 346a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 347a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_AN_RESTART; 348*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 349*758cc3dcSJack F Vogel if (ret_val) 3500ecc2ff0SJack F Vogel goto out; 351a621e3c8SJack F Vogel } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 352fd75b91dSJack F Vogel (ixgbe_device_supports_autoneg_fc(hw))) { 353a621e3c8SJack F Vogel hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 354a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); 355a621e3c8SJack F Vogel } 356a621e3c8SJack F Vogel 357*758cc3dcSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 358a621e3c8SJack F Vogel out: 359a621e3c8SJack F Vogel return ret_val; 360a621e3c8SJack F Vogel } 361a621e3c8SJack F Vogel 362a621e3c8SJack F Vogel /** 3639ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 36413705f88SJack F Vogel * @hw: pointer to hardware structure 36513705f88SJack F Vogel * 36613705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 36713705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 36813705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 36913705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 37013705f88SJack F Vogel **/ 37113705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 37213705f88SJack F Vogel { 373a621e3c8SJack F Vogel s32 ret_val; 37413705f88SJack F Vogel u32 ctrl_ext; 37513705f88SJack F Vogel 3762969bf0eSJack F Vogel DEBUGFUNC("ixgbe_start_hw_generic"); 3772969bf0eSJack F Vogel 37813705f88SJack F Vogel /* Set the media type */ 3799ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 38013705f88SJack F Vogel 3810ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 38213705f88SJack F Vogel 38313705f88SJack F Vogel /* Clear the VLAN filter table */ 3849ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 38513705f88SJack F Vogel 38613705f88SJack F Vogel /* Clear statistics registers */ 3879ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 38813705f88SJack F Vogel 38913705f88SJack F Vogel /* Set No Snoop Disable */ 39013705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 39113705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 39213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 3939ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 39413705f88SJack F Vogel 3950ac6dfecSJack F Vogel /* Setup flow control */ 396a621e3c8SJack F Vogel ret_val = ixgbe_setup_fc(hw); 397a621e3c8SJack F Vogel if (ret_val != IXGBE_SUCCESS) 398a621e3c8SJack F Vogel goto out; 3990ac6dfecSJack F Vogel 40013705f88SJack F Vogel /* Clear adapter stopped flag */ 40113705f88SJack F Vogel hw->adapter_stopped = FALSE; 40213705f88SJack F Vogel 403a621e3c8SJack F Vogel out: 404a621e3c8SJack F Vogel return ret_val; 4051a4e3449SJack F Vogel } 4061a4e3449SJack F Vogel 4071a4e3449SJack F Vogel /** 4081a4e3449SJack F Vogel * ixgbe_start_hw_gen2 - Init sequence for common device family 4091a4e3449SJack F Vogel * @hw: pointer to hw structure 4101a4e3449SJack F Vogel * 4111a4e3449SJack F Vogel * Performs the init sequence common to the second generation 4121a4e3449SJack F Vogel * of 10 GbE devices. 4131a4e3449SJack F Vogel * Devices in the second generation: 4141a4e3449SJack F Vogel * 82599 415182b3808SJack F Vogel * X540 4161a4e3449SJack F Vogel **/ 4171a4e3449SJack F Vogel s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 4181a4e3449SJack F Vogel { 4191a4e3449SJack F Vogel u32 i; 4201a4e3449SJack F Vogel u32 regval; 4211a4e3449SJack F Vogel 4221a4e3449SJack F Vogel /* Clear the rate limiters */ 4231a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4241a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 4251a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 4261a4e3449SJack F Vogel } 4271a4e3449SJack F Vogel IXGBE_WRITE_FLUSH(hw); 4281a4e3449SJack F Vogel 4291a4e3449SJack F Vogel /* Disable relaxed ordering */ 4301a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4311a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 432a621e3c8SJack F Vogel regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4331a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4341a4e3449SJack F Vogel } 4351a4e3449SJack F Vogel 4361a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4371a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 438a621e3c8SJack F Vogel regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | 439a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN); 4401a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4411a4e3449SJack F Vogel } 4421a4e3449SJack F Vogel 4431a4e3449SJack F Vogel return IXGBE_SUCCESS; 44413705f88SJack F Vogel } 44513705f88SJack F Vogel 44613705f88SJack F Vogel /** 44713705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 44813705f88SJack F Vogel * @hw: pointer to hardware structure 44913705f88SJack F Vogel * 4509ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 45113705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 45213705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 45313705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 45413705f88SJack F Vogel * disabled and uninitialized 45513705f88SJack F Vogel **/ 45613705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 45713705f88SJack F Vogel { 4581a4e3449SJack F Vogel s32 status; 4590ac6dfecSJack F Vogel 4602969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 4612969bf0eSJack F Vogel 46213705f88SJack F Vogel /* Reset the hardware */ 4630ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 46413705f88SJack F Vogel 4650ac6dfecSJack F Vogel if (status == IXGBE_SUCCESS) { 46613705f88SJack F Vogel /* Start the HW */ 4670ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 4680ac6dfecSJack F Vogel } 46913705f88SJack F Vogel 4700ac6dfecSJack F Vogel return status; 47113705f88SJack F Vogel } 47213705f88SJack F Vogel 47313705f88SJack F Vogel /** 47413705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 47513705f88SJack F Vogel * @hw: pointer to hardware structure 47613705f88SJack F Vogel * 47713705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 47813705f88SJack F Vogel * Statistics counters are clear on read. 47913705f88SJack F Vogel **/ 48013705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 48113705f88SJack F Vogel { 48213705f88SJack F Vogel u16 i = 0; 48313705f88SJack F Vogel 4842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 4852969bf0eSJack F Vogel 48613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 48713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 48813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 48913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 49013705f88SJack F Vogel for (i = 0; i < 8; i++) 49113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 49213705f88SJack F Vogel 49313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 49413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 49513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 49613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 49713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 4980ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 4990ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5000ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5010ac6dfecSJack F Vogel } else { 5021b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 50313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5040ac6dfecSJack F Vogel } 50513705f88SJack F Vogel 50613705f88SJack F Vogel for (i = 0; i < 8; i++) { 50713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 50813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5090ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5100ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5110ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5120ac6dfecSJack F Vogel } else { 5131b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 51413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 51513705f88SJack F Vogel } 5160ac6dfecSJack F Vogel } 5170ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5180ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5190ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 52013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 52113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 52213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 52313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 52413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 52513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 52613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 52713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 52813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 52913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 53013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 53113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 53213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 53313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 53485d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 53513705f88SJack F Vogel for (i = 0; i < 8; i++) 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 53713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 53813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 53913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 54013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 54113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 54213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 54513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 54613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 54713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 54813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 54913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 55013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 55113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 55213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 55313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 55413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 55513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 55613705f88SJack F Vogel for (i = 0; i < 16; i++) { 55713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 55813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 5591a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5601a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 5611a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 5621a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 5631a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 5641a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 5651a4e3449SJack F Vogel } else { 5661a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 56713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 56813705f88SJack F Vogel } 5691a4e3449SJack F Vogel } 5701a4e3449SJack F Vogel 571*758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 57285d0a26eSJack F Vogel if (hw->phy.id == 0) 57385d0a26eSJack F Vogel ixgbe_identify_phy(hw); 57485d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 57585d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 57685d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 57785d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 57885d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 57985d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 58085d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 58185d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 58285d0a26eSJack F Vogel } 58385d0a26eSJack F Vogel 5841a4e3449SJack F Vogel return IXGBE_SUCCESS; 5851a4e3449SJack F Vogel } 5861a4e3449SJack F Vogel 5871a4e3449SJack F Vogel /** 5881a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 5891a4e3449SJack F Vogel * @hw: pointer to hardware structure 5901a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 5911a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 5921a4e3449SJack F Vogel * 5931a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 5941a4e3449SJack F Vogel **/ 5951a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 5961a4e3449SJack F Vogel u32 pba_num_size) 5971a4e3449SJack F Vogel { 5981a4e3449SJack F Vogel s32 ret_val; 5991a4e3449SJack F Vogel u16 data; 6001a4e3449SJack F Vogel u16 pba_ptr; 6011a4e3449SJack F Vogel u16 offset; 6021a4e3449SJack F Vogel u16 length; 6031a4e3449SJack F Vogel 6041a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6051a4e3449SJack F Vogel 6061a4e3449SJack F Vogel if (pba_num == NULL) { 6071a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6081a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6091a4e3449SJack F Vogel } 6101a4e3449SJack F Vogel 6111a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6121a4e3449SJack F Vogel if (ret_val) { 6131a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6141a4e3449SJack F Vogel return ret_val; 6151a4e3449SJack F Vogel } 6161a4e3449SJack F Vogel 6171a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6181a4e3449SJack F Vogel if (ret_val) { 6191a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6201a4e3449SJack F Vogel return ret_val; 6211a4e3449SJack F Vogel } 6221a4e3449SJack F Vogel 6231a4e3449SJack F Vogel /* 6241a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6251a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6261a4e3449SJack F Vogel * and we can decode it into an ascii string 6271a4e3449SJack F Vogel */ 6281a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6291a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6301a4e3449SJack F Vogel 6311a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6321a4e3449SJack F Vogel if (pba_num_size < 11) { 6331a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6341a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6351a4e3449SJack F Vogel } 6361a4e3449SJack F Vogel 6371a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6381a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6391a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6401a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6411a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6421a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6431a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6441a4e3449SJack F Vogel pba_num[6] = '-'; 6451a4e3449SJack F Vogel pba_num[7] = 0; 6461a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6471a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6481a4e3449SJack F Vogel 6491a4e3449SJack F Vogel /* put a null character on the end of our string */ 6501a4e3449SJack F Vogel pba_num[10] = '\0'; 6511a4e3449SJack F Vogel 6521a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 6531a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 6541a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 6551a4e3449SJack F Vogel pba_num[offset] += '0'; 6561a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 6571a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 6581a4e3449SJack F Vogel } 6591a4e3449SJack F Vogel 6601a4e3449SJack F Vogel return IXGBE_SUCCESS; 6611a4e3449SJack F Vogel } 6621a4e3449SJack F Vogel 6631a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 6641a4e3449SJack F Vogel if (ret_val) { 6651a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6661a4e3449SJack F Vogel return ret_val; 6671a4e3449SJack F Vogel } 6681a4e3449SJack F Vogel 6691a4e3449SJack F Vogel if (length == 0xFFFF || length == 0) { 6701a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 6711a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 6721a4e3449SJack F Vogel } 6731a4e3449SJack F Vogel 6741a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 6751a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 6761a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6771a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6781a4e3449SJack F Vogel } 6791a4e3449SJack F Vogel 6801a4e3449SJack F Vogel /* trim pba length from start of string */ 6811a4e3449SJack F Vogel pba_ptr++; 6821a4e3449SJack F Vogel length--; 6831a4e3449SJack F Vogel 6841a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 6851a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 6861a4e3449SJack F Vogel if (ret_val) { 6871a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6881a4e3449SJack F Vogel return ret_val; 6891a4e3449SJack F Vogel } 6901a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 6911a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 6921a4e3449SJack F Vogel } 6931a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 6941a4e3449SJack F Vogel 6951a4e3449SJack F Vogel return IXGBE_SUCCESS; 6961a4e3449SJack F Vogel } 6971a4e3449SJack F Vogel 6981a4e3449SJack F Vogel /** 6991b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7009ca4041bSJack F Vogel * @hw: pointer to hardware structure 7019ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7029ca4041bSJack F Vogel * 7039ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7049ca4041bSJack F Vogel **/ 7059ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7069ca4041bSJack F Vogel { 7079ca4041bSJack F Vogel s32 ret_val; 7089ca4041bSJack F Vogel u16 data; 7099ca4041bSJack F Vogel 7109ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7119ca4041bSJack F Vogel 7129ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7139ca4041bSJack F Vogel if (ret_val) { 7149ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7159ca4041bSJack F Vogel return ret_val; 7161a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7171a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7181a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7199ca4041bSJack F Vogel } 7209ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7219ca4041bSJack F Vogel 7229ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7239ca4041bSJack F Vogel if (ret_val) { 7249ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7259ca4041bSJack F Vogel return ret_val; 7269ca4041bSJack F Vogel } 7279ca4041bSJack F Vogel *pba_num |= data; 7289ca4041bSJack F Vogel 7299ca4041bSJack F Vogel return IXGBE_SUCCESS; 7309ca4041bSJack F Vogel } 7319ca4041bSJack F Vogel 7329ca4041bSJack F Vogel /** 7330ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7340ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7350ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7360ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7370ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7380ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7390ecc2ff0SJack F Vogel * 7400ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7410ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7420ecc2ff0SJack F Vogel * 7430ecc2ff0SJack F Vogel **/ 7440ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7450ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7460ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7470ecc2ff0SJack F Vogel { 7480ecc2ff0SJack F Vogel s32 ret_val; 7490ecc2ff0SJack F Vogel u16 pba_block_size; 7500ecc2ff0SJack F Vogel 7510ecc2ff0SJack F Vogel if (pba == NULL) 7520ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 7530ecc2ff0SJack F Vogel 7540ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 7550ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 7560ecc2ff0SJack F Vogel &pba->word[0]); 7570ecc2ff0SJack F Vogel if (ret_val) 7580ecc2ff0SJack F Vogel return ret_val; 7590ecc2ff0SJack F Vogel } else { 7600ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 7610ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 7620ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 7630ecc2ff0SJack F Vogel } else { 7640ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 7650ecc2ff0SJack F Vogel } 7660ecc2ff0SJack F Vogel } 7670ecc2ff0SJack F Vogel 7680ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 7690ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 7700ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 7710ecc2ff0SJack F Vogel 7720ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 7730ecc2ff0SJack F Vogel eeprom_buf_size, 7740ecc2ff0SJack F Vogel &pba_block_size); 7750ecc2ff0SJack F Vogel if (ret_val) 7760ecc2ff0SJack F Vogel return ret_val; 7770ecc2ff0SJack F Vogel 7780ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 7790ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 7800ecc2ff0SJack F Vogel 7810ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 7820ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 7830ecc2ff0SJack F Vogel pba_block_size, 7840ecc2ff0SJack F Vogel pba->pba_block); 7850ecc2ff0SJack F Vogel if (ret_val) 7860ecc2ff0SJack F Vogel return ret_val; 7870ecc2ff0SJack F Vogel } else { 7880ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 789*758cc3dcSJack F Vogel pba_block_size)) { 7900ecc2ff0SJack F Vogel memcpy(pba->pba_block, 7910ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 7920ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 7930ecc2ff0SJack F Vogel } else { 7940ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 7950ecc2ff0SJack F Vogel } 7960ecc2ff0SJack F Vogel } 7970ecc2ff0SJack F Vogel } 7980ecc2ff0SJack F Vogel 7990ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8000ecc2ff0SJack F Vogel } 8010ecc2ff0SJack F Vogel 8020ecc2ff0SJack F Vogel /** 8030ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8040ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8050ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8060ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8070ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8080ecc2ff0SJack F Vogel * 8090ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8100ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8110ecc2ff0SJack F Vogel * 8120ecc2ff0SJack F Vogel **/ 8130ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8140ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8150ecc2ff0SJack F Vogel { 8160ecc2ff0SJack F Vogel s32 ret_val; 8170ecc2ff0SJack F Vogel 8180ecc2ff0SJack F Vogel if (pba == NULL) 8190ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8200ecc2ff0SJack F Vogel 8210ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8220ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8230ecc2ff0SJack F Vogel &pba->word[0]); 8240ecc2ff0SJack F Vogel if (ret_val) 8250ecc2ff0SJack F Vogel return ret_val; 8260ecc2ff0SJack F Vogel } else { 8270ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8280ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8290ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8300ecc2ff0SJack F Vogel } else { 8310ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8320ecc2ff0SJack F Vogel } 8330ecc2ff0SJack F Vogel } 8340ecc2ff0SJack F Vogel 8350ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8360ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8370ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8380ecc2ff0SJack F Vogel 8390ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8400ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8410ecc2ff0SJack F Vogel pba->pba_block[0], 8420ecc2ff0SJack F Vogel pba->pba_block); 8430ecc2ff0SJack F Vogel if (ret_val) 8440ecc2ff0SJack F Vogel return ret_val; 8450ecc2ff0SJack F Vogel } else { 8460ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8470ecc2ff0SJack F Vogel pba->pba_block[0])) { 8480ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8490ecc2ff0SJack F Vogel pba->pba_block, 8500ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 8510ecc2ff0SJack F Vogel } else { 8520ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8530ecc2ff0SJack F Vogel } 8540ecc2ff0SJack F Vogel } 8550ecc2ff0SJack F Vogel } 8560ecc2ff0SJack F Vogel 8570ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8580ecc2ff0SJack F Vogel } 8590ecc2ff0SJack F Vogel 8600ecc2ff0SJack F Vogel /** 8610ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 8620ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8630ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8640ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8650ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 8660ecc2ff0SJack F Vogel * 8670ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 8680ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 8690ecc2ff0SJack F Vogel * EEPROM device. 8700ecc2ff0SJack F Vogel * 8710ecc2ff0SJack F Vogel **/ 8720ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 8730ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 8740ecc2ff0SJack F Vogel { 8750ecc2ff0SJack F Vogel s32 ret_val; 8760ecc2ff0SJack F Vogel u16 pba_word[2]; 8770ecc2ff0SJack F Vogel u16 length; 8780ecc2ff0SJack F Vogel 8790ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 8800ecc2ff0SJack F Vogel 8810ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8820ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8830ecc2ff0SJack F Vogel &pba_word[0]); 8840ecc2ff0SJack F Vogel if (ret_val) 8850ecc2ff0SJack F Vogel return ret_val; 8860ecc2ff0SJack F Vogel } else { 8870ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8880ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8890ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8900ecc2ff0SJack F Vogel } else { 8910ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8920ecc2ff0SJack F Vogel } 8930ecc2ff0SJack F Vogel } 8940ecc2ff0SJack F Vogel 8950ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 8960ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8970ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 8980ecc2ff0SJack F Vogel &length); 8990ecc2ff0SJack F Vogel if (ret_val) 9000ecc2ff0SJack F Vogel return ret_val; 9010ecc2ff0SJack F Vogel } else { 9020ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9030ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9040ecc2ff0SJack F Vogel else 9050ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9060ecc2ff0SJack F Vogel } 9070ecc2ff0SJack F Vogel 9080ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9090ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9100ecc2ff0SJack F Vogel } else { 9110ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9120ecc2ff0SJack F Vogel length = 0; 9130ecc2ff0SJack F Vogel } 9140ecc2ff0SJack F Vogel 9150ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9160ecc2ff0SJack F Vogel *pba_block_size = length; 9170ecc2ff0SJack F Vogel 9180ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9190ecc2ff0SJack F Vogel } 9200ecc2ff0SJack F Vogel 9210ecc2ff0SJack F Vogel /** 92213705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 92313705f88SJack F Vogel * @hw: pointer to hardware structure 92413705f88SJack F Vogel * @mac_addr: Adapter MAC address 92513705f88SJack F Vogel * 92613705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 92713705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 92813705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 92913705f88SJack F Vogel **/ 93013705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 93113705f88SJack F Vogel { 93213705f88SJack F Vogel u32 rar_high; 93313705f88SJack F Vogel u32 rar_low; 93413705f88SJack F Vogel u16 i; 93513705f88SJack F Vogel 9362969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9372969bf0eSJack F Vogel 93813705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 93913705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 94013705f88SJack F Vogel 94113705f88SJack F Vogel for (i = 0; i < 4; i++) 94213705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 94313705f88SJack F Vogel 94413705f88SJack F Vogel for (i = 0; i < 2; i++) 94513705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 94613705f88SJack F Vogel 94713705f88SJack F Vogel return IXGBE_SUCCESS; 94813705f88SJack F Vogel } 94913705f88SJack F Vogel 95013705f88SJack F Vogel /** 951fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 95213705f88SJack F Vogel * @hw: pointer to hardware structure 953fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 95413705f88SJack F Vogel * 955fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 95613705f88SJack F Vogel **/ 957fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 95813705f88SJack F Vogel { 9591b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 9602969bf0eSJack F Vogel 961*758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 96213705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 96313705f88SJack F Vogel 96413705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 96513705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 96613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 96713705f88SJack F Vogel break; 96813705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 96913705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 97013705f88SJack F Vogel break; 97113705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 97213705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 97313705f88SJack F Vogel break; 97413705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 97513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 97613705f88SJack F Vogel break; 97713705f88SJack F Vogel default: 97813705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 97913705f88SJack F Vogel break; 98013705f88SJack F Vogel } 98113705f88SJack F Vogel 98213705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 98313705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 98413705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 98513705f88SJack F Vogel break; 98613705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 98713705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 98813705f88SJack F Vogel break; 989a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 990a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 991a621e3c8SJack F Vogel break; 99213705f88SJack F Vogel default: 99313705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 99413705f88SJack F Vogel break; 99513705f88SJack F Vogel } 99613705f88SJack F Vogel 9971b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 998fd75b91dSJack F Vogel } 999fd75b91dSJack F Vogel 1000fd75b91dSJack F Vogel /** 1001fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1002fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1003fd75b91dSJack F Vogel * 1004fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1005fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1006fd75b91dSJack F Vogel **/ 1007fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1008fd75b91dSJack F Vogel { 1009fd75b91dSJack F Vogel u16 link_status; 1010fd75b91dSJack F Vogel 1011fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1012fd75b91dSJack F Vogel 1013fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1014fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1015fd75b91dSJack F Vogel 1016fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10171b6e0dbaSJack F Vogel 101813705f88SJack F Vogel return IXGBE_SUCCESS; 101913705f88SJack F Vogel } 102013705f88SJack F Vogel 102113705f88SJack F Vogel /** 10221b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10231b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10241b6e0dbaSJack F Vogel * 10251b6e0dbaSJack F Vogel * Determines the LAN function id by reading memory-mapped registers 10261b6e0dbaSJack F Vogel * and swaps the port value if requested. 10271b6e0dbaSJack F Vogel **/ 10281b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10291b6e0dbaSJack F Vogel { 10301b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10311b6e0dbaSJack F Vogel u32 reg; 10321b6e0dbaSJack F Vogel 10332969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10342969bf0eSJack F Vogel 10351b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10361b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 10370ac6dfecSJack F Vogel bus->lan_id = bus->func; 10381b6e0dbaSJack F Vogel 10391b6e0dbaSJack F Vogel /* check for a port swap */ 10401b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); 10411b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10421b6e0dbaSJack F Vogel bus->func ^= 0x1; 10431b6e0dbaSJack F Vogel } 10441b6e0dbaSJack F Vogel 10451b6e0dbaSJack F Vogel /** 10469ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 104713705f88SJack F Vogel * @hw: pointer to hardware structure 104813705f88SJack F Vogel * 104913705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 105013705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 105113705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 105213705f88SJack F Vogel * state and should not touch the hardware. 105313705f88SJack F Vogel **/ 105413705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 105513705f88SJack F Vogel { 105613705f88SJack F Vogel u32 reg_val; 105713705f88SJack F Vogel u16 i; 105813705f88SJack F Vogel 10592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 10602969bf0eSJack F Vogel 106113705f88SJack F Vogel /* 106213705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 106313705f88SJack F Vogel * the hardware 106413705f88SJack F Vogel */ 106513705f88SJack F Vogel hw->adapter_stopped = TRUE; 106613705f88SJack F Vogel 106713705f88SJack F Vogel /* Disable the receive unit */ 1068*758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 106913705f88SJack F Vogel 107085d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 107113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 107213705f88SJack F Vogel 107385d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 107413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 107513705f88SJack F Vogel 107613705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 107785d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 107885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 107985d0a26eSJack F Vogel 108085d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 108185d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 108285d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 108385d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 108485d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 108585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 108613705f88SJack F Vogel } 108785d0a26eSJack F Vogel 108885d0a26eSJack F Vogel /* flush all queues disables */ 108985d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 109085d0a26eSJack F Vogel msec_delay(2); 109113705f88SJack F Vogel 10929ca4041bSJack F Vogel /* 10939ca4041bSJack F Vogel * Prevent the PCI-E bus from from hanging by disabling PCI-E master 10949ca4041bSJack F Vogel * access and verify no pending requests 10959ca4041bSJack F Vogel */ 109685d0a26eSJack F Vogel return ixgbe_disable_pcie_master(hw); 109713705f88SJack F Vogel } 109813705f88SJack F Vogel 109913705f88SJack F Vogel /** 110013705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 110113705f88SJack F Vogel * @hw: pointer to hardware structure 110213705f88SJack F Vogel * @index: led number to turn on 110313705f88SJack F Vogel **/ 110413705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 110513705f88SJack F Vogel { 110613705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 110713705f88SJack F Vogel 11082969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 11092969bf0eSJack F Vogel 111013705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 111113705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 111213705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 111313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 11149ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 111513705f88SJack F Vogel 111613705f88SJack F Vogel return IXGBE_SUCCESS; 111713705f88SJack F Vogel } 111813705f88SJack F Vogel 111913705f88SJack F Vogel /** 112013705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 112113705f88SJack F Vogel * @hw: pointer to hardware structure 112213705f88SJack F Vogel * @index: led number to turn off 112313705f88SJack F Vogel **/ 112413705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 112513705f88SJack F Vogel { 112613705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 112713705f88SJack F Vogel 11282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 11292969bf0eSJack F Vogel 113013705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 113113705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 113213705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 113313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 11349ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 113513705f88SJack F Vogel 113613705f88SJack F Vogel return IXGBE_SUCCESS; 113713705f88SJack F Vogel } 113813705f88SJack F Vogel 113913705f88SJack F Vogel /** 114013705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 114113705f88SJack F Vogel * @hw: pointer to hardware structure 114213705f88SJack F Vogel * 114313705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 114413705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 114513705f88SJack F Vogel **/ 114613705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 114713705f88SJack F Vogel { 114813705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 114913705f88SJack F Vogel u32 eec; 115013705f88SJack F Vogel u16 eeprom_size; 115113705f88SJack F Vogel 11522969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 11532969bf0eSJack F Vogel 115413705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 115513705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 11565b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 11575b7f4cedSJack F Vogel * tested value */ 11585b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 115985d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 116085d0a26eSJack F Vogel eeprom->word_page_size = 0; 116113705f88SJack F Vogel 116213705f88SJack F Vogel /* 116313705f88SJack F Vogel * Check for EEPROM present first. 116413705f88SJack F Vogel * If not present leave as none 116513705f88SJack F Vogel */ 116613705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 116713705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 116813705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 116913705f88SJack F Vogel 117013705f88SJack F Vogel /* 117113705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 117213705f88SJack F Vogel * change if a future EEPROM is not SPI. 117313705f88SJack F Vogel */ 117413705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 117513705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 117613705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 117785d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 117813705f88SJack F Vogel } 117913705f88SJack F Vogel 118013705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 118113705f88SJack F Vogel eeprom->address_bits = 16; 118213705f88SJack F Vogel else 118313705f88SJack F Vogel eeprom->address_bits = 8; 118413705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 118513705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 118613705f88SJack F Vogel eeprom->address_bits); 118713705f88SJack F Vogel } 118813705f88SJack F Vogel 118913705f88SJack F Vogel return IXGBE_SUCCESS; 119013705f88SJack F Vogel } 119113705f88SJack F Vogel 119213705f88SJack F Vogel /** 119385d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 119485d0a26eSJack F Vogel * @hw: pointer to hardware structure 119585d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 119685d0a26eSJack F Vogel * @words: number of word(s) 119785d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 119885d0a26eSJack F Vogel * 119985d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 120085d0a26eSJack F Vogel **/ 120185d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 120285d0a26eSJack F Vogel u16 words, u16 *data) 120385d0a26eSJack F Vogel { 120485d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 120585d0a26eSJack F Vogel u16 i, count; 120685d0a26eSJack F Vogel 120785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 120885d0a26eSJack F Vogel 120985d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 121085d0a26eSJack F Vogel 121185d0a26eSJack F Vogel if (words == 0) { 121285d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 121385d0a26eSJack F Vogel goto out; 121485d0a26eSJack F Vogel } 121585d0a26eSJack F Vogel 121685d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 121785d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 121885d0a26eSJack F Vogel goto out; 121985d0a26eSJack F Vogel } 122085d0a26eSJack F Vogel 122185d0a26eSJack F Vogel /* 122285d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 122385d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 122485d0a26eSJack F Vogel */ 122585d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 122685d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 122785d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 122885d0a26eSJack F Vogel 122985d0a26eSJack F Vogel /* 123085d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 123185d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 123285d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 123385d0a26eSJack F Vogel */ 123485d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 123585d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 123685d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 123785d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 123885d0a26eSJack F Vogel count, &data[i]); 123985d0a26eSJack F Vogel 124085d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 124185d0a26eSJack F Vogel break; 124285d0a26eSJack F Vogel } 124385d0a26eSJack F Vogel 124485d0a26eSJack F Vogel out: 124585d0a26eSJack F Vogel return status; 124685d0a26eSJack F Vogel } 124785d0a26eSJack F Vogel 124885d0a26eSJack F Vogel /** 124985d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 125013705f88SJack F Vogel * @hw: pointer to hardware structure 125113705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 125285d0a26eSJack F Vogel * @words: number of word(s) 125385d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 125413705f88SJack F Vogel * 125513705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 125613705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 125713705f88SJack F Vogel **/ 125885d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 125985d0a26eSJack F Vogel u16 words, u16 *data) 126013705f88SJack F Vogel { 126113705f88SJack F Vogel s32 status; 126285d0a26eSJack F Vogel u16 word; 126385d0a26eSJack F Vogel u16 page_size; 126485d0a26eSJack F Vogel u16 i; 126513705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 126613705f88SJack F Vogel 126785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 12689ca4041bSJack F Vogel 126913705f88SJack F Vogel /* Prepare the EEPROM for writing */ 127013705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 127113705f88SJack F Vogel 127213705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 127313705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 127413705f88SJack F Vogel ixgbe_release_eeprom(hw); 127513705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 127613705f88SJack F Vogel } 127713705f88SJack F Vogel } 127813705f88SJack F Vogel 127913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 128085d0a26eSJack F Vogel for (i = 0; i < words; i++) { 128113705f88SJack F Vogel ixgbe_standby_eeprom(hw); 128213705f88SJack F Vogel 128313705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 128485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 128585d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 128613705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 128713705f88SJack F Vogel 128813705f88SJack F Vogel ixgbe_standby_eeprom(hw); 128913705f88SJack F Vogel 129013705f88SJack F Vogel /* 129185d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 129285d0a26eSJack F Vogel * in the opcode 129313705f88SJack F Vogel */ 129485d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 129585d0a26eSJack F Vogel ((offset + i) >= 128)) 129613705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 129713705f88SJack F Vogel 129813705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 129913705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 130013705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 130185d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 130213705f88SJack F Vogel hw->eeprom.address_bits); 130313705f88SJack F Vogel 130485d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 130513705f88SJack F Vogel 130685d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 130785d0a26eSJack F Vogel do { 130885d0a26eSJack F Vogel word = data[i]; 130985d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 131085d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 131185d0a26eSJack F Vogel 131285d0a26eSJack F Vogel if (page_size == 0) 131385d0a26eSJack F Vogel break; 131485d0a26eSJack F Vogel 131585d0a26eSJack F Vogel /* do not wrap around page */ 131685d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 131785d0a26eSJack F Vogel (page_size - 1)) 131885d0a26eSJack F Vogel break; 131985d0a26eSJack F Vogel } while (++i < words); 132085d0a26eSJack F Vogel 132185d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 132285d0a26eSJack F Vogel msec_delay(10); 132385d0a26eSJack F Vogel } 132413705f88SJack F Vogel /* Done with writing - release the EEPROM */ 132513705f88SJack F Vogel ixgbe_release_eeprom(hw); 132613705f88SJack F Vogel } 132713705f88SJack F Vogel 132885d0a26eSJack F Vogel return status; 132985d0a26eSJack F Vogel } 133085d0a26eSJack F Vogel 133185d0a26eSJack F Vogel /** 133285d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 133385d0a26eSJack F Vogel * @hw: pointer to hardware structure 133485d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 133585d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 133685d0a26eSJack F Vogel * 133785d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 133885d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 133985d0a26eSJack F Vogel **/ 134085d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 134185d0a26eSJack F Vogel { 134285d0a26eSJack F Vogel s32 status; 134385d0a26eSJack F Vogel 134485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 134585d0a26eSJack F Vogel 134685d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 134785d0a26eSJack F Vogel 134885d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 134985d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 135085d0a26eSJack F Vogel goto out; 135185d0a26eSJack F Vogel } 135285d0a26eSJack F Vogel 135385d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 135485d0a26eSJack F Vogel 13559ca4041bSJack F Vogel out: 135613705f88SJack F Vogel return status; 135713705f88SJack F Vogel } 135813705f88SJack F Vogel 135913705f88SJack F Vogel /** 136085d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 136185d0a26eSJack F Vogel * @hw: pointer to hardware structure 136285d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 136385d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 136485d0a26eSJack F Vogel * @words: number of word(s) 136585d0a26eSJack F Vogel * 136685d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 136785d0a26eSJack F Vogel **/ 136885d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 136985d0a26eSJack F Vogel u16 words, u16 *data) 137085d0a26eSJack F Vogel { 137185d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 137285d0a26eSJack F Vogel u16 i, count; 137385d0a26eSJack F Vogel 137485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 137585d0a26eSJack F Vogel 137685d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 137785d0a26eSJack F Vogel 137885d0a26eSJack F Vogel if (words == 0) { 137985d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 138085d0a26eSJack F Vogel goto out; 138185d0a26eSJack F Vogel } 138285d0a26eSJack F Vogel 138385d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 138485d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 138585d0a26eSJack F Vogel goto out; 138685d0a26eSJack F Vogel } 138785d0a26eSJack F Vogel 138885d0a26eSJack F Vogel /* 138985d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 139085d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 139185d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 139285d0a26eSJack F Vogel */ 139385d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 139485d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 139585d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 139685d0a26eSJack F Vogel 139785d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 139885d0a26eSJack F Vogel count, &data[i]); 139985d0a26eSJack F Vogel 140085d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 140185d0a26eSJack F Vogel break; 140285d0a26eSJack F Vogel } 140385d0a26eSJack F Vogel 140485d0a26eSJack F Vogel out: 140585d0a26eSJack F Vogel return status; 140685d0a26eSJack F Vogel } 140785d0a26eSJack F Vogel 140885d0a26eSJack F Vogel /** 140985d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 141085d0a26eSJack F Vogel * @hw: pointer to hardware structure 141185d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 141285d0a26eSJack F Vogel * @words: number of word(s) 141385d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 141485d0a26eSJack F Vogel * 141585d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 141685d0a26eSJack F Vogel **/ 141785d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 141885d0a26eSJack F Vogel u16 words, u16 *data) 141985d0a26eSJack F Vogel { 142085d0a26eSJack F Vogel s32 status; 142185d0a26eSJack F Vogel u16 word_in; 142285d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 142385d0a26eSJack F Vogel u16 i; 142485d0a26eSJack F Vogel 142585d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 142685d0a26eSJack F Vogel 142785d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 142885d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 142985d0a26eSJack F Vogel 143085d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 143185d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 143285d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 143385d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 143485d0a26eSJack F Vogel } 143585d0a26eSJack F Vogel } 143685d0a26eSJack F Vogel 143785d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 143885d0a26eSJack F Vogel for (i = 0; i < words; i++) { 143985d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 144085d0a26eSJack F Vogel /* 144185d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 144285d0a26eSJack F Vogel * in the opcode 144385d0a26eSJack F Vogel */ 144485d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 144585d0a26eSJack F Vogel ((offset + i) >= 128)) 144685d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 144785d0a26eSJack F Vogel 144885d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 144985d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 145085d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 145185d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 145285d0a26eSJack F Vogel hw->eeprom.address_bits); 145385d0a26eSJack F Vogel 145485d0a26eSJack F Vogel /* Read the data. */ 145585d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 145685d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 145785d0a26eSJack F Vogel } 145885d0a26eSJack F Vogel 145985d0a26eSJack F Vogel /* End this read operation */ 146085d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 146185d0a26eSJack F Vogel } 146285d0a26eSJack F Vogel 146385d0a26eSJack F Vogel return status; 146485d0a26eSJack F Vogel } 146585d0a26eSJack F Vogel 146685d0a26eSJack F Vogel /** 146713705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 146813705f88SJack F Vogel * @hw: pointer to hardware structure 146913705f88SJack F Vogel * @offset: offset within the EEPROM to be read 147013705f88SJack F Vogel * @data: read 16 bit value from EEPROM 147113705f88SJack F Vogel * 147213705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 147313705f88SJack F Vogel **/ 147413705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147513705f88SJack F Vogel u16 *data) 147613705f88SJack F Vogel { 147713705f88SJack F Vogel s32 status; 147813705f88SJack F Vogel 14792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 14802969bf0eSJack F Vogel 14819ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 14829ca4041bSJack F Vogel 14839ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 14849ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 14859ca4041bSJack F Vogel goto out; 14869ca4041bSJack F Vogel } 14879ca4041bSJack F Vogel 148885d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 148913705f88SJack F Vogel 149085d0a26eSJack F Vogel out: 149185d0a26eSJack F Vogel return status; 149285d0a26eSJack F Vogel } 149385d0a26eSJack F Vogel 149485d0a26eSJack F Vogel /** 149585d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 149685d0a26eSJack F Vogel * @hw: pointer to hardware structure 149785d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 149885d0a26eSJack F Vogel * @words: number of word(s) 149985d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 150085d0a26eSJack F Vogel * 150185d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 150285d0a26eSJack F Vogel **/ 150385d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 150485d0a26eSJack F Vogel u16 words, u16 *data) 150585d0a26eSJack F Vogel { 150685d0a26eSJack F Vogel u32 eerd; 150785d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 150885d0a26eSJack F Vogel u32 i; 150985d0a26eSJack F Vogel 151085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 151185d0a26eSJack F Vogel 151285d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 151385d0a26eSJack F Vogel 151485d0a26eSJack F Vogel if (words == 0) { 151585d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1516fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 151785d0a26eSJack F Vogel goto out; 151885d0a26eSJack F Vogel } 151985d0a26eSJack F Vogel 152085d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 152113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1522fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 152385d0a26eSJack F Vogel goto out; 152413705f88SJack F Vogel } 152513705f88SJack F Vogel 152685d0a26eSJack F Vogel for (i = 0; i < words; i++) { 15270ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 152885d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 152985d0a26eSJack F Vogel 153085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 153185d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 153285d0a26eSJack F Vogel 153313705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 153485d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 153585d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 153685d0a26eSJack F Vogel } else { 153785d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 153885d0a26eSJack F Vogel goto out; 153985d0a26eSJack F Vogel } 154085d0a26eSJack F Vogel } 154185d0a26eSJack F Vogel out: 154285d0a26eSJack F Vogel return status; 154385d0a26eSJack F Vogel } 154485d0a26eSJack F Vogel 154585d0a26eSJack F Vogel /** 154685d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 154785d0a26eSJack F Vogel * @hw: pointer to hardware structure 154885d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 154985d0a26eSJack F Vogel * 155085d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 155185d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 155285d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 155385d0a26eSJack F Vogel **/ 155485d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 155585d0a26eSJack F Vogel u16 offset) 155685d0a26eSJack F Vogel { 155785d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 155885d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 155985d0a26eSJack F Vogel u16 i; 156085d0a26eSJack F Vogel 156185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 156285d0a26eSJack F Vogel 156385d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 156485d0a26eSJack F Vogel data[i] = i; 156585d0a26eSJack F Vogel 156685d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 156785d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 156885d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 156985d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 157085d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 157185d0a26eSJack F Vogel goto out; 157285d0a26eSJack F Vogel 157385d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 157485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 157585d0a26eSJack F Vogel goto out; 157613705f88SJack F Vogel 157713705f88SJack F Vogel /* 157885d0a26eSJack F Vogel * When writing in burst more than the actual page size 157985d0a26eSJack F Vogel * EEPROM address wraps around current page. 158013705f88SJack F Vogel */ 158185d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 158213705f88SJack F Vogel 158385d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 158485d0a26eSJack F Vogel hw->eeprom.word_page_size); 15859ca4041bSJack F Vogel out: 158613705f88SJack F Vogel return status; 158713705f88SJack F Vogel } 158813705f88SJack F Vogel 158913705f88SJack F Vogel /** 15902969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 159113705f88SJack F Vogel * @hw: pointer to hardware structure 159213705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 159313705f88SJack F Vogel * @data: word read from the EEPROM 159413705f88SJack F Vogel * 159513705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 159613705f88SJack F Vogel **/ 15972969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 159813705f88SJack F Vogel { 159985d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 160085d0a26eSJack F Vogel } 160113705f88SJack F Vogel 160285d0a26eSJack F Vogel /** 160385d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 160485d0a26eSJack F Vogel * @hw: pointer to hardware structure 160585d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 160685d0a26eSJack F Vogel * @words: number of word(s) 160785d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 160885d0a26eSJack F Vogel * 160985d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 161085d0a26eSJack F Vogel **/ 161185d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 161285d0a26eSJack F Vogel u16 words, u16 *data) 161385d0a26eSJack F Vogel { 161485d0a26eSJack F Vogel u32 eewr; 161585d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161685d0a26eSJack F Vogel u16 i; 161785d0a26eSJack F Vogel 161885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 16192969bf0eSJack F Vogel 16209ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 16219ca4041bSJack F Vogel 162285d0a26eSJack F Vogel if (words == 0) { 162385d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1624fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162585d0a26eSJack F Vogel goto out; 162685d0a26eSJack F Vogel } 162785d0a26eSJack F Vogel 16289ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 16299ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1630fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 16319ca4041bSJack F Vogel goto out; 16329ca4041bSJack F Vogel } 16339ca4041bSJack F Vogel 163485d0a26eSJack F Vogel for (i = 0; i < words; i++) { 163585d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163685d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 16372969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163813705f88SJack F Vogel 163985d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 164085d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 164185d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 164285d0a26eSJack F Vogel goto out; 164385d0a26eSJack F Vogel } 164413705f88SJack F Vogel 164585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 164685d0a26eSJack F Vogel 164785d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 164885d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 164985d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 165085d0a26eSJack F Vogel goto out; 165185d0a26eSJack F Vogel } 165285d0a26eSJack F Vogel } 165313705f88SJack F Vogel 16549ca4041bSJack F Vogel out: 165513705f88SJack F Vogel return status; 165613705f88SJack F Vogel } 165713705f88SJack F Vogel 165813705f88SJack F Vogel /** 16591a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 16601a4e3449SJack F Vogel * @hw: pointer to hardware structure 16611a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 16621a4e3449SJack F Vogel * @data: word write to the EEPROM 16631a4e3449SJack F Vogel * 16641a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 16651a4e3449SJack F Vogel **/ 16661a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 16671a4e3449SJack F Vogel { 166885d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 16691a4e3449SJack F Vogel } 16701a4e3449SJack F Vogel 16711a4e3449SJack F Vogel /** 16722969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 167313705f88SJack F Vogel * @hw: pointer to hardware structure 16742969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 167513705f88SJack F Vogel * 16762969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 16772969bf0eSJack F Vogel * read or write is done respectively. 167813705f88SJack F Vogel **/ 16792969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 168013705f88SJack F Vogel { 168113705f88SJack F Vogel u32 i; 168213705f88SJack F Vogel u32 reg; 168313705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 168413705f88SJack F Vogel 16852969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 16862969bf0eSJack F Vogel 16872969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 16882969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 168913705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 16902969bf0eSJack F Vogel else 16912969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 16922969bf0eSJack F Vogel 16932969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 169413705f88SJack F Vogel status = IXGBE_SUCCESS; 169513705f88SJack F Vogel break; 169613705f88SJack F Vogel } 169713705f88SJack F Vogel usec_delay(5); 169813705f88SJack F Vogel } 1699fd75b91dSJack F Vogel 1700fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1701fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1702fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1703fd75b91dSJack F Vogel 170413705f88SJack F Vogel return status; 170513705f88SJack F Vogel } 170613705f88SJack F Vogel 170713705f88SJack F Vogel /** 170813705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 170913705f88SJack F Vogel * @hw: pointer to hardware structure 171013705f88SJack F Vogel * 171113705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 171213705f88SJack F Vogel * be called before issuing a command to the EEPROM. 171313705f88SJack F Vogel **/ 171413705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 171513705f88SJack F Vogel { 171613705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 171713705f88SJack F Vogel u32 eec; 171813705f88SJack F Vogel u32 i; 171913705f88SJack F Vogel 17202969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 17212969bf0eSJack F Vogel 172285d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 172385d0a26eSJack F Vogel != IXGBE_SUCCESS) 172413705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 172513705f88SJack F Vogel 172613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 172713705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 172813705f88SJack F Vogel 172913705f88SJack F Vogel /* Request EEPROM Access */ 173013705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 173113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 173213705f88SJack F Vogel 173313705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 173413705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 173513705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 173613705f88SJack F Vogel break; 173713705f88SJack F Vogel usec_delay(5); 173813705f88SJack F Vogel } 173913705f88SJack F Vogel 17409ca4041bSJack F Vogel /* Release if grant not acquired */ 174113705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 174213705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 174313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 174413705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 174513705f88SJack F Vogel 174685d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 174713705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 174813705f88SJack F Vogel } 174913705f88SJack F Vogel 175013705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 175113705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 175213705f88SJack F Vogel /* Clear CS and SK */ 175313705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 175413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 175513705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 175613705f88SJack F Vogel usec_delay(1); 175713705f88SJack F Vogel } 17581a4e3449SJack F Vogel } 175913705f88SJack F Vogel return status; 176013705f88SJack F Vogel } 176113705f88SJack F Vogel 176213705f88SJack F Vogel /** 176313705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 176413705f88SJack F Vogel * @hw: pointer to hardware structure 176513705f88SJack F Vogel * 176613705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 176713705f88SJack F Vogel **/ 176813705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 176913705f88SJack F Vogel { 177013705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1771d8602bb9SJack F Vogel u32 timeout = 2000; 177213705f88SJack F Vogel u32 i; 177313705f88SJack F Vogel u32 swsm; 177413705f88SJack F Vogel 17752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 17762969bf0eSJack F Vogel 17771a4e3449SJack F Vogel 177813705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 177913705f88SJack F Vogel for (i = 0; i < timeout; i++) { 178013705f88SJack F Vogel /* 178113705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 178213705f88SJack F Vogel * set and we have the semaphore 178313705f88SJack F Vogel */ 178413705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 178513705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 178613705f88SJack F Vogel status = IXGBE_SUCCESS; 178713705f88SJack F Vogel break; 178813705f88SJack F Vogel } 17890ac6dfecSJack F Vogel usec_delay(50); 179013705f88SJack F Vogel } 179113705f88SJack F Vogel 179285d0a26eSJack F Vogel if (i == timeout) { 179385d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 179485d0a26eSJack F Vogel "not granted.\n"); 179585d0a26eSJack F Vogel /* 179685d0a26eSJack F Vogel * this release is particularly important because our attempts 179785d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 179885d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 179985d0a26eSJack F Vogel * bits to free the driver to make progress 180085d0a26eSJack F Vogel */ 180185d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 180285d0a26eSJack F Vogel 180385d0a26eSJack F Vogel usec_delay(50); 180485d0a26eSJack F Vogel /* 180585d0a26eSJack F Vogel * one last try 180685d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 180785d0a26eSJack F Vogel * set and we have the semaphore 180885d0a26eSJack F Vogel */ 180985d0a26eSJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 181085d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 181185d0a26eSJack F Vogel status = IXGBE_SUCCESS; 181285d0a26eSJack F Vogel } 181385d0a26eSJack F Vogel 181413705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 181513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 181613705f88SJack F Vogel for (i = 0; i < timeout; i++) { 181713705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 181813705f88SJack F Vogel 181913705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 182013705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 182113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 182213705f88SJack F Vogel 182313705f88SJack F Vogel /* 182413705f88SJack F Vogel * If we set the bit successfully then we got the 182513705f88SJack F Vogel * semaphore. 182613705f88SJack F Vogel */ 182713705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 182813705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 182913705f88SJack F Vogel break; 183013705f88SJack F Vogel 183113705f88SJack F Vogel usec_delay(50); 183213705f88SJack F Vogel } 183313705f88SJack F Vogel 183413705f88SJack F Vogel /* 183513705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 183613705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 183713705f88SJack F Vogel */ 183813705f88SJack F Vogel if (i >= timeout) { 1839fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1840fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 184113705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 184213705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 184313705f88SJack F Vogel } 18440ac6dfecSJack F Vogel } else { 1845fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1846fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 18470ac6dfecSJack F Vogel "not granted.\n"); 184813705f88SJack F Vogel } 184913705f88SJack F Vogel 185013705f88SJack F Vogel return status; 185113705f88SJack F Vogel } 185213705f88SJack F Vogel 185313705f88SJack F Vogel /** 185413705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 185513705f88SJack F Vogel * @hw: pointer to hardware structure 185613705f88SJack F Vogel * 185713705f88SJack F Vogel * This function clears hardware semaphore bits. 185813705f88SJack F Vogel **/ 185913705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 186013705f88SJack F Vogel { 186113705f88SJack F Vogel u32 swsm; 186213705f88SJack F Vogel 18632969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 18642969bf0eSJack F Vogel 186513705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 186613705f88SJack F Vogel 186713705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 186813705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 186913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 18709ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 187113705f88SJack F Vogel } 187213705f88SJack F Vogel 187313705f88SJack F Vogel /** 187413705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 187513705f88SJack F Vogel * @hw: pointer to hardware structure 187613705f88SJack F Vogel **/ 187713705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 187813705f88SJack F Vogel { 187913705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 188013705f88SJack F Vogel u16 i; 188113705f88SJack F Vogel u8 spi_stat_reg; 188213705f88SJack F Vogel 18832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 18842969bf0eSJack F Vogel 188513705f88SJack F Vogel /* 188613705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 188713705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 188813705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 188913705f88SJack F Vogel * 5 milliseconds, then error out. 189013705f88SJack F Vogel */ 189113705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 189213705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 189313705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 189413705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 189513705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 189613705f88SJack F Vogel break; 189713705f88SJack F Vogel 189813705f88SJack F Vogel usec_delay(5); 189913705f88SJack F Vogel ixgbe_standby_eeprom(hw); 190013705f88SJack F Vogel }; 190113705f88SJack F Vogel 190213705f88SJack F Vogel /* 190313705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 190413705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 190513705f88SJack F Vogel */ 190613705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 190713705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 190813705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 190913705f88SJack F Vogel } 191013705f88SJack F Vogel 191113705f88SJack F Vogel return status; 191213705f88SJack F Vogel } 191313705f88SJack F Vogel 191413705f88SJack F Vogel /** 191513705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 191613705f88SJack F Vogel * @hw: pointer to hardware structure 191713705f88SJack F Vogel **/ 191813705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 191913705f88SJack F Vogel { 192013705f88SJack F Vogel u32 eec; 192113705f88SJack F Vogel 19222969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 19232969bf0eSJack F Vogel 192413705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 192513705f88SJack F Vogel 192613705f88SJack F Vogel /* Toggle CS to flush commands */ 192713705f88SJack F Vogel eec |= IXGBE_EEC_CS; 192813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 192913705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 193013705f88SJack F Vogel usec_delay(1); 193113705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 193213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 193313705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 193413705f88SJack F Vogel usec_delay(1); 193513705f88SJack F Vogel } 193613705f88SJack F Vogel 193713705f88SJack F Vogel /** 193813705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 193913705f88SJack F Vogel * @hw: pointer to hardware structure 194013705f88SJack F Vogel * @data: data to send to the EEPROM 194113705f88SJack F Vogel * @count: number of bits to shift out 194213705f88SJack F Vogel **/ 194313705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 194413705f88SJack F Vogel u16 count) 194513705f88SJack F Vogel { 194613705f88SJack F Vogel u32 eec; 194713705f88SJack F Vogel u32 mask; 194813705f88SJack F Vogel u32 i; 194913705f88SJack F Vogel 19502969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 19512969bf0eSJack F Vogel 195213705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 195313705f88SJack F Vogel 195413705f88SJack F Vogel /* 195513705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 195613705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 195713705f88SJack F Vogel */ 195813705f88SJack F Vogel mask = 0x01 << (count - 1); 195913705f88SJack F Vogel 196013705f88SJack F Vogel for (i = 0; i < count; i++) { 196113705f88SJack F Vogel /* 196213705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 196313705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 196413705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 196513705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 196613705f88SJack F Vogel * raising and then lowering the clock. 196713705f88SJack F Vogel */ 196813705f88SJack F Vogel if (data & mask) 196913705f88SJack F Vogel eec |= IXGBE_EEC_DI; 197013705f88SJack F Vogel else 197113705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 197213705f88SJack F Vogel 197313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 197413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 197513705f88SJack F Vogel 197613705f88SJack F Vogel usec_delay(1); 197713705f88SJack F Vogel 197813705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 197913705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 198013705f88SJack F Vogel 198113705f88SJack F Vogel /* 198213705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 198313705f88SJack F Vogel * EEPROM 198413705f88SJack F Vogel */ 198513705f88SJack F Vogel mask = mask >> 1; 198613705f88SJack F Vogel }; 198713705f88SJack F Vogel 198813705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 198913705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 199013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 199113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 199213705f88SJack F Vogel } 199313705f88SJack F Vogel 199413705f88SJack F Vogel /** 199513705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 199613705f88SJack F Vogel * @hw: pointer to hardware structure 199713705f88SJack F Vogel **/ 199813705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 199913705f88SJack F Vogel { 200013705f88SJack F Vogel u32 eec; 200113705f88SJack F Vogel u32 i; 200213705f88SJack F Vogel u16 data = 0; 200313705f88SJack F Vogel 20042969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 20052969bf0eSJack F Vogel 200613705f88SJack F Vogel /* 200713705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 200813705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 200913705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 201013705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 201113705f88SJack F Vogel * "DI" bit should always be clear. 201213705f88SJack F Vogel */ 201313705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 201413705f88SJack F Vogel 201513705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 201613705f88SJack F Vogel 201713705f88SJack F Vogel for (i = 0; i < count; i++) { 201813705f88SJack F Vogel data = data << 1; 201913705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 202013705f88SJack F Vogel 202113705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 202213705f88SJack F Vogel 202313705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 202413705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 202513705f88SJack F Vogel data |= 1; 202613705f88SJack F Vogel 202713705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 202813705f88SJack F Vogel } 202913705f88SJack F Vogel 203013705f88SJack F Vogel return data; 203113705f88SJack F Vogel } 203213705f88SJack F Vogel 203313705f88SJack F Vogel /** 203413705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 203513705f88SJack F Vogel * @hw: pointer to hardware structure 203613705f88SJack F Vogel * @eec: EEC register's current value 203713705f88SJack F Vogel **/ 203813705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 203913705f88SJack F Vogel { 20402969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 20412969bf0eSJack F Vogel 204213705f88SJack F Vogel /* 204313705f88SJack F Vogel * Raise the clock input to the EEPROM 204413705f88SJack F Vogel * (setting the SK bit), then delay 204513705f88SJack F Vogel */ 204613705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 204713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 204813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 204913705f88SJack F Vogel usec_delay(1); 205013705f88SJack F Vogel } 205113705f88SJack F Vogel 205213705f88SJack F Vogel /** 205313705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 205413705f88SJack F Vogel * @hw: pointer to hardware structure 205513705f88SJack F Vogel * @eecd: EECD's current value 205613705f88SJack F Vogel **/ 205713705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 205813705f88SJack F Vogel { 20592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 20602969bf0eSJack F Vogel 206113705f88SJack F Vogel /* 206213705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 206313705f88SJack F Vogel * delay 206413705f88SJack F Vogel */ 206513705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 206613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 206713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 206813705f88SJack F Vogel usec_delay(1); 206913705f88SJack F Vogel } 207013705f88SJack F Vogel 207113705f88SJack F Vogel /** 207213705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 207313705f88SJack F Vogel * @hw: pointer to hardware structure 207413705f88SJack F Vogel **/ 207513705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 207613705f88SJack F Vogel { 207713705f88SJack F Vogel u32 eec; 207813705f88SJack F Vogel 20792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 20802969bf0eSJack F Vogel 208113705f88SJack F Vogel eec = IXGBE_READ_REG(hw, IXGBE_EEC); 208213705f88SJack F Vogel 208313705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 208413705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 208513705f88SJack F Vogel 208613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 208713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 208813705f88SJack F Vogel 208913705f88SJack F Vogel usec_delay(1); 209013705f88SJack F Vogel 209113705f88SJack F Vogel /* Stop requesting EEPROM access */ 209213705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 209313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 209413705f88SJack F Vogel 209585d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2096d8602bb9SJack F Vogel 2097d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2098d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 209913705f88SJack F Vogel } 210013705f88SJack F Vogel 210113705f88SJack F Vogel /** 21022969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 210313705f88SJack F Vogel * @hw: pointer to hardware structure 2104*758cc3dcSJack F Vogel * 2105*758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 210613705f88SJack F Vogel **/ 2107*758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 210813705f88SJack F Vogel { 210913705f88SJack F Vogel u16 i; 211013705f88SJack F Vogel u16 j; 211113705f88SJack F Vogel u16 checksum = 0; 211213705f88SJack F Vogel u16 length = 0; 211313705f88SJack F Vogel u16 pointer = 0; 211413705f88SJack F Vogel u16 word = 0; 211513705f88SJack F Vogel 21162969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 21172969bf0eSJack F Vogel 211813705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 211913705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2120*758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 212113705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2122*758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 212313705f88SJack F Vogel } 212413705f88SJack F Vogel checksum += word; 212513705f88SJack F Vogel } 212613705f88SJack F Vogel 212713705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 212813705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2129*758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2130*758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2131*758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2132*758cc3dcSJack F Vogel } 213313705f88SJack F Vogel 2134*758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2135*758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2136*758cc3dcSJack F Vogel continue; 213713705f88SJack F Vogel 2138*758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2139*758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2140*758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2141*758cc3dcSJack F Vogel } 2142*758cc3dcSJack F Vogel 2143*758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2144*758cc3dcSJack F Vogel continue; 2145*758cc3dcSJack F Vogel 214613705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2147*758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2148*758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2149*758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2150*758cc3dcSJack F Vogel } 215113705f88SJack F Vogel checksum += word; 215213705f88SJack F Vogel } 215313705f88SJack F Vogel } 215413705f88SJack F Vogel 215513705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 215613705f88SJack F Vogel 2157*758cc3dcSJack F Vogel return (s32)checksum; 215813705f88SJack F Vogel } 215913705f88SJack F Vogel 216013705f88SJack F Vogel /** 216113705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 216213705f88SJack F Vogel * @hw: pointer to hardware structure 216313705f88SJack F Vogel * @checksum_val: calculated checksum 216413705f88SJack F Vogel * 216513705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 216613705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 216713705f88SJack F Vogel **/ 216813705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 216913705f88SJack F Vogel u16 *checksum_val) 217013705f88SJack F Vogel { 217113705f88SJack F Vogel s32 status; 217213705f88SJack F Vogel u16 checksum; 217313705f88SJack F Vogel u16 read_checksum = 0; 217413705f88SJack F Vogel 21752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 21762969bf0eSJack F Vogel 2177*758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 217813705f88SJack F Vogel * not continue or we could be in for a very long wait while every 217913705f88SJack F Vogel * EEPROM read fails 218013705f88SJack F Vogel */ 21819ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2182*758cc3dcSJack F Vogel if (status) { 2183*758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2184*758cc3dcSJack F Vogel return status; 2185*758cc3dcSJack F Vogel } 218613705f88SJack F Vogel 2187*758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2188*758cc3dcSJack F Vogel if (status < 0) 2189*758cc3dcSJack F Vogel return status; 219013705f88SJack F Vogel 2191*758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 219213705f88SJack F Vogel 2193*758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2194*758cc3dcSJack F Vogel if (status) { 2195*758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2196*758cc3dcSJack F Vogel return status; 2197*758cc3dcSJack F Vogel } 2198*758cc3dcSJack F Vogel 2199*758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 220013705f88SJack F Vogel * calculated checksum 220113705f88SJack F Vogel */ 22029ca4041bSJack F Vogel if (read_checksum != checksum) 220313705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 220413705f88SJack F Vogel 220513705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 22069ca4041bSJack F Vogel if (checksum_val) 220713705f88SJack F Vogel *checksum_val = checksum; 220813705f88SJack F Vogel 220913705f88SJack F Vogel return status; 221013705f88SJack F Vogel } 221113705f88SJack F Vogel 221213705f88SJack F Vogel /** 22139ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 221413705f88SJack F Vogel * @hw: pointer to hardware structure 221513705f88SJack F Vogel **/ 221613705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 221713705f88SJack F Vogel { 221813705f88SJack F Vogel s32 status; 221913705f88SJack F Vogel u16 checksum; 222013705f88SJack F Vogel 22212969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 22222969bf0eSJack F Vogel 2223*758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 222413705f88SJack F Vogel * not continue or we could be in for a very long wait while every 222513705f88SJack F Vogel * EEPROM read fails 222613705f88SJack F Vogel */ 22279ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2228*758cc3dcSJack F Vogel if (status) { 222913705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2230*758cc3dcSJack F Vogel return status; 223113705f88SJack F Vogel } 223213705f88SJack F Vogel 2233*758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2234*758cc3dcSJack F Vogel if (status < 0) 2235*758cc3dcSJack F Vogel return status; 2236*758cc3dcSJack F Vogel 2237*758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2238*758cc3dcSJack F Vogel 2239*758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2240*758cc3dcSJack F Vogel 224113705f88SJack F Vogel return status; 224213705f88SJack F Vogel } 224313705f88SJack F Vogel 224413705f88SJack F Vogel /** 224513705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 224613705f88SJack F Vogel * @mac_addr: pointer to MAC address. 224713705f88SJack F Vogel * 224813705f88SJack F Vogel * Tests a MAC address to ensure it is a valid Individual Address 224913705f88SJack F Vogel **/ 225013705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 225113705f88SJack F Vogel { 225213705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 225313705f88SJack F Vogel 22542969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 22552969bf0eSJack F Vogel 225613705f88SJack F Vogel /* Make sure it is not a multicast address */ 225713705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 225813705f88SJack F Vogel DEBUGOUT("MAC address is multicast\n"); 225913705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 226013705f88SJack F Vogel /* Not a broadcast address */ 226113705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 226213705f88SJack F Vogel DEBUGOUT("MAC address is broadcast\n"); 226313705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 226413705f88SJack F Vogel /* Reject the zero address */ 226513705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 226613705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 226713705f88SJack F Vogel DEBUGOUT("MAC address is all zeros\n"); 226813705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 226913705f88SJack F Vogel } 227013705f88SJack F Vogel return status; 227113705f88SJack F Vogel } 227213705f88SJack F Vogel 227313705f88SJack F Vogel /** 22749ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 227513705f88SJack F Vogel * @hw: pointer to hardware structure 227613705f88SJack F Vogel * @index: Receive address register to write 22779ca4041bSJack F Vogel * @addr: Address to put into receive address register 22789ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 227913705f88SJack F Vogel * @enable_addr: set flag that address is active 228013705f88SJack F Vogel * 228113705f88SJack F Vogel * Puts an ethernet address into a receive address register. 228213705f88SJack F Vogel **/ 22839ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 228413705f88SJack F Vogel u32 enable_addr) 228513705f88SJack F Vogel { 228613705f88SJack F Vogel u32 rar_low, rar_high; 22879ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 228813705f88SJack F Vogel 22892969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 22902969bf0eSJack F Vogel 22911a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 22921a4e3449SJack F Vogel if (index >= rar_entries) { 2293fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2294fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 22951a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 22961a4e3449SJack F Vogel } 22971a4e3449SJack F Vogel 22989ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 22999ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 23009ca4041bSJack F Vogel 230113705f88SJack F Vogel /* 23029ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 23039ca4041bSJack F Vogel * order from network order (big endian) to little endian 230413705f88SJack F Vogel */ 230513705f88SJack F Vogel rar_low = ((u32)addr[0] | 230613705f88SJack F Vogel ((u32)addr[1] << 8) | 230713705f88SJack F Vogel ((u32)addr[2] << 16) | 230813705f88SJack F Vogel ((u32)addr[3] << 24)); 23099ca4041bSJack F Vogel /* 23109ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 23119ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 23129ca4041bSJack F Vogel * of the address and the address valid bit. 23139ca4041bSJack F Vogel */ 23149ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 23159ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 23169ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 231713705f88SJack F Vogel 231813705f88SJack F Vogel if (enable_addr != 0) 231913705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 232013705f88SJack F Vogel 232113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 232213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 232313705f88SJack F Vogel 232413705f88SJack F Vogel return IXGBE_SUCCESS; 232513705f88SJack F Vogel } 232613705f88SJack F Vogel 232713705f88SJack F Vogel /** 23285b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 23295b7f4cedSJack F Vogel * @hw: pointer to hardware structure 23305b7f4cedSJack F Vogel * @index: Receive address register to write 23315b7f4cedSJack F Vogel * 23325b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 23335b7f4cedSJack F Vogel **/ 23345b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 23355b7f4cedSJack F Vogel { 23365b7f4cedSJack F Vogel u32 rar_high; 23375b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 23385b7f4cedSJack F Vogel 23392969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 23402969bf0eSJack F Vogel 23415b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 23421a4e3449SJack F Vogel if (index >= rar_entries) { 2343fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2344fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23451a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 23461a4e3449SJack F Vogel } 23471a4e3449SJack F Vogel 23485b7f4cedSJack F Vogel /* 23495b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 23505b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 23515b7f4cedSJack F Vogel * of the address and the address valid bit. 23525b7f4cedSJack F Vogel */ 23535b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 23545b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 23555b7f4cedSJack F Vogel 23565b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 23575b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 23585b7f4cedSJack F Vogel 23595b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 23605b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 23615b7f4cedSJack F Vogel 23625b7f4cedSJack F Vogel return IXGBE_SUCCESS; 23635b7f4cedSJack F Vogel } 23645b7f4cedSJack F Vogel 23655b7f4cedSJack F Vogel /** 236613705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 236713705f88SJack F Vogel * @hw: pointer to hardware structure 236813705f88SJack F Vogel * 236913705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 23709ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 237113705f88SJack F Vogel * the receiver is in reset when the routine is called. 237213705f88SJack F Vogel **/ 237313705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 237413705f88SJack F Vogel { 237513705f88SJack F Vogel u32 i; 23769ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 237713705f88SJack F Vogel 23782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 23792969bf0eSJack F Vogel 238013705f88SJack F Vogel /* 238113705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 238213705f88SJack F Vogel * to the permanent address. 238313705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 238413705f88SJack F Vogel */ 238513705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 238613705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 238713705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 23889ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 238913705f88SJack F Vogel 239013705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 239113705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 239213705f88SJack F Vogel hw->mac.addr[2]); 239313705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 239413705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 239513705f88SJack F Vogel } else { 239613705f88SJack F Vogel /* Setup the receive address. */ 239713705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 239813705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 239913705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 240013705f88SJack F Vogel hw->mac.addr[2]); 240113705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 240213705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 240313705f88SJack F Vogel 24049ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 2405182b3808SJack F Vogel 2406182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2407182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 240813705f88SJack F Vogel } 24099ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 241013705f88SJack F Vogel 241113705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 241213705f88SJack F Vogel 241313705f88SJack F Vogel /* Zero out the other receive addresses. */ 24149ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 241513705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 241613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 241713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 241813705f88SJack F Vogel } 241913705f88SJack F Vogel 242013705f88SJack F Vogel /* Clear the MTA */ 242113705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 242213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 242313705f88SJack F Vogel 242413705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 24259ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 242613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 242713705f88SJack F Vogel 24285b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 24295b7f4cedSJack F Vogel 243013705f88SJack F Vogel return IXGBE_SUCCESS; 243113705f88SJack F Vogel } 243213705f88SJack F Vogel 243313705f88SJack F Vogel /** 24349ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 24359ca4041bSJack F Vogel * @hw: pointer to hardware structure 24369ca4041bSJack F Vogel * @addr: new address 24379ca4041bSJack F Vogel * 24389ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 24399ca4041bSJack F Vogel **/ 24409ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 24419ca4041bSJack F Vogel { 24429ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24439ca4041bSJack F Vogel u32 rar; 24449ca4041bSJack F Vogel 24452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_add_uc_addr"); 24462969bf0eSJack F Vogel 24479ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 24489ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 24499ca4041bSJack F Vogel 24509ca4041bSJack F Vogel /* 24519ca4041bSJack F Vogel * Place this address in the RAR if there is room, 24529ca4041bSJack F Vogel * else put the controller into promiscuous mode 24539ca4041bSJack F Vogel */ 24549ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 24550ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 24569ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 24579ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 24589ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 24599ca4041bSJack F Vogel } else { 24609ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 24619ca4041bSJack F Vogel } 24629ca4041bSJack F Vogel 24639ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 24649ca4041bSJack F Vogel } 24659ca4041bSJack F Vogel 24669ca4041bSJack F Vogel /** 24679ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 24689ca4041bSJack F Vogel * @hw: pointer to hardware structure 24699ca4041bSJack F Vogel * @addr_list: the list of new addresses 24709ca4041bSJack F Vogel * @addr_count: number of addresses 24719ca4041bSJack F Vogel * @next: iterator function to walk the address list 24729ca4041bSJack F Vogel * 24739ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 24749ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 24759ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 24769ca4041bSJack F Vogel * 24779ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 24789ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 24799ca4041bSJack F Vogel **/ 24809ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 24819ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 24829ca4041bSJack F Vogel { 24839ca4041bSJack F Vogel u8 *addr; 24849ca4041bSJack F Vogel u32 i; 24859ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 24869ca4041bSJack F Vogel u32 uc_addr_in_use; 24879ca4041bSJack F Vogel u32 fctrl; 24889ca4041bSJack F Vogel u32 vmdq; 24899ca4041bSJack F Vogel 24902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 24912969bf0eSJack F Vogel 24929ca4041bSJack F Vogel /* 24939ca4041bSJack F Vogel * Clear accounting of old secondary address list, 24949ca4041bSJack F Vogel * don't count RAR[0] 24959ca4041bSJack F Vogel */ 24960ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 24979ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 24989ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 24999ca4041bSJack F Vogel 25009ca4041bSJack F Vogel /* Zero out the other receive addresses */ 25012969bf0eSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); 25022969bf0eSJack F Vogel for (i = 0; i < uc_addr_in_use; i++) { 25032969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); 25042969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); 25059ca4041bSJack F Vogel } 25069ca4041bSJack F Vogel 25079ca4041bSJack F Vogel /* Add the new addresses */ 25089ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 25099ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 25109ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 25119ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 25129ca4041bSJack F Vogel } 25139ca4041bSJack F Vogel 25149ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 25159ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 25169ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 25179ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 25189ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 25199ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 25209ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 25219ca4041bSJack F Vogel } 25229ca4041bSJack F Vogel } else { 25239ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 25249ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 25259ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 25269ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 25279ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 25289ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 25299ca4041bSJack F Vogel } 25309ca4041bSJack F Vogel } 25319ca4041bSJack F Vogel 25329ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 25339ca4041bSJack F Vogel return IXGBE_SUCCESS; 25349ca4041bSJack F Vogel } 25359ca4041bSJack F Vogel 25369ca4041bSJack F Vogel /** 253713705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 253813705f88SJack F Vogel * @hw: pointer to hardware structure 253913705f88SJack F Vogel * @mc_addr: the multicast address 254013705f88SJack F Vogel * 254113705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 254213705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 254313705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 254413705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 25459ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 254613705f88SJack F Vogel * to mc_filter_type. 254713705f88SJack F Vogel **/ 254813705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 254913705f88SJack F Vogel { 255013705f88SJack F Vogel u32 vector = 0; 255113705f88SJack F Vogel 25522969bf0eSJack F Vogel DEBUGFUNC("ixgbe_mta_vector"); 25532969bf0eSJack F Vogel 255413705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 255513705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 255613705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 255713705f88SJack F Vogel break; 255813705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 255913705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 256013705f88SJack F Vogel break; 256113705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 256213705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 256313705f88SJack F Vogel break; 256413705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 256513705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 256613705f88SJack F Vogel break; 256713705f88SJack F Vogel default: /* Invalid mc_filter_type */ 256813705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 256913705f88SJack F Vogel ASSERT(0); 257013705f88SJack F Vogel break; 257113705f88SJack F Vogel } 257213705f88SJack F Vogel 257313705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 257413705f88SJack F Vogel vector &= 0xFFF; 257513705f88SJack F Vogel return vector; 257613705f88SJack F Vogel } 257713705f88SJack F Vogel 257813705f88SJack F Vogel /** 257913705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 258013705f88SJack F Vogel * @hw: pointer to hardware structure 258113705f88SJack F Vogel * @hash_value: Multicast address hash value 258213705f88SJack F Vogel * 258313705f88SJack F Vogel * Sets the bit-vector in the multicast table. 258413705f88SJack F Vogel **/ 258513705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 258613705f88SJack F Vogel { 258713705f88SJack F Vogel u32 vector; 258813705f88SJack F Vogel u32 vector_bit; 258913705f88SJack F Vogel u32 vector_reg; 259013705f88SJack F Vogel 25912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_mta"); 25922969bf0eSJack F Vogel 259313705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 259413705f88SJack F Vogel 259513705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 259613705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 259713705f88SJack F Vogel 259813705f88SJack F Vogel /* 259913705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 260013705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 260113705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 260213705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 260313705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 260413705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 260513705f88SJack F Vogel * the value. 260613705f88SJack F Vogel */ 260713705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 260813705f88SJack F Vogel vector_bit = vector & 0x1F; 26091a4e3449SJack F Vogel hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); 261013705f88SJack F Vogel } 261113705f88SJack F Vogel 261213705f88SJack F Vogel /** 261313705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 261413705f88SJack F Vogel * @hw: pointer to hardware structure 261513705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 261613705f88SJack F Vogel * @mc_addr_count: number of addresses 26179ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 261885d0a26eSJack F Vogel * @clear: flag, when set clears the table beforehand 261913705f88SJack F Vogel * 262085d0a26eSJack F Vogel * When the clear flag is set, the given list replaces any existing list. 262185d0a26eSJack F Vogel * Hashes the given addresses into the multicast table. 262213705f88SJack F Vogel **/ 262313705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 262485d0a26eSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next, 262585d0a26eSJack F Vogel bool clear) 262613705f88SJack F Vogel { 262713705f88SJack F Vogel u32 i; 26289ca4041bSJack F Vogel u32 vmdq; 262913705f88SJack F Vogel 26302969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 26312969bf0eSJack F Vogel 263213705f88SJack F Vogel /* 263313705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 263413705f88SJack F Vogel * use. 263513705f88SJack F Vogel */ 263613705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 263713705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 263813705f88SJack F Vogel 26391a4e3449SJack F Vogel /* Clear mta_shadow */ 264085d0a26eSJack F Vogel if (clear) { 264113705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 26421a4e3449SJack F Vogel memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 264385d0a26eSJack F Vogel } 264413705f88SJack F Vogel 26451a4e3449SJack F Vogel /* Update mta_shadow */ 264613705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 264713705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 26480ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 264913705f88SJack F Vogel } 265013705f88SJack F Vogel 265113705f88SJack F Vogel /* Enable mta */ 26521a4e3449SJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 26531a4e3449SJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 26541a4e3449SJack F Vogel hw->mac.mta_shadow[i]); 26551a4e3449SJack F Vogel 265613705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 265713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 265813705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 265913705f88SJack F Vogel 266013705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 266113705f88SJack F Vogel return IXGBE_SUCCESS; 266213705f88SJack F Vogel } 266313705f88SJack F Vogel 266413705f88SJack F Vogel /** 266513705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 266613705f88SJack F Vogel * @hw: pointer to hardware structure 266713705f88SJack F Vogel * 266813705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 266913705f88SJack F Vogel **/ 267013705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 267113705f88SJack F Vogel { 267213705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 267313705f88SJack F Vogel 26742969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_mc_generic"); 26752969bf0eSJack F Vogel 267613705f88SJack F Vogel if (a->mta_in_use > 0) 267713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 267813705f88SJack F Vogel hw->mac.mc_filter_type); 267913705f88SJack F Vogel 268013705f88SJack F Vogel return IXGBE_SUCCESS; 268113705f88SJack F Vogel } 268213705f88SJack F Vogel 268313705f88SJack F Vogel /** 26849ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 268513705f88SJack F Vogel * @hw: pointer to hardware structure 268613705f88SJack F Vogel * 268713705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 268813705f88SJack F Vogel **/ 268913705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 269013705f88SJack F Vogel { 269113705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 269213705f88SJack F Vogel 26932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_mc_generic"); 26942969bf0eSJack F Vogel 269513705f88SJack F Vogel if (a->mta_in_use > 0) 269613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 269713705f88SJack F Vogel 269813705f88SJack F Vogel return IXGBE_SUCCESS; 269913705f88SJack F Vogel } 270013705f88SJack F Vogel 27011b6e0dbaSJack F Vogel /** 27020ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 27031b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 27041b6e0dbaSJack F Vogel * 27050ac6dfecSJack F Vogel * Enable flow control according to the current settings. 27061b6e0dbaSJack F Vogel **/ 2707a621e3c8SJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 27081b6e0dbaSJack F Vogel { 27091b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 27100ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 27110ac6dfecSJack F Vogel u32 reg; 27121a4e3449SJack F Vogel u32 fcrtl, fcrth; 2713a621e3c8SJack F Vogel int i; 27141b6e0dbaSJack F Vogel 27150ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 27161b6e0dbaSJack F Vogel 2717a621e3c8SJack F Vogel /* Validate the water mark configuration */ 2718a621e3c8SJack F Vogel if (!hw->fc.pause_time) { 2719a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 27200ac6dfecSJack F Vogel goto out; 2721a621e3c8SJack F Vogel } 2722a621e3c8SJack F Vogel 2723a621e3c8SJack F Vogel /* Low water mark of zero causes XOFF floods */ 2724a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2725a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2726a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2727a621e3c8SJack F Vogel if (!hw->fc.low_water[i] || 2728a621e3c8SJack F Vogel hw->fc.low_water[i] >= hw->fc.high_water[i]) { 2729a621e3c8SJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 2730a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 2731a621e3c8SJack F Vogel goto out; 2732a621e3c8SJack F Vogel } 2733a621e3c8SJack F Vogel } 2734a621e3c8SJack F Vogel } 2735a621e3c8SJack F Vogel 2736a621e3c8SJack F Vogel /* Negotiate the fc mode to use */ 2737a621e3c8SJack F Vogel ixgbe_fc_autoneg(hw); 27380ac6dfecSJack F Vogel 27390ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 27400ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 2741a621e3c8SJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 27420ac6dfecSJack F Vogel 27430ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 27440ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 27451b6e0dbaSJack F Vogel 27461b6e0dbaSJack F Vogel /* 27471b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 27481b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 27491b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 27501b6e0dbaSJack F Vogel * but not send pause frames). 27511b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 27521b6e0dbaSJack F Vogel * we do not support receiving pause frames). 27531b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 27541b6e0dbaSJack F Vogel * other: Invalid. 27551b6e0dbaSJack F Vogel */ 27561b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 27571b6e0dbaSJack F Vogel case ixgbe_fc_none: 27581a4e3449SJack F Vogel /* 27591a4e3449SJack F Vogel * Flow control is disabled by software override or autoneg. 27600ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 27610ac6dfecSJack F Vogel */ 27621b6e0dbaSJack F Vogel break; 27631b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 27641b6e0dbaSJack F Vogel /* 27651b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 27661b6e0dbaSJack F Vogel * disabled by software override. Since there really 27671b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 27681b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 27691b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 27701b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 27711b6e0dbaSJack F Vogel */ 27720ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 27731b6e0dbaSJack F Vogel break; 27741b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 27751b6e0dbaSJack F Vogel /* 27761b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 27771b6e0dbaSJack F Vogel * disabled by software override. 27781b6e0dbaSJack F Vogel */ 27790ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 27801b6e0dbaSJack F Vogel break; 27811b6e0dbaSJack F Vogel case ixgbe_fc_full: 27821b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 27830ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 27840ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 27851b6e0dbaSJack F Vogel break; 27861b6e0dbaSJack F Vogel default: 2787fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 2788fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 27892969bf0eSJack F Vogel ret_val = IXGBE_ERR_CONFIG; 27901b6e0dbaSJack F Vogel goto out; 27911b6e0dbaSJack F Vogel break; 27921b6e0dbaSJack F Vogel } 27931b6e0dbaSJack F Vogel 27940ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 27950ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 27960ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 27970ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 27981b6e0dbaSJack F Vogel 2799d8602bb9SJack F Vogel 2800a621e3c8SJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 2801a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2802a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2803a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2804a621e3c8SJack F Vogel fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 2805a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 2806a621e3c8SJack F Vogel fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 2807a621e3c8SJack F Vogel } else { 2808a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 2809a621e3c8SJack F Vogel /* 2810a621e3c8SJack F Vogel * In order to prevent Tx hangs when the internal Tx 2811a621e3c8SJack F Vogel * switch is enabled we must set the high water mark 2812*758cc3dcSJack F Vogel * to the Rx packet buffer size - 24KB. This allows 2813*758cc3dcSJack F Vogel * the Tx switch to function even under heavy Rx 2814*758cc3dcSJack F Vogel * workloads. 2815a621e3c8SJack F Vogel */ 2816*758cc3dcSJack F Vogel fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 28171b6e0dbaSJack F Vogel } 28181b6e0dbaSJack F Vogel 2819a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 2820a621e3c8SJack F Vogel } 28210ac6dfecSJack F Vogel 28220ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 2823a621e3c8SJack F Vogel reg = hw->fc.pause_time * 0x00010001; 2824a621e3c8SJack F Vogel for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) 2825a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 28260ac6dfecSJack F Vogel 2827a621e3c8SJack F Vogel /* Configure flow control refresh threshold value */ 2828a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 28290ac6dfecSJack F Vogel 28300ac6dfecSJack F Vogel out: 28310ac6dfecSJack F Vogel return ret_val; 28320ac6dfecSJack F Vogel } 28330ac6dfecSJack F Vogel 28340ac6dfecSJack F Vogel /** 28351a4e3449SJack F Vogel * ixgbe_negotiate_fc - Negotiate flow control 28361a4e3449SJack F Vogel * @hw: pointer to hardware structure 28371a4e3449SJack F Vogel * @adv_reg: flow control advertised settings 28381a4e3449SJack F Vogel * @lp_reg: link partner's flow control settings 28391a4e3449SJack F Vogel * @adv_sym: symmetric pause bit in advertisement 28401a4e3449SJack F Vogel * @adv_asm: asymmetric pause bit in advertisement 28411a4e3449SJack F Vogel * @lp_sym: symmetric pause bit in link partner advertisement 28421a4e3449SJack F Vogel * @lp_asm: asymmetric pause bit in link partner advertisement 28431a4e3449SJack F Vogel * 28441a4e3449SJack F Vogel * Find the intersection between advertised settings and link partner's 28451a4e3449SJack F Vogel * advertised settings 28461a4e3449SJack F Vogel **/ 28471a4e3449SJack F Vogel static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 28481a4e3449SJack F Vogel u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 28491a4e3449SJack F Vogel { 2850fd75b91dSJack F Vogel if ((!(adv_reg)) || (!(lp_reg))) { 2851fd75b91dSJack F Vogel ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, 2852fd75b91dSJack F Vogel "Local or link partner's advertised flow control " 2853fd75b91dSJack F Vogel "settings are NULL. Local: %x, link partner: %x\n", 2854fd75b91dSJack F Vogel adv_reg, lp_reg); 28551a4e3449SJack F Vogel return IXGBE_ERR_FC_NOT_NEGOTIATED; 2856fd75b91dSJack F Vogel } 28571a4e3449SJack F Vogel 28581a4e3449SJack F Vogel if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 28592969bf0eSJack F Vogel /* 28602969bf0eSJack F Vogel * Now we need to check if the user selected Rx ONLY 28612969bf0eSJack F Vogel * of pause frames. In this case, we had to advertise 28622969bf0eSJack F Vogel * FULL flow control because we could not advertise RX 28632969bf0eSJack F Vogel * ONLY. Hence, we must now check to see if we need to 28642969bf0eSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 28652969bf0eSJack F Vogel */ 28662969bf0eSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 28672969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 28682969bf0eSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 28692969bf0eSJack F Vogel } else { 28702969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 28712969bf0eSJack F Vogel DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 28722969bf0eSJack F Vogel } 28731a4e3449SJack F Vogel } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 28741a4e3449SJack F Vogel (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 28752969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 28762969bf0eSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 28771a4e3449SJack F Vogel } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 28781a4e3449SJack F Vogel !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 28792969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 28802969bf0eSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 28812969bf0eSJack F Vogel } else { 28822969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 28832969bf0eSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 28842969bf0eSJack F Vogel } 28851a4e3449SJack F Vogel return IXGBE_SUCCESS; 28861b6e0dbaSJack F Vogel } 28871b6e0dbaSJack F Vogel 28880ac6dfecSJack F Vogel /** 2889a621e3c8SJack F Vogel * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 28900ac6dfecSJack F Vogel * @hw: pointer to hardware structure 28910ac6dfecSJack F Vogel * 2892a621e3c8SJack F Vogel * Enable flow control according on 1 gig fiber. 28930ac6dfecSJack F Vogel **/ 2894a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 28950ac6dfecSJack F Vogel { 2896a621e3c8SJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 2897a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 28980ac6dfecSJack F Vogel 2899a621e3c8SJack F Vogel /* 2900a621e3c8SJack F Vogel * On multispeed fiber at 1g, bail out if 2901a621e3c8SJack F Vogel * - link is up but AN did not complete, or if 2902a621e3c8SJack F Vogel * - link is up and AN completed but timed out 2903a621e3c8SJack F Vogel */ 29042969bf0eSJack F Vogel 2905a621e3c8SJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 2906a621e3c8SJack F Vogel if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 2907fd75b91dSJack F Vogel (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 2908*758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); 29090ac6dfecSJack F Vogel goto out; 2910fd75b91dSJack F Vogel } 29110ac6dfecSJack F Vogel 2912a621e3c8SJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 2913a621e3c8SJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 29140ac6dfecSJack F Vogel 2915a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 2916a621e3c8SJack F Vogel pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 2917a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE, 2918a621e3c8SJack F Vogel IXGBE_PCS1GANA_SYM_PAUSE, 2919a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE); 29200ac6dfecSJack F Vogel 29210ac6dfecSJack F Vogel out: 29220ac6dfecSJack F Vogel return ret_val; 29230ac6dfecSJack F Vogel } 29241b6e0dbaSJack F Vogel 292513705f88SJack F Vogel /** 2926a621e3c8SJack F Vogel * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 2927a621e3c8SJack F Vogel * @hw: pointer to hardware structure 2928a621e3c8SJack F Vogel * 2929a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 2930a621e3c8SJack F Vogel **/ 2931a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 2932a621e3c8SJack F Vogel { 2933a621e3c8SJack F Vogel u32 links2, anlp1_reg, autoc_reg, links; 2934a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 2935a621e3c8SJack F Vogel 2936a621e3c8SJack F Vogel /* 2937a621e3c8SJack F Vogel * On backplane, bail out if 2938a621e3c8SJack F Vogel * - backplane autoneg was not completed, or if 2939a621e3c8SJack F Vogel * - we are 82599 and link partner is not AN enabled 2940a621e3c8SJack F Vogel */ 2941a621e3c8SJack F Vogel links = IXGBE_READ_REG(hw, IXGBE_LINKS); 2942fd75b91dSJack F Vogel if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { 2943*758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete\n"); 2944a621e3c8SJack F Vogel goto out; 2945fd75b91dSJack F Vogel } 2946a621e3c8SJack F Vogel 2947a621e3c8SJack F Vogel if (hw->mac.type == ixgbe_mac_82599EB) { 2948a621e3c8SJack F Vogel links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 2949fd75b91dSJack F Vogel if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { 2950*758cc3dcSJack F Vogel DEBUGOUT("Link partner is not AN enabled\n"); 2951a621e3c8SJack F Vogel goto out; 2952a621e3c8SJack F Vogel } 2953fd75b91dSJack F Vogel } 2954a621e3c8SJack F Vogel /* 2955a621e3c8SJack F Vogel * Read the 10g AN autoc and LP ability registers and resolve 2956a621e3c8SJack F Vogel * local flow control settings accordingly 2957a621e3c8SJack F Vogel */ 2958a621e3c8SJack F Vogel autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 2959a621e3c8SJack F Vogel anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 2960a621e3c8SJack F Vogel 2961a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 2962a621e3c8SJack F Vogel anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 2963a621e3c8SJack F Vogel IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 2964a621e3c8SJack F Vogel 2965a621e3c8SJack F Vogel out: 2966a621e3c8SJack F Vogel return ret_val; 2967a621e3c8SJack F Vogel } 2968a621e3c8SJack F Vogel 2969a621e3c8SJack F Vogel /** 2970a621e3c8SJack F Vogel * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 2971a621e3c8SJack F Vogel * @hw: pointer to hardware structure 2972a621e3c8SJack F Vogel * 2973a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 2974a621e3c8SJack F Vogel **/ 2975a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 2976a621e3c8SJack F Vogel { 2977a621e3c8SJack F Vogel u16 technology_ability_reg = 0; 2978a621e3c8SJack F Vogel u16 lp_technology_ability_reg = 0; 2979a621e3c8SJack F Vogel 2980a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 2981a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2982a621e3c8SJack F Vogel &technology_ability_reg); 2983a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, 2984a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 2985a621e3c8SJack F Vogel &lp_technology_ability_reg); 2986a621e3c8SJack F Vogel 2987a621e3c8SJack F Vogel return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 2988a621e3c8SJack F Vogel (u32)lp_technology_ability_reg, 2989a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 2990a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 2991a621e3c8SJack F Vogel } 2992a621e3c8SJack F Vogel 2993a621e3c8SJack F Vogel /** 2994a621e3c8SJack F Vogel * ixgbe_fc_autoneg - Configure flow control 2995a621e3c8SJack F Vogel * @hw: pointer to hardware structure 2996a621e3c8SJack F Vogel * 2997a621e3c8SJack F Vogel * Compares our advertised flow control capabilities to those advertised by 2998a621e3c8SJack F Vogel * our link partner, and determines the proper flow control mode to use. 2999a621e3c8SJack F Vogel **/ 3000a621e3c8SJack F Vogel void ixgbe_fc_autoneg(struct ixgbe_hw *hw) 3001a621e3c8SJack F Vogel { 3002a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3003a621e3c8SJack F Vogel ixgbe_link_speed speed; 3004a621e3c8SJack F Vogel bool link_up; 3005a621e3c8SJack F Vogel 3006a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 3007a621e3c8SJack F Vogel 3008a621e3c8SJack F Vogel /* 3009a621e3c8SJack F Vogel * AN should have completed when the cable was plugged in. 3010a621e3c8SJack F Vogel * Look for reasons to bail out. Bail out if: 3011a621e3c8SJack F Vogel * - FC autoneg is disabled, or if 3012a621e3c8SJack F Vogel * - link is not up. 3013a621e3c8SJack F Vogel */ 3014fd75b91dSJack F Vogel if (hw->fc.disable_fc_autoneg) { 3015fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3016fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3017a621e3c8SJack F Vogel goto out; 3018fd75b91dSJack F Vogel } 3019a621e3c8SJack F Vogel 3020a621e3c8SJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3021fd75b91dSJack F Vogel if (!link_up) { 3022fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3023a621e3c8SJack F Vogel goto out; 3024fd75b91dSJack F Vogel } 3025a621e3c8SJack F Vogel 3026a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3027a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 30280ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3029*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3030a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3031a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3032a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3033a621e3c8SJack F Vogel break; 3034a621e3c8SJack F Vogel 3035a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3036a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3037a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3038a621e3c8SJack F Vogel break; 3039a621e3c8SJack F Vogel 3040a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3041a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3042fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3043a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3044a621e3c8SJack F Vogel break; 3045a621e3c8SJack F Vogel 3046a621e3c8SJack F Vogel default: 3047a621e3c8SJack F Vogel break; 3048a621e3c8SJack F Vogel } 3049a621e3c8SJack F Vogel 3050a621e3c8SJack F Vogel out: 3051a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 3052a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = TRUE; 3053a621e3c8SJack F Vogel } else { 3054a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = FALSE; 3055a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3056a621e3c8SJack F Vogel } 3057a621e3c8SJack F Vogel } 3058a621e3c8SJack F Vogel 3059fd75b91dSJack F Vogel /* 3060fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3061fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3062fd75b91dSJack F Vogel * 3063fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3064fd75b91dSJack F Vogel * 3065fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3066fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3067fd75b91dSJack F Vogel * 800 = 80 millisec. 3068fd75b91dSJack F Vogel */ 3069fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3070fd75b91dSJack F Vogel { 3071fd75b91dSJack F Vogel s16 devctl2; 3072fd75b91dSJack F Vogel u32 pollcnt; 3073fd75b91dSJack F Vogel 3074fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3075fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3076fd75b91dSJack F Vogel 3077fd75b91dSJack F Vogel switch (devctl2) { 3078fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3079fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3080fd75b91dSJack F Vogel break; 3081fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3082fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3083fd75b91dSJack F Vogel break; 3084fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3085fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3086fd75b91dSJack F Vogel break; 3087fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3088fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3089fd75b91dSJack F Vogel break; 3090fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3091fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3092fd75b91dSJack F Vogel break; 3093fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3094fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3095fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3096fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3097fd75b91dSJack F Vogel default: 3098fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3099fd75b91dSJack F Vogel break; 3100fd75b91dSJack F Vogel } 3101fd75b91dSJack F Vogel 3102fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3103fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3104fd75b91dSJack F Vogel } 3105fd75b91dSJack F Vogel 3106a621e3c8SJack F Vogel /** 310713705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 310813705f88SJack F Vogel * @hw: pointer to hardware structure 310913705f88SJack F Vogel * 311013705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 311113705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 311213705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 311313705f88SJack F Vogel * is returned signifying master requests disabled. 311413705f88SJack F Vogel **/ 311513705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 311613705f88SJack F Vogel { 3117c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3118fd75b91dSJack F Vogel u32 i, poll; 3119*758cc3dcSJack F Vogel u16 value; 312013705f88SJack F Vogel 31212969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_pcie_master"); 31222969bf0eSJack F Vogel 312385d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 312485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 312585d0a26eSJack F Vogel 3126fd75b91dSJack F Vogel /* Exit if master requests are blocked */ 3127*758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3128*758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3129c0014855SJack F Vogel goto out; 3130c0014855SJack F Vogel 313185d0a26eSJack F Vogel /* Poll for master request bit to clear */ 313213705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 313385d0a26eSJack F Vogel usec_delay(100); 3134c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3135182b3808SJack F Vogel goto out; 313685d0a26eSJack F Vogel } 3137c0014855SJack F Vogel 3138c0014855SJack F Vogel /* 3139c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 3140c0014855SJack F Vogel * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine 3141c0014855SJack F Vogel * of this need. The first reset prevents new master requests from 314285d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3143c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3144c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3145c0014855SJack F Vogel */ 314685d0a26eSJack F Vogel DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); 3147c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3148c0014855SJack F Vogel 314985d0a26eSJack F Vogel /* 315085d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 315185d0a26eSJack F Vogel * transactions pending. 315285d0a26eSJack F Vogel */ 3153fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3154fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 315585d0a26eSJack F Vogel usec_delay(100); 3156*758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3157*758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3158*758cc3dcSJack F Vogel goto out; 3159*758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 316085d0a26eSJack F Vogel goto out; 316185d0a26eSJack F Vogel } 316285d0a26eSJack F Vogel 3163fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3164fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 316585d0a26eSJack F Vogel status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 316685d0a26eSJack F Vogel 3167c0014855SJack F Vogel out: 316813705f88SJack F Vogel return status; 316913705f88SJack F Vogel } 317013705f88SJack F Vogel 317113705f88SJack F Vogel /** 31729ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 317313705f88SJack F Vogel * @hw: pointer to hardware structure 31749ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 317513705f88SJack F Vogel * 317685d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 317713705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 317813705f88SJack F Vogel **/ 3179*758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 318013705f88SJack F Vogel { 3181fd75b91dSJack F Vogel u32 gssr = 0; 318213705f88SJack F Vogel u32 swmask = mask; 318313705f88SJack F Vogel u32 fwmask = mask << 5; 3184fd75b91dSJack F Vogel u32 timeout = 200; 3185fd75b91dSJack F Vogel u32 i; 318613705f88SJack F Vogel 31872969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 31882969bf0eSJack F Vogel 3189fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 31900ac6dfecSJack F Vogel /* 3191fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3192fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 31930ac6dfecSJack F Vogel */ 319413705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 31952969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 319613705f88SJack F Vogel 319713705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3198fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 319913705f88SJack F Vogel gssr |= swmask; 320013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 320113705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 320213705f88SJack F Vogel return IXGBE_SUCCESS; 3203fd75b91dSJack F Vogel } else { 3204fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3205fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3206fd75b91dSJack F Vogel msec_delay(5); 3207fd75b91dSJack F Vogel } 3208fd75b91dSJack F Vogel } 3209fd75b91dSJack F Vogel 3210fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3211fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3212fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3213fd75b91dSJack F Vogel 3214fd75b91dSJack F Vogel msec_delay(5); 3215fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 321613705f88SJack F Vogel } 321713705f88SJack F Vogel 321813705f88SJack F Vogel /** 321913705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 322013705f88SJack F Vogel * @hw: pointer to hardware structure 32219ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 322213705f88SJack F Vogel * 322385d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 322413705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 322513705f88SJack F Vogel **/ 3226*758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 322713705f88SJack F Vogel { 322813705f88SJack F Vogel u32 gssr; 322913705f88SJack F Vogel u32 swmask = mask; 323013705f88SJack F Vogel 32312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 32322969bf0eSJack F Vogel 323313705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 323413705f88SJack F Vogel 323513705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 323613705f88SJack F Vogel gssr &= ~swmask; 323713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 323813705f88SJack F Vogel 323913705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 32400ac6dfecSJack F Vogel } 32410ac6dfecSJack F Vogel 32420ac6dfecSJack F Vogel /** 324385d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 324485d0a26eSJack F Vogel * @hw: pointer to hardware structure 324585d0a26eSJack F Vogel * 324685d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 324785d0a26eSJack F Vogel * the Rx security block 324885d0a26eSJack F Vogel **/ 324985d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 325085d0a26eSJack F Vogel { 325185d0a26eSJack F Vogel #define IXGBE_MAX_SECRX_POLL 40 325285d0a26eSJack F Vogel 325385d0a26eSJack F Vogel int i; 325485d0a26eSJack F Vogel int secrxreg; 325585d0a26eSJack F Vogel 325685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 325785d0a26eSJack F Vogel 325885d0a26eSJack F Vogel 325985d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 326085d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 326185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 326285d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 326385d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 326485d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 326585d0a26eSJack F Vogel break; 326685d0a26eSJack F Vogel else 326785d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 326885d0a26eSJack F Vogel usec_delay(1000); 326985d0a26eSJack F Vogel } 327085d0a26eSJack F Vogel 327185d0a26eSJack F Vogel /* For informational purposes only */ 327285d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 327385d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 327485d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 327585d0a26eSJack F Vogel 327685d0a26eSJack F Vogel return IXGBE_SUCCESS; 327785d0a26eSJack F Vogel } 327885d0a26eSJack F Vogel 327985d0a26eSJack F Vogel /** 3280*758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3281*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3282*758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3283*758cc3dcSJack F Vogel * 3284*758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3285*758cc3dcSJack F Vogel */ 3286*758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3287*758cc3dcSJack F Vogel { 3288*758cc3dcSJack F Vogel *locked = FALSE; 3289*758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3290*758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3291*758cc3dcSJack F Vogel } 3292*758cc3dcSJack F Vogel 3293*758cc3dcSJack F Vogel /** 3294*758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3295*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3296*758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3297*758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3298*758cc3dcSJack F Vogel * previous read. 3299*758cc3dcSJack F Vogel * 3300*758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3301*758cc3dcSJack F Vogel */ 3302*758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3303*758cc3dcSJack F Vogel { 3304*758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3305*758cc3dcSJack F Vogel 3306*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3307*758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3308*758cc3dcSJack F Vogel } 3309*758cc3dcSJack F Vogel 3310*758cc3dcSJack F Vogel /** 331185d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 331285d0a26eSJack F Vogel * @hw: pointer to hardware structure 331385d0a26eSJack F Vogel * 331485d0a26eSJack F Vogel * Enables the receive data path. 331585d0a26eSJack F Vogel **/ 331685d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 331785d0a26eSJack F Vogel { 331885d0a26eSJack F Vogel int secrxreg; 331985d0a26eSJack F Vogel 332085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 332185d0a26eSJack F Vogel 332285d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 332385d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 332485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 332585d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 332685d0a26eSJack F Vogel 332785d0a26eSJack F Vogel return IXGBE_SUCCESS; 332885d0a26eSJack F Vogel } 332985d0a26eSJack F Vogel 333085d0a26eSJack F Vogel /** 33310ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 33320ac6dfecSJack F Vogel * @hw: pointer to hardware structure 33330ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 33340ac6dfecSJack F Vogel * 33350ac6dfecSJack F Vogel * Enables the Rx DMA unit 33360ac6dfecSJack F Vogel **/ 33370ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 33380ac6dfecSJack F Vogel { 33392969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 33402969bf0eSJack F Vogel 3341*758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3342*758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3343*758cc3dcSJack F Vogel else 3344*758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 33450ac6dfecSJack F Vogel 33460ac6dfecSJack F Vogel return IXGBE_SUCCESS; 33470ac6dfecSJack F Vogel } 33480ac6dfecSJack F Vogel 33490ac6dfecSJack F Vogel /** 33500ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 33510ac6dfecSJack F Vogel * @hw: pointer to hardware structure 33520ac6dfecSJack F Vogel * @index: led number to blink 33530ac6dfecSJack F Vogel **/ 33540ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 33550ac6dfecSJack F Vogel { 33560ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 33570ac6dfecSJack F Vogel bool link_up = 0; 3358*758cc3dcSJack F Vogel u32 autoc_reg = 0; 33590ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 33600ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3361*758cc3dcSJack F Vogel bool locked = FALSE; 33620ac6dfecSJack F Vogel 33632969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 33642969bf0eSJack F Vogel 33650ac6dfecSJack F Vogel /* 33660ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 33670ac6dfecSJack F Vogel * Force it if link is down. 33680ac6dfecSJack F Vogel */ 33690ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 33700ac6dfecSJack F Vogel 33710ac6dfecSJack F Vogel if (!link_up) { 3372*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3373*758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 33740ecc2ff0SJack F Vogel goto out; 33750ecc2ff0SJack F Vogel 3376d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 33770ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 33780ecc2ff0SJack F Vogel 3379*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3380*758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3381*758cc3dcSJack F Vogel goto out; 3382*758cc3dcSJack F Vogel 3383*758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 33840ac6dfecSJack F Vogel msec_delay(10); 33850ac6dfecSJack F Vogel } 33860ac6dfecSJack F Vogel 33870ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 33880ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 33890ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 33900ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 33910ac6dfecSJack F Vogel 33920ecc2ff0SJack F Vogel out: 33930ecc2ff0SJack F Vogel return ret_val; 33940ac6dfecSJack F Vogel } 33950ac6dfecSJack F Vogel 33960ac6dfecSJack F Vogel /** 33970ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 33980ac6dfecSJack F Vogel * @hw: pointer to hardware structure 33990ac6dfecSJack F Vogel * @index: led number to stop blinking 34000ac6dfecSJack F Vogel **/ 34010ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 34020ac6dfecSJack F Vogel { 3403*758cc3dcSJack F Vogel u32 autoc_reg = 0; 34040ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34050ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3406*758cc3dcSJack F Vogel bool locked = FALSE; 34070ac6dfecSJack F Vogel 34082969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 34092969bf0eSJack F Vogel 3410*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3411*758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3412*758cc3dcSJack F Vogel goto out; 3413d8602bb9SJack F Vogel 34140ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 34150ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34160ac6dfecSJack F Vogel 3417*758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3418*758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3419*758cc3dcSJack F Vogel goto out; 34200ecc2ff0SJack F Vogel 34210ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 34220ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 34230ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 34240ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 34250ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34260ac6dfecSJack F Vogel 34270ecc2ff0SJack F Vogel out: 34280ecc2ff0SJack F Vogel return ret_val; 342913705f88SJack F Vogel } 343013705f88SJack F Vogel 34312969bf0eSJack F Vogel /** 34322969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 34332969bf0eSJack F Vogel * @hw: pointer to hardware structure 34342969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 34352969bf0eSJack F Vogel * 34362969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 34372969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 34382969bf0eSJack F Vogel * get and set mac_addr routines. 34392969bf0eSJack F Vogel **/ 34402969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 34412969bf0eSJack F Vogel u16 *san_mac_offset) 34422969bf0eSJack F Vogel { 3443fd75b91dSJack F Vogel s32 ret_val; 3444fd75b91dSJack F Vogel 34452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 34462969bf0eSJack F Vogel 34472969bf0eSJack F Vogel /* 34482969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 34492969bf0eSJack F Vogel * available. 34502969bf0eSJack F Vogel */ 3451fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3452fd75b91dSJack F Vogel san_mac_offset); 3453fd75b91dSJack F Vogel if (ret_val) { 3454fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3455fd75b91dSJack F Vogel "eeprom at offset %d failed", 3456fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3457fd75b91dSJack F Vogel } 34582969bf0eSJack F Vogel 3459fd75b91dSJack F Vogel return ret_val; 34602969bf0eSJack F Vogel } 34612969bf0eSJack F Vogel 34622969bf0eSJack F Vogel /** 34632969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 34642969bf0eSJack F Vogel * @hw: pointer to hardware structure 34652969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 34662969bf0eSJack F Vogel * 34672969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 34682969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 34692969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 34702969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 34712969bf0eSJack F Vogel **/ 34722969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 34732969bf0eSJack F Vogel { 34742969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 34752969bf0eSJack F Vogel u8 i; 3476fd75b91dSJack F Vogel s32 ret_val; 34772969bf0eSJack F Vogel 34782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 34792969bf0eSJack F Vogel 34802969bf0eSJack F Vogel /* 34812969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 34822969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 34832969bf0eSJack F Vogel */ 3484fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3485fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 34862969bf0eSJack F Vogel goto san_mac_addr_out; 34872969bf0eSJack F Vogel 34882969bf0eSJack F Vogel /* make sure we know which port we need to program */ 34892969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 34902969bf0eSJack F Vogel /* apply the port offset to the address offset */ 34912969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 34922969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 34932969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3494fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3495fd75b91dSJack F Vogel &san_mac_data); 3496fd75b91dSJack F Vogel if (ret_val) { 3497fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3498fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3499fd75b91dSJack F Vogel san_mac_offset); 3500fd75b91dSJack F Vogel goto san_mac_addr_out; 3501fd75b91dSJack F Vogel } 35022969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 35032969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 35042969bf0eSJack F Vogel san_mac_offset++; 35052969bf0eSJack F Vogel } 3506fd75b91dSJack F Vogel return IXGBE_SUCCESS; 35072969bf0eSJack F Vogel 35082969bf0eSJack F Vogel san_mac_addr_out: 3509fd75b91dSJack F Vogel /* 3510fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3511fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3512fd75b91dSJack F Vogel */ 3513fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3514fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 35152969bf0eSJack F Vogel return IXGBE_SUCCESS; 35162969bf0eSJack F Vogel } 35172969bf0eSJack F Vogel 35182969bf0eSJack F Vogel /** 35192969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 35202969bf0eSJack F Vogel * @hw: pointer to hardware structure 35212969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35222969bf0eSJack F Vogel * 35232969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 35242969bf0eSJack F Vogel **/ 35252969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35262969bf0eSJack F Vogel { 3527fd75b91dSJack F Vogel s32 ret_val; 35282969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35292969bf0eSJack F Vogel u8 i; 35302969bf0eSJack F Vogel 35312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 35322969bf0eSJack F Vogel 35332969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3534fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3535fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3536fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 35372969bf0eSJack F Vogel 35382969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 35392969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 35402969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 35412969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 35422969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 35432969bf0eSJack F Vogel 35442969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 35452969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 35462969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 35472969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 35482969bf0eSJack F Vogel san_mac_offset++; 35492969bf0eSJack F Vogel } 35502969bf0eSJack F Vogel 3551fd75b91dSJack F Vogel return IXGBE_SUCCESS; 35522969bf0eSJack F Vogel } 35532969bf0eSJack F Vogel 35542969bf0eSJack F Vogel /** 35552969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 35562969bf0eSJack F Vogel * @hw: pointer to hardware structure 35572969bf0eSJack F Vogel * 35582969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 35592969bf0eSJack F Vogel * the capabilities table. 35602969bf0eSJack F Vogel **/ 3561a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 35622969bf0eSJack F Vogel { 3563a621e3c8SJack F Vogel u16 msix_count = 1; 3564a621e3c8SJack F Vogel u16 max_msix_count; 3565a621e3c8SJack F Vogel u16 pcie_offset; 3566a621e3c8SJack F Vogel 3567a621e3c8SJack F Vogel switch (hw->mac.type) { 3568a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3569a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3570a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3571a621e3c8SJack F Vogel break; 3572a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3573a621e3c8SJack F Vogel case ixgbe_mac_X540: 3574*758cc3dcSJack F Vogel case ixgbe_mac_X550: 3575*758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 3576*758cc3dcSJack F Vogel case ixgbe_mac_X550EM_a: 3577a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3578a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3579a621e3c8SJack F Vogel break; 3580a621e3c8SJack F Vogel default: 3581a621e3c8SJack F Vogel return msix_count; 3582a621e3c8SJack F Vogel } 35832969bf0eSJack F Vogel 35842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3585a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3586*758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3587*758cc3dcSJack F Vogel msix_count = 0; 35882969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 35892969bf0eSJack F Vogel 3590a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 35912969bf0eSJack F Vogel msix_count++; 3592a621e3c8SJack F Vogel 3593a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3594a621e3c8SJack F Vogel msix_count = max_msix_count; 35952969bf0eSJack F Vogel 35962969bf0eSJack F Vogel return msix_count; 35972969bf0eSJack F Vogel } 35982969bf0eSJack F Vogel 35992969bf0eSJack F Vogel /** 36002969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 36012969bf0eSJack F Vogel * @hw: pointer to hardware structure 36022969bf0eSJack F Vogel * @addr: Address to put into receive address register 36032969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 36042969bf0eSJack F Vogel * 36052969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 36062969bf0eSJack F Vogel * finds the rar that it is aleady in; adds to the pool list 36072969bf0eSJack F Vogel **/ 36082969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 36092969bf0eSJack F Vogel { 36102969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 36112969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 36122969bf0eSJack F Vogel u32 rar; 36132969bf0eSJack F Vogel u32 rar_low, rar_high; 36142969bf0eSJack F Vogel u32 addr_low, addr_high; 36152969bf0eSJack F Vogel 36162969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 36172969bf0eSJack F Vogel 36182969bf0eSJack F Vogel /* swap bytes for HW little endian */ 36192969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 36202969bf0eSJack F Vogel | (addr[2] << 16) 36212969bf0eSJack F Vogel | (addr[3] << 24); 36222969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 36232969bf0eSJack F Vogel 36242969bf0eSJack F Vogel /* 36252969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 36262969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 36272969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 36282969bf0eSJack F Vogel * rar to the top. 36292969bf0eSJack F Vogel */ 36302969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 36312969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 36322969bf0eSJack F Vogel 36332969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 36342969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 36352969bf0eSJack F Vogel first_empty_rar = rar; 36362969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 36372969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 36382969bf0eSJack F Vogel if (rar_low == addr_low) 36392969bf0eSJack F Vogel break; /* found it already in the rars */ 36402969bf0eSJack F Vogel } 36412969bf0eSJack F Vogel } 36422969bf0eSJack F Vogel 36432969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 36442969bf0eSJack F Vogel /* already there so just add to the pool bits */ 36452969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 36462969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 36472969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 36482969bf0eSJack F Vogel rar = first_empty_rar; 36492969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 36502969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 36512969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 36522969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 36532969bf0eSJack F Vogel hw->mac.rar_highwater++; 36542969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 36552969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 36562969bf0eSJack F Vogel } 36572969bf0eSJack F Vogel 36582969bf0eSJack F Vogel /* 36592969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 36602969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 36612969bf0eSJack F Vogel */ 36622969bf0eSJack F Vogel if (rar == 0) 36632969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 36642969bf0eSJack F Vogel 36652969bf0eSJack F Vogel return rar; 36662969bf0eSJack F Vogel } 36672969bf0eSJack F Vogel 36682969bf0eSJack F Vogel /** 36692969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 36702969bf0eSJack F Vogel * @hw: pointer to hardware struct 36712969bf0eSJack F Vogel * @rar: receive address register index to disassociate 36722969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 36732969bf0eSJack F Vogel **/ 36742969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 36752969bf0eSJack F Vogel { 36762969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 36772969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 36782969bf0eSJack F Vogel 36792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 36802969bf0eSJack F Vogel 36811a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 36821a4e3449SJack F Vogel if (rar >= rar_entries) { 3683fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3684fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 36851a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 36861a4e3449SJack F Vogel } 36871a4e3449SJack F Vogel 36882969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 36892969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 36902969bf0eSJack F Vogel 3691*758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3692*758cc3dcSJack F Vogel goto done; 3693*758cc3dcSJack F Vogel 36942969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 36952969bf0eSJack F Vogel goto done; 36962969bf0eSJack F Vogel 36972969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 36982969bf0eSJack F Vogel if (mpsar_lo) { 36992969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 37002969bf0eSJack F Vogel mpsar_lo = 0; 37012969bf0eSJack F Vogel } 37022969bf0eSJack F Vogel if (mpsar_hi) { 37032969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 37042969bf0eSJack F Vogel mpsar_hi = 0; 37052969bf0eSJack F Vogel } 37062969bf0eSJack F Vogel } else if (vmdq < 32) { 37072969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 37082969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 37092969bf0eSJack F Vogel } else { 37102969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 37112969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 37122969bf0eSJack F Vogel } 37132969bf0eSJack F Vogel 37142969bf0eSJack F Vogel /* was that the last pool using this rar? */ 37152969bf0eSJack F Vogel if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) 37162969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 37172969bf0eSJack F Vogel done: 37182969bf0eSJack F Vogel return IXGBE_SUCCESS; 37192969bf0eSJack F Vogel } 37202969bf0eSJack F Vogel 37212969bf0eSJack F Vogel /** 37222969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 37232969bf0eSJack F Vogel * @hw: pointer to hardware struct 37242969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 37252969bf0eSJack F Vogel * @vmdq: VMDq pool index 37262969bf0eSJack F Vogel **/ 37272969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37282969bf0eSJack F Vogel { 37292969bf0eSJack F Vogel u32 mpsar; 37302969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37312969bf0eSJack F Vogel 37322969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 37332969bf0eSJack F Vogel 37341a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37351a4e3449SJack F Vogel if (rar >= rar_entries) { 3736fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3737fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 37381a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 37391a4e3449SJack F Vogel } 37401a4e3449SJack F Vogel 37412969bf0eSJack F Vogel if (vmdq < 32) { 37422969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 37432969bf0eSJack F Vogel mpsar |= 1 << vmdq; 37442969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 37452969bf0eSJack F Vogel } else { 37462969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 37472969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 37482969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 37492969bf0eSJack F Vogel } 37502969bf0eSJack F Vogel return IXGBE_SUCCESS; 37512969bf0eSJack F Vogel } 37522969bf0eSJack F Vogel 37532969bf0eSJack F Vogel /** 3754a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3755a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3756a621e3c8SJack F Vogel * VFs advertized and not 0. 3757a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3758a621e3c8SJack F Vogel * 3759a621e3c8SJack F Vogel * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address 3760a621e3c8SJack F Vogel * @hw: pointer to hardware struct 3761a621e3c8SJack F Vogel * @vmdq: VMDq pool index 3762a621e3c8SJack F Vogel **/ 3763a621e3c8SJack F Vogel s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 3764a621e3c8SJack F Vogel { 3765a621e3c8SJack F Vogel u32 rar = hw->mac.san_mac_rar_index; 3766a621e3c8SJack F Vogel 3767a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_san_mac"); 3768a621e3c8SJack F Vogel 3769a621e3c8SJack F Vogel if (vmdq < 32) { 3770a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); 3771a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 3772a621e3c8SJack F Vogel } else { 3773a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 3774a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); 3775a621e3c8SJack F Vogel } 3776a621e3c8SJack F Vogel 3777a621e3c8SJack F Vogel return IXGBE_SUCCESS; 3778a621e3c8SJack F Vogel } 3779a621e3c8SJack F Vogel 3780a621e3c8SJack F Vogel /** 37812969bf0eSJack F Vogel * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 37822969bf0eSJack F Vogel * @hw: pointer to hardware structure 37832969bf0eSJack F Vogel **/ 37842969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 37852969bf0eSJack F Vogel { 37862969bf0eSJack F Vogel int i; 37872969bf0eSJack F Vogel 37882969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_uta_tables_generic"); 37892969bf0eSJack F Vogel DEBUGOUT(" Clearing UTA\n"); 37902969bf0eSJack F Vogel 37912969bf0eSJack F Vogel for (i = 0; i < 128; i++) 37922969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 37932969bf0eSJack F Vogel 37942969bf0eSJack F Vogel return IXGBE_SUCCESS; 37952969bf0eSJack F Vogel } 37962969bf0eSJack F Vogel 37972969bf0eSJack F Vogel /** 37982969bf0eSJack F Vogel * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 37992969bf0eSJack F Vogel * @hw: pointer to hardware structure 38002969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 38012969bf0eSJack F Vogel * 38022969bf0eSJack F Vogel * return the VLVF index where this VLAN id should be placed 38032969bf0eSJack F Vogel * 38042969bf0eSJack F Vogel **/ 38052969bf0eSJack F Vogel s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) 38062969bf0eSJack F Vogel { 38072969bf0eSJack F Vogel u32 bits = 0; 38082969bf0eSJack F Vogel u32 first_empty_slot = 0; 38092969bf0eSJack F Vogel s32 regindex; 38102969bf0eSJack F Vogel 3811c0014855SJack F Vogel /* short cut the special case */ 3812c0014855SJack F Vogel if (vlan == 0) 3813c0014855SJack F Vogel return 0; 3814c0014855SJack F Vogel 38152969bf0eSJack F Vogel /* 38162969bf0eSJack F Vogel * Search for the vlan id in the VLVF entries. Save off the first empty 38172969bf0eSJack F Vogel * slot found along the way 38182969bf0eSJack F Vogel */ 38192969bf0eSJack F Vogel for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { 38202969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 38212969bf0eSJack F Vogel if (!bits && !(first_empty_slot)) 38222969bf0eSJack F Vogel first_empty_slot = regindex; 38232969bf0eSJack F Vogel else if ((bits & 0x0FFF) == vlan) 38242969bf0eSJack F Vogel break; 38252969bf0eSJack F Vogel } 38262969bf0eSJack F Vogel 38272969bf0eSJack F Vogel /* 38282969bf0eSJack F Vogel * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan 38292969bf0eSJack F Vogel * in the VLVF. Else use the first empty VLVF register for this 38302969bf0eSJack F Vogel * vlan id. 38312969bf0eSJack F Vogel */ 38322969bf0eSJack F Vogel if (regindex >= IXGBE_VLVF_ENTRIES) { 38332969bf0eSJack F Vogel if (first_empty_slot) 38342969bf0eSJack F Vogel regindex = first_empty_slot; 38352969bf0eSJack F Vogel else { 3836fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, 3837fd75b91dSJack F Vogel "No space in VLVF.\n"); 3838c0014855SJack F Vogel regindex = IXGBE_ERR_NO_SPACE; 38392969bf0eSJack F Vogel } 38402969bf0eSJack F Vogel } 38412969bf0eSJack F Vogel 38422969bf0eSJack F Vogel return regindex; 38432969bf0eSJack F Vogel } 38442969bf0eSJack F Vogel 38452969bf0eSJack F Vogel /** 38462969bf0eSJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 38472969bf0eSJack F Vogel * @hw: pointer to hardware structure 38482969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 38492969bf0eSJack F Vogel * @vind: VMDq output index that maps queue to VLAN id in VFVFB 38502969bf0eSJack F Vogel * @vlan_on: boolean flag to turn on/off VLAN in VFVF 38512969bf0eSJack F Vogel * 38522969bf0eSJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 38532969bf0eSJack F Vogel **/ 38542969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 38552969bf0eSJack F Vogel bool vlan_on) 38562969bf0eSJack F Vogel { 38572969bf0eSJack F Vogel s32 regindex; 38582969bf0eSJack F Vogel u32 bitindex; 3859c0014855SJack F Vogel u32 vfta; 3860c0014855SJack F Vogel u32 targetbit; 386185d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3862c0014855SJack F Vogel bool vfta_changed = FALSE; 38632969bf0eSJack F Vogel 38642969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vfta_generic"); 38652969bf0eSJack F Vogel 38662969bf0eSJack F Vogel if (vlan > 4095) 38672969bf0eSJack F Vogel return IXGBE_ERR_PARAM; 38682969bf0eSJack F Vogel 38692969bf0eSJack F Vogel /* 38702969bf0eSJack F Vogel * this is a 2 part operation - first the VFTA, then the 38712969bf0eSJack F Vogel * VLVF and VLVFB if VT Mode is set 3872c0014855SJack F Vogel * We don't write the VFTA until we know the VLVF part succeeded. 38732969bf0eSJack F Vogel */ 38742969bf0eSJack F Vogel 38752969bf0eSJack F Vogel /* Part 1 38762969bf0eSJack F Vogel * The VFTA is a bitstring made up of 128 32-bit registers 38772969bf0eSJack F Vogel * that enable the particular VLAN id, much like the MTA: 38782969bf0eSJack F Vogel * bits[11-5]: which register 38792969bf0eSJack F Vogel * bits[4-0]: which bit in the register 38802969bf0eSJack F Vogel */ 38812969bf0eSJack F Vogel regindex = (vlan >> 5) & 0x7F; 38822969bf0eSJack F Vogel bitindex = vlan & 0x1F; 3883c0014855SJack F Vogel targetbit = (1 << bitindex); 3884c0014855SJack F Vogel vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); 38852969bf0eSJack F Vogel 3886c0014855SJack F Vogel if (vlan_on) { 3887c0014855SJack F Vogel if (!(vfta & targetbit)) { 3888c0014855SJack F Vogel vfta |= targetbit; 3889c0014855SJack F Vogel vfta_changed = TRUE; 3890c0014855SJack F Vogel } 3891c0014855SJack F Vogel } else { 3892c0014855SJack F Vogel if ((vfta & targetbit)) { 3893c0014855SJack F Vogel vfta &= ~targetbit; 3894c0014855SJack F Vogel vfta_changed = TRUE; 3895c0014855SJack F Vogel } 3896c0014855SJack F Vogel } 38972969bf0eSJack F Vogel 38982969bf0eSJack F Vogel /* Part 2 389985d0a26eSJack F Vogel * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF 390085d0a26eSJack F Vogel */ 390185d0a26eSJack F Vogel ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, 390285d0a26eSJack F Vogel &vfta_changed); 390385d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 390485d0a26eSJack F Vogel return ret_val; 390585d0a26eSJack F Vogel 390685d0a26eSJack F Vogel if (vfta_changed) 390785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta); 390885d0a26eSJack F Vogel 390985d0a26eSJack F Vogel return IXGBE_SUCCESS; 391085d0a26eSJack F Vogel } 391185d0a26eSJack F Vogel 391285d0a26eSJack F Vogel /** 391385d0a26eSJack F Vogel * ixgbe_set_vlvf_generic - Set VLAN Pool Filter 391485d0a26eSJack F Vogel * @hw: pointer to hardware structure 391585d0a26eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 391685d0a26eSJack F Vogel * @vind: VMDq output index that maps queue to VLAN id in VFVFB 391785d0a26eSJack F Vogel * @vlan_on: boolean flag to turn on/off VLAN in VFVF 391885d0a26eSJack F Vogel * @vfta_changed: pointer to boolean flag which indicates whether VFTA 391985d0a26eSJack F Vogel * should be changed 392085d0a26eSJack F Vogel * 392185d0a26eSJack F Vogel * Turn on/off specified bit in VLVF table. 392285d0a26eSJack F Vogel **/ 392385d0a26eSJack F Vogel s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 392485d0a26eSJack F Vogel bool vlan_on, bool *vfta_changed) 392585d0a26eSJack F Vogel { 392685d0a26eSJack F Vogel u32 vt; 392785d0a26eSJack F Vogel 392885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_vlvf_generic"); 392985d0a26eSJack F Vogel 393085d0a26eSJack F Vogel if (vlan > 4095) 393185d0a26eSJack F Vogel return IXGBE_ERR_PARAM; 393285d0a26eSJack F Vogel 393385d0a26eSJack F Vogel /* If VT Mode is set 39342969bf0eSJack F Vogel * Either vlan_on 39352969bf0eSJack F Vogel * make sure the vlan is in VLVF 39362969bf0eSJack F Vogel * set the vind bit in the matching VLVFB 39372969bf0eSJack F Vogel * Or !vlan_on 39382969bf0eSJack F Vogel * clear the pool bit and possibly the vind 39392969bf0eSJack F Vogel */ 39402969bf0eSJack F Vogel vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); 39412969bf0eSJack F Vogel if (vt & IXGBE_VT_CTL_VT_ENABLE) { 3942c0014855SJack F Vogel s32 vlvf_index; 394385d0a26eSJack F Vogel u32 bits; 3944c0014855SJack F Vogel 3945c0014855SJack F Vogel vlvf_index = ixgbe_find_vlvf_slot(hw, vlan); 3946c0014855SJack F Vogel if (vlvf_index < 0) 3947c0014855SJack F Vogel return vlvf_index; 39482969bf0eSJack F Vogel 39492969bf0eSJack F Vogel if (vlan_on) { 39502969bf0eSJack F Vogel /* set the pool bit */ 39512969bf0eSJack F Vogel if (vind < 32) { 39522969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, 3953c0014855SJack F Vogel IXGBE_VLVFB(vlvf_index * 2)); 39542969bf0eSJack F Vogel bits |= (1 << vind); 39552969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, 3956c0014855SJack F Vogel IXGBE_VLVFB(vlvf_index * 2), 39572969bf0eSJack F Vogel bits); 39582969bf0eSJack F Vogel } else { 39592969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, 3960c0014855SJack F Vogel IXGBE_VLVFB((vlvf_index * 2) + 1)); 3961c0014855SJack F Vogel bits |= (1 << (vind - 32)); 39622969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, 3963c0014855SJack F Vogel IXGBE_VLVFB((vlvf_index * 2) + 1), 39642969bf0eSJack F Vogel bits); 39652969bf0eSJack F Vogel } 39662969bf0eSJack F Vogel } else { 39672969bf0eSJack F Vogel /* clear the pool bit */ 39682969bf0eSJack F Vogel if (vind < 32) { 39692969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, 3970c0014855SJack F Vogel IXGBE_VLVFB(vlvf_index * 2)); 39712969bf0eSJack F Vogel bits &= ~(1 << vind); 39722969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, 3973c0014855SJack F Vogel IXGBE_VLVFB(vlvf_index * 2), 39742969bf0eSJack F Vogel bits); 39752969bf0eSJack F Vogel bits |= IXGBE_READ_REG(hw, 3976c0014855SJack F Vogel IXGBE_VLVFB((vlvf_index * 2) + 1)); 39772969bf0eSJack F Vogel } else { 39782969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, 3979c0014855SJack F Vogel IXGBE_VLVFB((vlvf_index * 2) + 1)); 3980c0014855SJack F Vogel bits &= ~(1 << (vind - 32)); 39812969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, 3982c0014855SJack F Vogel IXGBE_VLVFB((vlvf_index * 2) + 1), 39832969bf0eSJack F Vogel bits); 39842969bf0eSJack F Vogel bits |= IXGBE_READ_REG(hw, 3985c0014855SJack F Vogel IXGBE_VLVFB(vlvf_index * 2)); 39862969bf0eSJack F Vogel } 39872969bf0eSJack F Vogel } 39882969bf0eSJack F Vogel 3989c0014855SJack F Vogel /* 3990c0014855SJack F Vogel * If there are still bits set in the VLVFB registers 3991c0014855SJack F Vogel * for the VLAN ID indicated we need to see if the 3992c0014855SJack F Vogel * caller is requesting that we clear the VFTA entry bit. 3993c0014855SJack F Vogel * If the caller has requested that we clear the VFTA 3994c0014855SJack F Vogel * entry bit but there are still pools/VFs using this VLAN 3995c0014855SJack F Vogel * ID entry then ignore the request. We're not worried 3996c0014855SJack F Vogel * about the case where we're turning the VFTA VLAN ID 3997c0014855SJack F Vogel * entry bit on, only when requested to turn it off as 3998c0014855SJack F Vogel * there may be multiple pools and/or VFs using the 3999c0014855SJack F Vogel * VLAN ID entry. In that case we cannot clear the 4000c0014855SJack F Vogel * VFTA bit until all pools/VFs using that VLAN ID have also 4001c0014855SJack F Vogel * been cleared. This will be indicated by "bits" being 4002c0014855SJack F Vogel * zero. 4003c0014855SJack F Vogel */ 4004c0014855SJack F Vogel if (bits) { 4005c0014855SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 40062969bf0eSJack F Vogel (IXGBE_VLVF_VIEN | vlan)); 400785d0a26eSJack F Vogel if ((!vlan_on) && (vfta_changed != NULL)) { 4008c0014855SJack F Vogel /* someone wants to clear the vfta entry 4009c0014855SJack F Vogel * but some pools/VFs are still using it. 4010c0014855SJack F Vogel * Ignore it. */ 401185d0a26eSJack F Vogel *vfta_changed = FALSE; 40122969bf0eSJack F Vogel } 401385d0a26eSJack F Vogel } else 4014c0014855SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 4015c0014855SJack F Vogel } 4016c0014855SJack F Vogel 40172969bf0eSJack F Vogel return IXGBE_SUCCESS; 40182969bf0eSJack F Vogel } 40192969bf0eSJack F Vogel 40202969bf0eSJack F Vogel /** 40212969bf0eSJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 40222969bf0eSJack F Vogel * @hw: pointer to hardware structure 40232969bf0eSJack F Vogel * 40242969bf0eSJack F Vogel * Clears the VLAN filer table, and the VMDq index associated with the filter 40252969bf0eSJack F Vogel **/ 40262969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 40272969bf0eSJack F Vogel { 40282969bf0eSJack F Vogel u32 offset; 40292969bf0eSJack F Vogel 40302969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vfta_generic"); 40312969bf0eSJack F Vogel 40322969bf0eSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 40332969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 40342969bf0eSJack F Vogel 40352969bf0eSJack F Vogel for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 40362969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 40372969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 40382969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); 40392969bf0eSJack F Vogel } 40402969bf0eSJack F Vogel 40412969bf0eSJack F Vogel return IXGBE_SUCCESS; 40422969bf0eSJack F Vogel } 40432969bf0eSJack F Vogel 40442969bf0eSJack F Vogel /** 40452969bf0eSJack F Vogel * ixgbe_check_mac_link_generic - Determine link and speed status 40462969bf0eSJack F Vogel * @hw: pointer to hardware structure 40472969bf0eSJack F Vogel * @speed: pointer to link speed 40482969bf0eSJack F Vogel * @link_up: TRUE when link is up 40492969bf0eSJack F Vogel * @link_up_wait_to_complete: bool used to wait for link up or not 40502969bf0eSJack F Vogel * 40512969bf0eSJack F Vogel * Reads the links register to determine if link is up and the current speed 40522969bf0eSJack F Vogel **/ 40532969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 40542969bf0eSJack F Vogel bool *link_up, bool link_up_wait_to_complete) 40552969bf0eSJack F Vogel { 4056c0014855SJack F Vogel u32 links_reg, links_orig; 40572969bf0eSJack F Vogel u32 i; 40582969bf0eSJack F Vogel 40592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_check_mac_link_generic"); 40602969bf0eSJack F Vogel 4061c0014855SJack F Vogel /* clear the old state */ 4062c0014855SJack F Vogel links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 4063c0014855SJack F Vogel 40642969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 4065c0014855SJack F Vogel 4066c0014855SJack F Vogel if (links_orig != links_reg) { 4067c0014855SJack F Vogel DEBUGOUT2("LINKS changed from %08X to %08X\n", 4068c0014855SJack F Vogel links_orig, links_reg); 4069c0014855SJack F Vogel } 4070c0014855SJack F Vogel 40712969bf0eSJack F Vogel if (link_up_wait_to_complete) { 40722969bf0eSJack F Vogel for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { 40732969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) { 40742969bf0eSJack F Vogel *link_up = TRUE; 40752969bf0eSJack F Vogel break; 40762969bf0eSJack F Vogel } else { 40772969bf0eSJack F Vogel *link_up = FALSE; 40782969bf0eSJack F Vogel } 40792969bf0eSJack F Vogel msec_delay(100); 40802969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 40812969bf0eSJack F Vogel } 40822969bf0eSJack F Vogel } else { 40832969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) 40842969bf0eSJack F Vogel *link_up = TRUE; 40852969bf0eSJack F Vogel else 40862969bf0eSJack F Vogel *link_up = FALSE; 40872969bf0eSJack F Vogel } 40882969bf0eSJack F Vogel 4089*758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4090*758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 40912969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4092*758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4093*758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4094*758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4095*758cc3dcSJack F Vogel } 4096*758cc3dcSJack F Vogel break; 4097*758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 40982969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4099*758cc3dcSJack F Vogel break; 4100*758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 41012969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 4102*758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4103*758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4104*758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4105*758cc3dcSJack F Vogel } 4106*758cc3dcSJack F Vogel break; 4107*758cc3dcSJack F Vogel default: 41081a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4109*758cc3dcSJack F Vogel } 41102969bf0eSJack F Vogel 41112969bf0eSJack F Vogel return IXGBE_SUCCESS; 41122969bf0eSJack F Vogel } 41132969bf0eSJack F Vogel 41142969bf0eSJack F Vogel /** 41152969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 41162969bf0eSJack F Vogel * the EEPROM 41172969bf0eSJack F Vogel * @hw: pointer to hardware structure 41182969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 41192969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 41202969bf0eSJack F Vogel * 41212969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 41222969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 41232969bf0eSJack F Vogel **/ 41242969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 41252969bf0eSJack F Vogel u16 *wwpn_prefix) 41262969bf0eSJack F Vogel { 41272969bf0eSJack F Vogel u16 offset, caps; 41282969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 41292969bf0eSJack F Vogel 41302969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 41312969bf0eSJack F Vogel 41322969bf0eSJack F Vogel /* clear output first */ 41332969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 41342969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 41352969bf0eSJack F Vogel 41362969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4137fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4138fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4139fd75b91dSJack F Vogel goto wwn_prefix_err; 41402969bf0eSJack F Vogel 41412969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 41422969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 41432969bf0eSJack F Vogel goto wwn_prefix_out; 41442969bf0eSJack F Vogel 41452969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 41462969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4147fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4148fd75b91dSJack F Vogel goto wwn_prefix_err; 41492969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 41502969bf0eSJack F Vogel goto wwn_prefix_out; 41512969bf0eSJack F Vogel 41522969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 41532969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4154fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4155fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4156fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4157fd75b91dSJack F Vogel } 41582969bf0eSJack F Vogel 41592969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4160fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4161fd75b91dSJack F Vogel goto wwn_prefix_err; 41622969bf0eSJack F Vogel 41632969bf0eSJack F Vogel wwn_prefix_out: 41642969bf0eSJack F Vogel return IXGBE_SUCCESS; 4165fd75b91dSJack F Vogel 4166fd75b91dSJack F Vogel wwn_prefix_err: 4167fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4168fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4169fd75b91dSJack F Vogel return IXGBE_SUCCESS; 41702969bf0eSJack F Vogel } 41711a4e3449SJack F Vogel 41721a4e3449SJack F Vogel /** 41731a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 41741a4e3449SJack F Vogel * @hw: pointer to hardware structure 41751a4e3449SJack F Vogel * @bs: the fcoe boot status 41761a4e3449SJack F Vogel * 41771a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 41781a4e3449SJack F Vogel **/ 41791a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 41801a4e3449SJack F Vogel { 41811a4e3449SJack F Vogel u16 offset, caps, flags; 41821a4e3449SJack F Vogel s32 status; 41831a4e3449SJack F Vogel 41841a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 41851a4e3449SJack F Vogel 41861a4e3449SJack F Vogel /* clear output first */ 41871a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 41881a4e3449SJack F Vogel 41891a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 41901a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 41911a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 41921a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 41931a4e3449SJack F Vogel goto out; 41941a4e3449SJack F Vogel 41951a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 41961a4e3449SJack F Vogel goto out; 41971a4e3449SJack F Vogel 41981a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 41991a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 42001a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 42011a4e3449SJack F Vogel goto out; 42021a4e3449SJack F Vogel 42031a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 42041a4e3449SJack F Vogel goto out; 42051a4e3449SJack F Vogel 42061a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 42071a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 42081a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 42091a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 42101a4e3449SJack F Vogel goto out; 42111a4e3449SJack F Vogel 42121a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 42131a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 42141a4e3449SJack F Vogel else 42151a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 42161a4e3449SJack F Vogel 42171a4e3449SJack F Vogel out: 42181a4e3449SJack F Vogel return status; 42191a4e3449SJack F Vogel } 42201a4e3449SJack F Vogel 42211a4e3449SJack F Vogel /** 42221a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 42231a4e3449SJack F Vogel * @hw: pointer to hardware structure 42241a4e3449SJack F Vogel * @enable: enable or disable switch for anti-spoofing 42251a4e3449SJack F Vogel * @pf: Physical Function pool - do not enable anti-spoofing for the PF 42261a4e3449SJack F Vogel * 42271a4e3449SJack F Vogel **/ 42281a4e3449SJack F Vogel void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf) 42291a4e3449SJack F Vogel { 42301a4e3449SJack F Vogel int j; 42311a4e3449SJack F Vogel int pf_target_reg = pf >> 3; 42321a4e3449SJack F Vogel int pf_target_shift = pf % 8; 42331a4e3449SJack F Vogel u32 pfvfspoof = 0; 42341a4e3449SJack F Vogel 42351a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 42361a4e3449SJack F Vogel return; 42371a4e3449SJack F Vogel 42381a4e3449SJack F Vogel if (enable) 42391a4e3449SJack F Vogel pfvfspoof = IXGBE_SPOOF_MACAS_MASK; 42401a4e3449SJack F Vogel 42411a4e3449SJack F Vogel /* 42421a4e3449SJack F Vogel * PFVFSPOOF register array is size 8 with 8 bits assigned to 42431a4e3449SJack F Vogel * MAC anti-spoof enables in each register array element. 42441a4e3449SJack F Vogel */ 4245a621e3c8SJack F Vogel for (j = 0; j < pf_target_reg; j++) 42461a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); 42471a4e3449SJack F Vogel 42481a4e3449SJack F Vogel /* 42491a4e3449SJack F Vogel * The PF should be allowed to spoof so that it can support 4250a621e3c8SJack F Vogel * emulation mode NICs. Do not set the bits assigned to the PF 42511a4e3449SJack F Vogel */ 4252a621e3c8SJack F Vogel pfvfspoof &= (1 << pf_target_shift) - 1; 4253a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); 4254a621e3c8SJack F Vogel 4255a621e3c8SJack F Vogel /* 4256a621e3c8SJack F Vogel * Remaining pools belong to the PF so they do not need to have 4257a621e3c8SJack F Vogel * anti-spoofing enabled. 4258a621e3c8SJack F Vogel */ 4259a621e3c8SJack F Vogel for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++) 4260a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0); 42611a4e3449SJack F Vogel } 42621a4e3449SJack F Vogel 42631a4e3449SJack F Vogel /** 42641a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 42651a4e3449SJack F Vogel * @hw: pointer to hardware structure 42661a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4267*758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 42681a4e3449SJack F Vogel * 42691a4e3449SJack F Vogel **/ 42701a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 42711a4e3449SJack F Vogel { 42721a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 42731a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 42741a4e3449SJack F Vogel u32 pfvfspoof; 42751a4e3449SJack F Vogel 42761a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 42771a4e3449SJack F Vogel return; 42781a4e3449SJack F Vogel 42791a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 42801a4e3449SJack F Vogel if (enable) 42811a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 42821a4e3449SJack F Vogel else 42831a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 42841a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 42851a4e3449SJack F Vogel } 4286182b3808SJack F Vogel 4287182b3808SJack F Vogel /** 4288182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4289182b3808SJack F Vogel * @hw: pointer to hardware structure 4290182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4291182b3808SJack F Vogel * 4292182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4293182b3808SJack F Vogel * and return the word through device_caps. 4294182b3808SJack F Vogel **/ 4295182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4296182b3808SJack F Vogel { 4297182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4298182b3808SJack F Vogel 4299182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4300182b3808SJack F Vogel 4301182b3808SJack F Vogel return IXGBE_SUCCESS; 4302182b3808SJack F Vogel } 4303182b3808SJack F Vogel 4304182b3808SJack F Vogel /** 4305182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4306182b3808SJack F Vogel * @hw: pointer to hardware structure 4307182b3808SJack F Vogel * 4308182b3808SJack F Vogel **/ 4309182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4310182b3808SJack F Vogel { 4311182b3808SJack F Vogel u32 regval; 4312182b3808SJack F Vogel u32 i; 4313182b3808SJack F Vogel 4314182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4315182b3808SJack F Vogel 4316182b3808SJack F Vogel /* Enable relaxed ordering */ 4317182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4318182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4319a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4320182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4321182b3808SJack F Vogel } 4322182b3808SJack F Vogel 4323182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4324182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4325a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4326a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4327182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4328182b3808SJack F Vogel } 4329182b3808SJack F Vogel 4330182b3808SJack F Vogel } 433185d0a26eSJack F Vogel 433285d0a26eSJack F Vogel /** 433385d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 433485d0a26eSJack F Vogel * @buffer: pointer to EEPROM 433585d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 433685d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 433785d0a26eSJack F Vogel * checksum calculated is returned. 433885d0a26eSJack F Vogel **/ 43390ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 434085d0a26eSJack F Vogel { 434185d0a26eSJack F Vogel u32 i; 434285d0a26eSJack F Vogel u8 sum = 0; 434385d0a26eSJack F Vogel 434485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 434585d0a26eSJack F Vogel 434685d0a26eSJack F Vogel if (!buffer) 434785d0a26eSJack F Vogel return 0; 434885d0a26eSJack F Vogel 434985d0a26eSJack F Vogel for (i = 0; i < length; i++) 435085d0a26eSJack F Vogel sum += buffer[i]; 435185d0a26eSJack F Vogel 435285d0a26eSJack F Vogel return (u8) (0 - sum); 435385d0a26eSJack F Vogel } 435485d0a26eSJack F Vogel 435585d0a26eSJack F Vogel /** 435685d0a26eSJack F Vogel * ixgbe_host_interface_command - Issue command to manageability block 435785d0a26eSJack F Vogel * @hw: pointer to the HW structure 435885d0a26eSJack F Vogel * @buffer: contains the command to write and where the return status will 435985d0a26eSJack F Vogel * be placed 4360a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4361*758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 4362*758cc3dcSJack F Vogel * @return_data: read and return data from the buffer (TRUE) or not (FALSE) 4363*758cc3dcSJack F Vogel * Needed because FW structures are big endian and decoding of 4364*758cc3dcSJack F Vogel * these fields can be 8 bit or 16 bit based on command. Decoding 4365*758cc3dcSJack F Vogel * is not easily understood without making a table of commands. 4366*758cc3dcSJack F Vogel * So we will leave this up to the caller to read back the data 4367*758cc3dcSJack F Vogel * in these cases. 436885d0a26eSJack F Vogel * 436985d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 437085d0a26eSJack F Vogel * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. 437185d0a26eSJack F Vogel **/ 43720ecc2ff0SJack F Vogel s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 4373*758cc3dcSJack F Vogel u32 length, u32 timeout, bool return_data) 437485d0a26eSJack F Vogel { 4375*758cc3dcSJack F Vogel u32 hicr, i, bi, fwsts; 437685d0a26eSJack F Vogel u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 4377*758cc3dcSJack F Vogel u16 buf_len; 4378*758cc3dcSJack F Vogel u16 dword_len; 437985d0a26eSJack F Vogel 438085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_host_interface_command"); 438185d0a26eSJack F Vogel 4382*758cc3dcSJack F Vogel if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4383*758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4384*758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 438585d0a26eSJack F Vogel } 4386*758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4387*758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4388*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 438985d0a26eSJack F Vogel 439085d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 439185d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 439285d0a26eSJack F Vogel if ((hicr & IXGBE_HICR_EN) == 0) { 439385d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4394*758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 439585d0a26eSJack F Vogel } 439685d0a26eSJack F Vogel 4397*758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 4398*758cc3dcSJack F Vogel if ((length % (sizeof(u32))) != 0) { 4399*758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4400*758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4401*758cc3dcSJack F Vogel } 4402*758cc3dcSJack F Vogel 440385d0a26eSJack F Vogel dword_len = length >> 2; 440485d0a26eSJack F Vogel 4405*758cc3dcSJack F Vogel /* The device driver writes the relevant command block 440685d0a26eSJack F Vogel * into the ram area. 440785d0a26eSJack F Vogel */ 440885d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 440985d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 441085d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 441185d0a26eSJack F Vogel 441285d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 441385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 441485d0a26eSJack F Vogel 4415*758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 441685d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 441785d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 441885d0a26eSJack F Vogel break; 441985d0a26eSJack F Vogel msec_delay(1); 442085d0a26eSJack F Vogel } 442185d0a26eSJack F Vogel 4422*758cc3dcSJack F Vogel /* Check command completion */ 4423*758cc3dcSJack F Vogel if ((timeout != 0 && i == timeout) || 4424*758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4425*758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4426*758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4427*758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 442885d0a26eSJack F Vogel } 442985d0a26eSJack F Vogel 4430*758cc3dcSJack F Vogel if (!return_data) 4431*758cc3dcSJack F Vogel return 0; 4432*758cc3dcSJack F Vogel 443385d0a26eSJack F Vogel /* Calculate length in DWORDs */ 443485d0a26eSJack F Vogel dword_len = hdr_size >> 2; 443585d0a26eSJack F Vogel 443685d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 443785d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 443885d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 443985d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 444085d0a26eSJack F Vogel } 444185d0a26eSJack F Vogel 444285d0a26eSJack F Vogel /* If there is any thing in data position pull it in */ 444385d0a26eSJack F Vogel buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; 444485d0a26eSJack F Vogel if (buf_len == 0) 4445*758cc3dcSJack F Vogel return 0; 444685d0a26eSJack F Vogel 4447*758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 444885d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 4449*758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 445085d0a26eSJack F Vogel } 445185d0a26eSJack F Vogel 445285d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 445385d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 445485d0a26eSJack F Vogel 445585d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 445685d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 445785d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 445885d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 445985d0a26eSJack F Vogel } 446085d0a26eSJack F Vogel 4461*758cc3dcSJack F Vogel return 0; 446285d0a26eSJack F Vogel } 446385d0a26eSJack F Vogel 446485d0a26eSJack F Vogel /** 446585d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 446685d0a26eSJack F Vogel * @hw: pointer to the HW structure 446785d0a26eSJack F Vogel * @maj: driver version major number 446885d0a26eSJack F Vogel * @min: driver version minor number 446985d0a26eSJack F Vogel * @build: driver version build number 447085d0a26eSJack F Vogel * @sub: driver version sub build number 447185d0a26eSJack F Vogel * 447285d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 447385d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 447485d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 447585d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 447685d0a26eSJack F Vogel **/ 447785d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 447885d0a26eSJack F Vogel u8 build, u8 sub) 447985d0a26eSJack F Vogel { 448085d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 448185d0a26eSJack F Vogel int i; 448285d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 448385d0a26eSJack F Vogel 448485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 448585d0a26eSJack F Vogel 448685d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) 448785d0a26eSJack F Vogel != IXGBE_SUCCESS) { 448885d0a26eSJack F Vogel ret_val = IXGBE_ERR_SWFW_SYNC; 448985d0a26eSJack F Vogel goto out; 449085d0a26eSJack F Vogel } 449185d0a26eSJack F Vogel 449285d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 449385d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 449485d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 449585d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 449685d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 449785d0a26eSJack F Vogel fw_cmd.ver_min = min; 449885d0a26eSJack F Vogel fw_cmd.ver_build = build; 449985d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 450085d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 450185d0a26eSJack F Vogel fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 450285d0a26eSJack F Vogel (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 450385d0a26eSJack F Vogel fw_cmd.pad = 0; 450485d0a26eSJack F Vogel fw_cmd.pad2 = 0; 450585d0a26eSJack F Vogel 450685d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 450785d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4508*758cc3dcSJack F Vogel sizeof(fw_cmd), 4509*758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 4510*758cc3dcSJack F Vogel TRUE); 451185d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 451285d0a26eSJack F Vogel continue; 451385d0a26eSJack F Vogel 451485d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 451585d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 451685d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 451785d0a26eSJack F Vogel else 451885d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 451985d0a26eSJack F Vogel 452085d0a26eSJack F Vogel break; 452185d0a26eSJack F Vogel } 452285d0a26eSJack F Vogel 452385d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 452485d0a26eSJack F Vogel out: 452585d0a26eSJack F Vogel return ret_val; 452685d0a26eSJack F Vogel } 452785d0a26eSJack F Vogel 452885d0a26eSJack F Vogel /** 452985d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 453085d0a26eSJack F Vogel * @hw: pointer to hardware structure 453185d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 453285d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 453385d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 453485d0a26eSJack F Vogel **/ 453585d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 453685d0a26eSJack F Vogel int strategy) 453785d0a26eSJack F Vogel { 453885d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 453985d0a26eSJack F Vogel int i = 0; 454085d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 454185d0a26eSJack F Vogel 454285d0a26eSJack F Vogel /* Reserve headroom */ 454385d0a26eSJack F Vogel pbsize -= headroom; 454485d0a26eSJack F Vogel 454585d0a26eSJack F Vogel if (!num_pb) 454685d0a26eSJack F Vogel num_pb = 1; 454785d0a26eSJack F Vogel 454885d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 454985d0a26eSJack F Vogel * buffers requested using supplied strategy. 455085d0a26eSJack F Vogel */ 455185d0a26eSJack F Vogel switch (strategy) { 4552a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 455385d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 455485d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 455585d0a26eSJack F Vogel */ 4556a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 455785d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 455885d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 455985d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 456085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 456185d0a26eSJack F Vogel /* Fall through to configure remaining packet buffers */ 4562a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 456385d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 456485d0a26eSJack F Vogel for (; i < num_pb; i++) 456585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 456685d0a26eSJack F Vogel break; 456785d0a26eSJack F Vogel default: 456885d0a26eSJack F Vogel break; 456985d0a26eSJack F Vogel } 457085d0a26eSJack F Vogel 457185d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 457285d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 457385d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 457485d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 457585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 457685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 457785d0a26eSJack F Vogel } 457885d0a26eSJack F Vogel 457985d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 458085d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 458185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 458285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 458385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 458485d0a26eSJack F Vogel } 458585d0a26eSJack F Vogel } 458685d0a26eSJack F Vogel 458785d0a26eSJack F Vogel /** 458885d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 458985d0a26eSJack F Vogel * @hw: pointer to the hardware structure 459085d0a26eSJack F Vogel * 459185d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 459285d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 459385d0a26eSJack F Vogel * buffers on the system. 459485d0a26eSJack F Vogel **/ 459585d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 459685d0a26eSJack F Vogel { 4597*758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4598*758cc3dcSJack F Vogel u16 value; 459985d0a26eSJack F Vogel 460085d0a26eSJack F Vogel /* 460185d0a26eSJack F Vogel * If double reset is not requested then all transactions should 460285d0a26eSJack F Vogel * already be clear and as such there is no work to do 460385d0a26eSJack F Vogel */ 460485d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 460585d0a26eSJack F Vogel return; 460685d0a26eSJack F Vogel 460785d0a26eSJack F Vogel /* 460885d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 460985d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 461085d0a26eSJack F Vogel * has already been cleared. 461185d0a26eSJack F Vogel */ 461285d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 461385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 461485d0a26eSJack F Vogel 4615*758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4616*758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4617*758cc3dcSJack F Vogel msec_delay(3); 4618*758cc3dcSJack F Vogel 4619*758cc3dcSJack F Vogel /* 4620*758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4621*758cc3dcSJack F Vogel * transactions pending. 4622*758cc3dcSJack F Vogel */ 4623*758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4624*758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4625*758cc3dcSJack F Vogel usec_delay(100); 4626*758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4627*758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4628*758cc3dcSJack F Vogel goto out; 4629*758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4630*758cc3dcSJack F Vogel goto out; 4631*758cc3dcSJack F Vogel } 4632*758cc3dcSJack F Vogel 4633*758cc3dcSJack F Vogel out: 463485d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 463585d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 463685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 463785d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 463885d0a26eSJack F Vogel 463985d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 464085d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 464185d0a26eSJack F Vogel usec_delay(20); 464285d0a26eSJack F Vogel 464385d0a26eSJack F Vogel /* restore previous register values */ 464485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 464585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 464685d0a26eSJack F Vogel } 464785d0a26eSJack F Vogel 4648fd75b91dSJack F Vogel 4649fd75b91dSJack F Vogel /** 4650fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 4651fd75b91dSJack F Vogel * @hw: pointer to hardware structure 4652fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 4653fd75b91dSJack F Vogel * 4654fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 4655fd75b91dSJack F Vogel **/ 4656fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 4657fd75b91dSJack F Vogel { 4658fd75b91dSJack F Vogel u32 reg, i; 4659fd75b91dSJack F Vogel 4660fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 4661fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 4662fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 4663fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 4664fd75b91dSJack F Vogel return; 4665fd75b91dSJack F Vogel } 4666*758cc3dcSJack F Vogel 4667*758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 4668*758cc3dcSJack F Vogel { 4669*758cc3dcSJack F Vogel u32 pfdtxgswc; 4670*758cc3dcSJack F Vogel u32 rxctrl; 4671*758cc3dcSJack F Vogel 4672*758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 4673*758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 4674*758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 4675*758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 4676*758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 4677*758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 4678*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 4679*758cc3dcSJack F Vogel hw->mac.set_lben = TRUE; 4680*758cc3dcSJack F Vogel } else { 4681*758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 4682*758cc3dcSJack F Vogel } 4683*758cc3dcSJack F Vogel } 4684*758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 4685*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 4686*758cc3dcSJack F Vogel } 4687*758cc3dcSJack F Vogel } 4688*758cc3dcSJack F Vogel 4689*758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 4690*758cc3dcSJack F Vogel { 4691*758cc3dcSJack F Vogel u32 pfdtxgswc; 4692*758cc3dcSJack F Vogel u32 rxctrl; 4693*758cc3dcSJack F Vogel 4694*758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 4695*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 4696*758cc3dcSJack F Vogel 4697*758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 4698*758cc3dcSJack F Vogel if (hw->mac.set_lben) { 4699*758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 4700*758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 4701*758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 4702*758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 4703*758cc3dcSJack F Vogel } 4704*758cc3dcSJack F Vogel } 4705*758cc3dcSJack F Vogel } 4706*758cc3dcSJack F Vogel 4707*758cc3dcSJack F Vogel /** 4708*758cc3dcSJack F Vogel * ixgbe_mng_present - returns TRUE when management capability is present 4709*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 4710*758cc3dcSJack F Vogel */ 4711*758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 4712*758cc3dcSJack F Vogel { 4713*758cc3dcSJack F Vogel u32 fwsm; 4714*758cc3dcSJack F Vogel 4715*758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 4716*758cc3dcSJack F Vogel return FALSE; 4717*758cc3dcSJack F Vogel 4718*758cc3dcSJack F Vogel fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 4719*758cc3dcSJack F Vogel fwsm &= IXGBE_FWSM_MODE_MASK; 4720*758cc3dcSJack F Vogel return fwsm == IXGBE_FWSM_FW_MODE_PT; 4721*758cc3dcSJack F Vogel } 4722*758cc3dcSJack F Vogel 4723*758cc3dcSJack F Vogel /** 4724*758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 4725*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 4726*758cc3dcSJack F Vogel * 4727*758cc3dcSJack F Vogel * Returns TRUE if the manageability engine is enabled. 4728*758cc3dcSJack F Vogel **/ 4729*758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 4730*758cc3dcSJack F Vogel { 4731*758cc3dcSJack F Vogel u32 fwsm, manc, factps; 4732*758cc3dcSJack F Vogel 4733*758cc3dcSJack F Vogel fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); 4734*758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 4735*758cc3dcSJack F Vogel return FALSE; 4736*758cc3dcSJack F Vogel 4737*758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 4738*758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 4739*758cc3dcSJack F Vogel return FALSE; 4740*758cc3dcSJack F Vogel 4741*758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 4742*758cc3dcSJack F Vogel factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); 4743*758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 4744*758cc3dcSJack F Vogel return FALSE; 4745*758cc3dcSJack F Vogel } 4746*758cc3dcSJack F Vogel 4747*758cc3dcSJack F Vogel return TRUE; 4748*758cc3dcSJack F Vogel } 4749*758cc3dcSJack F Vogel 4750*758cc3dcSJack F Vogel /** 4751*758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 4752*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 4753*758cc3dcSJack F Vogel * @speed: new link speed 4754*758cc3dcSJack F Vogel * @autoneg_wait_to_complete: TRUE when waiting for completion is needed 4755*758cc3dcSJack F Vogel * 4756*758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 4757*758cc3dcSJack F Vogel **/ 4758*758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 4759*758cc3dcSJack F Vogel ixgbe_link_speed speed, 4760*758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 4761*758cc3dcSJack F Vogel { 4762*758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 4763*758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 4764*758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 4765*758cc3dcSJack F Vogel u32 speedcnt = 0; 4766*758cc3dcSJack F Vogel u32 i = 0; 4767*758cc3dcSJack F Vogel bool autoneg, link_up = FALSE; 4768*758cc3dcSJack F Vogel 4769*758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 4770*758cc3dcSJack F Vogel 4771*758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 4772*758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 4773*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4774*758cc3dcSJack F Vogel return status; 4775*758cc3dcSJack F Vogel 4776*758cc3dcSJack F Vogel speed &= link_speed; 4777*758cc3dcSJack F Vogel 4778*758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 4779*758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 4780*758cc3dcSJack F Vogel */ 4781*758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 4782*758cc3dcSJack F Vogel speedcnt++; 4783*758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 4784*758cc3dcSJack F Vogel 4785*758cc3dcSJack F Vogel /* If we already have link at this speed, just jump out */ 4786*758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 4787*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4788*758cc3dcSJack F Vogel return status; 4789*758cc3dcSJack F Vogel 4790*758cc3dcSJack F Vogel if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) 4791*758cc3dcSJack F Vogel goto out; 4792*758cc3dcSJack F Vogel 4793*758cc3dcSJack F Vogel /* Set the module link speed */ 4794*758cc3dcSJack F Vogel switch (hw->phy.media_type) { 4795*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 4796*758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 4797*758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 4798*758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 4799*758cc3dcSJack F Vogel break; 4800*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 4801*758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 4802*758cc3dcSJack F Vogel break; 4803*758cc3dcSJack F Vogel default: 4804*758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 4805*758cc3dcSJack F Vogel break; 4806*758cc3dcSJack F Vogel } 4807*758cc3dcSJack F Vogel 4808*758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 4809*758cc3dcSJack F Vogel msec_delay(40); 4810*758cc3dcSJack F Vogel 4811*758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 4812*758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 4813*758cc3dcSJack F Vogel autoneg_wait_to_complete); 4814*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4815*758cc3dcSJack F Vogel return status; 4816*758cc3dcSJack F Vogel 4817*758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 4818*758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 4819*758cc3dcSJack F Vogel 4820*758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 4821*758cc3dcSJack F Vogel * Section 73.10.2, we may have to wait up to 500ms if KR is 4822*758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 4823*758cc3dcSJack F Vogel */ 4824*758cc3dcSJack F Vogel for (i = 0; i < 5; i++) { 4825*758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 4826*758cc3dcSJack F Vogel msec_delay(100); 4827*758cc3dcSJack F Vogel 4828*758cc3dcSJack F Vogel /* If we have link, just jump out */ 4829*758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 4830*758cc3dcSJack F Vogel &link_up, FALSE); 4831*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4832*758cc3dcSJack F Vogel return status; 4833*758cc3dcSJack F Vogel 4834*758cc3dcSJack F Vogel if (link_up) 4835*758cc3dcSJack F Vogel goto out; 4836*758cc3dcSJack F Vogel } 4837*758cc3dcSJack F Vogel } 4838*758cc3dcSJack F Vogel 4839*758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 4840*758cc3dcSJack F Vogel speedcnt++; 4841*758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 4842*758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 4843*758cc3dcSJack F Vogel 4844*758cc3dcSJack F Vogel /* If we already have link at this speed, just jump out */ 4845*758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 4846*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4847*758cc3dcSJack F Vogel return status; 4848*758cc3dcSJack F Vogel 4849*758cc3dcSJack F Vogel if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) 4850*758cc3dcSJack F Vogel goto out; 4851*758cc3dcSJack F Vogel 4852*758cc3dcSJack F Vogel /* Set the module link speed */ 4853*758cc3dcSJack F Vogel switch (hw->phy.media_type) { 4854*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 4855*758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 4856*758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 4857*758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 4858*758cc3dcSJack F Vogel break; 4859*758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 4860*758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 4861*758cc3dcSJack F Vogel break; 4862*758cc3dcSJack F Vogel default: 4863*758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 4864*758cc3dcSJack F Vogel break; 4865*758cc3dcSJack F Vogel } 4866*758cc3dcSJack F Vogel 4867*758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 4868*758cc3dcSJack F Vogel msec_delay(40); 4869*758cc3dcSJack F Vogel 4870*758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 4871*758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 4872*758cc3dcSJack F Vogel autoneg_wait_to_complete); 4873*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4874*758cc3dcSJack F Vogel return status; 4875*758cc3dcSJack F Vogel 4876*758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 4877*758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 4878*758cc3dcSJack F Vogel 4879*758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 4880*758cc3dcSJack F Vogel msec_delay(100); 4881*758cc3dcSJack F Vogel 4882*758cc3dcSJack F Vogel /* If we have link, just jump out */ 4883*758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 4884*758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 4885*758cc3dcSJack F Vogel return status; 4886*758cc3dcSJack F Vogel 4887*758cc3dcSJack F Vogel if (link_up) 4888*758cc3dcSJack F Vogel goto out; 4889*758cc3dcSJack F Vogel } 4890*758cc3dcSJack F Vogel 4891*758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 4892*758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 4893*758cc3dcSJack F Vogel * single highest speed that the user requested. 4894*758cc3dcSJack F Vogel */ 4895*758cc3dcSJack F Vogel if (speedcnt > 1) 4896*758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 4897*758cc3dcSJack F Vogel highest_link_speed, 4898*758cc3dcSJack F Vogel autoneg_wait_to_complete); 4899*758cc3dcSJack F Vogel 4900*758cc3dcSJack F Vogel out: 4901*758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 4902*758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 4903*758cc3dcSJack F Vogel 4904*758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 4905*758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 4906*758cc3dcSJack F Vogel 4907*758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 4908*758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 4909*758cc3dcSJack F Vogel 4910*758cc3dcSJack F Vogel return status; 4911*758cc3dcSJack F Vogel } 4912*758cc3dcSJack F Vogel 4913*758cc3dcSJack F Vogel /** 4914*758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 4915*758cc3dcSJack F Vogel * @hw: pointer to hardware structure 4916*758cc3dcSJack F Vogel * @speed: link speed to set 4917*758cc3dcSJack F Vogel * 4918*758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 4919*758cc3dcSJack F Vogel */ 4920*758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 4921*758cc3dcSJack F Vogel ixgbe_link_speed speed) 4922*758cc3dcSJack F Vogel { 4923*758cc3dcSJack F Vogel s32 status; 4924*758cc3dcSJack F Vogel u8 rs, eeprom_data; 4925*758cc3dcSJack F Vogel 4926*758cc3dcSJack F Vogel switch (speed) { 4927*758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 4928*758cc3dcSJack F Vogel /* one bit mask same as setting on */ 4929*758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 4930*758cc3dcSJack F Vogel break; 4931*758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 4932*758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 4933*758cc3dcSJack F Vogel break; 4934*758cc3dcSJack F Vogel default: 4935*758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 4936*758cc3dcSJack F Vogel return; 4937*758cc3dcSJack F Vogel } 4938*758cc3dcSJack F Vogel 4939*758cc3dcSJack F Vogel /* Set RS0 */ 4940*758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 4941*758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 4942*758cc3dcSJack F Vogel &eeprom_data); 4943*758cc3dcSJack F Vogel if (status) { 4944*758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 4945*758cc3dcSJack F Vogel goto out; 4946*758cc3dcSJack F Vogel } 4947*758cc3dcSJack F Vogel 4948*758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 4949*758cc3dcSJack F Vogel 4950*758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 4951*758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 4952*758cc3dcSJack F Vogel eeprom_data); 4953*758cc3dcSJack F Vogel if (status) { 4954*758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 4955*758cc3dcSJack F Vogel goto out; 4956*758cc3dcSJack F Vogel } 4957*758cc3dcSJack F Vogel 4958*758cc3dcSJack F Vogel /* Set RS1 */ 4959*758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 4960*758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 4961*758cc3dcSJack F Vogel &eeprom_data); 4962*758cc3dcSJack F Vogel if (status) { 4963*758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 4964*758cc3dcSJack F Vogel goto out; 4965*758cc3dcSJack F Vogel } 4966*758cc3dcSJack F Vogel 4967*758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 4968*758cc3dcSJack F Vogel 4969*758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 4970*758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 4971*758cc3dcSJack F Vogel eeprom_data); 4972*758cc3dcSJack F Vogel if (status) { 4973*758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 4974*758cc3dcSJack F Vogel goto out; 4975*758cc3dcSJack F Vogel } 4976*758cc3dcSJack F Vogel out: 4977*758cc3dcSJack F Vogel return; 4978*758cc3dcSJack F Vogel } 4979