19ca4041bSJack F Vogel /****************************************************************************** 213705f88SJack F Vogel 3*8eb6488eSEric Joyner Copyright (c) 2001-2017, 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; 73a9ca1c79SSean Bruno u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 7413705f88SJack F Vogel 752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_ops_generic"); 762969bf0eSJack F Vogel 7713705f88SJack F Vogel /* EEPROM */ 78758cc3dcSJack 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) { 81758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eerd_generic; 82758cc3dcSJack F Vogel eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; 8385d0a26eSJack F Vogel } else { 84758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; 8585d0a26eSJack F Vogel eeprom->ops.read_buffer = 86758cc3dcSJack F Vogel ixgbe_read_eeprom_buffer_bit_bang_generic; 8785d0a26eSJack F Vogel } 88758cc3dcSJack F Vogel eeprom->ops.write = ixgbe_write_eeprom_generic; 89758cc3dcSJack F Vogel eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; 909ca4041bSJack F Vogel eeprom->ops.validate_checksum = 91758cc3dcSJack F Vogel ixgbe_validate_eeprom_checksum_generic; 92758cc3dcSJack F Vogel eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; 93758cc3dcSJack F Vogel eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; 949ca4041bSJack F Vogel 959ca4041bSJack F Vogel /* MAC */ 96758cc3dcSJack F Vogel mac->ops.init_hw = ixgbe_init_hw_generic; 979ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 98758cc3dcSJack F Vogel mac->ops.start_hw = ixgbe_start_hw_generic; 99758cc3dcSJack 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; 102758cc3dcSJack F Vogel mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; 103758cc3dcSJack F Vogel mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; 104758cc3dcSJack F Vogel mac->ops.stop_adapter = ixgbe_stop_adapter_generic; 105758cc3dcSJack F Vogel mac->ops.get_bus_info = ixgbe_get_bus_info_generic; 106758cc3dcSJack F Vogel mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; 107758cc3dcSJack F Vogel mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; 108758cc3dcSJack F Vogel mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; 109758cc3dcSJack F Vogel mac->ops.prot_autoc_read = prot_autoc_read_generic; 110758cc3dcSJack F Vogel mac->ops.prot_autoc_write = prot_autoc_write_generic; 1119ca4041bSJack F Vogel 1129ca4041bSJack F Vogel /* LEDs */ 113758cc3dcSJack F Vogel mac->ops.led_on = ixgbe_led_on_generic; 114758cc3dcSJack F Vogel mac->ops.led_off = ixgbe_led_off_generic; 115758cc3dcSJack F Vogel mac->ops.blink_led_start = ixgbe_blink_led_start_generic; 116758cc3dcSJack F Vogel mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; 117*8eb6488eSEric Joyner mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic; 1189ca4041bSJack F Vogel 11913705f88SJack F Vogel /* RAR, Multicast, VLAN */ 120758cc3dcSJack F Vogel mac->ops.set_rar = ixgbe_set_rar_generic; 121758cc3dcSJack F Vogel mac->ops.clear_rar = ixgbe_clear_rar_generic; 1220ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1239ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1245b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 125758cc3dcSJack F Vogel mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; 126758cc3dcSJack F Vogel mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; 127758cc3dcSJack F Vogel mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; 128758cc3dcSJack F Vogel mac->ops.enable_mc = ixgbe_enable_mc_generic; 129758cc3dcSJack F Vogel mac->ops.disable_mc = ixgbe_disable_mc_generic; 1305b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1315b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 13285d0a26eSJack F Vogel mac->ops.set_vlvf = NULL; 1335b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 134758cc3dcSJack F Vogel mac->ops.enable_rx = ixgbe_enable_rx_generic; 135758cc3dcSJack F Vogel mac->ops.disable_rx = ixgbe_disable_rx_generic; 1369ca4041bSJack F Vogel 1370ac6dfecSJack F Vogel /* Flow Control */ 138758cc3dcSJack F Vogel mac->ops.fc_enable = ixgbe_fc_enable_generic; 139758cc3dcSJack F Vogel mac->ops.setup_fc = ixgbe_setup_fc_generic; 140*8eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg; 1419ca4041bSJack F Vogel 1429ca4041bSJack F Vogel /* Link */ 1439ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1449ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1459ca4041bSJack F Vogel mac->ops.check_link = NULL; 146fd75b91dSJack F Vogel mac->ops.dmac_config = NULL; 147fd75b91dSJack F Vogel mac->ops.dmac_update_tcs = NULL; 148fd75b91dSJack F Vogel mac->ops.dmac_config_tcs = NULL; 14913705f88SJack F Vogel 15013705f88SJack F Vogel return IXGBE_SUCCESS; 15113705f88SJack F Vogel } 15213705f88SJack F Vogel 15313705f88SJack F Vogel /** 154fd75b91dSJack F Vogel * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation 155fd75b91dSJack F Vogel * of flow control 156a621e3c8SJack F Vogel * @hw: pointer to hardware structure 157a621e3c8SJack F Vogel * 158fd75b91dSJack F Vogel * This function returns TRUE if the device supports flow control 159fd75b91dSJack F Vogel * autonegotiation, and FALSE if it does not. 160fd75b91dSJack F Vogel * 161a621e3c8SJack F Vogel **/ 162fd75b91dSJack F Vogel bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 163a621e3c8SJack F Vogel { 164fd75b91dSJack F Vogel bool supported = FALSE; 165fd75b91dSJack F Vogel ixgbe_link_speed speed; 166fd75b91dSJack F Vogel bool link_up; 167a621e3c8SJack F Vogel 168a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); 169a621e3c8SJack F Vogel 170fd75b91dSJack F Vogel switch (hw->phy.media_type) { 171fd75b91dSJack F Vogel case ixgbe_media_type_fiber_fixed: 172758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 173fd75b91dSJack F Vogel case ixgbe_media_type_fiber: 174*8eb6488eSEric Joyner /* flow control autoneg black list */ 175*8eb6488eSEric Joyner switch (hw->device_id) { 176*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP: 177*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N: 178*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP: 179*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP_N: 180*8eb6488eSEric Joyner supported = FALSE; 181*8eb6488eSEric Joyner break; 182*8eb6488eSEric Joyner default: 183fd75b91dSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 184fd75b91dSJack F Vogel /* if link is down, assume supported */ 185fd75b91dSJack F Vogel if (link_up) 186fd75b91dSJack F Vogel supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? 187fd75b91dSJack F Vogel TRUE : FALSE; 188fd75b91dSJack F Vogel else 189fd75b91dSJack F Vogel supported = TRUE; 190*8eb6488eSEric Joyner } 191*8eb6488eSEric Joyner 192fd75b91dSJack F Vogel break; 193fd75b91dSJack F Vogel case ixgbe_media_type_backplane: 194*8eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) 195*8eb6488eSEric Joyner supported = FALSE; 196*8eb6488eSEric Joyner else 197fd75b91dSJack F Vogel supported = TRUE; 198fd75b91dSJack F Vogel break; 199fd75b91dSJack F Vogel case ixgbe_media_type_copper: 200fd75b91dSJack F Vogel /* only some copper devices support flow control autoneg */ 201a621e3c8SJack F Vogel switch (hw->device_id) { 202a621e3c8SJack F Vogel case IXGBE_DEV_ID_82599_T3_LOM: 2030ecc2ff0SJack F Vogel case IXGBE_DEV_ID_X540T: 204758cc3dcSJack F Vogel case IXGBE_DEV_ID_X540T1: 205fd75b91dSJack F Vogel case IXGBE_DEV_ID_X540_BYPASS: 206758cc3dcSJack F Vogel case IXGBE_DEV_ID_X550T: 207a9ca1c79SSean Bruno case IXGBE_DEV_ID_X550T1: 2086f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T: 209*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T: 210*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T: 211*8eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L: 212fd75b91dSJack F Vogel supported = TRUE; 213fd75b91dSJack F Vogel break; 214a621e3c8SJack F Vogel default: 215fd75b91dSJack F Vogel supported = FALSE; 216a621e3c8SJack F Vogel } 217fd75b91dSJack F Vogel default: 218fd75b91dSJack F Vogel break; 219fd75b91dSJack F Vogel } 220fd75b91dSJack F Vogel 221*8eb6488eSEric Joyner if (!supported) 222fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, 223fd75b91dSJack F Vogel "Device %x does not support flow control autoneg", 224fd75b91dSJack F Vogel hw->device_id); 225fd75b91dSJack F Vogel return supported; 226a621e3c8SJack F Vogel } 227a621e3c8SJack F Vogel 228a621e3c8SJack F Vogel /** 229758cc3dcSJack F Vogel * ixgbe_setup_fc_generic - Set up flow control 230a621e3c8SJack F Vogel * @hw: pointer to hardware structure 231a621e3c8SJack F Vogel * 232a621e3c8SJack F Vogel * Called at init time to set up flow control. 233a621e3c8SJack F Vogel **/ 234758cc3dcSJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 235a621e3c8SJack F Vogel { 236a621e3c8SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 237a621e3c8SJack F Vogel u32 reg = 0, reg_bp = 0; 238a621e3c8SJack F Vogel u16 reg_cu = 0; 239758cc3dcSJack F Vogel bool locked = FALSE; 240a621e3c8SJack F Vogel 241758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_fc_generic"); 242a621e3c8SJack F Vogel 243758cc3dcSJack F Vogel /* Validate the requested mode */ 244a621e3c8SJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 245fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 246fd75b91dSJack F Vogel "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 247a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 248a621e3c8SJack F Vogel goto out; 249a621e3c8SJack F Vogel } 250a621e3c8SJack F Vogel 251a621e3c8SJack F Vogel /* 252a621e3c8SJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 253a621e3c8SJack F Vogel * default flow control setting, so we explicitly set it to full. 254a621e3c8SJack F Vogel */ 255a621e3c8SJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 256a621e3c8SJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 257a621e3c8SJack F Vogel 258a621e3c8SJack F Vogel /* 259a621e3c8SJack F Vogel * Set up the 1G and 10G flow control advertisement registers so the 260a621e3c8SJack F Vogel * HW will be able to do fc autoneg once the cable is plugged in. If 261a621e3c8SJack F Vogel * we link at 10G, the 1G advertisement is harmless and vice versa. 262a621e3c8SJack F Vogel */ 263a621e3c8SJack F Vogel switch (hw->phy.media_type) { 264a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 265758cc3dcSJack F Vogel /* some MAC's need RMW protection on AUTOC */ 266758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 267758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 268758cc3dcSJack F Vogel goto out; 269758cc3dcSJack F Vogel 270*8eb6488eSEric Joyner /* fall through - only backplane uses autoc */ 271758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 272758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 273758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 274a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 275758cc3dcSJack F Vogel 276a621e3c8SJack F Vogel break; 277a621e3c8SJack F Vogel case ixgbe_media_type_copper: 278a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 279a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); 280a621e3c8SJack F Vogel break; 281a621e3c8SJack F Vogel default: 282a621e3c8SJack F Vogel break; 283a621e3c8SJack F Vogel } 284a621e3c8SJack F Vogel 285a621e3c8SJack F Vogel /* 286a621e3c8SJack F Vogel * The possible values of fc.requested_mode are: 287a621e3c8SJack F Vogel * 0: Flow control is completely disabled 288a621e3c8SJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 289a621e3c8SJack F Vogel * but not send pause frames). 290a621e3c8SJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 291a621e3c8SJack F Vogel * we do not support receiving pause frames). 292a621e3c8SJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 293a621e3c8SJack F Vogel * other: Invalid. 294a621e3c8SJack F Vogel */ 295a621e3c8SJack F Vogel switch (hw->fc.requested_mode) { 296a621e3c8SJack F Vogel case ixgbe_fc_none: 297a621e3c8SJack F Vogel /* Flow control completely disabled by software override. */ 298a621e3c8SJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 299a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 300a621e3c8SJack F Vogel reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 301a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE); 302a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 303a621e3c8SJack F Vogel reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 304a621e3c8SJack F Vogel break; 305a621e3c8SJack F Vogel case ixgbe_fc_tx_pause: 306a621e3c8SJack F Vogel /* 307a621e3c8SJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 308a621e3c8SJack F Vogel * disabled by software override. 309a621e3c8SJack F Vogel */ 310a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_ASM_PAUSE; 311a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 312a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 313a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 314a621e3c8SJack F Vogel reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 315a621e3c8SJack F Vogel } else if (hw->phy.media_type == ixgbe_media_type_copper) { 316a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_ASM_PAUSE; 317a621e3c8SJack F Vogel reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 318a621e3c8SJack F Vogel } 319a621e3c8SJack F Vogel break; 320a621e3c8SJack F Vogel case ixgbe_fc_rx_pause: 321a621e3c8SJack F Vogel /* 322a621e3c8SJack F Vogel * Rx Flow control is enabled and Tx Flow control is 323a621e3c8SJack F Vogel * disabled by software override. Since there really 324a621e3c8SJack F Vogel * isn't a way to advertise that we are capable of RX 325a621e3c8SJack F Vogel * Pause ONLY, we will advertise that we support both 326a621e3c8SJack F Vogel * symmetric and asymmetric Rx PAUSE, as such we fall 327a621e3c8SJack F Vogel * through to the fc_full statement. Later, we will 328a621e3c8SJack F Vogel * disable the adapter's ability to send PAUSE frames. 329a621e3c8SJack F Vogel */ 330a621e3c8SJack F Vogel case ixgbe_fc_full: 331a621e3c8SJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 332a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 333a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 334a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 335a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE; 336a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 337a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 338a621e3c8SJack F Vogel break; 339a621e3c8SJack F Vogel default: 340fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 341fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 342a621e3c8SJack F Vogel ret_val = IXGBE_ERR_CONFIG; 343a621e3c8SJack F Vogel goto out; 344a621e3c8SJack F Vogel break; 345a621e3c8SJack F Vogel } 346a621e3c8SJack F Vogel 347758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_X540) { 348a621e3c8SJack F Vogel /* 349a621e3c8SJack F Vogel * Enable auto-negotiation between the MAC & PHY; 350a621e3c8SJack F Vogel * the MAC will advertise clause 37 flow control. 351a621e3c8SJack F Vogel */ 352a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 353a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 354a621e3c8SJack F Vogel 355a621e3c8SJack F Vogel /* Disable AN timeout */ 356a621e3c8SJack F Vogel if (hw->fc.strict_ieee) 357a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 358a621e3c8SJack F Vogel 359a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 360a621e3c8SJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 361a621e3c8SJack F Vogel } 362a621e3c8SJack F Vogel 363a621e3c8SJack F Vogel /* 364a621e3c8SJack F Vogel * AUTOC restart handles negotiation of 1G and 10G on backplane 365a621e3c8SJack F Vogel * and copper. There is no need to set the PCS1GCTL register. 366a621e3c8SJack F Vogel * 367a621e3c8SJack F Vogel */ 368a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 369a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_AN_RESTART; 370758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 371758cc3dcSJack F Vogel if (ret_val) 3720ecc2ff0SJack F Vogel goto out; 373a621e3c8SJack F Vogel } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 374fd75b91dSJack F Vogel (ixgbe_device_supports_autoneg_fc(hw))) { 375a621e3c8SJack F Vogel hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 376a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); 377a621e3c8SJack F Vogel } 378a621e3c8SJack F Vogel 379758cc3dcSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 380a621e3c8SJack F Vogel out: 381a621e3c8SJack F Vogel return ret_val; 382a621e3c8SJack F Vogel } 383a621e3c8SJack F Vogel 384a621e3c8SJack F Vogel /** 3859ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 38613705f88SJack F Vogel * @hw: pointer to hardware structure 38713705f88SJack F Vogel * 38813705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 38913705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 39013705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 39113705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 39213705f88SJack F Vogel **/ 39313705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 39413705f88SJack F Vogel { 395a621e3c8SJack F Vogel s32 ret_val; 39613705f88SJack F Vogel u32 ctrl_ext; 397*8eb6488eSEric Joyner u16 device_caps; 39813705f88SJack F Vogel 3992969bf0eSJack F Vogel DEBUGFUNC("ixgbe_start_hw_generic"); 4002969bf0eSJack F Vogel 40113705f88SJack F Vogel /* Set the media type */ 4029ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 40313705f88SJack F Vogel 4040ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 40513705f88SJack F Vogel 40613705f88SJack F Vogel /* Clear the VLAN filter table */ 4079ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 40813705f88SJack F Vogel 40913705f88SJack F Vogel /* Clear statistics registers */ 4109ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 41113705f88SJack F Vogel 41213705f88SJack F Vogel /* Set No Snoop Disable */ 41313705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 41413705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 41513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 4169ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 41713705f88SJack F Vogel 4180ac6dfecSJack F Vogel /* Setup flow control */ 419a621e3c8SJack F Vogel ret_val = ixgbe_setup_fc(hw); 420*8eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) { 421*8eb6488eSEric Joyner DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val); 422*8eb6488eSEric Joyner return ret_val; 423*8eb6488eSEric Joyner } 424*8eb6488eSEric Joyner 425*8eb6488eSEric Joyner /* Cache bit indicating need for crosstalk fix */ 426*8eb6488eSEric Joyner switch (hw->mac.type) { 427*8eb6488eSEric Joyner case ixgbe_mac_82599EB: 428*8eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 429*8eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 430*8eb6488eSEric Joyner hw->mac.ops.get_device_caps(hw, &device_caps); 431*8eb6488eSEric Joyner if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) 432*8eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 433*8eb6488eSEric Joyner else 434*8eb6488eSEric Joyner hw->need_crosstalk_fix = TRUE; 435*8eb6488eSEric Joyner break; 436*8eb6488eSEric Joyner default: 437*8eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 438*8eb6488eSEric Joyner break; 439*8eb6488eSEric Joyner } 4400ac6dfecSJack F Vogel 44113705f88SJack F Vogel /* Clear adapter stopped flag */ 44213705f88SJack F Vogel hw->adapter_stopped = FALSE; 44313705f88SJack F Vogel 444*8eb6488eSEric Joyner return IXGBE_SUCCESS; 4451a4e3449SJack F Vogel } 4461a4e3449SJack F Vogel 4471a4e3449SJack F Vogel /** 4481a4e3449SJack F Vogel * ixgbe_start_hw_gen2 - Init sequence for common device family 4491a4e3449SJack F Vogel * @hw: pointer to hw structure 4501a4e3449SJack F Vogel * 4511a4e3449SJack F Vogel * Performs the init sequence common to the second generation 4521a4e3449SJack F Vogel * of 10 GbE devices. 4531a4e3449SJack F Vogel * Devices in the second generation: 4541a4e3449SJack F Vogel * 82599 455182b3808SJack F Vogel * X540 4561a4e3449SJack F Vogel **/ 4571a4e3449SJack F Vogel s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 4581a4e3449SJack F Vogel { 4591a4e3449SJack F Vogel u32 i; 4601a4e3449SJack F Vogel u32 regval; 4611a4e3449SJack F Vogel 4621a4e3449SJack F Vogel /* Clear the rate limiters */ 4631a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4641a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 4651a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 4661a4e3449SJack F Vogel } 4671a4e3449SJack F Vogel IXGBE_WRITE_FLUSH(hw); 4681a4e3449SJack F Vogel 4691a4e3449SJack F Vogel /* Disable relaxed ordering */ 4701a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4711a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 472a621e3c8SJack F Vogel regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4731a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4741a4e3449SJack F Vogel } 4751a4e3449SJack F Vogel 4761a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4771a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 478a621e3c8SJack F Vogel regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | 479a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN); 4801a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4811a4e3449SJack F Vogel } 4821a4e3449SJack F Vogel 4831a4e3449SJack F Vogel return IXGBE_SUCCESS; 48413705f88SJack F Vogel } 48513705f88SJack F Vogel 48613705f88SJack F Vogel /** 48713705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 48813705f88SJack F Vogel * @hw: pointer to hardware structure 48913705f88SJack F Vogel * 4909ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 49113705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 49213705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 49313705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 49413705f88SJack F Vogel * disabled and uninitialized 49513705f88SJack F Vogel **/ 49613705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 49713705f88SJack F Vogel { 4981a4e3449SJack F Vogel s32 status; 4990ac6dfecSJack F Vogel 5002969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 5012969bf0eSJack F Vogel 50213705f88SJack F Vogel /* Reset the hardware */ 5030ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 50413705f88SJack F Vogel 505*8eb6488eSEric Joyner if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { 50613705f88SJack F Vogel /* Start the HW */ 5070ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 5080ac6dfecSJack F Vogel } 50913705f88SJack F Vogel 510*8eb6488eSEric Joyner /* Initialize the LED link active for LED blink support */ 511*8eb6488eSEric Joyner if (hw->mac.ops.init_led_link_act) 512*8eb6488eSEric Joyner hw->mac.ops.init_led_link_act(hw); 513*8eb6488eSEric Joyner 514*8eb6488eSEric Joyner if (status != IXGBE_SUCCESS) 515*8eb6488eSEric Joyner DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); 516*8eb6488eSEric Joyner 5170ac6dfecSJack F Vogel return status; 51813705f88SJack F Vogel } 51913705f88SJack F Vogel 52013705f88SJack F Vogel /** 52113705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 52213705f88SJack F Vogel * @hw: pointer to hardware structure 52313705f88SJack F Vogel * 52413705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 52513705f88SJack F Vogel * Statistics counters are clear on read. 52613705f88SJack F Vogel **/ 52713705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 52813705f88SJack F Vogel { 52913705f88SJack F Vogel u16 i = 0; 53013705f88SJack F Vogel 5312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 5322969bf0eSJack F Vogel 53313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 53413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 53513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 53713705f88SJack F Vogel for (i = 0; i < 8; i++) 53813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 53913705f88SJack F Vogel 54013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 54113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 54213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 5450ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5460ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5470ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5480ac6dfecSJack F Vogel } else { 5491b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 55013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5510ac6dfecSJack F Vogel } 55213705f88SJack F Vogel 55313705f88SJack F Vogel for (i = 0; i < 8; i++) { 55413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 55513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5560ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5570ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5580ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5590ac6dfecSJack F Vogel } else { 5601b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 56113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 56213705f88SJack F Vogel } 5630ac6dfecSJack F Vogel } 5640ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5650ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5660ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 56713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 56813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 56913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 57013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 57113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 57213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 57313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 57413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 57513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 57613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 57713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 57813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 57913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 58013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 58185d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 58213705f88SJack F Vogel for (i = 0; i < 8; i++) 58313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 58413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 58513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 58613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 58713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 58813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 58913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 59013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 59113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 59213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 59313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 59413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 59513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 59613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 59713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 59813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 59913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 60013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 60113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 60213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 60313705f88SJack F Vogel for (i = 0; i < 16; i++) { 60413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 60513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 6061a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 6071a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 6081a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 6091a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 6101a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 6111a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 6121a4e3449SJack F Vogel } else { 6131a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 61413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 61513705f88SJack F Vogel } 6161a4e3449SJack F Vogel } 6171a4e3449SJack F Vogel 618758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 61985d0a26eSJack F Vogel if (hw->phy.id == 0) 62085d0a26eSJack F Vogel ixgbe_identify_phy(hw); 62185d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 62285d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62385d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 62485d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62585d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 62685d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62785d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 62885d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62985d0a26eSJack F Vogel } 63085d0a26eSJack F Vogel 6311a4e3449SJack F Vogel return IXGBE_SUCCESS; 6321a4e3449SJack F Vogel } 6331a4e3449SJack F Vogel 6341a4e3449SJack F Vogel /** 6351a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 6361a4e3449SJack F Vogel * @hw: pointer to hardware structure 6371a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 6381a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 6391a4e3449SJack F Vogel * 6401a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 6411a4e3449SJack F Vogel **/ 6421a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 6431a4e3449SJack F Vogel u32 pba_num_size) 6441a4e3449SJack F Vogel { 6451a4e3449SJack F Vogel s32 ret_val; 6461a4e3449SJack F Vogel u16 data; 6471a4e3449SJack F Vogel u16 pba_ptr; 6481a4e3449SJack F Vogel u16 offset; 6491a4e3449SJack F Vogel u16 length; 6501a4e3449SJack F Vogel 6511a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6521a4e3449SJack F Vogel 6531a4e3449SJack F Vogel if (pba_num == NULL) { 6541a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6551a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6561a4e3449SJack F Vogel } 6571a4e3449SJack F Vogel 6581a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6591a4e3449SJack F Vogel if (ret_val) { 6601a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6611a4e3449SJack F Vogel return ret_val; 6621a4e3449SJack F Vogel } 6631a4e3449SJack F Vogel 6641a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6651a4e3449SJack F Vogel if (ret_val) { 6661a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6671a4e3449SJack F Vogel return ret_val; 6681a4e3449SJack F Vogel } 6691a4e3449SJack F Vogel 6701a4e3449SJack F Vogel /* 6711a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6721a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6731a4e3449SJack F Vogel * and we can decode it into an ascii string 6741a4e3449SJack F Vogel */ 6751a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6761a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6771a4e3449SJack F Vogel 6781a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6791a4e3449SJack F Vogel if (pba_num_size < 11) { 6801a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6811a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6821a4e3449SJack F Vogel } 6831a4e3449SJack F Vogel 6841a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6851a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6861a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6871a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6881a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6891a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6901a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6911a4e3449SJack F Vogel pba_num[6] = '-'; 6921a4e3449SJack F Vogel pba_num[7] = 0; 6931a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6941a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6951a4e3449SJack F Vogel 6961a4e3449SJack F Vogel /* put a null character on the end of our string */ 6971a4e3449SJack F Vogel pba_num[10] = '\0'; 6981a4e3449SJack F Vogel 6991a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 7001a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 7011a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 7021a4e3449SJack F Vogel pba_num[offset] += '0'; 7031a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 7041a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 7051a4e3449SJack F Vogel } 7061a4e3449SJack F Vogel 7071a4e3449SJack F Vogel return IXGBE_SUCCESS; 7081a4e3449SJack F Vogel } 7091a4e3449SJack F Vogel 7101a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 7111a4e3449SJack F Vogel if (ret_val) { 7121a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7131a4e3449SJack F Vogel return ret_val; 7141a4e3449SJack F Vogel } 7151a4e3449SJack F Vogel 7161a4e3449SJack F Vogel if (length == 0xFFFF || length == 0) { 7171a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 7181a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 7191a4e3449SJack F Vogel } 7201a4e3449SJack F Vogel 7211a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 7221a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 7231a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 7241a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 7251a4e3449SJack F Vogel } 7261a4e3449SJack F Vogel 7271a4e3449SJack F Vogel /* trim pba length from start of string */ 7281a4e3449SJack F Vogel pba_ptr++; 7291a4e3449SJack F Vogel length--; 7301a4e3449SJack F Vogel 7311a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 7321a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 7331a4e3449SJack F Vogel if (ret_val) { 7341a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7351a4e3449SJack F Vogel return ret_val; 7361a4e3449SJack F Vogel } 7371a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 7381a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 7391a4e3449SJack F Vogel } 7401a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 7411a4e3449SJack F Vogel 7421a4e3449SJack F Vogel return IXGBE_SUCCESS; 7431a4e3449SJack F Vogel } 7441a4e3449SJack F Vogel 7451a4e3449SJack F Vogel /** 7461b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7479ca4041bSJack F Vogel * @hw: pointer to hardware structure 7489ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7499ca4041bSJack F Vogel * 7509ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7519ca4041bSJack F Vogel **/ 7529ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7539ca4041bSJack F Vogel { 7549ca4041bSJack F Vogel s32 ret_val; 7559ca4041bSJack F Vogel u16 data; 7569ca4041bSJack F Vogel 7579ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7589ca4041bSJack F Vogel 7599ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7609ca4041bSJack F Vogel if (ret_val) { 7619ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7629ca4041bSJack F Vogel return ret_val; 7631a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7641a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7651a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7669ca4041bSJack F Vogel } 7679ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7689ca4041bSJack F Vogel 7699ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7709ca4041bSJack F Vogel if (ret_val) { 7719ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7729ca4041bSJack F Vogel return ret_val; 7739ca4041bSJack F Vogel } 7749ca4041bSJack F Vogel *pba_num |= data; 7759ca4041bSJack F Vogel 7769ca4041bSJack F Vogel return IXGBE_SUCCESS; 7779ca4041bSJack F Vogel } 7789ca4041bSJack F Vogel 7799ca4041bSJack F Vogel /** 7800ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7810ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7820ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7830ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7840ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7850ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7860ecc2ff0SJack F Vogel * 7870ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7880ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7890ecc2ff0SJack F Vogel * 7900ecc2ff0SJack F Vogel **/ 7910ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7920ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7930ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7940ecc2ff0SJack F Vogel { 7950ecc2ff0SJack F Vogel s32 ret_val; 7960ecc2ff0SJack F Vogel u16 pba_block_size; 7970ecc2ff0SJack F Vogel 7980ecc2ff0SJack F Vogel if (pba == NULL) 7990ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8000ecc2ff0SJack F Vogel 8010ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8020ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8030ecc2ff0SJack F Vogel &pba->word[0]); 8040ecc2ff0SJack F Vogel if (ret_val) 8050ecc2ff0SJack F Vogel return ret_val; 8060ecc2ff0SJack F Vogel } else { 8070ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8080ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8090ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8100ecc2ff0SJack F Vogel } else { 8110ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8120ecc2ff0SJack F Vogel } 8130ecc2ff0SJack F Vogel } 8140ecc2ff0SJack F Vogel 8150ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8160ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8170ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8180ecc2ff0SJack F Vogel 8190ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 8200ecc2ff0SJack F Vogel eeprom_buf_size, 8210ecc2ff0SJack F Vogel &pba_block_size); 8220ecc2ff0SJack F Vogel if (ret_val) 8230ecc2ff0SJack F Vogel return ret_val; 8240ecc2ff0SJack F Vogel 8250ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 8260ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8270ecc2ff0SJack F Vogel 8280ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8290ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 8300ecc2ff0SJack F Vogel pba_block_size, 8310ecc2ff0SJack F Vogel pba->pba_block); 8320ecc2ff0SJack F Vogel if (ret_val) 8330ecc2ff0SJack F Vogel return ret_val; 8340ecc2ff0SJack F Vogel } else { 8350ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 836758cc3dcSJack F Vogel pba_block_size)) { 8370ecc2ff0SJack F Vogel memcpy(pba->pba_block, 8380ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 8390ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 8400ecc2ff0SJack F Vogel } else { 8410ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8420ecc2ff0SJack F Vogel } 8430ecc2ff0SJack F Vogel } 8440ecc2ff0SJack F Vogel } 8450ecc2ff0SJack F Vogel 8460ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8470ecc2ff0SJack F Vogel } 8480ecc2ff0SJack F Vogel 8490ecc2ff0SJack F Vogel /** 8500ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8510ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8520ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8530ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8540ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8550ecc2ff0SJack F Vogel * 8560ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8570ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8580ecc2ff0SJack F Vogel * 8590ecc2ff0SJack F Vogel **/ 8600ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8610ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8620ecc2ff0SJack F Vogel { 8630ecc2ff0SJack F Vogel s32 ret_val; 8640ecc2ff0SJack F Vogel 8650ecc2ff0SJack F Vogel if (pba == NULL) 8660ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8670ecc2ff0SJack F Vogel 8680ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8690ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8700ecc2ff0SJack F Vogel &pba->word[0]); 8710ecc2ff0SJack F Vogel if (ret_val) 8720ecc2ff0SJack F Vogel return ret_val; 8730ecc2ff0SJack F Vogel } else { 8740ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8750ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8760ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8770ecc2ff0SJack F Vogel } else { 8780ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8790ecc2ff0SJack F Vogel } 8800ecc2ff0SJack F Vogel } 8810ecc2ff0SJack F Vogel 8820ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8830ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8840ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8850ecc2ff0SJack F Vogel 8860ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8870ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8880ecc2ff0SJack F Vogel pba->pba_block[0], 8890ecc2ff0SJack F Vogel pba->pba_block); 8900ecc2ff0SJack F Vogel if (ret_val) 8910ecc2ff0SJack F Vogel return ret_val; 8920ecc2ff0SJack F Vogel } else { 8930ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8940ecc2ff0SJack F Vogel pba->pba_block[0])) { 8950ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8960ecc2ff0SJack F Vogel pba->pba_block, 8970ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 8980ecc2ff0SJack F Vogel } else { 8990ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9000ecc2ff0SJack F Vogel } 9010ecc2ff0SJack F Vogel } 9020ecc2ff0SJack F Vogel } 9030ecc2ff0SJack F Vogel 9040ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9050ecc2ff0SJack F Vogel } 9060ecc2ff0SJack F Vogel 9070ecc2ff0SJack F Vogel /** 9080ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 9090ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 9100ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 9110ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 9120ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 9130ecc2ff0SJack F Vogel * 9140ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 9150ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 9160ecc2ff0SJack F Vogel * EEPROM device. 9170ecc2ff0SJack F Vogel * 9180ecc2ff0SJack F Vogel **/ 9190ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 9200ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 9210ecc2ff0SJack F Vogel { 9220ecc2ff0SJack F Vogel s32 ret_val; 9230ecc2ff0SJack F Vogel u16 pba_word[2]; 9240ecc2ff0SJack F Vogel u16 length; 9250ecc2ff0SJack F Vogel 9260ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 9270ecc2ff0SJack F Vogel 9280ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9290ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 9300ecc2ff0SJack F Vogel &pba_word[0]); 9310ecc2ff0SJack F Vogel if (ret_val) 9320ecc2ff0SJack F Vogel return ret_val; 9330ecc2ff0SJack F Vogel } else { 9340ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 9350ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 9360ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 9370ecc2ff0SJack F Vogel } else { 9380ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9390ecc2ff0SJack F Vogel } 9400ecc2ff0SJack F Vogel } 9410ecc2ff0SJack F Vogel 9420ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 9430ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9440ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 9450ecc2ff0SJack F Vogel &length); 9460ecc2ff0SJack F Vogel if (ret_val) 9470ecc2ff0SJack F Vogel return ret_val; 9480ecc2ff0SJack F Vogel } else { 9490ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9500ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9510ecc2ff0SJack F Vogel else 9520ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9530ecc2ff0SJack F Vogel } 9540ecc2ff0SJack F Vogel 9550ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9560ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9570ecc2ff0SJack F Vogel } else { 9580ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9590ecc2ff0SJack F Vogel length = 0; 9600ecc2ff0SJack F Vogel } 9610ecc2ff0SJack F Vogel 9620ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9630ecc2ff0SJack F Vogel *pba_block_size = length; 9640ecc2ff0SJack F Vogel 9650ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9660ecc2ff0SJack F Vogel } 9670ecc2ff0SJack F Vogel 9680ecc2ff0SJack F Vogel /** 96913705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 97013705f88SJack F Vogel * @hw: pointer to hardware structure 97113705f88SJack F Vogel * @mac_addr: Adapter MAC address 97213705f88SJack F Vogel * 97313705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 97413705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 97513705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 97613705f88SJack F Vogel **/ 97713705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 97813705f88SJack F Vogel { 97913705f88SJack F Vogel u32 rar_high; 98013705f88SJack F Vogel u32 rar_low; 98113705f88SJack F Vogel u16 i; 98213705f88SJack F Vogel 9832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9842969bf0eSJack F Vogel 98513705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 98613705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 98713705f88SJack F Vogel 98813705f88SJack F Vogel for (i = 0; i < 4; i++) 98913705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 99013705f88SJack F Vogel 99113705f88SJack F Vogel for (i = 0; i < 2; i++) 99213705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 99313705f88SJack F Vogel 99413705f88SJack F Vogel return IXGBE_SUCCESS; 99513705f88SJack F Vogel } 99613705f88SJack F Vogel 99713705f88SJack F Vogel /** 998fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 99913705f88SJack F Vogel * @hw: pointer to hardware structure 1000fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 100113705f88SJack F Vogel * 1002fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 100313705f88SJack F Vogel **/ 1004fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 100513705f88SJack F Vogel { 10061b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 10072969bf0eSJack F Vogel 1008758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 100913705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 101013705f88SJack F Vogel 101113705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 101213705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 101313705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 101413705f88SJack F Vogel break; 101513705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 101613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 101713705f88SJack F Vogel break; 101813705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 101913705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 102013705f88SJack F Vogel break; 102113705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 102213705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 102313705f88SJack F Vogel break; 102413705f88SJack F Vogel default: 102513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 102613705f88SJack F Vogel break; 102713705f88SJack F Vogel } 102813705f88SJack F Vogel 102913705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 103013705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 103113705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 103213705f88SJack F Vogel break; 103313705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 103413705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 103513705f88SJack F Vogel break; 1036a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 1037a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 1038a621e3c8SJack F Vogel break; 103913705f88SJack F Vogel default: 104013705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 104113705f88SJack F Vogel break; 104213705f88SJack F Vogel } 104313705f88SJack F Vogel 10441b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 1045fd75b91dSJack F Vogel } 1046fd75b91dSJack F Vogel 1047fd75b91dSJack F Vogel /** 1048fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1049fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1050fd75b91dSJack F Vogel * 1051fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1052fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1053fd75b91dSJack F Vogel **/ 1054fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1055fd75b91dSJack F Vogel { 1056fd75b91dSJack F Vogel u16 link_status; 1057fd75b91dSJack F Vogel 1058fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1059fd75b91dSJack F Vogel 1060fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1061fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1062fd75b91dSJack F Vogel 1063fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10641b6e0dbaSJack F Vogel 106513705f88SJack F Vogel return IXGBE_SUCCESS; 106613705f88SJack F Vogel } 106713705f88SJack F Vogel 106813705f88SJack F Vogel /** 10691b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10701b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10711b6e0dbaSJack F Vogel * 1072*8eb6488eSEric Joyner * Determines the LAN function id by reading memory-mapped registers and swaps 1073*8eb6488eSEric Joyner * the port value if requested, and set MAC instance for devices that share 1074*8eb6488eSEric Joyner * CS4227. 10751b6e0dbaSJack F Vogel **/ 10761b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10771b6e0dbaSJack F Vogel { 10781b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10791b6e0dbaSJack F Vogel u32 reg; 1080*8eb6488eSEric Joyner u16 ee_ctrl_4; 10811b6e0dbaSJack F Vogel 10822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10832969bf0eSJack F Vogel 10841b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10851b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 1086*8eb6488eSEric Joyner bus->lan_id = (u8)bus->func; 10871b6e0dbaSJack F Vogel 10881b6e0dbaSJack F Vogel /* check for a port swap */ 1089a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 10901b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10911b6e0dbaSJack F Vogel bus->func ^= 0x1; 1092*8eb6488eSEric Joyner 1093*8eb6488eSEric Joyner /* Get MAC instance from EEPROM for configuring CS4227 */ 1094*8eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 1095*8eb6488eSEric Joyner hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 1096*8eb6488eSEric Joyner bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 1097*8eb6488eSEric Joyner IXGBE_EE_CTRL_4_INST_ID_SHIFT; 1098*8eb6488eSEric Joyner } 10991b6e0dbaSJack F Vogel } 11001b6e0dbaSJack F Vogel 11011b6e0dbaSJack F Vogel /** 11029ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 110313705f88SJack F Vogel * @hw: pointer to hardware structure 110413705f88SJack F Vogel * 110513705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 110613705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 110713705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 110813705f88SJack F Vogel * state and should not touch the hardware. 110913705f88SJack F Vogel **/ 111013705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 111113705f88SJack F Vogel { 111213705f88SJack F Vogel u32 reg_val; 111313705f88SJack F Vogel u16 i; 111413705f88SJack F Vogel 11152969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 11162969bf0eSJack F Vogel 111713705f88SJack F Vogel /* 111813705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 111913705f88SJack F Vogel * the hardware 112013705f88SJack F Vogel */ 112113705f88SJack F Vogel hw->adapter_stopped = TRUE; 112213705f88SJack F Vogel 112313705f88SJack F Vogel /* Disable the receive unit */ 1124758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 112513705f88SJack F Vogel 112685d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 112713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 112813705f88SJack F Vogel 112985d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 113013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 113113705f88SJack F Vogel 113213705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 113385d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 113485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 113585d0a26eSJack F Vogel 113685d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 113785d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 113885d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 113985d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 114085d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 114185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 114213705f88SJack F Vogel } 114385d0a26eSJack F Vogel 114485d0a26eSJack F Vogel /* flush all queues disables */ 114585d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 114685d0a26eSJack F Vogel msec_delay(2); 114713705f88SJack F Vogel 11489ca4041bSJack F Vogel /* 11496f37f232SEric Joyner * Prevent the PCI-E bus from hanging by disabling PCI-E master 11509ca4041bSJack F Vogel * access and verify no pending requests 11519ca4041bSJack F Vogel */ 115285d0a26eSJack F Vogel return ixgbe_disable_pcie_master(hw); 115313705f88SJack F Vogel } 115413705f88SJack F Vogel 115513705f88SJack F Vogel /** 1156*8eb6488eSEric Joyner * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 1157*8eb6488eSEric Joyner * @hw: pointer to hardware structure 1158*8eb6488eSEric Joyner * 1159*8eb6488eSEric Joyner * Store the index for the link active LED. This will be used to support 1160*8eb6488eSEric Joyner * blinking the LED. 1161*8eb6488eSEric Joyner **/ 1162*8eb6488eSEric Joyner s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 1163*8eb6488eSEric Joyner { 1164*8eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac; 1165*8eb6488eSEric Joyner u32 led_reg, led_mode; 1166*8eb6488eSEric Joyner u8 i; 1167*8eb6488eSEric Joyner 1168*8eb6488eSEric Joyner led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 1169*8eb6488eSEric Joyner 1170*8eb6488eSEric Joyner /* Get LED link active from the LEDCTL register */ 1171*8eb6488eSEric Joyner for (i = 0; i < 4; i++) { 1172*8eb6488eSEric Joyner led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 1173*8eb6488eSEric Joyner 1174*8eb6488eSEric Joyner if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 1175*8eb6488eSEric Joyner IXGBE_LED_LINK_ACTIVE) { 1176*8eb6488eSEric Joyner mac->led_link_act = i; 1177*8eb6488eSEric Joyner return IXGBE_SUCCESS; 1178*8eb6488eSEric Joyner } 1179*8eb6488eSEric Joyner } 1180*8eb6488eSEric Joyner 1181*8eb6488eSEric Joyner /* 1182*8eb6488eSEric Joyner * If LEDCTL register does not have the LED link active set, then use 1183*8eb6488eSEric Joyner * known MAC defaults. 1184*8eb6488eSEric Joyner */ 1185*8eb6488eSEric Joyner switch (hw->mac.type) { 1186*8eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 1187*8eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 1188*8eb6488eSEric Joyner mac->led_link_act = 1; 1189*8eb6488eSEric Joyner break; 1190*8eb6488eSEric Joyner default: 1191*8eb6488eSEric Joyner mac->led_link_act = 2; 1192*8eb6488eSEric Joyner } 1193*8eb6488eSEric Joyner return IXGBE_SUCCESS; 1194*8eb6488eSEric Joyner } 1195*8eb6488eSEric Joyner 1196*8eb6488eSEric Joyner /** 119713705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 119813705f88SJack F Vogel * @hw: pointer to hardware structure 119913705f88SJack F Vogel * @index: led number to turn on 120013705f88SJack F Vogel **/ 120113705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 120213705f88SJack F Vogel { 120313705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 120413705f88SJack F Vogel 12052969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 12062969bf0eSJack F Vogel 1207*8eb6488eSEric Joyner if (index > 3) 1208*8eb6488eSEric Joyner return IXGBE_ERR_PARAM; 1209*8eb6488eSEric Joyner 121013705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 121113705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 121213705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 121313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12149ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 121513705f88SJack F Vogel 121613705f88SJack F Vogel return IXGBE_SUCCESS; 121713705f88SJack F Vogel } 121813705f88SJack F Vogel 121913705f88SJack F Vogel /** 122013705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 122113705f88SJack F Vogel * @hw: pointer to hardware structure 122213705f88SJack F Vogel * @index: led number to turn off 122313705f88SJack F Vogel **/ 122413705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 122513705f88SJack F Vogel { 122613705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 122713705f88SJack F Vogel 12282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 12292969bf0eSJack F Vogel 1230*8eb6488eSEric Joyner if (index > 3) 1231*8eb6488eSEric Joyner return IXGBE_ERR_PARAM; 1232*8eb6488eSEric Joyner 123313705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 123413705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 123513705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 123613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12379ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 123813705f88SJack F Vogel 123913705f88SJack F Vogel return IXGBE_SUCCESS; 124013705f88SJack F Vogel } 124113705f88SJack F Vogel 124213705f88SJack F Vogel /** 124313705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 124413705f88SJack F Vogel * @hw: pointer to hardware structure 124513705f88SJack F Vogel * 124613705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 124713705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 124813705f88SJack F Vogel **/ 124913705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 125013705f88SJack F Vogel { 125113705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 125213705f88SJack F Vogel u32 eec; 125313705f88SJack F Vogel u16 eeprom_size; 125413705f88SJack F Vogel 12552969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 12562969bf0eSJack F Vogel 125713705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 125813705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 12595b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 12605b7f4cedSJack F Vogel * tested value */ 12615b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 126285d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 126385d0a26eSJack F Vogel eeprom->word_page_size = 0; 126413705f88SJack F Vogel 126513705f88SJack F Vogel /* 126613705f88SJack F Vogel * Check for EEPROM present first. 126713705f88SJack F Vogel * If not present leave as none 126813705f88SJack F Vogel */ 1269a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 127013705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 127113705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 127213705f88SJack F Vogel 127313705f88SJack F Vogel /* 127413705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 127513705f88SJack F Vogel * change if a future EEPROM is not SPI. 127613705f88SJack F Vogel */ 127713705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 127813705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 127913705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 128085d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 128113705f88SJack F Vogel } 128213705f88SJack F Vogel 128313705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 128413705f88SJack F Vogel eeprom->address_bits = 16; 128513705f88SJack F Vogel else 128613705f88SJack F Vogel eeprom->address_bits = 8; 128713705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 128813705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 128913705f88SJack F Vogel eeprom->address_bits); 129013705f88SJack F Vogel } 129113705f88SJack F Vogel 129213705f88SJack F Vogel return IXGBE_SUCCESS; 129313705f88SJack F Vogel } 129413705f88SJack F Vogel 129513705f88SJack F Vogel /** 129685d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 129785d0a26eSJack F Vogel * @hw: pointer to hardware structure 129885d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 129985d0a26eSJack F Vogel * @words: number of word(s) 130085d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 130185d0a26eSJack F Vogel * 130285d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 130385d0a26eSJack F Vogel **/ 130485d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 130585d0a26eSJack F Vogel u16 words, u16 *data) 130685d0a26eSJack F Vogel { 130785d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 130885d0a26eSJack F Vogel u16 i, count; 130985d0a26eSJack F Vogel 131085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 131185d0a26eSJack F Vogel 131285d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 131385d0a26eSJack F Vogel 131485d0a26eSJack F Vogel if (words == 0) { 131585d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 131685d0a26eSJack F Vogel goto out; 131785d0a26eSJack F Vogel } 131885d0a26eSJack F Vogel 131985d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 132085d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 132185d0a26eSJack F Vogel goto out; 132285d0a26eSJack F Vogel } 132385d0a26eSJack F Vogel 132485d0a26eSJack F Vogel /* 132585d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 132685d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 132785d0a26eSJack F Vogel */ 132885d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 132985d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 133085d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 133185d0a26eSJack F Vogel 133285d0a26eSJack F Vogel /* 133385d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 133485d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 133585d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 133685d0a26eSJack F Vogel */ 133785d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 133885d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 133985d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 134085d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 134185d0a26eSJack F Vogel count, &data[i]); 134285d0a26eSJack F Vogel 134385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 134485d0a26eSJack F Vogel break; 134585d0a26eSJack F Vogel } 134685d0a26eSJack F Vogel 134785d0a26eSJack F Vogel out: 134885d0a26eSJack F Vogel return status; 134985d0a26eSJack F Vogel } 135085d0a26eSJack F Vogel 135185d0a26eSJack F Vogel /** 135285d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 135313705f88SJack F Vogel * @hw: pointer to hardware structure 135413705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 135585d0a26eSJack F Vogel * @words: number of word(s) 135685d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 135713705f88SJack F Vogel * 135813705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 135913705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 136013705f88SJack F Vogel **/ 136185d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 136285d0a26eSJack F Vogel u16 words, u16 *data) 136313705f88SJack F Vogel { 136413705f88SJack F Vogel s32 status; 136585d0a26eSJack F Vogel u16 word; 136685d0a26eSJack F Vogel u16 page_size; 136785d0a26eSJack F Vogel u16 i; 136813705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 136913705f88SJack F Vogel 137085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 13719ca4041bSJack F Vogel 137213705f88SJack F Vogel /* Prepare the EEPROM for writing */ 137313705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 137413705f88SJack F Vogel 137513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 137613705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 137713705f88SJack F Vogel ixgbe_release_eeprom(hw); 137813705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 137913705f88SJack F Vogel } 138013705f88SJack F Vogel } 138113705f88SJack F Vogel 138213705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 138385d0a26eSJack F Vogel for (i = 0; i < words; i++) { 138413705f88SJack F Vogel ixgbe_standby_eeprom(hw); 138513705f88SJack F Vogel 138613705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 138785d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 138885d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 138913705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 139013705f88SJack F Vogel 139113705f88SJack F Vogel ixgbe_standby_eeprom(hw); 139213705f88SJack F Vogel 139313705f88SJack F Vogel /* 139485d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 139585d0a26eSJack F Vogel * in the opcode 139613705f88SJack F Vogel */ 139785d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 139885d0a26eSJack F Vogel ((offset + i) >= 128)) 139913705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 140013705f88SJack F Vogel 140113705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 140213705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 140313705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 140485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 140513705f88SJack F Vogel hw->eeprom.address_bits); 140613705f88SJack F Vogel 140785d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 140813705f88SJack F Vogel 140985d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 141085d0a26eSJack F Vogel do { 141185d0a26eSJack F Vogel word = data[i]; 141285d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 141385d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 141485d0a26eSJack F Vogel 141585d0a26eSJack F Vogel if (page_size == 0) 141685d0a26eSJack F Vogel break; 141785d0a26eSJack F Vogel 141885d0a26eSJack F Vogel /* do not wrap around page */ 141985d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 142085d0a26eSJack F Vogel (page_size - 1)) 142185d0a26eSJack F Vogel break; 142285d0a26eSJack F Vogel } while (++i < words); 142385d0a26eSJack F Vogel 142485d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 142585d0a26eSJack F Vogel msec_delay(10); 142685d0a26eSJack F Vogel } 142713705f88SJack F Vogel /* Done with writing - release the EEPROM */ 142813705f88SJack F Vogel ixgbe_release_eeprom(hw); 142913705f88SJack F Vogel } 143013705f88SJack F Vogel 143185d0a26eSJack F Vogel return status; 143285d0a26eSJack F Vogel } 143385d0a26eSJack F Vogel 143485d0a26eSJack F Vogel /** 143585d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 143685d0a26eSJack F Vogel * @hw: pointer to hardware structure 143785d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 143885d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 143985d0a26eSJack F Vogel * 144085d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 144185d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 144285d0a26eSJack F Vogel **/ 144385d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 144485d0a26eSJack F Vogel { 144585d0a26eSJack F Vogel s32 status; 144685d0a26eSJack F Vogel 144785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 144885d0a26eSJack F Vogel 144985d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 145085d0a26eSJack F Vogel 145185d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 145285d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 145385d0a26eSJack F Vogel goto out; 145485d0a26eSJack F Vogel } 145585d0a26eSJack F Vogel 145685d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 145785d0a26eSJack F Vogel 14589ca4041bSJack F Vogel out: 145913705f88SJack F Vogel return status; 146013705f88SJack F Vogel } 146113705f88SJack F Vogel 146213705f88SJack F Vogel /** 146385d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 146485d0a26eSJack F Vogel * @hw: pointer to hardware structure 146585d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 146685d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 146785d0a26eSJack F Vogel * @words: number of word(s) 146885d0a26eSJack F Vogel * 146985d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 147085d0a26eSJack F Vogel **/ 147185d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147285d0a26eSJack F Vogel u16 words, u16 *data) 147385d0a26eSJack F Vogel { 147485d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 147585d0a26eSJack F Vogel u16 i, count; 147685d0a26eSJack F Vogel 147785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 147885d0a26eSJack F Vogel 147985d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 148085d0a26eSJack F Vogel 148185d0a26eSJack F Vogel if (words == 0) { 148285d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 148385d0a26eSJack F Vogel goto out; 148485d0a26eSJack F Vogel } 148585d0a26eSJack F Vogel 148685d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 148785d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 148885d0a26eSJack F Vogel goto out; 148985d0a26eSJack F Vogel } 149085d0a26eSJack F Vogel 149185d0a26eSJack F Vogel /* 149285d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 149385d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 149485d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 149585d0a26eSJack F Vogel */ 149685d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 149785d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 149885d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 149985d0a26eSJack F Vogel 150085d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 150185d0a26eSJack F Vogel count, &data[i]); 150285d0a26eSJack F Vogel 150385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 150485d0a26eSJack F Vogel break; 150585d0a26eSJack F Vogel } 150685d0a26eSJack F Vogel 150785d0a26eSJack F Vogel out: 150885d0a26eSJack F Vogel return status; 150985d0a26eSJack F Vogel } 151085d0a26eSJack F Vogel 151185d0a26eSJack F Vogel /** 151285d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 151385d0a26eSJack F Vogel * @hw: pointer to hardware structure 151485d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 151585d0a26eSJack F Vogel * @words: number of word(s) 151685d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 151785d0a26eSJack F Vogel * 151885d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 151985d0a26eSJack F Vogel **/ 152085d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 152185d0a26eSJack F Vogel u16 words, u16 *data) 152285d0a26eSJack F Vogel { 152385d0a26eSJack F Vogel s32 status; 152485d0a26eSJack F Vogel u16 word_in; 152585d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 152685d0a26eSJack F Vogel u16 i; 152785d0a26eSJack F Vogel 152885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 152985d0a26eSJack F Vogel 153085d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 153185d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 153285d0a26eSJack F Vogel 153385d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 153485d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 153585d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 153685d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 153785d0a26eSJack F Vogel } 153885d0a26eSJack F Vogel } 153985d0a26eSJack F Vogel 154085d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 154185d0a26eSJack F Vogel for (i = 0; i < words; i++) { 154285d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 154385d0a26eSJack F Vogel /* 154485d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 154585d0a26eSJack F Vogel * in the opcode 154685d0a26eSJack F Vogel */ 154785d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 154885d0a26eSJack F Vogel ((offset + i) >= 128)) 154985d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 155085d0a26eSJack F Vogel 155185d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 155285d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 155385d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 155485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 155585d0a26eSJack F Vogel hw->eeprom.address_bits); 155685d0a26eSJack F Vogel 155785d0a26eSJack F Vogel /* Read the data. */ 155885d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 155985d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 156085d0a26eSJack F Vogel } 156185d0a26eSJack F Vogel 156285d0a26eSJack F Vogel /* End this read operation */ 156385d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 156485d0a26eSJack F Vogel } 156585d0a26eSJack F Vogel 156685d0a26eSJack F Vogel return status; 156785d0a26eSJack F Vogel } 156885d0a26eSJack F Vogel 156985d0a26eSJack F Vogel /** 157013705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 157113705f88SJack F Vogel * @hw: pointer to hardware structure 157213705f88SJack F Vogel * @offset: offset within the EEPROM to be read 157313705f88SJack F Vogel * @data: read 16 bit value from EEPROM 157413705f88SJack F Vogel * 157513705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 157613705f88SJack F Vogel **/ 157713705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 157813705f88SJack F Vogel u16 *data) 157913705f88SJack F Vogel { 158013705f88SJack F Vogel s32 status; 158113705f88SJack F Vogel 15822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 15832969bf0eSJack F Vogel 15849ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 15859ca4041bSJack F Vogel 15869ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 15879ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 15889ca4041bSJack F Vogel goto out; 15899ca4041bSJack F Vogel } 15909ca4041bSJack F Vogel 159185d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 159213705f88SJack F Vogel 159385d0a26eSJack F Vogel out: 159485d0a26eSJack F Vogel return status; 159585d0a26eSJack F Vogel } 159685d0a26eSJack F Vogel 159785d0a26eSJack F Vogel /** 159885d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 159985d0a26eSJack F Vogel * @hw: pointer to hardware structure 160085d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 160185d0a26eSJack F Vogel * @words: number of word(s) 160285d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 160385d0a26eSJack F Vogel * 160485d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 160585d0a26eSJack F Vogel **/ 160685d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 160785d0a26eSJack F Vogel u16 words, u16 *data) 160885d0a26eSJack F Vogel { 160985d0a26eSJack F Vogel u32 eerd; 161085d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161185d0a26eSJack F Vogel u32 i; 161285d0a26eSJack F Vogel 161385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 161485d0a26eSJack F Vogel 161585d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 161685d0a26eSJack F Vogel 161785d0a26eSJack F Vogel if (words == 0) { 161885d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1619fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162085d0a26eSJack F Vogel goto out; 162185d0a26eSJack F Vogel } 162285d0a26eSJack F Vogel 162385d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 162413705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1625fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 162685d0a26eSJack F Vogel goto out; 162713705f88SJack F Vogel } 162813705f88SJack F Vogel 162985d0a26eSJack F Vogel for (i = 0; i < words; i++) { 16300ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163185d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163285d0a26eSJack F Vogel 163385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 163485d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 163585d0a26eSJack F Vogel 163613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 163785d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 163885d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 163985d0a26eSJack F Vogel } else { 164085d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 164185d0a26eSJack F Vogel goto out; 164285d0a26eSJack F Vogel } 164385d0a26eSJack F Vogel } 164485d0a26eSJack F Vogel out: 164585d0a26eSJack F Vogel return status; 164685d0a26eSJack F Vogel } 164785d0a26eSJack F Vogel 164885d0a26eSJack F Vogel /** 164985d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 165085d0a26eSJack F Vogel * @hw: pointer to hardware structure 165185d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 165285d0a26eSJack F Vogel * 165385d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 165485d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 165585d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 165685d0a26eSJack F Vogel **/ 165785d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 165885d0a26eSJack F Vogel u16 offset) 165985d0a26eSJack F Vogel { 166085d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 166185d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 166285d0a26eSJack F Vogel u16 i; 166385d0a26eSJack F Vogel 166485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 166585d0a26eSJack F Vogel 166685d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 166785d0a26eSJack F Vogel data[i] = i; 166885d0a26eSJack F Vogel 166985d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 167085d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 167185d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 167285d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 167385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167485d0a26eSJack F Vogel goto out; 167585d0a26eSJack F Vogel 167685d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 167785d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167885d0a26eSJack F Vogel goto out; 167913705f88SJack F Vogel 168013705f88SJack F Vogel /* 168185d0a26eSJack F Vogel * When writing in burst more than the actual page size 168285d0a26eSJack F Vogel * EEPROM address wraps around current page. 168313705f88SJack F Vogel */ 168485d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 168513705f88SJack F Vogel 168685d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 168785d0a26eSJack F Vogel hw->eeprom.word_page_size); 16889ca4041bSJack F Vogel out: 168913705f88SJack F Vogel return status; 169013705f88SJack F Vogel } 169113705f88SJack F Vogel 169213705f88SJack F Vogel /** 16932969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 169413705f88SJack F Vogel * @hw: pointer to hardware structure 169513705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 169613705f88SJack F Vogel * @data: word read from the EEPROM 169713705f88SJack F Vogel * 169813705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 169913705f88SJack F Vogel **/ 17002969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 170113705f88SJack F Vogel { 170285d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 170385d0a26eSJack F Vogel } 170413705f88SJack F Vogel 170585d0a26eSJack F Vogel /** 170685d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 170785d0a26eSJack F Vogel * @hw: pointer to hardware structure 170885d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 170985d0a26eSJack F Vogel * @words: number of word(s) 171085d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 171185d0a26eSJack F Vogel * 171285d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 171385d0a26eSJack F Vogel **/ 171485d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 171585d0a26eSJack F Vogel u16 words, u16 *data) 171685d0a26eSJack F Vogel { 171785d0a26eSJack F Vogel u32 eewr; 171885d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 171985d0a26eSJack F Vogel u16 i; 172085d0a26eSJack F Vogel 172185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 17222969bf0eSJack F Vogel 17239ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 17249ca4041bSJack F Vogel 172585d0a26eSJack F Vogel if (words == 0) { 172685d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1727fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 172885d0a26eSJack F Vogel goto out; 172985d0a26eSJack F Vogel } 173085d0a26eSJack F Vogel 17319ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 17329ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1733fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 17349ca4041bSJack F Vogel goto out; 17359ca4041bSJack F Vogel } 17369ca4041bSJack F Vogel 173785d0a26eSJack F Vogel for (i = 0; i < words; i++) { 173885d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 173985d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 17402969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 174113705f88SJack F Vogel 174285d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 174385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 174485d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 174585d0a26eSJack F Vogel goto out; 174685d0a26eSJack F Vogel } 174713705f88SJack F Vogel 174885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 174985d0a26eSJack F Vogel 175085d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 175185d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 175285d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 175385d0a26eSJack F Vogel goto out; 175485d0a26eSJack F Vogel } 175585d0a26eSJack F Vogel } 175613705f88SJack F Vogel 17579ca4041bSJack F Vogel out: 175813705f88SJack F Vogel return status; 175913705f88SJack F Vogel } 176013705f88SJack F Vogel 176113705f88SJack F Vogel /** 17621a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 17631a4e3449SJack F Vogel * @hw: pointer to hardware structure 17641a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 17651a4e3449SJack F Vogel * @data: word write to the EEPROM 17661a4e3449SJack F Vogel * 17671a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 17681a4e3449SJack F Vogel **/ 17691a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 17701a4e3449SJack F Vogel { 177185d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 17721a4e3449SJack F Vogel } 17731a4e3449SJack F Vogel 17741a4e3449SJack F Vogel /** 17752969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 177613705f88SJack F Vogel * @hw: pointer to hardware structure 17772969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 177813705f88SJack F Vogel * 17792969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 17802969bf0eSJack F Vogel * read or write is done respectively. 178113705f88SJack F Vogel **/ 17822969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 178313705f88SJack F Vogel { 178413705f88SJack F Vogel u32 i; 178513705f88SJack F Vogel u32 reg; 178613705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 178713705f88SJack F Vogel 17882969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 17892969bf0eSJack F Vogel 17902969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 17912969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 179213705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 17932969bf0eSJack F Vogel else 17942969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 17952969bf0eSJack F Vogel 17962969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 179713705f88SJack F Vogel status = IXGBE_SUCCESS; 179813705f88SJack F Vogel break; 179913705f88SJack F Vogel } 180013705f88SJack F Vogel usec_delay(5); 180113705f88SJack F Vogel } 1802fd75b91dSJack F Vogel 1803fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1804fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1805fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1806fd75b91dSJack F Vogel 180713705f88SJack F Vogel return status; 180813705f88SJack F Vogel } 180913705f88SJack F Vogel 181013705f88SJack F Vogel /** 181113705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 181213705f88SJack F Vogel * @hw: pointer to hardware structure 181313705f88SJack F Vogel * 181413705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 181513705f88SJack F Vogel * be called before issuing a command to the EEPROM. 181613705f88SJack F Vogel **/ 181713705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 181813705f88SJack F Vogel { 181913705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 182013705f88SJack F Vogel u32 eec; 182113705f88SJack F Vogel u32 i; 182213705f88SJack F Vogel 18232969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 18242969bf0eSJack F Vogel 182585d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 182685d0a26eSJack F Vogel != IXGBE_SUCCESS) 182713705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 182813705f88SJack F Vogel 182913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 1830a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183113705f88SJack F Vogel 183213705f88SJack F Vogel /* Request EEPROM Access */ 183313705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 1834a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 183513705f88SJack F Vogel 183613705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 1837a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183813705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 183913705f88SJack F Vogel break; 184013705f88SJack F Vogel usec_delay(5); 184113705f88SJack F Vogel } 184213705f88SJack F Vogel 18439ca4041bSJack F Vogel /* Release if grant not acquired */ 184413705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 184513705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 1846a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 184713705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 184813705f88SJack F Vogel 184985d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 185013705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 185113705f88SJack F Vogel } 185213705f88SJack F Vogel 185313705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 185413705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 185513705f88SJack F Vogel /* Clear CS and SK */ 185613705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 1857a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 185813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 185913705f88SJack F Vogel usec_delay(1); 186013705f88SJack F Vogel } 18611a4e3449SJack F Vogel } 186213705f88SJack F Vogel return status; 186313705f88SJack F Vogel } 186413705f88SJack F Vogel 186513705f88SJack F Vogel /** 186613705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 186713705f88SJack F Vogel * @hw: pointer to hardware structure 186813705f88SJack F Vogel * 186913705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 187013705f88SJack F Vogel **/ 187113705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 187213705f88SJack F Vogel { 187313705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1874d8602bb9SJack F Vogel u32 timeout = 2000; 187513705f88SJack F Vogel u32 i; 187613705f88SJack F Vogel u32 swsm; 187713705f88SJack F Vogel 18782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 18792969bf0eSJack F Vogel 18801a4e3449SJack F Vogel 188113705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 188213705f88SJack F Vogel for (i = 0; i < timeout; i++) { 188313705f88SJack F Vogel /* 188413705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 188513705f88SJack F Vogel * set and we have the semaphore 188613705f88SJack F Vogel */ 1887a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 188813705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 188913705f88SJack F Vogel status = IXGBE_SUCCESS; 189013705f88SJack F Vogel break; 189113705f88SJack F Vogel } 18920ac6dfecSJack F Vogel usec_delay(50); 189313705f88SJack F Vogel } 189413705f88SJack F Vogel 189585d0a26eSJack F Vogel if (i == timeout) { 189685d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 189785d0a26eSJack F Vogel "not granted.\n"); 189885d0a26eSJack F Vogel /* 189985d0a26eSJack F Vogel * this release is particularly important because our attempts 190085d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 190185d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 190285d0a26eSJack F Vogel * bits to free the driver to make progress 190385d0a26eSJack F Vogel */ 190485d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 190585d0a26eSJack F Vogel 190685d0a26eSJack F Vogel usec_delay(50); 190785d0a26eSJack F Vogel /* 190885d0a26eSJack F Vogel * one last try 190985d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 191085d0a26eSJack F Vogel * set and we have the semaphore 191185d0a26eSJack F Vogel */ 1912a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 191385d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 191485d0a26eSJack F Vogel status = IXGBE_SUCCESS; 191585d0a26eSJack F Vogel } 191685d0a26eSJack F Vogel 191713705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 191813705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 191913705f88SJack F Vogel for (i = 0; i < timeout; i++) { 1920a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 192113705f88SJack F Vogel 192213705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 192313705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 1924a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); 192513705f88SJack F Vogel 192613705f88SJack F Vogel /* 192713705f88SJack F Vogel * If we set the bit successfully then we got the 192813705f88SJack F Vogel * semaphore. 192913705f88SJack F Vogel */ 1930a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 193113705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 193213705f88SJack F Vogel break; 193313705f88SJack F Vogel 193413705f88SJack F Vogel usec_delay(50); 193513705f88SJack F Vogel } 193613705f88SJack F Vogel 193713705f88SJack F Vogel /* 193813705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 193913705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 194013705f88SJack F Vogel */ 194113705f88SJack F Vogel if (i >= timeout) { 1942fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1943fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 194413705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 194513705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 194613705f88SJack F Vogel } 19470ac6dfecSJack F Vogel } else { 1948fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1949fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 19500ac6dfecSJack F Vogel "not granted.\n"); 195113705f88SJack F Vogel } 195213705f88SJack F Vogel 195313705f88SJack F Vogel return status; 195413705f88SJack F Vogel } 195513705f88SJack F Vogel 195613705f88SJack F Vogel /** 195713705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 195813705f88SJack F Vogel * @hw: pointer to hardware structure 195913705f88SJack F Vogel * 196013705f88SJack F Vogel * This function clears hardware semaphore bits. 196113705f88SJack F Vogel **/ 196213705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 196313705f88SJack F Vogel { 196413705f88SJack F Vogel u32 swsm; 196513705f88SJack F Vogel 19662969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 19672969bf0eSJack F Vogel 196813705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 196913705f88SJack F Vogel 197013705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 197113705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 197213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 19739ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 197413705f88SJack F Vogel } 197513705f88SJack F Vogel 197613705f88SJack F Vogel /** 197713705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 197813705f88SJack F Vogel * @hw: pointer to hardware structure 197913705f88SJack F Vogel **/ 198013705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 198113705f88SJack F Vogel { 198213705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 198313705f88SJack F Vogel u16 i; 198413705f88SJack F Vogel u8 spi_stat_reg; 198513705f88SJack F Vogel 19862969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 19872969bf0eSJack F Vogel 198813705f88SJack F Vogel /* 198913705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 199013705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 199113705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 199213705f88SJack F Vogel * 5 milliseconds, then error out. 199313705f88SJack F Vogel */ 199413705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 199513705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 199613705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 199713705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 199813705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 199913705f88SJack F Vogel break; 200013705f88SJack F Vogel 200113705f88SJack F Vogel usec_delay(5); 200213705f88SJack F Vogel ixgbe_standby_eeprom(hw); 2003*8eb6488eSEric Joyner }; 200413705f88SJack F Vogel 200513705f88SJack F Vogel /* 200613705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 200713705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 200813705f88SJack F Vogel */ 200913705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 201013705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 201113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 201213705f88SJack F Vogel } 201313705f88SJack F Vogel 201413705f88SJack F Vogel return status; 201513705f88SJack F Vogel } 201613705f88SJack F Vogel 201713705f88SJack F Vogel /** 201813705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 201913705f88SJack F Vogel * @hw: pointer to hardware structure 202013705f88SJack F Vogel **/ 202113705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 202213705f88SJack F Vogel { 202313705f88SJack F Vogel u32 eec; 202413705f88SJack F Vogel 20252969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 20262969bf0eSJack F Vogel 2027a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 202813705f88SJack F Vogel 202913705f88SJack F Vogel /* Toggle CS to flush commands */ 203013705f88SJack F Vogel eec |= IXGBE_EEC_CS; 2031a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203313705f88SJack F Vogel usec_delay(1); 203413705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 2035a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203613705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203713705f88SJack F Vogel usec_delay(1); 203813705f88SJack F Vogel } 203913705f88SJack F Vogel 204013705f88SJack F Vogel /** 204113705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 204213705f88SJack F Vogel * @hw: pointer to hardware structure 204313705f88SJack F Vogel * @data: data to send to the EEPROM 204413705f88SJack F Vogel * @count: number of bits to shift out 204513705f88SJack F Vogel **/ 204613705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 204713705f88SJack F Vogel u16 count) 204813705f88SJack F Vogel { 204913705f88SJack F Vogel u32 eec; 205013705f88SJack F Vogel u32 mask; 205113705f88SJack F Vogel u32 i; 205213705f88SJack F Vogel 20532969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 20542969bf0eSJack F Vogel 2055a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 205613705f88SJack F Vogel 205713705f88SJack F Vogel /* 205813705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 205913705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 206013705f88SJack F Vogel */ 206113705f88SJack F Vogel mask = 0x01 << (count - 1); 206213705f88SJack F Vogel 206313705f88SJack F Vogel for (i = 0; i < count; i++) { 206413705f88SJack F Vogel /* 206513705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 206613705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 206713705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 206813705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 206913705f88SJack F Vogel * raising and then lowering the clock. 207013705f88SJack F Vogel */ 207113705f88SJack F Vogel if (data & mask) 207213705f88SJack F Vogel eec |= IXGBE_EEC_DI; 207313705f88SJack F Vogel else 207413705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 207513705f88SJack F Vogel 2076a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 207713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 207813705f88SJack F Vogel 207913705f88SJack F Vogel usec_delay(1); 208013705f88SJack F Vogel 208113705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 208213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 208313705f88SJack F Vogel 208413705f88SJack F Vogel /* 208513705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 208613705f88SJack F Vogel * EEPROM 208713705f88SJack F Vogel */ 208813705f88SJack F Vogel mask = mask >> 1; 2089*8eb6488eSEric Joyner }; 209013705f88SJack F Vogel 209113705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 209213705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 2093a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 209413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 209513705f88SJack F Vogel } 209613705f88SJack F Vogel 209713705f88SJack F Vogel /** 209813705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 209913705f88SJack F Vogel * @hw: pointer to hardware structure 210013705f88SJack F Vogel **/ 210113705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 210213705f88SJack F Vogel { 210313705f88SJack F Vogel u32 eec; 210413705f88SJack F Vogel u32 i; 210513705f88SJack F Vogel u16 data = 0; 210613705f88SJack F Vogel 21072969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 21082969bf0eSJack F Vogel 210913705f88SJack F Vogel /* 211013705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 211113705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 211213705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 211313705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 211413705f88SJack F Vogel * "DI" bit should always be clear. 211513705f88SJack F Vogel */ 2116a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 211713705f88SJack F Vogel 211813705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 211913705f88SJack F Vogel 212013705f88SJack F Vogel for (i = 0; i < count; i++) { 212113705f88SJack F Vogel data = data << 1; 212213705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 212313705f88SJack F Vogel 2124a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212513705f88SJack F Vogel 212613705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 212713705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 212813705f88SJack F Vogel data |= 1; 212913705f88SJack F Vogel 213013705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 213113705f88SJack F Vogel } 213213705f88SJack F Vogel 213313705f88SJack F Vogel return data; 213413705f88SJack F Vogel } 213513705f88SJack F Vogel 213613705f88SJack F Vogel /** 213713705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 213813705f88SJack F Vogel * @hw: pointer to hardware structure 213913705f88SJack F Vogel * @eec: EEC register's current value 214013705f88SJack F Vogel **/ 214113705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 214213705f88SJack F Vogel { 21432969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 21442969bf0eSJack F Vogel 214513705f88SJack F Vogel /* 214613705f88SJack F Vogel * Raise the clock input to the EEPROM 214713705f88SJack F Vogel * (setting the SK bit), then delay 214813705f88SJack F Vogel */ 214913705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 2150a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 215113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 215213705f88SJack F Vogel usec_delay(1); 215313705f88SJack F Vogel } 215413705f88SJack F Vogel 215513705f88SJack F Vogel /** 215613705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 215713705f88SJack F Vogel * @hw: pointer to hardware structure 215813705f88SJack F Vogel * @eecd: EECD's current value 215913705f88SJack F Vogel **/ 216013705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 216113705f88SJack F Vogel { 21622969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 21632969bf0eSJack F Vogel 216413705f88SJack F Vogel /* 216513705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 216613705f88SJack F Vogel * delay 216713705f88SJack F Vogel */ 216813705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 2169a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 217013705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 217113705f88SJack F Vogel usec_delay(1); 217213705f88SJack F Vogel } 217313705f88SJack F Vogel 217413705f88SJack F Vogel /** 217513705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 217613705f88SJack F Vogel * @hw: pointer to hardware structure 217713705f88SJack F Vogel **/ 217813705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 217913705f88SJack F Vogel { 218013705f88SJack F Vogel u32 eec; 218113705f88SJack F Vogel 21822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 21832969bf0eSJack F Vogel 2184a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 218513705f88SJack F Vogel 218613705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 218713705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 218813705f88SJack F Vogel 2189a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219013705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 219113705f88SJack F Vogel 219213705f88SJack F Vogel usec_delay(1); 219313705f88SJack F Vogel 219413705f88SJack F Vogel /* Stop requesting EEPROM access */ 219513705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 2196a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219713705f88SJack F Vogel 219885d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2199d8602bb9SJack F Vogel 2200d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2201d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 220213705f88SJack F Vogel } 220313705f88SJack F Vogel 220413705f88SJack F Vogel /** 22052969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 220613705f88SJack F Vogel * @hw: pointer to hardware structure 2207758cc3dcSJack F Vogel * 2208758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 220913705f88SJack F Vogel **/ 2210758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 221113705f88SJack F Vogel { 221213705f88SJack F Vogel u16 i; 221313705f88SJack F Vogel u16 j; 221413705f88SJack F Vogel u16 checksum = 0; 221513705f88SJack F Vogel u16 length = 0; 221613705f88SJack F Vogel u16 pointer = 0; 221713705f88SJack F Vogel u16 word = 0; 221813705f88SJack F Vogel 22192969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 22202969bf0eSJack F Vogel 222113705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 222213705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2223758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 222413705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2225758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 222613705f88SJack F Vogel } 222713705f88SJack F Vogel checksum += word; 222813705f88SJack F Vogel } 222913705f88SJack F Vogel 223013705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 223113705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2232758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2233758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2234758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2235758cc3dcSJack F Vogel } 223613705f88SJack F Vogel 2237758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2238758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2239758cc3dcSJack F Vogel continue; 224013705f88SJack F Vogel 2241758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2242758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2243758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2244758cc3dcSJack F Vogel } 2245758cc3dcSJack F Vogel 2246758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2247758cc3dcSJack F Vogel continue; 2248758cc3dcSJack F Vogel 224913705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2250758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2251758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2252758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2253758cc3dcSJack F Vogel } 225413705f88SJack F Vogel checksum += word; 225513705f88SJack F Vogel } 225613705f88SJack F Vogel } 225713705f88SJack F Vogel 225813705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 225913705f88SJack F Vogel 2260758cc3dcSJack F Vogel return (s32)checksum; 226113705f88SJack F Vogel } 226213705f88SJack F Vogel 226313705f88SJack F Vogel /** 226413705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 226513705f88SJack F Vogel * @hw: pointer to hardware structure 226613705f88SJack F Vogel * @checksum_val: calculated checksum 226713705f88SJack F Vogel * 226813705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 226913705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 227013705f88SJack F Vogel **/ 227113705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 227213705f88SJack F Vogel u16 *checksum_val) 227313705f88SJack F Vogel { 227413705f88SJack F Vogel s32 status; 227513705f88SJack F Vogel u16 checksum; 227613705f88SJack F Vogel u16 read_checksum = 0; 227713705f88SJack F Vogel 22782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 22792969bf0eSJack F Vogel 2280758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 228113705f88SJack F Vogel * not continue or we could be in for a very long wait while every 228213705f88SJack F Vogel * EEPROM read fails 228313705f88SJack F Vogel */ 22849ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2285758cc3dcSJack F Vogel if (status) { 2286758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2287758cc3dcSJack F Vogel return status; 2288758cc3dcSJack F Vogel } 228913705f88SJack F Vogel 2290758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2291758cc3dcSJack F Vogel if (status < 0) 2292758cc3dcSJack F Vogel return status; 229313705f88SJack F Vogel 2294758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 229513705f88SJack F Vogel 2296758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2297758cc3dcSJack F Vogel if (status) { 2298758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2299758cc3dcSJack F Vogel return status; 2300758cc3dcSJack F Vogel } 2301758cc3dcSJack F Vogel 2302758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 230313705f88SJack F Vogel * calculated checksum 230413705f88SJack F Vogel */ 23059ca4041bSJack F Vogel if (read_checksum != checksum) 230613705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 230713705f88SJack F Vogel 230813705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 23099ca4041bSJack F Vogel if (checksum_val) 231013705f88SJack F Vogel *checksum_val = checksum; 231113705f88SJack F Vogel 231213705f88SJack F Vogel return status; 231313705f88SJack F Vogel } 231413705f88SJack F Vogel 231513705f88SJack F Vogel /** 23169ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 231713705f88SJack F Vogel * @hw: pointer to hardware structure 231813705f88SJack F Vogel **/ 231913705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 232013705f88SJack F Vogel { 232113705f88SJack F Vogel s32 status; 232213705f88SJack F Vogel u16 checksum; 232313705f88SJack F Vogel 23242969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 23252969bf0eSJack F Vogel 2326758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 232713705f88SJack F Vogel * not continue or we could be in for a very long wait while every 232813705f88SJack F Vogel * EEPROM read fails 232913705f88SJack F Vogel */ 23309ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2331758cc3dcSJack F Vogel if (status) { 233213705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2333758cc3dcSJack F Vogel return status; 233413705f88SJack F Vogel } 233513705f88SJack F Vogel 2336758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2337758cc3dcSJack F Vogel if (status < 0) 2338758cc3dcSJack F Vogel return status; 2339758cc3dcSJack F Vogel 2340758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2341758cc3dcSJack F Vogel 2342758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2343758cc3dcSJack F Vogel 234413705f88SJack F Vogel return status; 234513705f88SJack F Vogel } 234613705f88SJack F Vogel 234713705f88SJack F Vogel /** 234813705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 234913705f88SJack F Vogel * @mac_addr: pointer to MAC address. 235013705f88SJack F Vogel * 2351*8eb6488eSEric Joyner * Tests a MAC address to ensure it is a valid Individual Address. 235213705f88SJack F Vogel **/ 235313705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 235413705f88SJack F Vogel { 235513705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 235613705f88SJack F Vogel 23572969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 23582969bf0eSJack F Vogel 235913705f88SJack F Vogel /* Make sure it is not a multicast address */ 236013705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 236113705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236213705f88SJack F Vogel /* Not a broadcast address */ 236313705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 236413705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236513705f88SJack F Vogel /* Reject the zero address */ 236613705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 236713705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 236813705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236913705f88SJack F Vogel } 237013705f88SJack F Vogel return status; 237113705f88SJack F Vogel } 237213705f88SJack F Vogel 237313705f88SJack F Vogel /** 23749ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 237513705f88SJack F Vogel * @hw: pointer to hardware structure 237613705f88SJack F Vogel * @index: Receive address register to write 23779ca4041bSJack F Vogel * @addr: Address to put into receive address register 23789ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 237913705f88SJack F Vogel * @enable_addr: set flag that address is active 238013705f88SJack F Vogel * 238113705f88SJack F Vogel * Puts an ethernet address into a receive address register. 238213705f88SJack F Vogel **/ 23839ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 238413705f88SJack F Vogel u32 enable_addr) 238513705f88SJack F Vogel { 238613705f88SJack F Vogel u32 rar_low, rar_high; 23879ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 238813705f88SJack F Vogel 23892969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 23902969bf0eSJack F Vogel 23911a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 23921a4e3449SJack F Vogel if (index >= rar_entries) { 2393fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2394fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23951a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 23961a4e3449SJack F Vogel } 23971a4e3449SJack F Vogel 23989ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 23999ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 24009ca4041bSJack F Vogel 240113705f88SJack F Vogel /* 24029ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 24039ca4041bSJack F Vogel * order from network order (big endian) to little endian 240413705f88SJack F Vogel */ 240513705f88SJack F Vogel rar_low = ((u32)addr[0] | 240613705f88SJack F Vogel ((u32)addr[1] << 8) | 240713705f88SJack F Vogel ((u32)addr[2] << 16) | 240813705f88SJack F Vogel ((u32)addr[3] << 24)); 24099ca4041bSJack F Vogel /* 24109ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24119ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 24129ca4041bSJack F Vogel * of the address and the address valid bit. 24139ca4041bSJack F Vogel */ 24149ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24159ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24169ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 241713705f88SJack F Vogel 241813705f88SJack F Vogel if (enable_addr != 0) 241913705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 242013705f88SJack F Vogel 242113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 242213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 242313705f88SJack F Vogel 242413705f88SJack F Vogel return IXGBE_SUCCESS; 242513705f88SJack F Vogel } 242613705f88SJack F Vogel 242713705f88SJack F Vogel /** 24285b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 24295b7f4cedSJack F Vogel * @hw: pointer to hardware structure 24305b7f4cedSJack F Vogel * @index: Receive address register to write 24315b7f4cedSJack F Vogel * 24325b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 24335b7f4cedSJack F Vogel **/ 24345b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 24355b7f4cedSJack F Vogel { 24365b7f4cedSJack F Vogel u32 rar_high; 24375b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24385b7f4cedSJack F Vogel 24392969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 24402969bf0eSJack F Vogel 24415b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 24421a4e3449SJack F Vogel if (index >= rar_entries) { 2443fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2444fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 24451a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24461a4e3449SJack F Vogel } 24471a4e3449SJack F Vogel 24485b7f4cedSJack F Vogel /* 24495b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24505b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 24515b7f4cedSJack F Vogel * of the address and the address valid bit. 24525b7f4cedSJack F Vogel */ 24535b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24545b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24555b7f4cedSJack F Vogel 24565b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 24575b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 24585b7f4cedSJack F Vogel 24595b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 24605b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 24615b7f4cedSJack F Vogel 24625b7f4cedSJack F Vogel return IXGBE_SUCCESS; 24635b7f4cedSJack F Vogel } 24645b7f4cedSJack F Vogel 24655b7f4cedSJack F Vogel /** 246613705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 246713705f88SJack F Vogel * @hw: pointer to hardware structure 246813705f88SJack F Vogel * 246913705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 24709ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 247113705f88SJack F Vogel * the receiver is in reset when the routine is called. 247213705f88SJack F Vogel **/ 247313705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 247413705f88SJack F Vogel { 247513705f88SJack F Vogel u32 i; 24769ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 247713705f88SJack F Vogel 24782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 24792969bf0eSJack F Vogel 248013705f88SJack F Vogel /* 248113705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 248213705f88SJack F Vogel * to the permanent address. 248313705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 248413705f88SJack F Vogel */ 248513705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 248613705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 248713705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 24889ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 248913705f88SJack F Vogel 249013705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 249113705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 249213705f88SJack F Vogel hw->mac.addr[2]); 249313705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 249413705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 249513705f88SJack F Vogel } else { 249613705f88SJack F Vogel /* Setup the receive address. */ 249713705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 249813705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 249913705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 250013705f88SJack F Vogel hw->mac.addr[2]); 250113705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 250213705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 250313705f88SJack F Vogel 25049ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 2505*8eb6488eSEric Joyner } 2506182b3808SJack F Vogel 2507182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2508182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 2509*8eb6488eSEric Joyner 25109ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 251113705f88SJack F Vogel 251213705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 251313705f88SJack F Vogel 251413705f88SJack F Vogel /* Zero out the other receive addresses. */ 25159ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 251613705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 251713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 251813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 251913705f88SJack F Vogel } 252013705f88SJack F Vogel 252113705f88SJack F Vogel /* Clear the MTA */ 252213705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 252313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 252413705f88SJack F Vogel 252513705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 25269ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 252713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 252813705f88SJack F Vogel 25295b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 25305b7f4cedSJack F Vogel 253113705f88SJack F Vogel return IXGBE_SUCCESS; 253213705f88SJack F Vogel } 253313705f88SJack F Vogel 253413705f88SJack F Vogel /** 25359ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 25369ca4041bSJack F Vogel * @hw: pointer to hardware structure 25379ca4041bSJack F Vogel * @addr: new address 25389ca4041bSJack F Vogel * 25399ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 25409ca4041bSJack F Vogel **/ 25419ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 25429ca4041bSJack F Vogel { 25439ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 25449ca4041bSJack F Vogel u32 rar; 25459ca4041bSJack F Vogel 25462969bf0eSJack F Vogel DEBUGFUNC("ixgbe_add_uc_addr"); 25472969bf0eSJack F Vogel 25489ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 25499ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 25509ca4041bSJack F Vogel 25519ca4041bSJack F Vogel /* 25529ca4041bSJack F Vogel * Place this address in the RAR if there is room, 25539ca4041bSJack F Vogel * else put the controller into promiscuous mode 25549ca4041bSJack F Vogel */ 25559ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 25560ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 25579ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 25589ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 25599ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 25609ca4041bSJack F Vogel } else { 25619ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 25629ca4041bSJack F Vogel } 25639ca4041bSJack F Vogel 25649ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 25659ca4041bSJack F Vogel } 25669ca4041bSJack F Vogel 25679ca4041bSJack F Vogel /** 25689ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 25699ca4041bSJack F Vogel * @hw: pointer to hardware structure 25709ca4041bSJack F Vogel * @addr_list: the list of new addresses 25719ca4041bSJack F Vogel * @addr_count: number of addresses 25729ca4041bSJack F Vogel * @next: iterator function to walk the address list 25739ca4041bSJack F Vogel * 25749ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 25759ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 25769ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 25779ca4041bSJack F Vogel * 25789ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 25799ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 25809ca4041bSJack F Vogel **/ 25819ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 25829ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 25839ca4041bSJack F Vogel { 25849ca4041bSJack F Vogel u8 *addr; 25859ca4041bSJack F Vogel u32 i; 25869ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 25879ca4041bSJack F Vogel u32 uc_addr_in_use; 25889ca4041bSJack F Vogel u32 fctrl; 25899ca4041bSJack F Vogel u32 vmdq; 25909ca4041bSJack F Vogel 25912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 25922969bf0eSJack F Vogel 25939ca4041bSJack F Vogel /* 25949ca4041bSJack F Vogel * Clear accounting of old secondary address list, 25959ca4041bSJack F Vogel * don't count RAR[0] 25969ca4041bSJack F Vogel */ 25970ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 25989ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 25999ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 26009ca4041bSJack F Vogel 26019ca4041bSJack F Vogel /* Zero out the other receive addresses */ 26022969bf0eSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); 26032969bf0eSJack F Vogel for (i = 0; i < uc_addr_in_use; i++) { 26042969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); 26052969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); 26069ca4041bSJack F Vogel } 26079ca4041bSJack F Vogel 26089ca4041bSJack F Vogel /* Add the new addresses */ 26099ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 26109ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 26119ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 26129ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 26139ca4041bSJack F Vogel } 26149ca4041bSJack F Vogel 26159ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 26169ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 26179ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26189ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 26199ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26209ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 26219ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26229ca4041bSJack F Vogel } 26239ca4041bSJack F Vogel } else { 26249ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 26259ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26269ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 26279ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26289ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 26299ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26309ca4041bSJack F Vogel } 26319ca4041bSJack F Vogel } 26329ca4041bSJack F Vogel 26339ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 26349ca4041bSJack F Vogel return IXGBE_SUCCESS; 26359ca4041bSJack F Vogel } 26369ca4041bSJack F Vogel 26379ca4041bSJack F Vogel /** 263813705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 263913705f88SJack F Vogel * @hw: pointer to hardware structure 264013705f88SJack F Vogel * @mc_addr: the multicast address 264113705f88SJack F Vogel * 264213705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 264313705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 264413705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 264513705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 26469ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 264713705f88SJack F Vogel * to mc_filter_type. 264813705f88SJack F Vogel **/ 264913705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 265013705f88SJack F Vogel { 265113705f88SJack F Vogel u32 vector = 0; 265213705f88SJack F Vogel 26532969bf0eSJack F Vogel DEBUGFUNC("ixgbe_mta_vector"); 26542969bf0eSJack F Vogel 265513705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 265613705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 265713705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 265813705f88SJack F Vogel break; 265913705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 266013705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 266113705f88SJack F Vogel break; 266213705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 266313705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 266413705f88SJack F Vogel break; 266513705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 266613705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 266713705f88SJack F Vogel break; 266813705f88SJack F Vogel default: /* Invalid mc_filter_type */ 266913705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 267013705f88SJack F Vogel ASSERT(0); 267113705f88SJack F Vogel break; 267213705f88SJack F Vogel } 267313705f88SJack F Vogel 267413705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 267513705f88SJack F Vogel vector &= 0xFFF; 267613705f88SJack F Vogel return vector; 267713705f88SJack F Vogel } 267813705f88SJack F Vogel 267913705f88SJack F Vogel /** 268013705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 268113705f88SJack F Vogel * @hw: pointer to hardware structure 268213705f88SJack F Vogel * @hash_value: Multicast address hash value 268313705f88SJack F Vogel * 268413705f88SJack F Vogel * Sets the bit-vector in the multicast table. 268513705f88SJack F Vogel **/ 268613705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 268713705f88SJack F Vogel { 268813705f88SJack F Vogel u32 vector; 268913705f88SJack F Vogel u32 vector_bit; 269013705f88SJack F Vogel u32 vector_reg; 269113705f88SJack F Vogel 26922969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_mta"); 26932969bf0eSJack F Vogel 269413705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 269513705f88SJack F Vogel 269613705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 269713705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 269813705f88SJack F Vogel 269913705f88SJack F Vogel /* 270013705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 270113705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 270213705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 270313705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 270413705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 270513705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 270613705f88SJack F Vogel * the value. 270713705f88SJack F Vogel */ 270813705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 270913705f88SJack F Vogel vector_bit = vector & 0x1F; 27101a4e3449SJack F Vogel hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); 271113705f88SJack F Vogel } 271213705f88SJack F Vogel 271313705f88SJack F Vogel /** 271413705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 271513705f88SJack F Vogel * @hw: pointer to hardware structure 271613705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 271713705f88SJack F Vogel * @mc_addr_count: number of addresses 27189ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 271985d0a26eSJack F Vogel * @clear: flag, when set clears the table beforehand 272013705f88SJack F Vogel * 272185d0a26eSJack F Vogel * When the clear flag is set, the given list replaces any existing list. 272285d0a26eSJack F Vogel * Hashes the given addresses into the multicast table. 272313705f88SJack F Vogel **/ 272413705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 272585d0a26eSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next, 272685d0a26eSJack F Vogel bool clear) 272713705f88SJack F Vogel { 272813705f88SJack F Vogel u32 i; 27299ca4041bSJack F Vogel u32 vmdq; 273013705f88SJack F Vogel 27312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 27322969bf0eSJack F Vogel 273313705f88SJack F Vogel /* 273413705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 273513705f88SJack F Vogel * use. 273613705f88SJack F Vogel */ 273713705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 273813705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 273913705f88SJack F Vogel 27401a4e3449SJack F Vogel /* Clear mta_shadow */ 274185d0a26eSJack F Vogel if (clear) { 274213705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 27431a4e3449SJack F Vogel memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 274485d0a26eSJack F Vogel } 274513705f88SJack F Vogel 27461a4e3449SJack F Vogel /* Update mta_shadow */ 274713705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 274813705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 27490ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 275013705f88SJack F Vogel } 275113705f88SJack F Vogel 275213705f88SJack F Vogel /* Enable mta */ 27531a4e3449SJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 27541a4e3449SJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 27551a4e3449SJack F Vogel hw->mac.mta_shadow[i]); 27561a4e3449SJack F Vogel 275713705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 275813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 275913705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 276013705f88SJack F Vogel 276113705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 276213705f88SJack F Vogel return IXGBE_SUCCESS; 276313705f88SJack F Vogel } 276413705f88SJack F Vogel 276513705f88SJack F Vogel /** 276613705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 276713705f88SJack F Vogel * @hw: pointer to hardware structure 276813705f88SJack F Vogel * 276913705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 277013705f88SJack F Vogel **/ 277113705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 277213705f88SJack F Vogel { 277313705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 277413705f88SJack F Vogel 27752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_mc_generic"); 27762969bf0eSJack F Vogel 277713705f88SJack F Vogel if (a->mta_in_use > 0) 277813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 277913705f88SJack F Vogel hw->mac.mc_filter_type); 278013705f88SJack F Vogel 278113705f88SJack F Vogel return IXGBE_SUCCESS; 278213705f88SJack F Vogel } 278313705f88SJack F Vogel 278413705f88SJack F Vogel /** 27859ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 278613705f88SJack F Vogel * @hw: pointer to hardware structure 278713705f88SJack F Vogel * 278813705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 278913705f88SJack F Vogel **/ 279013705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 279113705f88SJack F Vogel { 279213705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 279313705f88SJack F Vogel 27942969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_mc_generic"); 27952969bf0eSJack F Vogel 279613705f88SJack F Vogel if (a->mta_in_use > 0) 279713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 279813705f88SJack F Vogel 279913705f88SJack F Vogel return IXGBE_SUCCESS; 280013705f88SJack F Vogel } 280113705f88SJack F Vogel 28021b6e0dbaSJack F Vogel /** 28030ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 28041b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 28051b6e0dbaSJack F Vogel * 28060ac6dfecSJack F Vogel * Enable flow control according to the current settings. 28071b6e0dbaSJack F Vogel **/ 2808a621e3c8SJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 28091b6e0dbaSJack F Vogel { 28101b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 28110ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 28120ac6dfecSJack F Vogel u32 reg; 28131a4e3449SJack F Vogel u32 fcrtl, fcrth; 2814a621e3c8SJack F Vogel int i; 28151b6e0dbaSJack F Vogel 28160ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 28171b6e0dbaSJack F Vogel 2818a621e3c8SJack F Vogel /* Validate the water mark configuration */ 2819a621e3c8SJack F Vogel if (!hw->fc.pause_time) { 2820a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 28210ac6dfecSJack F Vogel goto out; 2822a621e3c8SJack F Vogel } 2823a621e3c8SJack F Vogel 2824a621e3c8SJack F Vogel /* Low water mark of zero causes XOFF floods */ 2825a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2826a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2827a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2828a621e3c8SJack F Vogel if (!hw->fc.low_water[i] || 2829a621e3c8SJack F Vogel hw->fc.low_water[i] >= hw->fc.high_water[i]) { 2830a621e3c8SJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 2831a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 2832a621e3c8SJack F Vogel goto out; 2833a621e3c8SJack F Vogel } 2834a621e3c8SJack F Vogel } 2835a621e3c8SJack F Vogel } 2836a621e3c8SJack F Vogel 2837a621e3c8SJack F Vogel /* Negotiate the fc mode to use */ 2838*8eb6488eSEric Joyner hw->mac.ops.fc_autoneg(hw); 28390ac6dfecSJack F Vogel 28400ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 28410ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 2842a621e3c8SJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 28430ac6dfecSJack F Vogel 28440ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 28450ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 28461b6e0dbaSJack F Vogel 28471b6e0dbaSJack F Vogel /* 28481b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 28491b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 28501b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 28511b6e0dbaSJack F Vogel * but not send pause frames). 28521b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 28531b6e0dbaSJack F Vogel * we do not support receiving pause frames). 28541b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 28551b6e0dbaSJack F Vogel * other: Invalid. 28561b6e0dbaSJack F Vogel */ 28571b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 28581b6e0dbaSJack F Vogel case ixgbe_fc_none: 28591a4e3449SJack F Vogel /* 28601a4e3449SJack F Vogel * Flow control is disabled by software override or autoneg. 28610ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 28620ac6dfecSJack F Vogel */ 28631b6e0dbaSJack F Vogel break; 28641b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 28651b6e0dbaSJack F Vogel /* 28661b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 28671b6e0dbaSJack F Vogel * disabled by software override. Since there really 28681b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 28691b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 28701b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 28711b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 28721b6e0dbaSJack F Vogel */ 28730ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28741b6e0dbaSJack F Vogel break; 28751b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 28761b6e0dbaSJack F Vogel /* 28771b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 28781b6e0dbaSJack F Vogel * disabled by software override. 28791b6e0dbaSJack F Vogel */ 28800ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28811b6e0dbaSJack F Vogel break; 28821b6e0dbaSJack F Vogel case ixgbe_fc_full: 28831b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 28840ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28850ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28861b6e0dbaSJack F Vogel break; 28871b6e0dbaSJack F Vogel default: 2888fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 2889fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 28902969bf0eSJack F Vogel ret_val = IXGBE_ERR_CONFIG; 28911b6e0dbaSJack F Vogel goto out; 28921b6e0dbaSJack F Vogel break; 28931b6e0dbaSJack F Vogel } 28941b6e0dbaSJack F Vogel 28950ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 28960ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 28970ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 28980ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 28991b6e0dbaSJack F Vogel 2900d8602bb9SJack F Vogel 2901a621e3c8SJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 2902a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2903a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2904a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2905a621e3c8SJack F Vogel fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 2906a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 2907a621e3c8SJack F Vogel fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 2908a621e3c8SJack F Vogel } else { 2909a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 2910a621e3c8SJack F Vogel /* 2911a621e3c8SJack F Vogel * In order to prevent Tx hangs when the internal Tx 2912a621e3c8SJack F Vogel * switch is enabled we must set the high water mark 2913758cc3dcSJack F Vogel * to the Rx packet buffer size - 24KB. This allows 2914758cc3dcSJack F Vogel * the Tx switch to function even under heavy Rx 2915758cc3dcSJack F Vogel * workloads. 2916a621e3c8SJack F Vogel */ 2917758cc3dcSJack F Vogel fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 29181b6e0dbaSJack F Vogel } 29191b6e0dbaSJack F Vogel 2920a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 2921a621e3c8SJack F Vogel } 29220ac6dfecSJack F Vogel 29230ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 2924a621e3c8SJack F Vogel reg = hw->fc.pause_time * 0x00010001; 2925a621e3c8SJack F Vogel for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) 2926a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 29270ac6dfecSJack F Vogel 2928a621e3c8SJack F Vogel /* Configure flow control refresh threshold value */ 2929a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 29300ac6dfecSJack F Vogel 29310ac6dfecSJack F Vogel out: 29320ac6dfecSJack F Vogel return ret_val; 29330ac6dfecSJack F Vogel } 29340ac6dfecSJack F Vogel 29350ac6dfecSJack F Vogel /** 29361a4e3449SJack F Vogel * ixgbe_negotiate_fc - Negotiate flow control 29371a4e3449SJack F Vogel * @hw: pointer to hardware structure 29381a4e3449SJack F Vogel * @adv_reg: flow control advertised settings 29391a4e3449SJack F Vogel * @lp_reg: link partner's flow control settings 29401a4e3449SJack F Vogel * @adv_sym: symmetric pause bit in advertisement 29411a4e3449SJack F Vogel * @adv_asm: asymmetric pause bit in advertisement 29421a4e3449SJack F Vogel * @lp_sym: symmetric pause bit in link partner advertisement 29431a4e3449SJack F Vogel * @lp_asm: asymmetric pause bit in link partner advertisement 29441a4e3449SJack F Vogel * 29451a4e3449SJack F Vogel * Find the intersection between advertised settings and link partner's 29461a4e3449SJack F Vogel * advertised settings 29471a4e3449SJack F Vogel **/ 2948*8eb6488eSEric Joyner s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 29491a4e3449SJack F Vogel u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 29501a4e3449SJack F Vogel { 2951fd75b91dSJack F Vogel if ((!(adv_reg)) || (!(lp_reg))) { 2952fd75b91dSJack F Vogel ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, 2953fd75b91dSJack F Vogel "Local or link partner's advertised flow control " 2954fd75b91dSJack F Vogel "settings are NULL. Local: %x, link partner: %x\n", 2955fd75b91dSJack F Vogel adv_reg, lp_reg); 29561a4e3449SJack F Vogel return IXGBE_ERR_FC_NOT_NEGOTIATED; 2957fd75b91dSJack F Vogel } 29581a4e3449SJack F Vogel 29591a4e3449SJack F Vogel if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 29602969bf0eSJack F Vogel /* 29612969bf0eSJack F Vogel * Now we need to check if the user selected Rx ONLY 29622969bf0eSJack F Vogel * of pause frames. In this case, we had to advertise 29632969bf0eSJack F Vogel * FULL flow control because we could not advertise RX 29642969bf0eSJack F Vogel * ONLY. Hence, we must now check to see if we need to 29652969bf0eSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 29662969bf0eSJack F Vogel */ 29672969bf0eSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 29682969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 29692969bf0eSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 29702969bf0eSJack F Vogel } else { 29712969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29722969bf0eSJack F Vogel DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 29732969bf0eSJack F Vogel } 29741a4e3449SJack F Vogel } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 29751a4e3449SJack F Vogel (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29762969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 29772969bf0eSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 29781a4e3449SJack F Vogel } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 29791a4e3449SJack F Vogel !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29802969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29812969bf0eSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 29822969bf0eSJack F Vogel } else { 29832969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 29842969bf0eSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 29852969bf0eSJack F Vogel } 29861a4e3449SJack F Vogel return IXGBE_SUCCESS; 29871b6e0dbaSJack F Vogel } 29881b6e0dbaSJack F Vogel 29890ac6dfecSJack F Vogel /** 2990a621e3c8SJack F Vogel * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 29910ac6dfecSJack F Vogel * @hw: pointer to hardware structure 29920ac6dfecSJack F Vogel * 2993a621e3c8SJack F Vogel * Enable flow control according on 1 gig fiber. 29940ac6dfecSJack F Vogel **/ 2995a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 29960ac6dfecSJack F Vogel { 2997a621e3c8SJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 2998a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 29990ac6dfecSJack F Vogel 3000a621e3c8SJack F Vogel /* 3001a621e3c8SJack F Vogel * On multispeed fiber at 1g, bail out if 3002a621e3c8SJack F Vogel * - link is up but AN did not complete, or if 3003a621e3c8SJack F Vogel * - link is up and AN completed but timed out 3004a621e3c8SJack F Vogel */ 30052969bf0eSJack F Vogel 3006a621e3c8SJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 3007a621e3c8SJack F Vogel if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 3008fd75b91dSJack F Vogel (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 3009758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); 30100ac6dfecSJack F Vogel goto out; 3011fd75b91dSJack F Vogel } 30120ac6dfecSJack F Vogel 3013a621e3c8SJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 3014a621e3c8SJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 30150ac6dfecSJack F Vogel 3016a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 3017a621e3c8SJack F Vogel pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 3018a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE, 3019a621e3c8SJack F Vogel IXGBE_PCS1GANA_SYM_PAUSE, 3020a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE); 30210ac6dfecSJack F Vogel 30220ac6dfecSJack F Vogel out: 30230ac6dfecSJack F Vogel return ret_val; 30240ac6dfecSJack F Vogel } 30251b6e0dbaSJack F Vogel 302613705f88SJack F Vogel /** 3027a621e3c8SJack F Vogel * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 3028a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3029a621e3c8SJack F Vogel * 3030a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3031a621e3c8SJack F Vogel **/ 3032a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 3033a621e3c8SJack F Vogel { 3034a621e3c8SJack F Vogel u32 links2, anlp1_reg, autoc_reg, links; 3035a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3036a621e3c8SJack F Vogel 3037a621e3c8SJack F Vogel /* 3038a621e3c8SJack F Vogel * On backplane, bail out if 3039a621e3c8SJack F Vogel * - backplane autoneg was not completed, or if 3040a621e3c8SJack F Vogel * - we are 82599 and link partner is not AN enabled 3041a621e3c8SJack F Vogel */ 3042a621e3c8SJack F Vogel links = IXGBE_READ_REG(hw, IXGBE_LINKS); 3043fd75b91dSJack F Vogel if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { 3044758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete\n"); 3045a621e3c8SJack F Vogel goto out; 3046fd75b91dSJack F Vogel } 3047a621e3c8SJack F Vogel 3048a621e3c8SJack F Vogel if (hw->mac.type == ixgbe_mac_82599EB) { 3049a621e3c8SJack F Vogel links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 3050fd75b91dSJack F Vogel if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { 3051758cc3dcSJack F Vogel DEBUGOUT("Link partner is not AN enabled\n"); 3052a621e3c8SJack F Vogel goto out; 3053a621e3c8SJack F Vogel } 3054fd75b91dSJack F Vogel } 3055a621e3c8SJack F Vogel /* 3056a621e3c8SJack F Vogel * Read the 10g AN autoc and LP ability registers and resolve 3057a621e3c8SJack F Vogel * local flow control settings accordingly 3058a621e3c8SJack F Vogel */ 3059a621e3c8SJack F Vogel autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3060a621e3c8SJack F Vogel anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 3061a621e3c8SJack F Vogel 3062a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 3063a621e3c8SJack F Vogel anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 3064a621e3c8SJack F Vogel IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 3065a621e3c8SJack F Vogel 3066a621e3c8SJack F Vogel out: 3067a621e3c8SJack F Vogel return ret_val; 3068a621e3c8SJack F Vogel } 3069a621e3c8SJack F Vogel 3070a621e3c8SJack F Vogel /** 3071a621e3c8SJack F Vogel * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 3072a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3073a621e3c8SJack F Vogel * 3074a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3075a621e3c8SJack F Vogel **/ 3076a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 3077a621e3c8SJack F Vogel { 3078a621e3c8SJack F Vogel u16 technology_ability_reg = 0; 3079a621e3c8SJack F Vogel u16 lp_technology_ability_reg = 0; 3080a621e3c8SJack F Vogel 3081a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 3082a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3083a621e3c8SJack F Vogel &technology_ability_reg); 3084a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, 3085a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3086a621e3c8SJack F Vogel &lp_technology_ability_reg); 3087a621e3c8SJack F Vogel 3088a621e3c8SJack F Vogel return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 3089a621e3c8SJack F Vogel (u32)lp_technology_ability_reg, 3090a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 3091a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 3092a621e3c8SJack F Vogel } 3093a621e3c8SJack F Vogel 3094a621e3c8SJack F Vogel /** 3095a621e3c8SJack F Vogel * ixgbe_fc_autoneg - Configure flow control 3096a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3097a621e3c8SJack F Vogel * 3098a621e3c8SJack F Vogel * Compares our advertised flow control capabilities to those advertised by 3099a621e3c8SJack F Vogel * our link partner, and determines the proper flow control mode to use. 3100a621e3c8SJack F Vogel **/ 3101a621e3c8SJack F Vogel void ixgbe_fc_autoneg(struct ixgbe_hw *hw) 3102a621e3c8SJack F Vogel { 3103a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3104a621e3c8SJack F Vogel ixgbe_link_speed speed; 3105a621e3c8SJack F Vogel bool link_up; 3106a621e3c8SJack F Vogel 3107a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 3108a621e3c8SJack F Vogel 3109a621e3c8SJack F Vogel /* 3110a621e3c8SJack F Vogel * AN should have completed when the cable was plugged in. 3111a621e3c8SJack F Vogel * Look for reasons to bail out. Bail out if: 3112a621e3c8SJack F Vogel * - FC autoneg is disabled, or if 3113a621e3c8SJack F Vogel * - link is not up. 3114a621e3c8SJack F Vogel */ 3115fd75b91dSJack F Vogel if (hw->fc.disable_fc_autoneg) { 3116fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3117fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3118a621e3c8SJack F Vogel goto out; 3119fd75b91dSJack F Vogel } 3120a621e3c8SJack F Vogel 3121a621e3c8SJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3122fd75b91dSJack F Vogel if (!link_up) { 3123fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3124a621e3c8SJack F Vogel goto out; 3125fd75b91dSJack F Vogel } 3126a621e3c8SJack F Vogel 3127a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3128a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 31290ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3130758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3131a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3132a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3133a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3134a621e3c8SJack F Vogel break; 3135a621e3c8SJack F Vogel 3136a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3137a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3138a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3139a621e3c8SJack F Vogel break; 3140a621e3c8SJack F Vogel 3141a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3142a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3143fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3144a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3145a621e3c8SJack F Vogel break; 3146a621e3c8SJack F Vogel 3147a621e3c8SJack F Vogel default: 3148a621e3c8SJack F Vogel break; 3149a621e3c8SJack F Vogel } 3150a621e3c8SJack F Vogel 3151a621e3c8SJack F Vogel out: 3152a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 3153a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = TRUE; 3154a621e3c8SJack F Vogel } else { 3155a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = FALSE; 3156a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3157a621e3c8SJack F Vogel } 3158a621e3c8SJack F Vogel } 3159a621e3c8SJack F Vogel 3160fd75b91dSJack F Vogel /* 3161fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3162fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3163fd75b91dSJack F Vogel * 3164fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3165fd75b91dSJack F Vogel * 3166fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3167fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3168fd75b91dSJack F Vogel * 800 = 80 millisec. 3169fd75b91dSJack F Vogel */ 3170fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3171fd75b91dSJack F Vogel { 3172fd75b91dSJack F Vogel s16 devctl2; 3173fd75b91dSJack F Vogel u32 pollcnt; 3174fd75b91dSJack F Vogel 3175fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3176fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3177fd75b91dSJack F Vogel 3178fd75b91dSJack F Vogel switch (devctl2) { 3179fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3180fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3181fd75b91dSJack F Vogel break; 3182fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3183fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3184fd75b91dSJack F Vogel break; 3185fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3186fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3187fd75b91dSJack F Vogel break; 3188fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3189fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3190fd75b91dSJack F Vogel break; 3191fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3192fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3193fd75b91dSJack F Vogel break; 3194fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3195fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3196fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3197fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3198fd75b91dSJack F Vogel default: 3199fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3200fd75b91dSJack F Vogel break; 3201fd75b91dSJack F Vogel } 3202fd75b91dSJack F Vogel 3203fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3204fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3205fd75b91dSJack F Vogel } 3206fd75b91dSJack F Vogel 3207a621e3c8SJack F Vogel /** 320813705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 320913705f88SJack F Vogel * @hw: pointer to hardware structure 321013705f88SJack F Vogel * 321113705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 321213705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 321313705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 321413705f88SJack F Vogel * is returned signifying master requests disabled. 321513705f88SJack F Vogel **/ 321613705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 321713705f88SJack F Vogel { 3218c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3219fd75b91dSJack F Vogel u32 i, poll; 3220758cc3dcSJack F Vogel u16 value; 322113705f88SJack F Vogel 32222969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_pcie_master"); 32232969bf0eSJack F Vogel 322485d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 322585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 322685d0a26eSJack F Vogel 3227fd75b91dSJack F Vogel /* Exit if master requests are blocked */ 3228758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3229758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3230c0014855SJack F Vogel goto out; 3231c0014855SJack F Vogel 323285d0a26eSJack F Vogel /* Poll for master request bit to clear */ 323313705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 323485d0a26eSJack F Vogel usec_delay(100); 3235c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3236182b3808SJack F Vogel goto out; 323785d0a26eSJack F Vogel } 3238c0014855SJack F Vogel 3239c0014855SJack F Vogel /* 3240c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 3241c0014855SJack F Vogel * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine 3242c0014855SJack F Vogel * of this need. The first reset prevents new master requests from 324385d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3244c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3245c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3246c0014855SJack F Vogel */ 324785d0a26eSJack F Vogel DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); 3248c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3249c0014855SJack F Vogel 3250a9ca1c79SSean Bruno if (hw->mac.type >= ixgbe_mac_X550) 3251a9ca1c79SSean Bruno goto out; 3252a9ca1c79SSean Bruno 325385d0a26eSJack F Vogel /* 325485d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 325585d0a26eSJack F Vogel * transactions pending. 325685d0a26eSJack F Vogel */ 3257fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3258fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 325985d0a26eSJack F Vogel usec_delay(100); 3260758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3261758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3262758cc3dcSJack F Vogel goto out; 3263758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 326485d0a26eSJack F Vogel goto out; 326585d0a26eSJack F Vogel } 326685d0a26eSJack F Vogel 3267fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3268fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 326985d0a26eSJack F Vogel status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 327085d0a26eSJack F Vogel 3271c0014855SJack F Vogel out: 327213705f88SJack F Vogel return status; 327313705f88SJack F Vogel } 327413705f88SJack F Vogel 327513705f88SJack F Vogel /** 32769ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 327713705f88SJack F Vogel * @hw: pointer to hardware structure 32789ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 327913705f88SJack F Vogel * 328085d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 328113705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 328213705f88SJack F Vogel **/ 3283758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 328413705f88SJack F Vogel { 3285fd75b91dSJack F Vogel u32 gssr = 0; 328613705f88SJack F Vogel u32 swmask = mask; 328713705f88SJack F Vogel u32 fwmask = mask << 5; 3288fd75b91dSJack F Vogel u32 timeout = 200; 3289fd75b91dSJack F Vogel u32 i; 329013705f88SJack F Vogel 32912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 32922969bf0eSJack F Vogel 3293fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 32940ac6dfecSJack F Vogel /* 3295fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3296fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 32970ac6dfecSJack F Vogel */ 329813705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 32992969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 330013705f88SJack F Vogel 330113705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3302fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 330313705f88SJack F Vogel gssr |= swmask; 330413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 330513705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 330613705f88SJack F Vogel return IXGBE_SUCCESS; 3307fd75b91dSJack F Vogel } else { 3308fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3309fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3310fd75b91dSJack F Vogel msec_delay(5); 3311fd75b91dSJack F Vogel } 3312fd75b91dSJack F Vogel } 3313fd75b91dSJack F Vogel 3314fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3315fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3316fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3317fd75b91dSJack F Vogel 3318fd75b91dSJack F Vogel msec_delay(5); 3319fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 332013705f88SJack F Vogel } 332113705f88SJack F Vogel 332213705f88SJack F Vogel /** 332313705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 332413705f88SJack F Vogel * @hw: pointer to hardware structure 33259ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 332613705f88SJack F Vogel * 332785d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 332813705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 332913705f88SJack F Vogel **/ 3330758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 333113705f88SJack F Vogel { 333213705f88SJack F Vogel u32 gssr; 333313705f88SJack F Vogel u32 swmask = mask; 333413705f88SJack F Vogel 33352969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 33362969bf0eSJack F Vogel 333713705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 333813705f88SJack F Vogel 333913705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 334013705f88SJack F Vogel gssr &= ~swmask; 334113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 334213705f88SJack F Vogel 334313705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 33440ac6dfecSJack F Vogel } 33450ac6dfecSJack F Vogel 33460ac6dfecSJack F Vogel /** 334785d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 334885d0a26eSJack F Vogel * @hw: pointer to hardware structure 334985d0a26eSJack F Vogel * 335085d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 335185d0a26eSJack F Vogel * the Rx security block 335285d0a26eSJack F Vogel **/ 335385d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 335485d0a26eSJack F Vogel { 335585d0a26eSJack F Vogel #define IXGBE_MAX_SECRX_POLL 40 335685d0a26eSJack F Vogel 335785d0a26eSJack F Vogel int i; 335885d0a26eSJack F Vogel int secrxreg; 335985d0a26eSJack F Vogel 336085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 336185d0a26eSJack F Vogel 336285d0a26eSJack F Vogel 336385d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 336485d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 336585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 336685d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 336785d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 336885d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 336985d0a26eSJack F Vogel break; 337085d0a26eSJack F Vogel else 337185d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 337285d0a26eSJack F Vogel usec_delay(1000); 337385d0a26eSJack F Vogel } 337485d0a26eSJack F Vogel 337585d0a26eSJack F Vogel /* For informational purposes only */ 337685d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 337785d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 337885d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 337985d0a26eSJack F Vogel 338085d0a26eSJack F Vogel return IXGBE_SUCCESS; 338185d0a26eSJack F Vogel } 338285d0a26eSJack F Vogel 338385d0a26eSJack F Vogel /** 3384758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3385758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3386758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3387758cc3dcSJack F Vogel * 3388758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3389758cc3dcSJack F Vogel */ 3390758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3391758cc3dcSJack F Vogel { 3392758cc3dcSJack F Vogel *locked = FALSE; 3393758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3394758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3395758cc3dcSJack F Vogel } 3396758cc3dcSJack F Vogel 3397758cc3dcSJack F Vogel /** 3398758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3399758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3400758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3401758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3402758cc3dcSJack F Vogel * previous read. 3403758cc3dcSJack F Vogel * 3404758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3405758cc3dcSJack F Vogel */ 3406758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3407758cc3dcSJack F Vogel { 3408758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3409758cc3dcSJack F Vogel 3410758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3411758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3412758cc3dcSJack F Vogel } 3413758cc3dcSJack F Vogel 3414758cc3dcSJack F Vogel /** 341585d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 341685d0a26eSJack F Vogel * @hw: pointer to hardware structure 341785d0a26eSJack F Vogel * 341885d0a26eSJack F Vogel * Enables the receive data path. 341985d0a26eSJack F Vogel **/ 342085d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 342185d0a26eSJack F Vogel { 3422*8eb6488eSEric Joyner u32 secrxreg; 342385d0a26eSJack F Vogel 342485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 342585d0a26eSJack F Vogel 342685d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 342785d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 342885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 342985d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 343085d0a26eSJack F Vogel 343185d0a26eSJack F Vogel return IXGBE_SUCCESS; 343285d0a26eSJack F Vogel } 343385d0a26eSJack F Vogel 343485d0a26eSJack F Vogel /** 34350ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 34360ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34370ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 34380ac6dfecSJack F Vogel * 34390ac6dfecSJack F Vogel * Enables the Rx DMA unit 34400ac6dfecSJack F Vogel **/ 34410ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 34420ac6dfecSJack F Vogel { 34432969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 34442969bf0eSJack F Vogel 3445758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3446758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3447758cc3dcSJack F Vogel else 3448758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 34490ac6dfecSJack F Vogel 34500ac6dfecSJack F Vogel return IXGBE_SUCCESS; 34510ac6dfecSJack F Vogel } 34520ac6dfecSJack F Vogel 34530ac6dfecSJack F Vogel /** 34540ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 34550ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34560ac6dfecSJack F Vogel * @index: led number to blink 34570ac6dfecSJack F Vogel **/ 34580ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 34590ac6dfecSJack F Vogel { 34600ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 34610ac6dfecSJack F Vogel bool link_up = 0; 3462758cc3dcSJack F Vogel u32 autoc_reg = 0; 34630ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34640ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3465758cc3dcSJack F Vogel bool locked = FALSE; 34660ac6dfecSJack F Vogel 34672969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 34682969bf0eSJack F Vogel 3469*8eb6488eSEric Joyner if (index > 3) 3470*8eb6488eSEric Joyner return IXGBE_ERR_PARAM; 3471*8eb6488eSEric Joyner 34720ac6dfecSJack F Vogel /* 34730ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 34740ac6dfecSJack F Vogel * Force it if link is down. 34750ac6dfecSJack F Vogel */ 34760ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 34770ac6dfecSJack F Vogel 34780ac6dfecSJack F Vogel if (!link_up) { 3479758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3480758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 34810ecc2ff0SJack F Vogel goto out; 34820ecc2ff0SJack F Vogel 3483d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34840ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 34850ecc2ff0SJack F Vogel 3486758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3487758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3488758cc3dcSJack F Vogel goto out; 3489758cc3dcSJack F Vogel 3490758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34910ac6dfecSJack F Vogel msec_delay(10); 34920ac6dfecSJack F Vogel } 34930ac6dfecSJack F Vogel 34940ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 34950ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 34960ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 34970ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34980ac6dfecSJack F Vogel 34990ecc2ff0SJack F Vogel out: 35000ecc2ff0SJack F Vogel return ret_val; 35010ac6dfecSJack F Vogel } 35020ac6dfecSJack F Vogel 35030ac6dfecSJack F Vogel /** 35040ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 35050ac6dfecSJack F Vogel * @hw: pointer to hardware structure 35060ac6dfecSJack F Vogel * @index: led number to stop blinking 35070ac6dfecSJack F Vogel **/ 35080ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 35090ac6dfecSJack F Vogel { 3510758cc3dcSJack F Vogel u32 autoc_reg = 0; 35110ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 35120ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3513758cc3dcSJack F Vogel bool locked = FALSE; 35140ac6dfecSJack F Vogel 35152969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 35162969bf0eSJack F Vogel 3517*8eb6488eSEric Joyner if (index > 3) 3518*8eb6488eSEric Joyner return IXGBE_ERR_PARAM; 3519*8eb6488eSEric Joyner 3520*8eb6488eSEric Joyner 3521758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3522758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3523758cc3dcSJack F Vogel goto out; 3524d8602bb9SJack F Vogel 35250ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 35260ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 35270ac6dfecSJack F Vogel 3528758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3529758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3530758cc3dcSJack F Vogel goto out; 35310ecc2ff0SJack F Vogel 35320ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35330ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 35340ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 35350ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35360ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35370ac6dfecSJack F Vogel 35380ecc2ff0SJack F Vogel out: 35390ecc2ff0SJack F Vogel return ret_val; 354013705f88SJack F Vogel } 354113705f88SJack F Vogel 35422969bf0eSJack F Vogel /** 35432969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 35442969bf0eSJack F Vogel * @hw: pointer to hardware structure 35452969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 35462969bf0eSJack F Vogel * 35472969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 35482969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 35492969bf0eSJack F Vogel * get and set mac_addr routines. 35502969bf0eSJack F Vogel **/ 35512969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 35522969bf0eSJack F Vogel u16 *san_mac_offset) 35532969bf0eSJack F Vogel { 3554fd75b91dSJack F Vogel s32 ret_val; 3555fd75b91dSJack F Vogel 35562969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 35572969bf0eSJack F Vogel 35582969bf0eSJack F Vogel /* 35592969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35602969bf0eSJack F Vogel * available. 35612969bf0eSJack F Vogel */ 3562fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3563fd75b91dSJack F Vogel san_mac_offset); 3564fd75b91dSJack F Vogel if (ret_val) { 3565fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3566fd75b91dSJack F Vogel "eeprom at offset %d failed", 3567fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3568fd75b91dSJack F Vogel } 35692969bf0eSJack F Vogel 3570fd75b91dSJack F Vogel return ret_val; 35712969bf0eSJack F Vogel } 35722969bf0eSJack F Vogel 35732969bf0eSJack F Vogel /** 35742969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 35752969bf0eSJack F Vogel * @hw: pointer to hardware structure 35762969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35772969bf0eSJack F Vogel * 35782969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 35792969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 35802969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 35812969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 35822969bf0eSJack F Vogel **/ 35832969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35842969bf0eSJack F Vogel { 35852969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35862969bf0eSJack F Vogel u8 i; 3587fd75b91dSJack F Vogel s32 ret_val; 35882969bf0eSJack F Vogel 35892969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 35902969bf0eSJack F Vogel 35912969bf0eSJack F Vogel /* 35922969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35932969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 35942969bf0eSJack F Vogel */ 3595fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3596fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 35972969bf0eSJack F Vogel goto san_mac_addr_out; 35982969bf0eSJack F Vogel 35992969bf0eSJack F Vogel /* make sure we know which port we need to program */ 36002969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36012969bf0eSJack F Vogel /* apply the port offset to the address offset */ 36022969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36032969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36042969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3605fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3606fd75b91dSJack F Vogel &san_mac_data); 3607fd75b91dSJack F Vogel if (ret_val) { 3608fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3609fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3610fd75b91dSJack F Vogel san_mac_offset); 3611fd75b91dSJack F Vogel goto san_mac_addr_out; 3612fd75b91dSJack F Vogel } 36132969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 36142969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 36152969bf0eSJack F Vogel san_mac_offset++; 36162969bf0eSJack F Vogel } 3617fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36182969bf0eSJack F Vogel 36192969bf0eSJack F Vogel san_mac_addr_out: 3620fd75b91dSJack F Vogel /* 3621fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3622fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3623fd75b91dSJack F Vogel */ 3624fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3625fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 36262969bf0eSJack F Vogel return IXGBE_SUCCESS; 36272969bf0eSJack F Vogel } 36282969bf0eSJack F Vogel 36292969bf0eSJack F Vogel /** 36302969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 36312969bf0eSJack F Vogel * @hw: pointer to hardware structure 36322969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 36332969bf0eSJack F Vogel * 36342969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 36352969bf0eSJack F Vogel **/ 36362969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 36372969bf0eSJack F Vogel { 3638fd75b91dSJack F Vogel s32 ret_val; 36392969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 36402969bf0eSJack F Vogel u8 i; 36412969bf0eSJack F Vogel 36422969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 36432969bf0eSJack F Vogel 36442969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3645fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3646fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3647fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 36482969bf0eSJack F Vogel 36492969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 36502969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36512969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 36522969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36532969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36542969bf0eSJack F Vogel 36552969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 36562969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 36572969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 36582969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 36592969bf0eSJack F Vogel san_mac_offset++; 36602969bf0eSJack F Vogel } 36612969bf0eSJack F Vogel 3662fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36632969bf0eSJack F Vogel } 36642969bf0eSJack F Vogel 36652969bf0eSJack F Vogel /** 36662969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 36672969bf0eSJack F Vogel * @hw: pointer to hardware structure 36682969bf0eSJack F Vogel * 36692969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 36702969bf0eSJack F Vogel * the capabilities table. 36712969bf0eSJack F Vogel **/ 3672a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 36732969bf0eSJack F Vogel { 3674a621e3c8SJack F Vogel u16 msix_count = 1; 3675a621e3c8SJack F Vogel u16 max_msix_count; 3676a621e3c8SJack F Vogel u16 pcie_offset; 3677a621e3c8SJack F Vogel 3678a621e3c8SJack F Vogel switch (hw->mac.type) { 3679a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3680a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3681a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3682a621e3c8SJack F Vogel break; 3683a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3684a621e3c8SJack F Vogel case ixgbe_mac_X540: 3685758cc3dcSJack F Vogel case ixgbe_mac_X550: 3686758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 3687*8eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3688a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3689a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3690a621e3c8SJack F Vogel break; 3691a621e3c8SJack F Vogel default: 3692a621e3c8SJack F Vogel return msix_count; 3693a621e3c8SJack F Vogel } 36942969bf0eSJack F Vogel 36952969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3696a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3697758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3698758cc3dcSJack F Vogel msix_count = 0; 36992969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 37002969bf0eSJack F Vogel 3701a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 37022969bf0eSJack F Vogel msix_count++; 3703a621e3c8SJack F Vogel 3704a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3705a621e3c8SJack F Vogel msix_count = max_msix_count; 37062969bf0eSJack F Vogel 37072969bf0eSJack F Vogel return msix_count; 37082969bf0eSJack F Vogel } 37092969bf0eSJack F Vogel 37102969bf0eSJack F Vogel /** 37112969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 37122969bf0eSJack F Vogel * @hw: pointer to hardware structure 37132969bf0eSJack F Vogel * @addr: Address to put into receive address register 37142969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 37152969bf0eSJack F Vogel * 37162969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 3717*8eb6488eSEric Joyner * finds the rar that it is aleady in; adds to the pool list 37182969bf0eSJack F Vogel **/ 37192969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 37202969bf0eSJack F Vogel { 37212969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 37222969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 37232969bf0eSJack F Vogel u32 rar; 37242969bf0eSJack F Vogel u32 rar_low, rar_high; 37252969bf0eSJack F Vogel u32 addr_low, addr_high; 37262969bf0eSJack F Vogel 37272969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 37282969bf0eSJack F Vogel 37292969bf0eSJack F Vogel /* swap bytes for HW little endian */ 37302969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 37312969bf0eSJack F Vogel | (addr[2] << 16) 37322969bf0eSJack F Vogel | (addr[3] << 24); 37332969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 37342969bf0eSJack F Vogel 37352969bf0eSJack F Vogel /* 37362969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 37372969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 37382969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 37392969bf0eSJack F Vogel * rar to the top. 37402969bf0eSJack F Vogel */ 37412969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 37422969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 37432969bf0eSJack F Vogel 37442969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 37452969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 37462969bf0eSJack F Vogel first_empty_rar = rar; 37472969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 37482969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 37492969bf0eSJack F Vogel if (rar_low == addr_low) 37502969bf0eSJack F Vogel break; /* found it already in the rars */ 37512969bf0eSJack F Vogel } 37522969bf0eSJack F Vogel } 37532969bf0eSJack F Vogel 37542969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 37552969bf0eSJack F Vogel /* already there so just add to the pool bits */ 37562969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 37572969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 37582969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 37592969bf0eSJack F Vogel rar = first_empty_rar; 37602969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37612969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 37622969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 37632969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37642969bf0eSJack F Vogel hw->mac.rar_highwater++; 37652969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 37662969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 37672969bf0eSJack F Vogel } 37682969bf0eSJack F Vogel 37692969bf0eSJack F Vogel /* 37702969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 37712969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 37722969bf0eSJack F Vogel */ 37732969bf0eSJack F Vogel if (rar == 0) 37742969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 37752969bf0eSJack F Vogel 37762969bf0eSJack F Vogel return rar; 37772969bf0eSJack F Vogel } 37782969bf0eSJack F Vogel 37792969bf0eSJack F Vogel /** 37802969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 37812969bf0eSJack F Vogel * @hw: pointer to hardware struct 37822969bf0eSJack F Vogel * @rar: receive address register index to disassociate 37832969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 37842969bf0eSJack F Vogel **/ 37852969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37862969bf0eSJack F Vogel { 37872969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 37882969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37892969bf0eSJack F Vogel 37902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 37912969bf0eSJack F Vogel 37921a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37931a4e3449SJack F Vogel if (rar >= rar_entries) { 3794fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3795fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 37961a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 37971a4e3449SJack F Vogel } 37981a4e3449SJack F Vogel 37992969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38002969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38012969bf0eSJack F Vogel 3802758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3803758cc3dcSJack F Vogel goto done; 3804758cc3dcSJack F Vogel 38052969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 38062969bf0eSJack F Vogel goto done; 38072969bf0eSJack F Vogel 38082969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 38092969bf0eSJack F Vogel if (mpsar_lo) { 38102969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 38112969bf0eSJack F Vogel mpsar_lo = 0; 38122969bf0eSJack F Vogel } 38132969bf0eSJack F Vogel if (mpsar_hi) { 38142969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 38152969bf0eSJack F Vogel mpsar_hi = 0; 38162969bf0eSJack F Vogel } 38172969bf0eSJack F Vogel } else if (vmdq < 32) { 38182969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 38192969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 38202969bf0eSJack F Vogel } else { 38212969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 38222969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 38232969bf0eSJack F Vogel } 38242969bf0eSJack F Vogel 38252969bf0eSJack F Vogel /* was that the last pool using this rar? */ 3826*8eb6488eSEric Joyner if (mpsar_lo == 0 && mpsar_hi == 0 && 3827*8eb6488eSEric Joyner rar != 0 && rar != hw->mac.san_mac_rar_index) 38282969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 38292969bf0eSJack F Vogel done: 38302969bf0eSJack F Vogel return IXGBE_SUCCESS; 38312969bf0eSJack F Vogel } 38322969bf0eSJack F Vogel 38332969bf0eSJack F Vogel /** 38342969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 38352969bf0eSJack F Vogel * @hw: pointer to hardware struct 38362969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 38372969bf0eSJack F Vogel * @vmdq: VMDq pool index 38382969bf0eSJack F Vogel **/ 38392969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 38402969bf0eSJack F Vogel { 38412969bf0eSJack F Vogel u32 mpsar; 38422969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 38432969bf0eSJack F Vogel 38442969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 38452969bf0eSJack F Vogel 38461a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 38471a4e3449SJack F Vogel if (rar >= rar_entries) { 3848fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3849fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38501a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38511a4e3449SJack F Vogel } 38521a4e3449SJack F Vogel 38532969bf0eSJack F Vogel if (vmdq < 32) { 38542969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38552969bf0eSJack F Vogel mpsar |= 1 << vmdq; 38562969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 38572969bf0eSJack F Vogel } else { 38582969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38592969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 38602969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 38612969bf0eSJack F Vogel } 38622969bf0eSJack F Vogel return IXGBE_SUCCESS; 38632969bf0eSJack F Vogel } 38642969bf0eSJack F Vogel 38652969bf0eSJack F Vogel /** 3866a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3867a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3868a621e3c8SJack F Vogel * VFs advertized and not 0. 3869a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3870a621e3c8SJack F Vogel * 3871a621e3c8SJack F Vogel * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address 3872a621e3c8SJack F Vogel * @hw: pointer to hardware struct 3873a621e3c8SJack F Vogel * @vmdq: VMDq pool index 3874a621e3c8SJack F Vogel **/ 3875a621e3c8SJack F Vogel s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 3876a621e3c8SJack F Vogel { 3877a621e3c8SJack F Vogel u32 rar = hw->mac.san_mac_rar_index; 3878a621e3c8SJack F Vogel 3879a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_san_mac"); 3880a621e3c8SJack F Vogel 3881a621e3c8SJack F Vogel if (vmdq < 32) { 3882a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); 3883a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 3884a621e3c8SJack F Vogel } else { 3885a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 3886a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); 3887a621e3c8SJack F Vogel } 3888a621e3c8SJack F Vogel 3889a621e3c8SJack F Vogel return IXGBE_SUCCESS; 3890a621e3c8SJack F Vogel } 3891a621e3c8SJack F Vogel 3892a621e3c8SJack F Vogel /** 38932969bf0eSJack F Vogel * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 38942969bf0eSJack F Vogel * @hw: pointer to hardware structure 38952969bf0eSJack F Vogel **/ 38962969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 38972969bf0eSJack F Vogel { 38982969bf0eSJack F Vogel int i; 38992969bf0eSJack F Vogel 39002969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_uta_tables_generic"); 39012969bf0eSJack F Vogel DEBUGOUT(" Clearing UTA\n"); 39022969bf0eSJack F Vogel 39032969bf0eSJack F Vogel for (i = 0; i < 128; i++) 39042969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 39052969bf0eSJack F Vogel 39062969bf0eSJack F Vogel return IXGBE_SUCCESS; 39072969bf0eSJack F Vogel } 39082969bf0eSJack F Vogel 39092969bf0eSJack F Vogel /** 39102969bf0eSJack F Vogel * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 39112969bf0eSJack F Vogel * @hw: pointer to hardware structure 39122969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39132969bf0eSJack F Vogel * 39142969bf0eSJack F Vogel * return the VLVF index where this VLAN id should be placed 39152969bf0eSJack F Vogel * 39162969bf0eSJack F Vogel **/ 3917*8eb6488eSEric Joyner s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) 39182969bf0eSJack F Vogel { 3919*8eb6488eSEric Joyner s32 regindex, first_empty_slot; 3920*8eb6488eSEric Joyner u32 bits; 39212969bf0eSJack F Vogel 3922c0014855SJack F Vogel /* short cut the special case */ 3923c0014855SJack F Vogel if (vlan == 0) 3924c0014855SJack F Vogel return 0; 3925c0014855SJack F Vogel 3926*8eb6488eSEric Joyner /* if vlvf_bypass is set we don't want to use an empty slot, we 3927*8eb6488eSEric Joyner * will simply bypass the VLVF if there are no entries present in the 3928*8eb6488eSEric Joyner * VLVF that contain our VLAN 39292969bf0eSJack F Vogel */ 3930*8eb6488eSEric Joyner first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0; 3931*8eb6488eSEric Joyner 3932*8eb6488eSEric Joyner /* add VLAN enable bit for comparison */ 3933*8eb6488eSEric Joyner vlan |= IXGBE_VLVF_VIEN; 3934*8eb6488eSEric Joyner 3935*8eb6488eSEric Joyner /* Search for the vlan id in the VLVF entries. Save off the first empty 3936*8eb6488eSEric Joyner * slot found along the way. 3937*8eb6488eSEric Joyner * 3938*8eb6488eSEric Joyner * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 3939*8eb6488eSEric Joyner */ 3940*8eb6488eSEric Joyner for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { 39412969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 3942*8eb6488eSEric Joyner if (bits == vlan) 39432969bf0eSJack F Vogel return regindex; 3944*8eb6488eSEric Joyner if (!first_empty_slot && !bits) 3945*8eb6488eSEric Joyner first_empty_slot = regindex; 3946*8eb6488eSEric Joyner } 3947*8eb6488eSEric Joyner 3948*8eb6488eSEric Joyner /* If we are here then we didn't find the VLAN. Return first empty 3949*8eb6488eSEric Joyner * slot we found during our search, else error. 3950*8eb6488eSEric Joyner */ 3951*8eb6488eSEric Joyner if (!first_empty_slot) 3952*8eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); 3953*8eb6488eSEric Joyner 3954*8eb6488eSEric Joyner return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE; 39552969bf0eSJack F Vogel } 39562969bf0eSJack F Vogel 39572969bf0eSJack F Vogel /** 39582969bf0eSJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 39592969bf0eSJack F Vogel * @hw: pointer to hardware structure 39602969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 3961*8eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 3962*8eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN 3963*8eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 39642969bf0eSJack F Vogel * 39652969bf0eSJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 39662969bf0eSJack F Vogel **/ 39672969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 3968*8eb6488eSEric Joyner bool vlan_on, bool vlvf_bypass) 39692969bf0eSJack F Vogel { 3970*8eb6488eSEric Joyner u32 regidx, vfta_delta, vfta; 3971*8eb6488eSEric Joyner s32 ret_val; 39722969bf0eSJack F Vogel 39732969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vfta_generic"); 39742969bf0eSJack F Vogel 3975*8eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 39762969bf0eSJack F Vogel return IXGBE_ERR_PARAM; 39772969bf0eSJack F Vogel 39782969bf0eSJack F Vogel /* 39792969bf0eSJack F Vogel * this is a 2 part operation - first the VFTA, then the 39802969bf0eSJack F Vogel * VLVF and VLVFB if VT Mode is set 3981c0014855SJack F Vogel * We don't write the VFTA until we know the VLVF part succeeded. 39822969bf0eSJack F Vogel */ 39832969bf0eSJack F Vogel 39842969bf0eSJack F Vogel /* Part 1 39852969bf0eSJack F Vogel * The VFTA is a bitstring made up of 128 32-bit registers 39862969bf0eSJack F Vogel * that enable the particular VLAN id, much like the MTA: 39872969bf0eSJack F Vogel * bits[11-5]: which register 39882969bf0eSJack F Vogel * bits[4-0]: which bit in the register 39892969bf0eSJack F Vogel */ 3990*8eb6488eSEric Joyner regidx = vlan / 32; 3991*8eb6488eSEric Joyner vfta_delta = 1 << (vlan % 32); 3992*8eb6488eSEric Joyner vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); 39932969bf0eSJack F Vogel 3994*8eb6488eSEric Joyner /* 3995*8eb6488eSEric Joyner * vfta_delta represents the difference between the current value 3996*8eb6488eSEric Joyner * of vfta and the value we want in the register. Since the diff 3997*8eb6488eSEric Joyner * is an XOR mask we can just update the vfta using an XOR 3998*8eb6488eSEric Joyner */ 3999*8eb6488eSEric Joyner vfta_delta &= vlan_on ? ~vfta : vfta; 4000*8eb6488eSEric Joyner vfta ^= vfta_delta; 40012969bf0eSJack F Vogel 40022969bf0eSJack F Vogel /* Part 2 400385d0a26eSJack F Vogel * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF 400485d0a26eSJack F Vogel */ 4005*8eb6488eSEric Joyner ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta, 4006*8eb6488eSEric Joyner vfta, vlvf_bypass); 4007*8eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS) { 4008*8eb6488eSEric Joyner if (vlvf_bypass) 4009*8eb6488eSEric Joyner goto vfta_update; 401085d0a26eSJack F Vogel return ret_val; 4011*8eb6488eSEric Joyner } 401285d0a26eSJack F Vogel 4013*8eb6488eSEric Joyner vfta_update: 4014*8eb6488eSEric Joyner /* Update VFTA now that we are ready for traffic */ 4015*8eb6488eSEric Joyner if (vfta_delta) 4016*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 401785d0a26eSJack F Vogel 401885d0a26eSJack F Vogel return IXGBE_SUCCESS; 401985d0a26eSJack F Vogel } 402085d0a26eSJack F Vogel 402185d0a26eSJack F Vogel /** 402285d0a26eSJack F Vogel * ixgbe_set_vlvf_generic - Set VLAN Pool Filter 402385d0a26eSJack F Vogel * @hw: pointer to hardware structure 402485d0a26eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 4025*8eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 4026*8eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN in VLVF 4027*8eb6488eSEric Joyner * @vfta_delta: pointer to the difference between the current value of VFTA 4028*8eb6488eSEric Joyner * and the desired value 4029*8eb6488eSEric Joyner * @vfta: the desired value of the VFTA 4030*8eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 403185d0a26eSJack F Vogel * 403285d0a26eSJack F Vogel * Turn on/off specified bit in VLVF table. 403385d0a26eSJack F Vogel **/ 403485d0a26eSJack F Vogel s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 4035*8eb6488eSEric Joyner bool vlan_on, u32 *vfta_delta, u32 vfta, 4036*8eb6488eSEric Joyner bool vlvf_bypass) 403785d0a26eSJack F Vogel { 4038*8eb6488eSEric Joyner u32 bits; 4039*8eb6488eSEric Joyner s32 vlvf_index; 404085d0a26eSJack F Vogel 404185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_vlvf_generic"); 404285d0a26eSJack F Vogel 4043*8eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 404485d0a26eSJack F Vogel return IXGBE_ERR_PARAM; 404585d0a26eSJack F Vogel 404685d0a26eSJack F Vogel /* If VT Mode is set 40472969bf0eSJack F Vogel * Either vlan_on 40482969bf0eSJack F Vogel * make sure the vlan is in VLVF 40492969bf0eSJack F Vogel * set the vind bit in the matching VLVFB 40502969bf0eSJack F Vogel * Or !vlan_on 40512969bf0eSJack F Vogel * clear the pool bit and possibly the vind 40522969bf0eSJack F Vogel */ 4053*8eb6488eSEric Joyner if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) 4054*8eb6488eSEric Joyner return IXGBE_SUCCESS; 4055c0014855SJack F Vogel 4056*8eb6488eSEric Joyner vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); 4057c0014855SJack F Vogel if (vlvf_index < 0) 4058c0014855SJack F Vogel return vlvf_index; 40592969bf0eSJack F Vogel 4060*8eb6488eSEric Joyner bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); 4061*8eb6488eSEric Joyner 40622969bf0eSJack F Vogel /* set the pool bit */ 4063*8eb6488eSEric Joyner bits |= 1 << (vind % 32); 4064*8eb6488eSEric Joyner if (vlan_on) 4065*8eb6488eSEric Joyner goto vlvf_update; 4066*8eb6488eSEric Joyner 40672969bf0eSJack F Vogel /* clear the pool bit */ 4068*8eb6488eSEric Joyner bits ^= 1 << (vind % 32); 4069*8eb6488eSEric Joyner 4070*8eb6488eSEric Joyner if (!bits && 4071*8eb6488eSEric Joyner !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { 4072*8eb6488eSEric Joyner /* Clear VFTA first, then disable VLVF. Otherwise 4073*8eb6488eSEric Joyner * we run the risk of stray packets leaking into 4074*8eb6488eSEric Joyner * the PF via the default pool 4075*8eb6488eSEric Joyner */ 4076*8eb6488eSEric Joyner if (*vfta_delta) 4077*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta); 4078*8eb6488eSEric Joyner 4079*8eb6488eSEric Joyner /* disable VLVF and clear remaining bit from pool */ 4080*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 4081*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); 4082*8eb6488eSEric Joyner 4083*8eb6488eSEric Joyner return IXGBE_SUCCESS; 40842969bf0eSJack F Vogel } 40852969bf0eSJack F Vogel 4086*8eb6488eSEric Joyner /* If there are still bits set in the VLVFB registers 4087c0014855SJack F Vogel * for the VLAN ID indicated we need to see if the 4088c0014855SJack F Vogel * caller is requesting that we clear the VFTA entry bit. 4089c0014855SJack F Vogel * If the caller has requested that we clear the VFTA 4090c0014855SJack F Vogel * entry bit but there are still pools/VFs using this VLAN 4091c0014855SJack F Vogel * ID entry then ignore the request. We're not worried 4092c0014855SJack F Vogel * about the case where we're turning the VFTA VLAN ID 4093c0014855SJack F Vogel * entry bit on, only when requested to turn it off as 4094c0014855SJack F Vogel * there may be multiple pools and/or VFs using the 4095c0014855SJack F Vogel * VLAN ID entry. In that case we cannot clear the 4096c0014855SJack F Vogel * VFTA bit until all pools/VFs using that VLAN ID have also 4097c0014855SJack F Vogel * been cleared. This will be indicated by "bits" being 4098c0014855SJack F Vogel * zero. 4099c0014855SJack F Vogel */ 4100*8eb6488eSEric Joyner *vfta_delta = 0; 4101*8eb6488eSEric Joyner 4102*8eb6488eSEric Joyner vlvf_update: 4103*8eb6488eSEric Joyner /* record pool change and enable VLAN ID if not already enabled */ 4104*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); 4105*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); 4106c0014855SJack F Vogel 41072969bf0eSJack F Vogel return IXGBE_SUCCESS; 41082969bf0eSJack F Vogel } 41092969bf0eSJack F Vogel 41102969bf0eSJack F Vogel /** 41112969bf0eSJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 41122969bf0eSJack F Vogel * @hw: pointer to hardware structure 41132969bf0eSJack F Vogel * 41142969bf0eSJack F Vogel * Clears the VLAN filer table, and the VMDq index associated with the filter 41152969bf0eSJack F Vogel **/ 41162969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 41172969bf0eSJack F Vogel { 41182969bf0eSJack F Vogel u32 offset; 41192969bf0eSJack F Vogel 41202969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vfta_generic"); 41212969bf0eSJack F Vogel 41222969bf0eSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 41232969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 41242969bf0eSJack F Vogel 41252969bf0eSJack F Vogel for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 41262969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 41272969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 4128*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2 + 1), 0); 41292969bf0eSJack F Vogel } 41302969bf0eSJack F Vogel 41312969bf0eSJack F Vogel return IXGBE_SUCCESS; 41322969bf0eSJack F Vogel } 41332969bf0eSJack F Vogel 41342969bf0eSJack F Vogel /** 4135*8eb6488eSEric Joyner * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix 4136*8eb6488eSEric Joyner * @hw: pointer to hardware structure 4137*8eb6488eSEric Joyner * 4138*8eb6488eSEric Joyner * Contains the logic to identify if we need to verify link for the 4139*8eb6488eSEric Joyner * crosstalk fix 4140*8eb6488eSEric Joyner **/ 4141*8eb6488eSEric Joyner static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) 4142*8eb6488eSEric Joyner { 4143*8eb6488eSEric Joyner 4144*8eb6488eSEric Joyner /* Does FW say we need the fix */ 4145*8eb6488eSEric Joyner if (!hw->need_crosstalk_fix) 4146*8eb6488eSEric Joyner return FALSE; 4147*8eb6488eSEric Joyner 4148*8eb6488eSEric Joyner /* Only consider SFP+ PHYs i.e. media type fiber */ 4149*8eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 4150*8eb6488eSEric Joyner case ixgbe_media_type_fiber: 4151*8eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 4152*8eb6488eSEric Joyner break; 4153*8eb6488eSEric Joyner default: 4154*8eb6488eSEric Joyner return FALSE; 4155*8eb6488eSEric Joyner } 4156*8eb6488eSEric Joyner 4157*8eb6488eSEric Joyner return TRUE; 4158*8eb6488eSEric Joyner } 4159*8eb6488eSEric Joyner 4160*8eb6488eSEric Joyner /** 41612969bf0eSJack F Vogel * ixgbe_check_mac_link_generic - Determine link and speed status 41622969bf0eSJack F Vogel * @hw: pointer to hardware structure 41632969bf0eSJack F Vogel * @speed: pointer to link speed 41642969bf0eSJack F Vogel * @link_up: TRUE when link is up 41652969bf0eSJack F Vogel * @link_up_wait_to_complete: bool used to wait for link up or not 41662969bf0eSJack F Vogel * 41672969bf0eSJack F Vogel * Reads the links register to determine if link is up and the current speed 41682969bf0eSJack F Vogel **/ 41692969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 41702969bf0eSJack F Vogel bool *link_up, bool link_up_wait_to_complete) 41712969bf0eSJack F Vogel { 4172c0014855SJack F Vogel u32 links_reg, links_orig; 41732969bf0eSJack F Vogel u32 i; 41742969bf0eSJack F Vogel 41752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_check_mac_link_generic"); 41762969bf0eSJack F Vogel 4177*8eb6488eSEric Joyner /* If Crosstalk fix enabled do the sanity check of making sure 4178*8eb6488eSEric Joyner * the SFP+ cage is full. 4179*8eb6488eSEric Joyner */ 4180*8eb6488eSEric Joyner if (ixgbe_need_crosstalk_fix(hw)) { 4181*8eb6488eSEric Joyner u32 sfp_cage_full; 4182*8eb6488eSEric Joyner 4183*8eb6488eSEric Joyner switch (hw->mac.type) { 4184*8eb6488eSEric Joyner case ixgbe_mac_82599EB: 4185*8eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 4186*8eb6488eSEric Joyner IXGBE_ESDP_SDP2; 4187*8eb6488eSEric Joyner break; 4188*8eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4189*8eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4190*8eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 4191*8eb6488eSEric Joyner IXGBE_ESDP_SDP0; 4192*8eb6488eSEric Joyner break; 4193*8eb6488eSEric Joyner default: 4194*8eb6488eSEric Joyner /* sanity check - No SFP+ devices here */ 4195*8eb6488eSEric Joyner sfp_cage_full = FALSE; 4196*8eb6488eSEric Joyner break; 4197*8eb6488eSEric Joyner } 4198*8eb6488eSEric Joyner 4199*8eb6488eSEric Joyner if (!sfp_cage_full) { 4200*8eb6488eSEric Joyner *link_up = FALSE; 4201*8eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 4202*8eb6488eSEric Joyner return IXGBE_SUCCESS; 4203*8eb6488eSEric Joyner } 4204*8eb6488eSEric Joyner } 4205*8eb6488eSEric Joyner 4206c0014855SJack F Vogel /* clear the old state */ 4207c0014855SJack F Vogel links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 4208c0014855SJack F Vogel 42092969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 4210c0014855SJack F Vogel 4211c0014855SJack F Vogel if (links_orig != links_reg) { 4212c0014855SJack F Vogel DEBUGOUT2("LINKS changed from %08X to %08X\n", 4213c0014855SJack F Vogel links_orig, links_reg); 4214c0014855SJack F Vogel } 4215c0014855SJack F Vogel 42162969bf0eSJack F Vogel if (link_up_wait_to_complete) { 4217a9ca1c79SSean Bruno for (i = 0; i < hw->mac.max_link_up_time; i++) { 42182969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) { 42192969bf0eSJack F Vogel *link_up = TRUE; 42202969bf0eSJack F Vogel break; 42212969bf0eSJack F Vogel } else { 42222969bf0eSJack F Vogel *link_up = FALSE; 42232969bf0eSJack F Vogel } 42242969bf0eSJack F Vogel msec_delay(100); 42252969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 42262969bf0eSJack F Vogel } 42272969bf0eSJack F Vogel } else { 42282969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) 42292969bf0eSJack F Vogel *link_up = TRUE; 42302969bf0eSJack F Vogel else 42312969bf0eSJack F Vogel *link_up = FALSE; 42322969bf0eSJack F Vogel } 42332969bf0eSJack F Vogel 4234758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4235758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 42362969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4237758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4238758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4239758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4240758cc3dcSJack F Vogel } 4241758cc3dcSJack F Vogel break; 4242758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 42432969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4244758cc3dcSJack F Vogel break; 4245758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 42462969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 4247*8eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550) { 4248758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4249758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4250758cc3dcSJack F Vogel } 4251758cc3dcSJack F Vogel break; 4252*8eb6488eSEric Joyner case IXGBE_LINKS_SPEED_10_X550EM_A: 4253*8eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 4254*8eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 4255*8eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { 4256*8eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_10_FULL; 4257*8eb6488eSEric Joyner } 4258*8eb6488eSEric Joyner break; 4259758cc3dcSJack F Vogel default: 42601a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4261758cc3dcSJack F Vogel } 42622969bf0eSJack F Vogel 42632969bf0eSJack F Vogel return IXGBE_SUCCESS; 42642969bf0eSJack F Vogel } 42652969bf0eSJack F Vogel 42662969bf0eSJack F Vogel /** 42672969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 42682969bf0eSJack F Vogel * the EEPROM 42692969bf0eSJack F Vogel * @hw: pointer to hardware structure 42702969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 42712969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 42722969bf0eSJack F Vogel * 42732969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 42742969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 42752969bf0eSJack F Vogel **/ 42762969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 42772969bf0eSJack F Vogel u16 *wwpn_prefix) 42782969bf0eSJack F Vogel { 42792969bf0eSJack F Vogel u16 offset, caps; 42802969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 42812969bf0eSJack F Vogel 42822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 42832969bf0eSJack F Vogel 42842969bf0eSJack F Vogel /* clear output first */ 42852969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 42862969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 42872969bf0eSJack F Vogel 42882969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4289fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4290fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4291fd75b91dSJack F Vogel goto wwn_prefix_err; 42922969bf0eSJack F Vogel 42932969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 42942969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 42952969bf0eSJack F Vogel goto wwn_prefix_out; 42962969bf0eSJack F Vogel 42972969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 42982969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4299fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4300fd75b91dSJack F Vogel goto wwn_prefix_err; 43012969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 43022969bf0eSJack F Vogel goto wwn_prefix_out; 43032969bf0eSJack F Vogel 43042969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 43052969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4306fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4307fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4308fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4309fd75b91dSJack F Vogel } 43102969bf0eSJack F Vogel 43112969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4312fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4313fd75b91dSJack F Vogel goto wwn_prefix_err; 43142969bf0eSJack F Vogel 43152969bf0eSJack F Vogel wwn_prefix_out: 43162969bf0eSJack F Vogel return IXGBE_SUCCESS; 4317fd75b91dSJack F Vogel 4318fd75b91dSJack F Vogel wwn_prefix_err: 4319fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4320fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4321fd75b91dSJack F Vogel return IXGBE_SUCCESS; 43222969bf0eSJack F Vogel } 43231a4e3449SJack F Vogel 43241a4e3449SJack F Vogel /** 43251a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 43261a4e3449SJack F Vogel * @hw: pointer to hardware structure 43271a4e3449SJack F Vogel * @bs: the fcoe boot status 43281a4e3449SJack F Vogel * 43291a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 43301a4e3449SJack F Vogel **/ 43311a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 43321a4e3449SJack F Vogel { 43331a4e3449SJack F Vogel u16 offset, caps, flags; 43341a4e3449SJack F Vogel s32 status; 43351a4e3449SJack F Vogel 43361a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 43371a4e3449SJack F Vogel 43381a4e3449SJack F Vogel /* clear output first */ 43391a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 43401a4e3449SJack F Vogel 43411a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 43421a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 43431a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 43441a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43451a4e3449SJack F Vogel goto out; 43461a4e3449SJack F Vogel 43471a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 43481a4e3449SJack F Vogel goto out; 43491a4e3449SJack F Vogel 43501a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 43511a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 43521a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43531a4e3449SJack F Vogel goto out; 43541a4e3449SJack F Vogel 43551a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 43561a4e3449SJack F Vogel goto out; 43571a4e3449SJack F Vogel 43581a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 43591a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 43601a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 43611a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43621a4e3449SJack F Vogel goto out; 43631a4e3449SJack F Vogel 43641a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 43651a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 43661a4e3449SJack F Vogel else 43671a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 43681a4e3449SJack F Vogel 43691a4e3449SJack F Vogel out: 43701a4e3449SJack F Vogel return status; 43711a4e3449SJack F Vogel } 43721a4e3449SJack F Vogel 43731a4e3449SJack F Vogel /** 43741a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 43751a4e3449SJack F Vogel * @hw: pointer to hardware structure 4376*8eb6488eSEric Joyner * @enable: enable or disable switch for MAC anti-spoofing 4377*8eb6488eSEric Joyner * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 43781a4e3449SJack F Vogel * 43791a4e3449SJack F Vogel **/ 4380*8eb6488eSEric Joyner void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 43811a4e3449SJack F Vogel { 4382*8eb6488eSEric Joyner int vf_target_reg = vf >> 3; 4383*8eb6488eSEric Joyner int vf_target_shift = vf % 8; 4384*8eb6488eSEric Joyner u32 pfvfspoof; 43851a4e3449SJack F Vogel 43861a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 43871a4e3449SJack F Vogel return; 43881a4e3449SJack F Vogel 4389*8eb6488eSEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 43901a4e3449SJack F Vogel if (enable) 4391*8eb6488eSEric Joyner pfvfspoof |= (1 << vf_target_shift); 4392*8eb6488eSEric Joyner else 4393*8eb6488eSEric Joyner pfvfspoof &= ~(1 << vf_target_shift); 4394*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 43951a4e3449SJack F Vogel } 43961a4e3449SJack F Vogel 43971a4e3449SJack F Vogel /** 43981a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 43991a4e3449SJack F Vogel * @hw: pointer to hardware structure 44001a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4401758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 44021a4e3449SJack F Vogel * 44031a4e3449SJack F Vogel **/ 44041a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44051a4e3449SJack F Vogel { 44061a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 44071a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 44081a4e3449SJack F Vogel u32 pfvfspoof; 44091a4e3449SJack F Vogel 44101a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44111a4e3449SJack F Vogel return; 44121a4e3449SJack F Vogel 44131a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44141a4e3449SJack F Vogel if (enable) 44151a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 44161a4e3449SJack F Vogel else 44171a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 44181a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44191a4e3449SJack F Vogel } 4420182b3808SJack F Vogel 4421182b3808SJack F Vogel /** 4422182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4423182b3808SJack F Vogel * @hw: pointer to hardware structure 4424182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4425182b3808SJack F Vogel * 4426182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4427182b3808SJack F Vogel * and return the word through device_caps. 4428182b3808SJack F Vogel **/ 4429182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4430182b3808SJack F Vogel { 4431182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4432182b3808SJack F Vogel 4433182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4434182b3808SJack F Vogel 4435182b3808SJack F Vogel return IXGBE_SUCCESS; 4436182b3808SJack F Vogel } 4437182b3808SJack F Vogel 4438182b3808SJack F Vogel /** 4439182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4440182b3808SJack F Vogel * @hw: pointer to hardware structure 4441182b3808SJack F Vogel * 4442182b3808SJack F Vogel **/ 4443182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4444182b3808SJack F Vogel { 4445182b3808SJack F Vogel u32 regval; 4446182b3808SJack F Vogel u32 i; 4447182b3808SJack F Vogel 4448182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4449182b3808SJack F Vogel 4450182b3808SJack F Vogel /* Enable relaxed ordering */ 4451182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4452182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4453a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4454182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4455182b3808SJack F Vogel } 4456182b3808SJack F Vogel 4457182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4458182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4459a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4460a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4461182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4462182b3808SJack F Vogel } 4463182b3808SJack F Vogel 4464182b3808SJack F Vogel } 446585d0a26eSJack F Vogel 446685d0a26eSJack F Vogel /** 446785d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 446885d0a26eSJack F Vogel * @buffer: pointer to EEPROM 446985d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 447085d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 447185d0a26eSJack F Vogel * checksum calculated is returned. 447285d0a26eSJack F Vogel **/ 44730ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 447485d0a26eSJack F Vogel { 447585d0a26eSJack F Vogel u32 i; 447685d0a26eSJack F Vogel u8 sum = 0; 447785d0a26eSJack F Vogel 447885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 447985d0a26eSJack F Vogel 448085d0a26eSJack F Vogel if (!buffer) 448185d0a26eSJack F Vogel return 0; 448285d0a26eSJack F Vogel 448385d0a26eSJack F Vogel for (i = 0; i < length; i++) 448485d0a26eSJack F Vogel sum += buffer[i]; 448585d0a26eSJack F Vogel 448685d0a26eSJack F Vogel return (u8) (0 - sum); 448785d0a26eSJack F Vogel } 448885d0a26eSJack F Vogel 448985d0a26eSJack F Vogel /** 4490*8eb6488eSEric Joyner * ixgbe_hic_unlocked - Issue command to manageability block unlocked 449185d0a26eSJack F Vogel * @hw: pointer to the HW structure 4492*8eb6488eSEric Joyner * @buffer: command to write and where the return status will be placed 4493a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4494758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 449585d0a26eSJack F Vogel * 449685d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 4497*8eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 4498*8eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 4499*8eb6488eSEric Joyner * 4500*8eb6488eSEric Joyner * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 4501*8eb6488eSEric Joyner * by the caller. 450285d0a26eSJack F Vogel **/ 4503*8eb6488eSEric Joyner s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 4504*8eb6488eSEric Joyner u32 timeout) 450585d0a26eSJack F Vogel { 4506*8eb6488eSEric Joyner u32 hicr, i, fwsts; 4507758cc3dcSJack F Vogel u16 dword_len; 450885d0a26eSJack F Vogel 4509*8eb6488eSEric Joyner DEBUGFUNC("ixgbe_hic_unlocked"); 451085d0a26eSJack F Vogel 4511*8eb6488eSEric Joyner if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4512758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4513758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 451485d0a26eSJack F Vogel } 4515*8eb6488eSEric Joyner 4516758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4517758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4518758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 451985d0a26eSJack F Vogel 452085d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 452185d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 4522*8eb6488eSEric Joyner if (!(hicr & IXGBE_HICR_EN)) { 452385d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4524758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 452585d0a26eSJack F Vogel } 452685d0a26eSJack F Vogel 4527758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 4528*8eb6488eSEric Joyner if (length % sizeof(u32)) { 4529758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4530758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4531758cc3dcSJack F Vogel } 4532758cc3dcSJack F Vogel 453385d0a26eSJack F Vogel dword_len = length >> 2; 453485d0a26eSJack F Vogel 4535758cc3dcSJack F Vogel /* The device driver writes the relevant command block 453685d0a26eSJack F Vogel * into the ram area. 453785d0a26eSJack F Vogel */ 453885d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 453985d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 454085d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 454185d0a26eSJack F Vogel 454285d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 454385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 454485d0a26eSJack F Vogel 4545758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 454685d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 454785d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 454885d0a26eSJack F Vogel break; 454985d0a26eSJack F Vogel msec_delay(1); 455085d0a26eSJack F Vogel } 455185d0a26eSJack F Vogel 4552758cc3dcSJack F Vogel /* Check command completion */ 4553*8eb6488eSEric Joyner if ((timeout && i == timeout) || 4554758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4555758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4556758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4557758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 455885d0a26eSJack F Vogel } 455985d0a26eSJack F Vogel 4560*8eb6488eSEric Joyner return IXGBE_SUCCESS; 4561*8eb6488eSEric Joyner } 4562*8eb6488eSEric Joyner 4563*8eb6488eSEric Joyner /** 4564*8eb6488eSEric Joyner * ixgbe_host_interface_command - Issue command to manageability block 4565*8eb6488eSEric Joyner * @hw: pointer to the HW structure 4566*8eb6488eSEric Joyner * @buffer: contains the command to write and where the return status will 4567*8eb6488eSEric Joyner * be placed 4568*8eb6488eSEric Joyner * @length: length of buffer, must be multiple of 4 bytes 4569*8eb6488eSEric Joyner * @timeout: time in ms to wait for command completion 4570*8eb6488eSEric Joyner * @return_data: read and return data from the buffer (TRUE) or not (FALSE) 4571*8eb6488eSEric Joyner * Needed because FW structures are big endian and decoding of 4572*8eb6488eSEric Joyner * these fields can be 8 bit or 16 bit based on command. Decoding 4573*8eb6488eSEric Joyner * is not easily understood without making a table of commands. 4574*8eb6488eSEric Joyner * So we will leave this up to the caller to read back the data 4575*8eb6488eSEric Joyner * in these cases. 4576*8eb6488eSEric Joyner * 4577*8eb6488eSEric Joyner * Communicates with the manageability block. On success return IXGBE_SUCCESS 4578*8eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 4579*8eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 4580*8eb6488eSEric Joyner **/ 4581*8eb6488eSEric Joyner s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 4582*8eb6488eSEric Joyner u32 length, u32 timeout, bool return_data) 4583*8eb6488eSEric Joyner { 4584*8eb6488eSEric Joyner u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 4585*8eb6488eSEric Joyner u16 dword_len; 4586*8eb6488eSEric Joyner u16 buf_len; 4587*8eb6488eSEric Joyner s32 status; 4588*8eb6488eSEric Joyner u32 bi; 4589*8eb6488eSEric Joyner 4590*8eb6488eSEric Joyner DEBUGFUNC("ixgbe_host_interface_command"); 4591*8eb6488eSEric Joyner 4592*8eb6488eSEric Joyner if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4593*8eb6488eSEric Joyner DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4594*8eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND; 4595*8eb6488eSEric Joyner } 4596*8eb6488eSEric Joyner 4597*8eb6488eSEric Joyner /* Take management host interface semaphore */ 4598*8eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 4599*8eb6488eSEric Joyner if (status) 4600*8eb6488eSEric Joyner return status; 4601*8eb6488eSEric Joyner 4602*8eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 4603*8eb6488eSEric Joyner if (status) 4604*8eb6488eSEric Joyner goto rel_out; 4605*8eb6488eSEric Joyner 4606758cc3dcSJack F Vogel if (!return_data) 4607*8eb6488eSEric Joyner goto rel_out; 4608758cc3dcSJack F Vogel 460985d0a26eSJack F Vogel /* Calculate length in DWORDs */ 461085d0a26eSJack F Vogel dword_len = hdr_size >> 2; 461185d0a26eSJack F Vogel 461285d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 461385d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 461485d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 461585d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 461685d0a26eSJack F Vogel } 461785d0a26eSJack F Vogel 461885d0a26eSJack F Vogel /* If there is any thing in data position pull it in */ 461985d0a26eSJack F Vogel buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; 4620*8eb6488eSEric Joyner if (!buf_len) 4621*8eb6488eSEric Joyner goto rel_out; 462285d0a26eSJack F Vogel 4623758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 462485d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 4625*8eb6488eSEric Joyner status = IXGBE_ERR_HOST_INTERFACE_COMMAND; 4626*8eb6488eSEric Joyner goto rel_out; 462785d0a26eSJack F Vogel } 462885d0a26eSJack F Vogel 462985d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 463085d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 463185d0a26eSJack F Vogel 463285d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 463385d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 463485d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 463585d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 463685d0a26eSJack F Vogel } 463785d0a26eSJack F Vogel 4638*8eb6488eSEric Joyner rel_out: 4639*8eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 4640*8eb6488eSEric Joyner 4641*8eb6488eSEric Joyner return status; 464285d0a26eSJack F Vogel } 464385d0a26eSJack F Vogel 464485d0a26eSJack F Vogel /** 464585d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 464685d0a26eSJack F Vogel * @hw: pointer to the HW structure 464785d0a26eSJack F Vogel * @maj: driver version major number 464885d0a26eSJack F Vogel * @min: driver version minor number 464985d0a26eSJack F Vogel * @build: driver version build number 465085d0a26eSJack F Vogel * @sub: driver version sub build number 465185d0a26eSJack F Vogel * 465285d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 465385d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 465485d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 465585d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 465685d0a26eSJack F Vogel **/ 465785d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 4658*8eb6488eSEric Joyner u8 build, u8 sub, u16 len, 4659*8eb6488eSEric Joyner const char *driver_ver) 466085d0a26eSJack F Vogel { 466185d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 466285d0a26eSJack F Vogel int i; 466385d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 466485d0a26eSJack F Vogel 466585d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 4666*8eb6488eSEric Joyner UNREFERENCED_2PARAMETER(len, driver_ver); 466785d0a26eSJack F Vogel 466885d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 466985d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 467085d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 467185d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 467285d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 467385d0a26eSJack F Vogel fw_cmd.ver_min = min; 467485d0a26eSJack F Vogel fw_cmd.ver_build = build; 467585d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 467685d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 467785d0a26eSJack F Vogel fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 467885d0a26eSJack F Vogel (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 467985d0a26eSJack F Vogel fw_cmd.pad = 0; 468085d0a26eSJack F Vogel fw_cmd.pad2 = 0; 468185d0a26eSJack F Vogel 468285d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 468385d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4684758cc3dcSJack F Vogel sizeof(fw_cmd), 4685758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 4686758cc3dcSJack F Vogel TRUE); 468785d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 468885d0a26eSJack F Vogel continue; 468985d0a26eSJack F Vogel 469085d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 469185d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 469285d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 469385d0a26eSJack F Vogel else 469485d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 469585d0a26eSJack F Vogel 469685d0a26eSJack F Vogel break; 469785d0a26eSJack F Vogel } 469885d0a26eSJack F Vogel 469985d0a26eSJack F Vogel return ret_val; 470085d0a26eSJack F Vogel } 470185d0a26eSJack F Vogel 470285d0a26eSJack F Vogel /** 470385d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 470485d0a26eSJack F Vogel * @hw: pointer to hardware structure 470585d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 470685d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 470785d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 470885d0a26eSJack F Vogel **/ 470985d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 471085d0a26eSJack F Vogel int strategy) 471185d0a26eSJack F Vogel { 471285d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 471385d0a26eSJack F Vogel int i = 0; 471485d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 471585d0a26eSJack F Vogel 471685d0a26eSJack F Vogel /* Reserve headroom */ 471785d0a26eSJack F Vogel pbsize -= headroom; 471885d0a26eSJack F Vogel 471985d0a26eSJack F Vogel if (!num_pb) 472085d0a26eSJack F Vogel num_pb = 1; 472185d0a26eSJack F Vogel 472285d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 472385d0a26eSJack F Vogel * buffers requested using supplied strategy. 472485d0a26eSJack F Vogel */ 472585d0a26eSJack F Vogel switch (strategy) { 4726a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 472785d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 472885d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 472985d0a26eSJack F Vogel */ 4730a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 473185d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 473285d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 473385d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 473485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 4735*8eb6488eSEric Joyner /* fall through - configure remaining packet buffers */ 4736a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 473785d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 473885d0a26eSJack F Vogel for (; i < num_pb; i++) 473985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 474085d0a26eSJack F Vogel break; 474185d0a26eSJack F Vogel default: 474285d0a26eSJack F Vogel break; 474385d0a26eSJack F Vogel } 474485d0a26eSJack F Vogel 474585d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 474685d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 474785d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 474885d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 474985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 475085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 475185d0a26eSJack F Vogel } 475285d0a26eSJack F Vogel 475385d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 475485d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 475585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 475685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 475785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 475885d0a26eSJack F Vogel } 475985d0a26eSJack F Vogel } 476085d0a26eSJack F Vogel 476185d0a26eSJack F Vogel /** 476285d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 476385d0a26eSJack F Vogel * @hw: pointer to the hardware structure 476485d0a26eSJack F Vogel * 476585d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 476685d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 476785d0a26eSJack F Vogel * buffers on the system. 476885d0a26eSJack F Vogel **/ 476985d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 477085d0a26eSJack F Vogel { 4771758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4772758cc3dcSJack F Vogel u16 value; 477385d0a26eSJack F Vogel 477485d0a26eSJack F Vogel /* 477585d0a26eSJack F Vogel * If double reset is not requested then all transactions should 477685d0a26eSJack F Vogel * already be clear and as such there is no work to do 477785d0a26eSJack F Vogel */ 477885d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 477985d0a26eSJack F Vogel return; 478085d0a26eSJack F Vogel 478185d0a26eSJack F Vogel /* 478285d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 478385d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 478485d0a26eSJack F Vogel * has already been cleared. 478585d0a26eSJack F Vogel */ 478685d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 478785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 478885d0a26eSJack F Vogel 4789758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4790758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4791758cc3dcSJack F Vogel msec_delay(3); 4792758cc3dcSJack F Vogel 4793758cc3dcSJack F Vogel /* 4794758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4795758cc3dcSJack F Vogel * transactions pending. 4796758cc3dcSJack F Vogel */ 4797758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4798758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4799758cc3dcSJack F Vogel usec_delay(100); 4800758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4801758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4802758cc3dcSJack F Vogel goto out; 4803758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4804758cc3dcSJack F Vogel goto out; 4805758cc3dcSJack F Vogel } 4806758cc3dcSJack F Vogel 4807758cc3dcSJack F Vogel out: 480885d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 480985d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 481085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 481185d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 481285d0a26eSJack F Vogel 481385d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 481485d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 481585d0a26eSJack F Vogel usec_delay(20); 481685d0a26eSJack F Vogel 481785d0a26eSJack F Vogel /* restore previous register values */ 481885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 481985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 482085d0a26eSJack F Vogel } 482185d0a26eSJack F Vogel 4822*8eb6488eSEric Joyner /** 4823*8eb6488eSEric Joyner * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW 4824*8eb6488eSEric Joyner * 4825*8eb6488eSEric Joyner * @hw: pointer to hardware structure 4826*8eb6488eSEric Joyner * @cmd: Command we send to the FW 4827*8eb6488eSEric Joyner * @status: The reply from the FW 4828*8eb6488eSEric Joyner * 4829*8eb6488eSEric Joyner * Bit-bangs the cmd to the by_pass FW status points to what is returned. 4830*8eb6488eSEric Joyner **/ 4831*8eb6488eSEric Joyner #define IXGBE_BYPASS_BB_WAIT 1 4832*8eb6488eSEric Joyner s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) 4833*8eb6488eSEric Joyner { 4834*8eb6488eSEric Joyner int i; 4835*8eb6488eSEric Joyner u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; 4836*8eb6488eSEric Joyner u32 esdp; 4837*8eb6488eSEric Joyner 4838*8eb6488eSEric Joyner if (!status) 4839*8eb6488eSEric Joyner return IXGBE_ERR_PARAM; 4840*8eb6488eSEric Joyner 4841*8eb6488eSEric Joyner *status = 0; 4842*8eb6488eSEric Joyner 4843*8eb6488eSEric Joyner /* SDP vary by MAC type */ 4844*8eb6488eSEric Joyner switch (hw->mac.type) { 4845*8eb6488eSEric Joyner case ixgbe_mac_82599EB: 4846*8eb6488eSEric Joyner sck = IXGBE_ESDP_SDP7; 4847*8eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 4848*8eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP6; 4849*8eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP7_DIR; 4850*8eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 4851*8eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP6_DIR; 4852*8eb6488eSEric Joyner break; 4853*8eb6488eSEric Joyner case ixgbe_mac_X540: 4854*8eb6488eSEric Joyner sck = IXGBE_ESDP_SDP2; 4855*8eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 4856*8eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP1; 4857*8eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP2_DIR; 4858*8eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 4859*8eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP1_DIR; 4860*8eb6488eSEric Joyner break; 4861*8eb6488eSEric Joyner default: 4862*8eb6488eSEric Joyner return IXGBE_ERR_DEVICE_NOT_SUPPORTED; 4863*8eb6488eSEric Joyner } 4864*8eb6488eSEric Joyner 4865*8eb6488eSEric Joyner /* Set SDP pins direction */ 4866*8eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 4867*8eb6488eSEric Joyner esdp |= dir_sck; /* SCK as output */ 4868*8eb6488eSEric Joyner esdp |= dir_sdi; /* SDI as output */ 4869*8eb6488eSEric Joyner esdp &= ~dir_sdo; /* SDO as input */ 4870*8eb6488eSEric Joyner esdp |= sck; 4871*8eb6488eSEric Joyner esdp |= sdi; 4872*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4873*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4874*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4875*8eb6488eSEric Joyner 4876*8eb6488eSEric Joyner /* Generate start condition */ 4877*8eb6488eSEric Joyner esdp &= ~sdi; 4878*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4879*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4880*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4881*8eb6488eSEric Joyner 4882*8eb6488eSEric Joyner esdp &= ~sck; 4883*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4884*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4885*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4886*8eb6488eSEric Joyner 4887*8eb6488eSEric Joyner /* Clock out the new control word and clock in the status */ 4888*8eb6488eSEric Joyner for (i = 0; i < 32; i++) { 4889*8eb6488eSEric Joyner if ((cmd >> (31 - i)) & 0x01) { 4890*8eb6488eSEric Joyner esdp |= sdi; 4891*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4892*8eb6488eSEric Joyner } else { 4893*8eb6488eSEric Joyner esdp &= ~sdi; 4894*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4895*8eb6488eSEric Joyner } 4896*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4897*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4898*8eb6488eSEric Joyner 4899*8eb6488eSEric Joyner esdp |= sck; 4900*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4901*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4902*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4903*8eb6488eSEric Joyner 4904*8eb6488eSEric Joyner esdp &= ~sck; 4905*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4906*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4907*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4908*8eb6488eSEric Joyner 4909*8eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 4910*8eb6488eSEric Joyner if (esdp & sdo) 4911*8eb6488eSEric Joyner *status = (*status << 1) | 0x01; 4912*8eb6488eSEric Joyner else 4913*8eb6488eSEric Joyner *status = (*status << 1) | 0x00; 4914*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4915*8eb6488eSEric Joyner } 4916*8eb6488eSEric Joyner 4917*8eb6488eSEric Joyner /* stop condition */ 4918*8eb6488eSEric Joyner esdp |= sck; 4919*8eb6488eSEric Joyner esdp &= ~sdi; 4920*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4921*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4922*8eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 4923*8eb6488eSEric Joyner 4924*8eb6488eSEric Joyner esdp |= sdi; 4925*8eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 4926*8eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 4927*8eb6488eSEric Joyner 4928*8eb6488eSEric Joyner /* set the page bits to match the cmd that the status it belongs to */ 4929*8eb6488eSEric Joyner *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); 4930*8eb6488eSEric Joyner 4931*8eb6488eSEric Joyner return IXGBE_SUCCESS; 4932*8eb6488eSEric Joyner } 4933*8eb6488eSEric Joyner 4934*8eb6488eSEric Joyner /** 4935*8eb6488eSEric Joyner * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. 4936*8eb6488eSEric Joyner * 4937*8eb6488eSEric Joyner * If we send a write we can't be sure it took until we can read back 4938*8eb6488eSEric Joyner * that same register. It can be a problem as some of the feilds may 4939*8eb6488eSEric Joyner * for valid reasons change inbetween the time wrote the register and 4940*8eb6488eSEric Joyner * we read it again to verify. So this function check everything we 4941*8eb6488eSEric Joyner * can check and then assumes it worked. 4942*8eb6488eSEric Joyner * 4943*8eb6488eSEric Joyner * @u32 in_reg - The register cmd for the bit-bang read. 4944*8eb6488eSEric Joyner * @u32 out_reg - The register returned from a bit-bang read. 4945*8eb6488eSEric Joyner **/ 4946*8eb6488eSEric Joyner bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) 4947*8eb6488eSEric Joyner { 4948*8eb6488eSEric Joyner u32 mask; 4949*8eb6488eSEric Joyner 4950*8eb6488eSEric Joyner /* Page must match for all control pages */ 4951*8eb6488eSEric Joyner if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) 4952*8eb6488eSEric Joyner return FALSE; 4953*8eb6488eSEric Joyner 4954*8eb6488eSEric Joyner switch (in_reg & BYPASS_PAGE_M) { 4955*8eb6488eSEric Joyner case BYPASS_PAGE_CTL0: 4956*8eb6488eSEric Joyner /* All the following can't change since the last write 4957*8eb6488eSEric Joyner * - All the event actions 4958*8eb6488eSEric Joyner * - The timeout value 4959*8eb6488eSEric Joyner */ 4960*8eb6488eSEric Joyner mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | 4961*8eb6488eSEric Joyner BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | 4962*8eb6488eSEric Joyner BYPASS_WDTIMEOUT_M | 4963*8eb6488eSEric Joyner BYPASS_WDT_VALUE_M; 4964*8eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 4965*8eb6488eSEric Joyner return FALSE; 4966*8eb6488eSEric Joyner 4967*8eb6488eSEric Joyner /* 0x0 is never a valid value for bypass status */ 4968*8eb6488eSEric Joyner if (!(out_reg & BYPASS_STATUS_OFF_M)) 4969*8eb6488eSEric Joyner return FALSE; 4970*8eb6488eSEric Joyner break; 4971*8eb6488eSEric Joyner case BYPASS_PAGE_CTL1: 4972*8eb6488eSEric Joyner /* All the following can't change since the last write 4973*8eb6488eSEric Joyner * - time valid bit 4974*8eb6488eSEric Joyner * - time we last sent 4975*8eb6488eSEric Joyner */ 4976*8eb6488eSEric Joyner mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; 4977*8eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 4978*8eb6488eSEric Joyner return FALSE; 4979*8eb6488eSEric Joyner break; 4980*8eb6488eSEric Joyner case BYPASS_PAGE_CTL2: 4981*8eb6488eSEric Joyner /* All we can check in this page is control number 4982*8eb6488eSEric Joyner * which is already done above. 4983*8eb6488eSEric Joyner */ 4984*8eb6488eSEric Joyner break; 4985*8eb6488eSEric Joyner } 4986*8eb6488eSEric Joyner 4987*8eb6488eSEric Joyner /* We are as sure as we can be return TRUE */ 4988*8eb6488eSEric Joyner return TRUE; 4989*8eb6488eSEric Joyner } 4990*8eb6488eSEric Joyner 4991*8eb6488eSEric Joyner /** 4992*8eb6488eSEric Joyner * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. 4993*8eb6488eSEric Joyner * 4994*8eb6488eSEric Joyner * @hw: pointer to hardware structure 4995*8eb6488eSEric Joyner * @cmd: The control word we are setting. 4996*8eb6488eSEric Joyner * @event: The event we are setting in the FW. This also happens to 4997*8eb6488eSEric Joyner * be the mask for the event we are setting (handy) 4998*8eb6488eSEric Joyner * @action: The action we set the event to in the FW. This is in a 4999*8eb6488eSEric Joyner * bit field that happens to be what we want to put in 5000*8eb6488eSEric Joyner * the event spot (also handy) 5001*8eb6488eSEric Joyner **/ 5002*8eb6488eSEric Joyner s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, 5003*8eb6488eSEric Joyner u32 action) 5004*8eb6488eSEric Joyner { 5005*8eb6488eSEric Joyner u32 by_ctl = 0; 5006*8eb6488eSEric Joyner u32 cmd, verify; 5007*8eb6488eSEric Joyner u32 count = 0; 5008*8eb6488eSEric Joyner 5009*8eb6488eSEric Joyner /* Get current values */ 5010*8eb6488eSEric Joyner cmd = ctrl; /* just reading only need control number */ 5011*8eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 5012*8eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 5013*8eb6488eSEric Joyner 5014*8eb6488eSEric Joyner /* Set to new action */ 5015*8eb6488eSEric Joyner cmd = (by_ctl & ~event) | BYPASS_WE | action; 5016*8eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 5017*8eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 5018*8eb6488eSEric Joyner 5019*8eb6488eSEric Joyner /* Page 0 force a FW eeprom write which is slow so verify */ 5020*8eb6488eSEric Joyner if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { 5021*8eb6488eSEric Joyner verify = BYPASS_PAGE_CTL0; 5022*8eb6488eSEric Joyner do { 5023*8eb6488eSEric Joyner if (count++ > 5) 5024*8eb6488eSEric Joyner return IXGBE_BYPASS_FW_WRITE_FAILURE; 5025*8eb6488eSEric Joyner 5026*8eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) 5027*8eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 5028*8eb6488eSEric Joyner } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); 5029*8eb6488eSEric Joyner } else { 5030*8eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 5031*8eb6488eSEric Joyner msec_delay(100); 5032*8eb6488eSEric Joyner } 5033*8eb6488eSEric Joyner 5034*8eb6488eSEric Joyner return IXGBE_SUCCESS; 5035*8eb6488eSEric Joyner } 5036*8eb6488eSEric Joyner 5037*8eb6488eSEric Joyner /** 5038*8eb6488eSEric Joyner * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. 5039*8eb6488eSEric Joyner * 5040*8eb6488eSEric Joyner * @hw: pointer to hardware structure 5041*8eb6488eSEric Joyner * @addr: The bypass eeprom address to read. 5042*8eb6488eSEric Joyner * @value: The 8b of data at the address above. 5043*8eb6488eSEric Joyner **/ 5044*8eb6488eSEric Joyner s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) 5045*8eb6488eSEric Joyner { 5046*8eb6488eSEric Joyner u32 cmd; 5047*8eb6488eSEric Joyner u32 status; 5048*8eb6488eSEric Joyner 5049*8eb6488eSEric Joyner 5050*8eb6488eSEric Joyner /* send the request */ 5051*8eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 5052*8eb6488eSEric Joyner cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 5053*8eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 5054*8eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 5055*8eb6488eSEric Joyner 5056*8eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 5057*8eb6488eSEric Joyner msec_delay(100); 5058*8eb6488eSEric Joyner 5059*8eb6488eSEric Joyner /* now read the results */ 5060*8eb6488eSEric Joyner cmd &= ~BYPASS_WE; 5061*8eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 5062*8eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 5063*8eb6488eSEric Joyner 5064*8eb6488eSEric Joyner *value = status & BYPASS_CTL2_DATA_M; 5065*8eb6488eSEric Joyner 5066*8eb6488eSEric Joyner return IXGBE_SUCCESS; 5067*8eb6488eSEric Joyner } 5068*8eb6488eSEric Joyner 5069fd75b91dSJack F Vogel 5070fd75b91dSJack F Vogel /** 5071fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 5072fd75b91dSJack F Vogel * @hw: pointer to hardware structure 5073fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 5074fd75b91dSJack F Vogel * 5075fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 5076fd75b91dSJack F Vogel **/ 5077fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 5078fd75b91dSJack F Vogel { 5079fd75b91dSJack F Vogel u32 reg, i; 5080fd75b91dSJack F Vogel 5081fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 5082fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 5083fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 5084fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 5085fd75b91dSJack F Vogel return; 5086fd75b91dSJack F Vogel } 5087758cc3dcSJack F Vogel 5088758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 5089758cc3dcSJack F Vogel { 5090758cc3dcSJack F Vogel u32 pfdtxgswc; 5091758cc3dcSJack F Vogel u32 rxctrl; 5092758cc3dcSJack F Vogel 5093758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5094758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 5095758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5096758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5097758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 5098758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 5099758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5100758cc3dcSJack F Vogel hw->mac.set_lben = TRUE; 5101758cc3dcSJack F Vogel } else { 5102758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5103758cc3dcSJack F Vogel } 5104758cc3dcSJack F Vogel } 5105758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 5106758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 5107758cc3dcSJack F Vogel } 5108758cc3dcSJack F Vogel } 5109758cc3dcSJack F Vogel 5110758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 5111758cc3dcSJack F Vogel { 5112758cc3dcSJack F Vogel u32 pfdtxgswc; 5113758cc3dcSJack F Vogel u32 rxctrl; 5114758cc3dcSJack F Vogel 5115758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5116758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 5117758cc3dcSJack F Vogel 5118758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5119758cc3dcSJack F Vogel if (hw->mac.set_lben) { 5120758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5121758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 5122758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5123758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5124758cc3dcSJack F Vogel } 5125758cc3dcSJack F Vogel } 5126758cc3dcSJack F Vogel } 5127758cc3dcSJack F Vogel 5128758cc3dcSJack F Vogel /** 5129758cc3dcSJack F Vogel * ixgbe_mng_present - returns TRUE when management capability is present 5130758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5131758cc3dcSJack F Vogel */ 5132758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 5133758cc3dcSJack F Vogel { 5134758cc3dcSJack F Vogel u32 fwsm; 5135758cc3dcSJack F Vogel 5136758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 5137758cc3dcSJack F Vogel return FALSE; 5138758cc3dcSJack F Vogel 5139a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5140758cc3dcSJack F Vogel fwsm &= IXGBE_FWSM_MODE_MASK; 5141758cc3dcSJack F Vogel return fwsm == IXGBE_FWSM_FW_MODE_PT; 5142758cc3dcSJack F Vogel } 5143758cc3dcSJack F Vogel 5144758cc3dcSJack F Vogel /** 5145758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 5146758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5147758cc3dcSJack F Vogel * 5148758cc3dcSJack F Vogel * Returns TRUE if the manageability engine is enabled. 5149758cc3dcSJack F Vogel **/ 5150758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 5151758cc3dcSJack F Vogel { 5152758cc3dcSJack F Vogel u32 fwsm, manc, factps; 5153758cc3dcSJack F Vogel 5154a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5155758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 5156758cc3dcSJack F Vogel return FALSE; 5157758cc3dcSJack F Vogel 5158758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 5159758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 5160758cc3dcSJack F Vogel return FALSE; 5161758cc3dcSJack F Vogel 5162758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 5163a9ca1c79SSean Bruno factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 5164758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 5165758cc3dcSJack F Vogel return FALSE; 5166758cc3dcSJack F Vogel } 5167758cc3dcSJack F Vogel 5168758cc3dcSJack F Vogel return TRUE; 5169758cc3dcSJack F Vogel } 5170758cc3dcSJack F Vogel 5171758cc3dcSJack F Vogel /** 5172758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 5173758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5174758cc3dcSJack F Vogel * @speed: new link speed 5175758cc3dcSJack F Vogel * @autoneg_wait_to_complete: TRUE when waiting for completion is needed 5176758cc3dcSJack F Vogel * 5177758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 5178758cc3dcSJack F Vogel **/ 5179758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 5180758cc3dcSJack F Vogel ixgbe_link_speed speed, 5181758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 5182758cc3dcSJack F Vogel { 5183758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5184758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5185758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 5186758cc3dcSJack F Vogel u32 speedcnt = 0; 5187758cc3dcSJack F Vogel u32 i = 0; 5188758cc3dcSJack F Vogel bool autoneg, link_up = FALSE; 5189758cc3dcSJack F Vogel 5190758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 5191758cc3dcSJack F Vogel 5192758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 5193758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 5194758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5195758cc3dcSJack F Vogel return status; 5196758cc3dcSJack F Vogel 5197758cc3dcSJack F Vogel speed &= link_speed; 5198758cc3dcSJack F Vogel 5199758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 5200758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 5201758cc3dcSJack F Vogel */ 5202758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 5203758cc3dcSJack F Vogel speedcnt++; 5204758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 5205758cc3dcSJack F Vogel 5206758cc3dcSJack F Vogel /* Set the module link speed */ 5207758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5208758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5209758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5210758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5211758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 5212758cc3dcSJack F Vogel break; 5213758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5214758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 5215758cc3dcSJack F Vogel break; 5216758cc3dcSJack F Vogel default: 5217758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5218758cc3dcSJack F Vogel break; 5219758cc3dcSJack F Vogel } 5220758cc3dcSJack F Vogel 5221758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 5222758cc3dcSJack F Vogel msec_delay(40); 5223758cc3dcSJack F Vogel 5224758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5225758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 5226758cc3dcSJack F Vogel autoneg_wait_to_complete); 5227758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5228758cc3dcSJack F Vogel return status; 5229758cc3dcSJack F Vogel 5230758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5231758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5232758cc3dcSJack F Vogel 5233758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 5234758cc3dcSJack F Vogel * Section 73.10.2, we may have to wait up to 500ms if KR is 5235758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 5236758cc3dcSJack F Vogel */ 5237758cc3dcSJack F Vogel for (i = 0; i < 5; i++) { 5238758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5239758cc3dcSJack F Vogel msec_delay(100); 5240758cc3dcSJack F Vogel 5241758cc3dcSJack F Vogel /* If we have link, just jump out */ 5242758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 5243758cc3dcSJack F Vogel &link_up, FALSE); 5244758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5245758cc3dcSJack F Vogel return status; 5246758cc3dcSJack F Vogel 5247758cc3dcSJack F Vogel if (link_up) 5248758cc3dcSJack F Vogel goto out; 5249758cc3dcSJack F Vogel } 5250758cc3dcSJack F Vogel } 5251758cc3dcSJack F Vogel 5252758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 5253758cc3dcSJack F Vogel speedcnt++; 5254758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 5255758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 5256758cc3dcSJack F Vogel 5257758cc3dcSJack F Vogel /* Set the module link speed */ 5258758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5259758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5260758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5261758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5262758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 5263758cc3dcSJack F Vogel break; 5264758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5265758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 5266758cc3dcSJack F Vogel break; 5267758cc3dcSJack F Vogel default: 5268758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5269758cc3dcSJack F Vogel break; 5270758cc3dcSJack F Vogel } 5271758cc3dcSJack F Vogel 5272758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 5273758cc3dcSJack F Vogel msec_delay(40); 5274758cc3dcSJack F Vogel 5275758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5276758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 5277758cc3dcSJack F Vogel autoneg_wait_to_complete); 5278758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5279758cc3dcSJack F Vogel return status; 5280758cc3dcSJack F Vogel 5281758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5282758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5283758cc3dcSJack F Vogel 5284758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5285758cc3dcSJack F Vogel msec_delay(100); 5286758cc3dcSJack F Vogel 5287758cc3dcSJack F Vogel /* If we have link, just jump out */ 5288758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 5289758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5290758cc3dcSJack F Vogel return status; 5291758cc3dcSJack F Vogel 5292758cc3dcSJack F Vogel if (link_up) 5293758cc3dcSJack F Vogel goto out; 5294758cc3dcSJack F Vogel } 5295758cc3dcSJack F Vogel 5296758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 5297758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 5298758cc3dcSJack F Vogel * single highest speed that the user requested. 5299758cc3dcSJack F Vogel */ 5300758cc3dcSJack F Vogel if (speedcnt > 1) 5301758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 5302758cc3dcSJack F Vogel highest_link_speed, 5303758cc3dcSJack F Vogel autoneg_wait_to_complete); 5304758cc3dcSJack F Vogel 5305758cc3dcSJack F Vogel out: 5306758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 5307758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 5308758cc3dcSJack F Vogel 5309758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 5310758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 5311758cc3dcSJack F Vogel 5312758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 5313758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5314758cc3dcSJack F Vogel 5315758cc3dcSJack F Vogel return status; 5316758cc3dcSJack F Vogel } 5317758cc3dcSJack F Vogel 5318758cc3dcSJack F Vogel /** 5319758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 5320758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5321758cc3dcSJack F Vogel * @speed: link speed to set 5322758cc3dcSJack F Vogel * 5323758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 5324758cc3dcSJack F Vogel */ 5325758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 5326758cc3dcSJack F Vogel ixgbe_link_speed speed) 5327758cc3dcSJack F Vogel { 5328758cc3dcSJack F Vogel s32 status; 5329758cc3dcSJack F Vogel u8 rs, eeprom_data; 5330758cc3dcSJack F Vogel 5331758cc3dcSJack F Vogel switch (speed) { 5332758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 5333758cc3dcSJack F Vogel /* one bit mask same as setting on */ 5334758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 5335758cc3dcSJack F Vogel break; 5336758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 5337758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 5338758cc3dcSJack F Vogel break; 5339758cc3dcSJack F Vogel default: 5340758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 5341758cc3dcSJack F Vogel return; 5342758cc3dcSJack F Vogel } 5343758cc3dcSJack F Vogel 5344758cc3dcSJack F Vogel /* Set RS0 */ 5345758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5346758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5347758cc3dcSJack F Vogel &eeprom_data); 5348758cc3dcSJack F Vogel if (status) { 5349758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 5350758cc3dcSJack F Vogel goto out; 5351758cc3dcSJack F Vogel } 5352758cc3dcSJack F Vogel 5353758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5354758cc3dcSJack F Vogel 5355758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5356758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5357758cc3dcSJack F Vogel eeprom_data); 5358758cc3dcSJack F Vogel if (status) { 5359758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 5360758cc3dcSJack F Vogel goto out; 5361758cc3dcSJack F Vogel } 5362758cc3dcSJack F Vogel 5363758cc3dcSJack F Vogel /* Set RS1 */ 5364758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5365758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5366758cc3dcSJack F Vogel &eeprom_data); 5367758cc3dcSJack F Vogel if (status) { 5368758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 5369758cc3dcSJack F Vogel goto out; 5370758cc3dcSJack F Vogel } 5371758cc3dcSJack F Vogel 5372758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5373758cc3dcSJack F Vogel 5374758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5375758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5376758cc3dcSJack F Vogel eeprom_data); 5377758cc3dcSJack F Vogel if (status) { 5378758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 5379758cc3dcSJack F Vogel goto out; 5380758cc3dcSJack F Vogel } 5381758cc3dcSJack F Vogel out: 5382758cc3dcSJack F Vogel return; 5383758cc3dcSJack F Vogel } 5384