19ca4041bSJack F Vogel /****************************************************************************** 27282444bSPedro F. Giffuni SPDX-License-Identifier: BSD-3-Clause 313705f88SJack F Vogel 48eb6488eSEric Joyner Copyright (c) 2001-2017, Intel Corporation 513705f88SJack F Vogel All rights reserved. 613705f88SJack F Vogel 713705f88SJack F Vogel Redistribution and use in source and binary forms, with or without 813705f88SJack F Vogel modification, are permitted provided that the following conditions are met: 913705f88SJack F Vogel 1013705f88SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 1113705f88SJack F Vogel this list of conditions and the following disclaimer. 1213705f88SJack F Vogel 1313705f88SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 1413705f88SJack F Vogel notice, this list of conditions and the following disclaimer in the 1513705f88SJack F Vogel documentation and/or other materials provided with the distribution. 1613705f88SJack F Vogel 1713705f88SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 1813705f88SJack F Vogel contributors may be used to endorse or promote products derived from 1913705f88SJack F Vogel this software without specific prior written permission. 2013705f88SJack F Vogel 2113705f88SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2213705f88SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2313705f88SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2413705f88SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2513705f88SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2613705f88SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2713705f88SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2813705f88SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2913705f88SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3013705f88SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3113705f88SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 3213705f88SJack F Vogel 339ca4041bSJack F Vogel ******************************************************************************/ 3413705f88SJack F Vogel /*$FreeBSD$*/ 3513705f88SJack F Vogel 3613705f88SJack F Vogel #include "ixgbe_common.h" 371a4e3449SJack F Vogel #include "ixgbe_phy.h" 38fd75b91dSJack F Vogel #include "ixgbe_dcb.h" 39fd75b91dSJack F Vogel #include "ixgbe_dcb_82599.h" 4013705f88SJack F Vogel #include "ixgbe_api.h" 4113705f88SJack F Vogel 4213705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 4313705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 4413705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 4513705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 4613705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 4713705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 4813705f88SJack F Vogel u16 count); 4913705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 5013705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5113705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5213705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 5313705f88SJack F Vogel 5413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 552969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 562969bf0eSJack F Vogel u16 *san_mac_offset); 5785d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5885d0a26eSJack F Vogel u16 words, u16 *data); 5985d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 6085d0a26eSJack F Vogel u16 words, u16 *data); 6185d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 6285d0a26eSJack F Vogel u16 offset); 6313705f88SJack F Vogel 6413705f88SJack F Vogel /** 659ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 669ca4041bSJack F Vogel * @hw: pointer to the hardware structure 6713705f88SJack F Vogel * 689ca4041bSJack F Vogel * Initialize the function pointers. 6913705f88SJack F Vogel **/ 709ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 7113705f88SJack F Vogel { 729ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 739ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 74a9ca1c79SSean Bruno u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 7513705f88SJack F Vogel 762969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_ops_generic"); 772969bf0eSJack F Vogel 7813705f88SJack F Vogel /* EEPROM */ 79758cc3dcSJack F Vogel eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; 809ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 8185d0a26eSJack F Vogel if (eec & IXGBE_EEC_PRES) { 82758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eerd_generic; 83758cc3dcSJack F Vogel eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; 8485d0a26eSJack F Vogel } else { 85758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; 8685d0a26eSJack F Vogel eeprom->ops.read_buffer = 87758cc3dcSJack F Vogel ixgbe_read_eeprom_buffer_bit_bang_generic; 8885d0a26eSJack F Vogel } 89758cc3dcSJack F Vogel eeprom->ops.write = ixgbe_write_eeprom_generic; 90758cc3dcSJack F Vogel eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; 919ca4041bSJack F Vogel eeprom->ops.validate_checksum = 92758cc3dcSJack F Vogel ixgbe_validate_eeprom_checksum_generic; 93758cc3dcSJack F Vogel eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; 94758cc3dcSJack F Vogel eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; 959ca4041bSJack F Vogel 969ca4041bSJack F Vogel /* MAC */ 97758cc3dcSJack F Vogel mac->ops.init_hw = ixgbe_init_hw_generic; 989ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 99758cc3dcSJack F Vogel mac->ops.start_hw = ixgbe_start_hw_generic; 100758cc3dcSJack F Vogel mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; 1019ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 1021b6e0dbaSJack F Vogel mac->ops.get_supported_physical_layer = NULL; 103758cc3dcSJack F Vogel mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; 104758cc3dcSJack F Vogel mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; 105758cc3dcSJack F Vogel mac->ops.stop_adapter = ixgbe_stop_adapter_generic; 106758cc3dcSJack F Vogel mac->ops.get_bus_info = ixgbe_get_bus_info_generic; 107758cc3dcSJack F Vogel mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; 108758cc3dcSJack F Vogel mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; 109758cc3dcSJack F Vogel mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; 110758cc3dcSJack F Vogel mac->ops.prot_autoc_read = prot_autoc_read_generic; 111758cc3dcSJack F Vogel mac->ops.prot_autoc_write = prot_autoc_write_generic; 1129ca4041bSJack F Vogel 1139ca4041bSJack F Vogel /* LEDs */ 114758cc3dcSJack F Vogel mac->ops.led_on = ixgbe_led_on_generic; 115758cc3dcSJack F Vogel mac->ops.led_off = ixgbe_led_off_generic; 116758cc3dcSJack F Vogel mac->ops.blink_led_start = ixgbe_blink_led_start_generic; 117758cc3dcSJack F Vogel mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; 1188eb6488eSEric Joyner mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic; 1199ca4041bSJack F Vogel 12013705f88SJack F Vogel /* RAR, Multicast, VLAN */ 121758cc3dcSJack F Vogel mac->ops.set_rar = ixgbe_set_rar_generic; 122758cc3dcSJack F Vogel mac->ops.clear_rar = ixgbe_clear_rar_generic; 1230ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1249ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1255b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 126758cc3dcSJack F Vogel mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; 127758cc3dcSJack F Vogel mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; 128758cc3dcSJack F Vogel mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; 129758cc3dcSJack F Vogel mac->ops.enable_mc = ixgbe_enable_mc_generic; 130758cc3dcSJack F Vogel mac->ops.disable_mc = ixgbe_disable_mc_generic; 1315b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1325b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 13385d0a26eSJack F Vogel mac->ops.set_vlvf = NULL; 1345b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 135758cc3dcSJack F Vogel mac->ops.enable_rx = ixgbe_enable_rx_generic; 136758cc3dcSJack F Vogel mac->ops.disable_rx = ixgbe_disable_rx_generic; 1379ca4041bSJack F Vogel 1380ac6dfecSJack F Vogel /* Flow Control */ 139758cc3dcSJack F Vogel mac->ops.fc_enable = ixgbe_fc_enable_generic; 140758cc3dcSJack F Vogel mac->ops.setup_fc = ixgbe_setup_fc_generic; 1418eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg; 1429ca4041bSJack F Vogel 1439ca4041bSJack F Vogel /* Link */ 1449ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1459ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1469ca4041bSJack F Vogel mac->ops.check_link = NULL; 147fd75b91dSJack F Vogel mac->ops.dmac_config = NULL; 148fd75b91dSJack F Vogel mac->ops.dmac_update_tcs = NULL; 149fd75b91dSJack F Vogel mac->ops.dmac_config_tcs = NULL; 15013705f88SJack F Vogel 15113705f88SJack F Vogel return IXGBE_SUCCESS; 15213705f88SJack F Vogel } 15313705f88SJack F Vogel 15413705f88SJack F Vogel /** 155fd75b91dSJack F Vogel * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation 156fd75b91dSJack F Vogel * of flow control 157a621e3c8SJack F Vogel * @hw: pointer to hardware structure 158a621e3c8SJack F Vogel * 159fd75b91dSJack F Vogel * This function returns TRUE if the device supports flow control 160fd75b91dSJack F Vogel * autonegotiation, and FALSE if it does not. 161fd75b91dSJack F Vogel * 162a621e3c8SJack F Vogel **/ 163fd75b91dSJack F Vogel bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 164a621e3c8SJack F Vogel { 165fd75b91dSJack F Vogel bool supported = FALSE; 166fd75b91dSJack F Vogel ixgbe_link_speed speed; 167fd75b91dSJack F Vogel bool link_up; 168a621e3c8SJack F Vogel 169a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); 170a621e3c8SJack F Vogel 171fd75b91dSJack F Vogel switch (hw->phy.media_type) { 172fd75b91dSJack F Vogel case ixgbe_media_type_fiber_fixed: 173758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 174fd75b91dSJack F Vogel case ixgbe_media_type_fiber: 1758eb6488eSEric Joyner /* flow control autoneg black list */ 1768eb6488eSEric Joyner switch (hw->device_id) { 1778eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP: 1788eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N: 1798eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP: 1808eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP_N: 1818eb6488eSEric Joyner supported = FALSE; 1828eb6488eSEric Joyner break; 1838eb6488eSEric Joyner default: 184fd75b91dSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 185fd75b91dSJack F Vogel /* if link is down, assume supported */ 186fd75b91dSJack F Vogel if (link_up) 187fd75b91dSJack F Vogel supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? 188fd75b91dSJack F Vogel TRUE : FALSE; 189fd75b91dSJack F Vogel else 190fd75b91dSJack F Vogel supported = TRUE; 1918eb6488eSEric Joyner } 1928eb6488eSEric Joyner 193fd75b91dSJack F Vogel break; 194fd75b91dSJack F Vogel case ixgbe_media_type_backplane: 1958eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) 1968eb6488eSEric Joyner supported = FALSE; 1978eb6488eSEric Joyner else 198fd75b91dSJack F Vogel supported = TRUE; 199fd75b91dSJack F Vogel break; 200fd75b91dSJack F Vogel case ixgbe_media_type_copper: 201fd75b91dSJack F Vogel /* only some copper devices support flow control autoneg */ 202a621e3c8SJack F Vogel switch (hw->device_id) { 203a621e3c8SJack F Vogel case IXGBE_DEV_ID_82599_T3_LOM: 2040ecc2ff0SJack F Vogel case IXGBE_DEV_ID_X540T: 205758cc3dcSJack F Vogel case IXGBE_DEV_ID_X540T1: 206fd75b91dSJack F Vogel case IXGBE_DEV_ID_X540_BYPASS: 207758cc3dcSJack F Vogel case IXGBE_DEV_ID_X550T: 208a9ca1c79SSean Bruno case IXGBE_DEV_ID_X550T1: 2096f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T: 2108eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T: 2118eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T: 2128eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L: 213fd75b91dSJack F Vogel supported = TRUE; 214fd75b91dSJack F Vogel break; 215a621e3c8SJack F Vogel default: 216fd75b91dSJack F Vogel supported = FALSE; 217a621e3c8SJack F Vogel } 218fd75b91dSJack F Vogel default: 219fd75b91dSJack F Vogel break; 220fd75b91dSJack F Vogel } 221fd75b91dSJack F Vogel 2228eb6488eSEric Joyner if (!supported) 223fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, 224fd75b91dSJack F Vogel "Device %x does not support flow control autoneg", 225fd75b91dSJack F Vogel hw->device_id); 226c19c7afeSEric Joyner 227fd75b91dSJack F Vogel return supported; 228a621e3c8SJack F Vogel } 229a621e3c8SJack F Vogel 230a621e3c8SJack F Vogel /** 231758cc3dcSJack F Vogel * ixgbe_setup_fc_generic - Set up flow control 232a621e3c8SJack F Vogel * @hw: pointer to hardware structure 233a621e3c8SJack F Vogel * 234a621e3c8SJack F Vogel * Called at init time to set up flow control. 235a621e3c8SJack F Vogel **/ 236758cc3dcSJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 237a621e3c8SJack F Vogel { 238a621e3c8SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 239a621e3c8SJack F Vogel u32 reg = 0, reg_bp = 0; 240a621e3c8SJack F Vogel u16 reg_cu = 0; 241758cc3dcSJack F Vogel bool locked = FALSE; 242a621e3c8SJack F Vogel 243758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_fc_generic"); 244a621e3c8SJack F Vogel 245758cc3dcSJack F Vogel /* Validate the requested mode */ 246a621e3c8SJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 247fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 248fd75b91dSJack F Vogel "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 249a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 250a621e3c8SJack F Vogel goto out; 251a621e3c8SJack F Vogel } 252a621e3c8SJack F Vogel 253a621e3c8SJack F Vogel /* 254a621e3c8SJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 255a621e3c8SJack F Vogel * default flow control setting, so we explicitly set it to full. 256a621e3c8SJack F Vogel */ 257a621e3c8SJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 258a621e3c8SJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 259a621e3c8SJack F Vogel 260a621e3c8SJack F Vogel /* 261a621e3c8SJack F Vogel * Set up the 1G and 10G flow control advertisement registers so the 262a621e3c8SJack F Vogel * HW will be able to do fc autoneg once the cable is plugged in. If 263a621e3c8SJack F Vogel * we link at 10G, the 1G advertisement is harmless and vice versa. 264a621e3c8SJack F Vogel */ 265a621e3c8SJack F Vogel switch (hw->phy.media_type) { 266a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 267758cc3dcSJack F Vogel /* some MAC's need RMW protection on AUTOC */ 268758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 269758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 270758cc3dcSJack F Vogel goto out; 271758cc3dcSJack F Vogel 272be9f17dbSToomas Soome /* only backplane uses autoc */ 273be9f17dbSToomas Soome /* FALLTHROUGH */ 274758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 275758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 276758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 277a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 278758cc3dcSJack F Vogel 279a621e3c8SJack F Vogel break; 280a621e3c8SJack F Vogel case ixgbe_media_type_copper: 281a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 282a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); 283a621e3c8SJack F Vogel break; 284a621e3c8SJack F Vogel default: 285a621e3c8SJack F Vogel break; 286a621e3c8SJack F Vogel } 287a621e3c8SJack F Vogel 288a621e3c8SJack F Vogel /* 289a621e3c8SJack F Vogel * The possible values of fc.requested_mode are: 290a621e3c8SJack F Vogel * 0: Flow control is completely disabled 291a621e3c8SJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 292a621e3c8SJack F Vogel * but not send pause frames). 293a621e3c8SJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 294a621e3c8SJack F Vogel * we do not support receiving pause frames). 295a621e3c8SJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 296a621e3c8SJack F Vogel * other: Invalid. 297a621e3c8SJack F Vogel */ 298a621e3c8SJack F Vogel switch (hw->fc.requested_mode) { 299a621e3c8SJack F Vogel case ixgbe_fc_none: 300a621e3c8SJack F Vogel /* Flow control completely disabled by software override. */ 301a621e3c8SJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 302a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 303a621e3c8SJack F Vogel reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 304a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE); 305a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 306a621e3c8SJack F Vogel reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 307a621e3c8SJack F Vogel break; 308a621e3c8SJack F Vogel case ixgbe_fc_tx_pause: 309a621e3c8SJack F Vogel /* 310a621e3c8SJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 311a621e3c8SJack F Vogel * disabled by software override. 312a621e3c8SJack F Vogel */ 313a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_ASM_PAUSE; 314a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 315a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 316a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 317a621e3c8SJack F Vogel reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 318a621e3c8SJack F Vogel } else if (hw->phy.media_type == ixgbe_media_type_copper) { 319a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_ASM_PAUSE; 320a621e3c8SJack F Vogel reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 321a621e3c8SJack F Vogel } 322a621e3c8SJack F Vogel break; 323a621e3c8SJack F Vogel case ixgbe_fc_rx_pause: 324a621e3c8SJack F Vogel /* 325a621e3c8SJack F Vogel * Rx Flow control is enabled and Tx Flow control is 326a621e3c8SJack F Vogel * disabled by software override. Since there really 327a621e3c8SJack F Vogel * isn't a way to advertise that we are capable of RX 328a621e3c8SJack F Vogel * Pause ONLY, we will advertise that we support both 329a621e3c8SJack F Vogel * symmetric and asymmetric Rx PAUSE, as such we fall 330a621e3c8SJack F Vogel * through to the fc_full statement. Later, we will 331a621e3c8SJack F Vogel * disable the adapter's ability to send PAUSE frames. 332a621e3c8SJack F Vogel */ 333a621e3c8SJack F Vogel case ixgbe_fc_full: 334a621e3c8SJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 335a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 336a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 337a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 338a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE; 339a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 340a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 341a621e3c8SJack F Vogel break; 342a621e3c8SJack F Vogel default: 343fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 344fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 345a621e3c8SJack F Vogel ret_val = IXGBE_ERR_CONFIG; 346a621e3c8SJack F Vogel goto out; 347a621e3c8SJack F Vogel break; 348a621e3c8SJack F Vogel } 349a621e3c8SJack F Vogel 350758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_X540) { 351a621e3c8SJack F Vogel /* 352a621e3c8SJack F Vogel * Enable auto-negotiation between the MAC & PHY; 353a621e3c8SJack F Vogel * the MAC will advertise clause 37 flow control. 354a621e3c8SJack F Vogel */ 355a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 356a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 357a621e3c8SJack F Vogel 358a621e3c8SJack F Vogel /* Disable AN timeout */ 359a621e3c8SJack F Vogel if (hw->fc.strict_ieee) 360a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 361a621e3c8SJack F Vogel 362a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 363a621e3c8SJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 364a621e3c8SJack F Vogel } 365a621e3c8SJack F Vogel 366a621e3c8SJack F Vogel /* 367a621e3c8SJack F Vogel * AUTOC restart handles negotiation of 1G and 10G on backplane 368a621e3c8SJack F Vogel * and copper. There is no need to set the PCS1GCTL register. 369a621e3c8SJack F Vogel * 370a621e3c8SJack F Vogel */ 371a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 372a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_AN_RESTART; 373758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 374758cc3dcSJack F Vogel if (ret_val) 3750ecc2ff0SJack F Vogel goto out; 376a621e3c8SJack F Vogel } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 377fd75b91dSJack F Vogel (ixgbe_device_supports_autoneg_fc(hw))) { 378a621e3c8SJack F Vogel hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 379a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); 380a621e3c8SJack F Vogel } 381a621e3c8SJack F Vogel 382758cc3dcSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 383a621e3c8SJack F Vogel out: 384a621e3c8SJack F Vogel return ret_val; 385a621e3c8SJack F Vogel } 386a621e3c8SJack F Vogel 387a621e3c8SJack F Vogel /** 3889ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 38913705f88SJack F Vogel * @hw: pointer to hardware structure 39013705f88SJack F Vogel * 39113705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 39213705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 39313705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 39413705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 39513705f88SJack F Vogel **/ 39613705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 39713705f88SJack F Vogel { 398a621e3c8SJack F Vogel s32 ret_val; 39913705f88SJack F Vogel u32 ctrl_ext; 4008eb6488eSEric Joyner u16 device_caps; 40113705f88SJack F Vogel 4022969bf0eSJack F Vogel DEBUGFUNC("ixgbe_start_hw_generic"); 4032969bf0eSJack F Vogel 40413705f88SJack F Vogel /* Set the media type */ 4059ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 40613705f88SJack F Vogel 4070ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 40813705f88SJack F Vogel 40913705f88SJack F Vogel /* Clear the VLAN filter table */ 4109ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 41113705f88SJack F Vogel 41213705f88SJack F Vogel /* Clear statistics registers */ 4139ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 41413705f88SJack F Vogel 41513705f88SJack F Vogel /* Set No Snoop Disable */ 41613705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 41713705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 41813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 4199ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 42013705f88SJack F Vogel 4210ac6dfecSJack F Vogel /* Setup flow control */ 422a621e3c8SJack F Vogel ret_val = ixgbe_setup_fc(hw); 4238eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) { 4248eb6488eSEric Joyner DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val); 4258eb6488eSEric Joyner return ret_val; 4268eb6488eSEric Joyner } 4278eb6488eSEric Joyner 4288eb6488eSEric Joyner /* Cache bit indicating need for crosstalk fix */ 4298eb6488eSEric Joyner switch (hw->mac.type) { 4308eb6488eSEric Joyner case ixgbe_mac_82599EB: 4318eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4328eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4338eb6488eSEric Joyner hw->mac.ops.get_device_caps(hw, &device_caps); 4348eb6488eSEric Joyner if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) 4358eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 4368eb6488eSEric Joyner else 4378eb6488eSEric Joyner hw->need_crosstalk_fix = TRUE; 4388eb6488eSEric Joyner break; 4398eb6488eSEric Joyner default: 4408eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 4418eb6488eSEric Joyner break; 4428eb6488eSEric Joyner } 4430ac6dfecSJack F Vogel 44413705f88SJack F Vogel /* Clear adapter stopped flag */ 44513705f88SJack F Vogel hw->adapter_stopped = FALSE; 44613705f88SJack F Vogel 4478eb6488eSEric Joyner return IXGBE_SUCCESS; 4481a4e3449SJack F Vogel } 4491a4e3449SJack F Vogel 4501a4e3449SJack F Vogel /** 4511a4e3449SJack F Vogel * ixgbe_start_hw_gen2 - Init sequence for common device family 4521a4e3449SJack F Vogel * @hw: pointer to hw structure 4531a4e3449SJack F Vogel * 4541a4e3449SJack F Vogel * Performs the init sequence common to the second generation 4551a4e3449SJack F Vogel * of 10 GbE devices. 4561a4e3449SJack F Vogel * Devices in the second generation: 4571a4e3449SJack F Vogel * 82599 458182b3808SJack F Vogel * X540 4591a4e3449SJack F Vogel **/ 4601a4e3449SJack F Vogel s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 4611a4e3449SJack F Vogel { 4621a4e3449SJack F Vogel u32 i; 4631a4e3449SJack F Vogel u32 regval; 4641a4e3449SJack F Vogel 4651a4e3449SJack F Vogel /* Clear the rate limiters */ 4661a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4671a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 4681a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 4691a4e3449SJack F Vogel } 4701a4e3449SJack F Vogel IXGBE_WRITE_FLUSH(hw); 4711a4e3449SJack F Vogel 4721a4e3449SJack F Vogel /* Disable relaxed ordering */ 4731a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4741a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 475a621e3c8SJack F Vogel regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4761a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4771a4e3449SJack F Vogel } 4781a4e3449SJack F Vogel 4791a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4801a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 481a621e3c8SJack F Vogel regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | 482a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN); 4831a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4841a4e3449SJack F Vogel } 4851a4e3449SJack F Vogel 4861a4e3449SJack F Vogel return IXGBE_SUCCESS; 48713705f88SJack F Vogel } 48813705f88SJack F Vogel 48913705f88SJack F Vogel /** 49013705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 49113705f88SJack F Vogel * @hw: pointer to hardware structure 49213705f88SJack F Vogel * 4939ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 49413705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 49513705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 49613705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 49713705f88SJack F Vogel * disabled and uninitialized 49813705f88SJack F Vogel **/ 49913705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 50013705f88SJack F Vogel { 5011a4e3449SJack F Vogel s32 status; 5020ac6dfecSJack F Vogel 5032969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 5042969bf0eSJack F Vogel 50513705f88SJack F Vogel /* Reset the hardware */ 5060ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 50713705f88SJack F Vogel 5088eb6488eSEric Joyner if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { 50913705f88SJack F Vogel /* Start the HW */ 5100ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 5110ac6dfecSJack F Vogel } 51213705f88SJack F Vogel 5138eb6488eSEric Joyner /* Initialize the LED link active for LED blink support */ 5148eb6488eSEric Joyner if (hw->mac.ops.init_led_link_act) 5158eb6488eSEric Joyner hw->mac.ops.init_led_link_act(hw); 5168eb6488eSEric Joyner 5178eb6488eSEric Joyner if (status != IXGBE_SUCCESS) 5188eb6488eSEric Joyner DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); 5198eb6488eSEric Joyner 5200ac6dfecSJack F Vogel return status; 52113705f88SJack F Vogel } 52213705f88SJack F Vogel 52313705f88SJack F Vogel /** 52413705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 52513705f88SJack F Vogel * @hw: pointer to hardware structure 52613705f88SJack F Vogel * 52713705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 52813705f88SJack F Vogel * Statistics counters are clear on read. 52913705f88SJack F Vogel **/ 53013705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 53113705f88SJack F Vogel { 53213705f88SJack F Vogel u16 i = 0; 53313705f88SJack F Vogel 5342969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 5352969bf0eSJack F Vogel 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 53713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 53813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 53913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 54013705f88SJack F Vogel for (i = 0; i < 8; i++) 54113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 54213705f88SJack F Vogel 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 54513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 54613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 54713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 5480ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5490ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5500ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5510ac6dfecSJack F Vogel } else { 5521b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 55313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5540ac6dfecSJack F Vogel } 55513705f88SJack F Vogel 55613705f88SJack F Vogel for (i = 0; i < 8; i++) { 55713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 55813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5590ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5600ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5610ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5620ac6dfecSJack F Vogel } else { 5631b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 56413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 56513705f88SJack F Vogel } 5660ac6dfecSJack F Vogel } 5670ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5680ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5690ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 57013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 57113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 57213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 57313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 57413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 57513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 57613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 57713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 57813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 57913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 58013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 58113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 58213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 58313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 58485d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 58513705f88SJack F Vogel for (i = 0; i < 8; i++) 58613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 58713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 58813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 58913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 59013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 59113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 59213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 59313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 59413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 59513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 59613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 59713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 59813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 59913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 60013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 60113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 60213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 60313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 60413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 60513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 60613705f88SJack F Vogel for (i = 0; i < 16; i++) { 60713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 60813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 6091a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 6101a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 6111a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 6121a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 6131a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 6141a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 6151a4e3449SJack F Vogel } else { 6161a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 61713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 61813705f88SJack F Vogel } 6191a4e3449SJack F Vogel } 6201a4e3449SJack F Vogel 621758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 62285d0a26eSJack F Vogel if (hw->phy.id == 0) 62385d0a26eSJack F Vogel ixgbe_identify_phy(hw); 62485d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 62585d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62685d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 62785d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62885d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 62985d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 63085d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 63185d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 63285d0a26eSJack F Vogel } 63385d0a26eSJack F Vogel 6341a4e3449SJack F Vogel return IXGBE_SUCCESS; 6351a4e3449SJack F Vogel } 6361a4e3449SJack F Vogel 6371a4e3449SJack F Vogel /** 6381a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 6391a4e3449SJack F Vogel * @hw: pointer to hardware structure 6401a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 6411a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 6421a4e3449SJack F Vogel * 6431a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 6441a4e3449SJack F Vogel **/ 6451a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 6461a4e3449SJack F Vogel u32 pba_num_size) 6471a4e3449SJack F Vogel { 6481a4e3449SJack F Vogel s32 ret_val; 6491a4e3449SJack F Vogel u16 data; 6501a4e3449SJack F Vogel u16 pba_ptr; 6511a4e3449SJack F Vogel u16 offset; 6521a4e3449SJack F Vogel u16 length; 6531a4e3449SJack F Vogel 6541a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6551a4e3449SJack F Vogel 6561a4e3449SJack F Vogel if (pba_num == NULL) { 6571a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6581a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6591a4e3449SJack F Vogel } 6601a4e3449SJack F Vogel 6611a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6621a4e3449SJack F Vogel if (ret_val) { 6631a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6641a4e3449SJack F Vogel return ret_val; 6651a4e3449SJack F Vogel } 6661a4e3449SJack F Vogel 6671a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6681a4e3449SJack F Vogel if (ret_val) { 6691a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6701a4e3449SJack F Vogel return ret_val; 6711a4e3449SJack F Vogel } 6721a4e3449SJack F Vogel 6731a4e3449SJack F Vogel /* 6741a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6751a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6761a4e3449SJack F Vogel * and we can decode it into an ascii string 6771a4e3449SJack F Vogel */ 6781a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6791a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6801a4e3449SJack F Vogel 6811a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6821a4e3449SJack F Vogel if (pba_num_size < 11) { 6831a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6841a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6851a4e3449SJack F Vogel } 6861a4e3449SJack F Vogel 6871a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6881a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6891a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6901a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6911a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6921a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6931a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6941a4e3449SJack F Vogel pba_num[6] = '-'; 6951a4e3449SJack F Vogel pba_num[7] = 0; 6961a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6971a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6981a4e3449SJack F Vogel 6991a4e3449SJack F Vogel /* put a null character on the end of our string */ 7001a4e3449SJack F Vogel pba_num[10] = '\0'; 7011a4e3449SJack F Vogel 7021a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 7031a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 7041a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 7051a4e3449SJack F Vogel pba_num[offset] += '0'; 7061a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 7071a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 7081a4e3449SJack F Vogel } 7091a4e3449SJack F Vogel 7101a4e3449SJack F Vogel return IXGBE_SUCCESS; 7111a4e3449SJack F Vogel } 7121a4e3449SJack F Vogel 7131a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 7141a4e3449SJack F Vogel if (ret_val) { 7151a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7161a4e3449SJack F Vogel return ret_val; 7171a4e3449SJack F Vogel } 7181a4e3449SJack F Vogel 7191a4e3449SJack F Vogel if (length == 0xFFFF || length == 0) { 7201a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 7211a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 7221a4e3449SJack F Vogel } 7231a4e3449SJack F Vogel 7241a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 7251a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 7261a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 7271a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 7281a4e3449SJack F Vogel } 7291a4e3449SJack F Vogel 7301a4e3449SJack F Vogel /* trim pba length from start of string */ 7311a4e3449SJack F Vogel pba_ptr++; 7321a4e3449SJack F Vogel length--; 7331a4e3449SJack F Vogel 7341a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 7351a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 7361a4e3449SJack F Vogel if (ret_val) { 7371a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7381a4e3449SJack F Vogel return ret_val; 7391a4e3449SJack F Vogel } 7401a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 7411a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 7421a4e3449SJack F Vogel } 7431a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 7441a4e3449SJack F Vogel 7451a4e3449SJack F Vogel return IXGBE_SUCCESS; 7461a4e3449SJack F Vogel } 7471a4e3449SJack F Vogel 7481a4e3449SJack F Vogel /** 7491b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7509ca4041bSJack F Vogel * @hw: pointer to hardware structure 7519ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7529ca4041bSJack F Vogel * 7539ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7549ca4041bSJack F Vogel **/ 7559ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7569ca4041bSJack F Vogel { 7579ca4041bSJack F Vogel s32 ret_val; 7589ca4041bSJack F Vogel u16 data; 7599ca4041bSJack F Vogel 7609ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7619ca4041bSJack F Vogel 7629ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7639ca4041bSJack F Vogel if (ret_val) { 7649ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7659ca4041bSJack F Vogel return ret_val; 7661a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7671a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7681a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7699ca4041bSJack F Vogel } 7709ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7719ca4041bSJack F Vogel 7729ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7739ca4041bSJack F Vogel if (ret_val) { 7749ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7759ca4041bSJack F Vogel return ret_val; 7769ca4041bSJack F Vogel } 7779ca4041bSJack F Vogel *pba_num |= data; 7789ca4041bSJack F Vogel 7799ca4041bSJack F Vogel return IXGBE_SUCCESS; 7809ca4041bSJack F Vogel } 7819ca4041bSJack F Vogel 7829ca4041bSJack F Vogel /** 7830ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7840ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7850ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7860ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7870ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7880ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7890ecc2ff0SJack F Vogel * 7900ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7910ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7920ecc2ff0SJack F Vogel * 7930ecc2ff0SJack F Vogel **/ 7940ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7950ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7960ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7970ecc2ff0SJack F Vogel { 7980ecc2ff0SJack F Vogel s32 ret_val; 7990ecc2ff0SJack F Vogel u16 pba_block_size; 8000ecc2ff0SJack F Vogel 8010ecc2ff0SJack F Vogel if (pba == NULL) 8020ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8030ecc2ff0SJack F Vogel 8040ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8050ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8060ecc2ff0SJack F Vogel &pba->word[0]); 8070ecc2ff0SJack F Vogel if (ret_val) 8080ecc2ff0SJack F Vogel return ret_val; 8090ecc2ff0SJack F Vogel } else { 8100ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8110ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8120ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8130ecc2ff0SJack F Vogel } else { 8140ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8150ecc2ff0SJack F Vogel } 8160ecc2ff0SJack F Vogel } 8170ecc2ff0SJack F Vogel 8180ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8190ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8200ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8210ecc2ff0SJack F Vogel 8220ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 8230ecc2ff0SJack F Vogel eeprom_buf_size, 8240ecc2ff0SJack F Vogel &pba_block_size); 8250ecc2ff0SJack F Vogel if (ret_val) 8260ecc2ff0SJack F Vogel return ret_val; 8270ecc2ff0SJack F Vogel 8280ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 8290ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8300ecc2ff0SJack F Vogel 8310ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8320ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 8330ecc2ff0SJack F Vogel pba_block_size, 8340ecc2ff0SJack F Vogel pba->pba_block); 8350ecc2ff0SJack F Vogel if (ret_val) 8360ecc2ff0SJack F Vogel return ret_val; 8370ecc2ff0SJack F Vogel } else { 8380ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 839758cc3dcSJack F Vogel pba_block_size)) { 8400ecc2ff0SJack F Vogel memcpy(pba->pba_block, 8410ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 8420ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 8430ecc2ff0SJack F Vogel } else { 8440ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8450ecc2ff0SJack F Vogel } 8460ecc2ff0SJack F Vogel } 8470ecc2ff0SJack F Vogel } 8480ecc2ff0SJack F Vogel 8490ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8500ecc2ff0SJack F Vogel } 8510ecc2ff0SJack F Vogel 8520ecc2ff0SJack F Vogel /** 8530ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8540ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8550ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8560ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8570ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8580ecc2ff0SJack F Vogel * 8590ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8600ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8610ecc2ff0SJack F Vogel * 8620ecc2ff0SJack F Vogel **/ 8630ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8640ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8650ecc2ff0SJack F Vogel { 8660ecc2ff0SJack F Vogel s32 ret_val; 8670ecc2ff0SJack F Vogel 8680ecc2ff0SJack F Vogel if (pba == NULL) 8690ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8700ecc2ff0SJack F Vogel 8710ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8720ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8730ecc2ff0SJack F Vogel &pba->word[0]); 8740ecc2ff0SJack F Vogel if (ret_val) 8750ecc2ff0SJack F Vogel return ret_val; 8760ecc2ff0SJack F Vogel } else { 8770ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8780ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8790ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8800ecc2ff0SJack F Vogel } else { 8810ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8820ecc2ff0SJack F Vogel } 8830ecc2ff0SJack F Vogel } 8840ecc2ff0SJack F Vogel 8850ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8860ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8870ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8880ecc2ff0SJack F Vogel 8890ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8900ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8910ecc2ff0SJack F Vogel pba->pba_block[0], 8920ecc2ff0SJack F Vogel pba->pba_block); 8930ecc2ff0SJack F Vogel if (ret_val) 8940ecc2ff0SJack F Vogel return ret_val; 8950ecc2ff0SJack F Vogel } else { 8960ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8970ecc2ff0SJack F Vogel pba->pba_block[0])) { 8980ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8990ecc2ff0SJack F Vogel pba->pba_block, 9000ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 9010ecc2ff0SJack F Vogel } else { 9020ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9030ecc2ff0SJack F Vogel } 9040ecc2ff0SJack F Vogel } 9050ecc2ff0SJack F Vogel } 9060ecc2ff0SJack F Vogel 9070ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9080ecc2ff0SJack F Vogel } 9090ecc2ff0SJack F Vogel 9100ecc2ff0SJack F Vogel /** 9110ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 9120ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 9130ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 9140ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 9150ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 9160ecc2ff0SJack F Vogel * 9170ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 9180ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 9190ecc2ff0SJack F Vogel * EEPROM device. 9200ecc2ff0SJack F Vogel * 9210ecc2ff0SJack F Vogel **/ 9220ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 9230ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 9240ecc2ff0SJack F Vogel { 9250ecc2ff0SJack F Vogel s32 ret_val; 9260ecc2ff0SJack F Vogel u16 pba_word[2]; 9270ecc2ff0SJack F Vogel u16 length; 9280ecc2ff0SJack F Vogel 9290ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 9300ecc2ff0SJack F Vogel 9310ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9320ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 9330ecc2ff0SJack F Vogel &pba_word[0]); 9340ecc2ff0SJack F Vogel if (ret_val) 9350ecc2ff0SJack F Vogel return ret_val; 9360ecc2ff0SJack F Vogel } else { 9370ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 9380ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 9390ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 9400ecc2ff0SJack F Vogel } else { 9410ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9420ecc2ff0SJack F Vogel } 9430ecc2ff0SJack F Vogel } 9440ecc2ff0SJack F Vogel 9450ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 9460ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9470ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 9480ecc2ff0SJack F Vogel &length); 9490ecc2ff0SJack F Vogel if (ret_val) 9500ecc2ff0SJack F Vogel return ret_val; 9510ecc2ff0SJack F Vogel } else { 9520ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9530ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9540ecc2ff0SJack F Vogel else 9550ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9560ecc2ff0SJack F Vogel } 9570ecc2ff0SJack F Vogel 9580ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9590ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9600ecc2ff0SJack F Vogel } else { 9610ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9620ecc2ff0SJack F Vogel length = 0; 9630ecc2ff0SJack F Vogel } 9640ecc2ff0SJack F Vogel 9650ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9660ecc2ff0SJack F Vogel *pba_block_size = length; 9670ecc2ff0SJack F Vogel 9680ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9690ecc2ff0SJack F Vogel } 9700ecc2ff0SJack F Vogel 9710ecc2ff0SJack F Vogel /** 97213705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 97313705f88SJack F Vogel * @hw: pointer to hardware structure 97413705f88SJack F Vogel * @mac_addr: Adapter MAC address 97513705f88SJack F Vogel * 97613705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 97713705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 97813705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 97913705f88SJack F Vogel **/ 98013705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 98113705f88SJack F Vogel { 98213705f88SJack F Vogel u32 rar_high; 98313705f88SJack F Vogel u32 rar_low; 98413705f88SJack F Vogel u16 i; 98513705f88SJack F Vogel 9862969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9872969bf0eSJack F Vogel 98813705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 98913705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 99013705f88SJack F Vogel 99113705f88SJack F Vogel for (i = 0; i < 4; i++) 99213705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 99313705f88SJack F Vogel 99413705f88SJack F Vogel for (i = 0; i < 2; i++) 99513705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 99613705f88SJack F Vogel 99713705f88SJack F Vogel return IXGBE_SUCCESS; 99813705f88SJack F Vogel } 99913705f88SJack F Vogel 100013705f88SJack F Vogel /** 1001fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 100213705f88SJack F Vogel * @hw: pointer to hardware structure 1003fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 100413705f88SJack F Vogel * 1005fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 100613705f88SJack F Vogel **/ 1007fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 100813705f88SJack F Vogel { 10091b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 10102969bf0eSJack F Vogel 1011758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 101213705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 101313705f88SJack F Vogel 101413705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 101513705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 101613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 101713705f88SJack F Vogel break; 101813705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 101913705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 102013705f88SJack F Vogel break; 102113705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 102213705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 102313705f88SJack F Vogel break; 102413705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 102513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 102613705f88SJack F Vogel break; 102713705f88SJack F Vogel default: 102813705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 102913705f88SJack F Vogel break; 103013705f88SJack F Vogel } 103113705f88SJack F Vogel 103213705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 103313705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 103413705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 103513705f88SJack F Vogel break; 103613705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 103713705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 103813705f88SJack F Vogel break; 1039a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 1040a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 1041a621e3c8SJack F Vogel break; 104213705f88SJack F Vogel default: 104313705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 104413705f88SJack F Vogel break; 104513705f88SJack F Vogel } 104613705f88SJack F Vogel 10471b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 1048fd75b91dSJack F Vogel } 1049fd75b91dSJack F Vogel 1050fd75b91dSJack F Vogel /** 1051fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1052fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1053fd75b91dSJack F Vogel * 1054fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1055fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1056fd75b91dSJack F Vogel **/ 1057fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1058fd75b91dSJack F Vogel { 1059fd75b91dSJack F Vogel u16 link_status; 1060fd75b91dSJack F Vogel 1061fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1062fd75b91dSJack F Vogel 1063fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1064fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1065fd75b91dSJack F Vogel 1066fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10671b6e0dbaSJack F Vogel 106813705f88SJack F Vogel return IXGBE_SUCCESS; 106913705f88SJack F Vogel } 107013705f88SJack F Vogel 107113705f88SJack F Vogel /** 10721b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10731b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10741b6e0dbaSJack F Vogel * 10758eb6488eSEric Joyner * Determines the LAN function id by reading memory-mapped registers and swaps 10768eb6488eSEric Joyner * the port value if requested, and set MAC instance for devices that share 10778eb6488eSEric Joyner * CS4227. 10781b6e0dbaSJack F Vogel **/ 10791b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10801b6e0dbaSJack F Vogel { 10811b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10821b6e0dbaSJack F Vogel u32 reg; 10838eb6488eSEric Joyner u16 ee_ctrl_4; 10841b6e0dbaSJack F Vogel 10852969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10862969bf0eSJack F Vogel 10871b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10881b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 10898eb6488eSEric Joyner bus->lan_id = (u8)bus->func; 10901b6e0dbaSJack F Vogel 10911b6e0dbaSJack F Vogel /* check for a port swap */ 1092a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 10931b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10941b6e0dbaSJack F Vogel bus->func ^= 0x1; 10958eb6488eSEric Joyner 10968eb6488eSEric Joyner /* Get MAC instance from EEPROM for configuring CS4227 */ 10978eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 10988eb6488eSEric Joyner hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 10998eb6488eSEric Joyner bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 11008eb6488eSEric Joyner IXGBE_EE_CTRL_4_INST_ID_SHIFT; 11018eb6488eSEric Joyner } 11021b6e0dbaSJack F Vogel } 11031b6e0dbaSJack F Vogel 11041b6e0dbaSJack F Vogel /** 11059ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 110613705f88SJack F Vogel * @hw: pointer to hardware structure 110713705f88SJack F Vogel * 110813705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 110913705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 111013705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 111113705f88SJack F Vogel * state and should not touch the hardware. 111213705f88SJack F Vogel **/ 111313705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 111413705f88SJack F Vogel { 111513705f88SJack F Vogel u32 reg_val; 111613705f88SJack F Vogel u16 i; 111713705f88SJack F Vogel 11182969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 11192969bf0eSJack F Vogel 112013705f88SJack F Vogel /* 112113705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 112213705f88SJack F Vogel * the hardware 112313705f88SJack F Vogel */ 112413705f88SJack F Vogel hw->adapter_stopped = TRUE; 112513705f88SJack F Vogel 112613705f88SJack F Vogel /* Disable the receive unit */ 1127758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 112813705f88SJack F Vogel 112985d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 113013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 113113705f88SJack F Vogel 113285d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 113313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 113413705f88SJack F Vogel 113513705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 113685d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 113785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 113885d0a26eSJack F Vogel 113985d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 114085d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 114185d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 114285d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 114385d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 114485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 114513705f88SJack F Vogel } 114685d0a26eSJack F Vogel 114785d0a26eSJack F Vogel /* flush all queues disables */ 114885d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 114985d0a26eSJack F Vogel msec_delay(2); 115013705f88SJack F Vogel 11519ca4041bSJack F Vogel /* 11526f37f232SEric Joyner * Prevent the PCI-E bus from hanging by disabling PCI-E master 11539ca4041bSJack F Vogel * access and verify no pending requests 11549ca4041bSJack F Vogel */ 115585d0a26eSJack F Vogel return ixgbe_disable_pcie_master(hw); 115613705f88SJack F Vogel } 115713705f88SJack F Vogel 115813705f88SJack F Vogel /** 11598eb6488eSEric Joyner * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 11608eb6488eSEric Joyner * @hw: pointer to hardware structure 11618eb6488eSEric Joyner * 11628eb6488eSEric Joyner * Store the index for the link active LED. This will be used to support 11638eb6488eSEric Joyner * blinking the LED. 11648eb6488eSEric Joyner **/ 11658eb6488eSEric Joyner s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 11668eb6488eSEric Joyner { 11678eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac; 11688eb6488eSEric Joyner u32 led_reg, led_mode; 11698eb6488eSEric Joyner u8 i; 11708eb6488eSEric Joyner 11718eb6488eSEric Joyner led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 11728eb6488eSEric Joyner 11738eb6488eSEric Joyner /* Get LED link active from the LEDCTL register */ 11748eb6488eSEric Joyner for (i = 0; i < 4; i++) { 11758eb6488eSEric Joyner led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 11768eb6488eSEric Joyner 11778eb6488eSEric Joyner if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 11788eb6488eSEric Joyner IXGBE_LED_LINK_ACTIVE) { 11798eb6488eSEric Joyner mac->led_link_act = i; 11808eb6488eSEric Joyner return IXGBE_SUCCESS; 11818eb6488eSEric Joyner } 11828eb6488eSEric Joyner } 11838eb6488eSEric Joyner 11848eb6488eSEric Joyner /* 11858eb6488eSEric Joyner * If LEDCTL register does not have the LED link active set, then use 11868eb6488eSEric Joyner * known MAC defaults. 11878eb6488eSEric Joyner */ 11888eb6488eSEric Joyner switch (hw->mac.type) { 11898eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 11908eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 11918eb6488eSEric Joyner mac->led_link_act = 1; 11928eb6488eSEric Joyner break; 11938eb6488eSEric Joyner default: 11948eb6488eSEric Joyner mac->led_link_act = 2; 11958eb6488eSEric Joyner } 11968eb6488eSEric Joyner return IXGBE_SUCCESS; 11978eb6488eSEric Joyner } 11988eb6488eSEric Joyner 11998eb6488eSEric Joyner /** 120013705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 120113705f88SJack F Vogel * @hw: pointer to hardware structure 120213705f88SJack F Vogel * @index: led number to turn on 120313705f88SJack F Vogel **/ 120413705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 120513705f88SJack F Vogel { 120613705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 120713705f88SJack F Vogel 12082969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 12092969bf0eSJack F Vogel 12108eb6488eSEric Joyner if (index > 3) 12118eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12128eb6488eSEric Joyner 121313705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 121413705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 121513705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 121613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12179ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 121813705f88SJack F Vogel 121913705f88SJack F Vogel return IXGBE_SUCCESS; 122013705f88SJack F Vogel } 122113705f88SJack F Vogel 122213705f88SJack F Vogel /** 122313705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 122413705f88SJack F Vogel * @hw: pointer to hardware structure 122513705f88SJack F Vogel * @index: led number to turn off 122613705f88SJack F Vogel **/ 122713705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 122813705f88SJack F Vogel { 122913705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 123013705f88SJack F Vogel 12312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 12322969bf0eSJack F Vogel 12338eb6488eSEric Joyner if (index > 3) 12348eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12358eb6488eSEric Joyner 123613705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 123713705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 123813705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 123913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12409ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 124113705f88SJack F Vogel 124213705f88SJack F Vogel return IXGBE_SUCCESS; 124313705f88SJack F Vogel } 124413705f88SJack F Vogel 124513705f88SJack F Vogel /** 124613705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 124713705f88SJack F Vogel * @hw: pointer to hardware structure 124813705f88SJack F Vogel * 124913705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 125013705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 125113705f88SJack F Vogel **/ 125213705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 125313705f88SJack F Vogel { 125413705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 125513705f88SJack F Vogel u32 eec; 125613705f88SJack F Vogel u16 eeprom_size; 125713705f88SJack F Vogel 12582969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 12592969bf0eSJack F Vogel 126013705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 126113705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 12625b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 12635b7f4cedSJack F Vogel * tested value */ 12645b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 126585d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 126685d0a26eSJack F Vogel eeprom->word_page_size = 0; 126713705f88SJack F Vogel 126813705f88SJack F Vogel /* 126913705f88SJack F Vogel * Check for EEPROM present first. 127013705f88SJack F Vogel * If not present leave as none 127113705f88SJack F Vogel */ 1272a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 127313705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 127413705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 127513705f88SJack F Vogel 127613705f88SJack F Vogel /* 127713705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 127813705f88SJack F Vogel * change if a future EEPROM is not SPI. 127913705f88SJack F Vogel */ 128013705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 128113705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 128213705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 128385d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 128413705f88SJack F Vogel } 128513705f88SJack F Vogel 128613705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 128713705f88SJack F Vogel eeprom->address_bits = 16; 128813705f88SJack F Vogel else 128913705f88SJack F Vogel eeprom->address_bits = 8; 129013705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 129113705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 129213705f88SJack F Vogel eeprom->address_bits); 129313705f88SJack F Vogel } 129413705f88SJack F Vogel 129513705f88SJack F Vogel return IXGBE_SUCCESS; 129613705f88SJack F Vogel } 129713705f88SJack F Vogel 129813705f88SJack F Vogel /** 129985d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 130085d0a26eSJack F Vogel * @hw: pointer to hardware structure 130185d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 130285d0a26eSJack F Vogel * @words: number of word(s) 130385d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 130485d0a26eSJack F Vogel * 130585d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 130685d0a26eSJack F Vogel **/ 130785d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 130885d0a26eSJack F Vogel u16 words, u16 *data) 130985d0a26eSJack F Vogel { 131085d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 131185d0a26eSJack F Vogel u16 i, count; 131285d0a26eSJack F Vogel 131385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 131485d0a26eSJack F Vogel 131585d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 131685d0a26eSJack F Vogel 131785d0a26eSJack F Vogel if (words == 0) { 131885d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 131985d0a26eSJack F Vogel goto out; 132085d0a26eSJack F Vogel } 132185d0a26eSJack F Vogel 132285d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 132385d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 132485d0a26eSJack F Vogel goto out; 132585d0a26eSJack F Vogel } 132685d0a26eSJack F Vogel 132785d0a26eSJack F Vogel /* 132885d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 132985d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 133085d0a26eSJack F Vogel */ 133185d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 133285d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 133385d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 133485d0a26eSJack F Vogel 133585d0a26eSJack F Vogel /* 133685d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 133785d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 133885d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 133985d0a26eSJack F Vogel */ 134085d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 134185d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 134285d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 134385d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 134485d0a26eSJack F Vogel count, &data[i]); 134585d0a26eSJack F Vogel 134685d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 134785d0a26eSJack F Vogel break; 134885d0a26eSJack F Vogel } 134985d0a26eSJack F Vogel 135085d0a26eSJack F Vogel out: 135185d0a26eSJack F Vogel return status; 135285d0a26eSJack F Vogel } 135385d0a26eSJack F Vogel 135485d0a26eSJack F Vogel /** 135585d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 135613705f88SJack F Vogel * @hw: pointer to hardware structure 135713705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 135885d0a26eSJack F Vogel * @words: number of word(s) 135985d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 136013705f88SJack F Vogel * 136113705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 136213705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 136313705f88SJack F Vogel **/ 136485d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 136585d0a26eSJack F Vogel u16 words, u16 *data) 136613705f88SJack F Vogel { 136713705f88SJack F Vogel s32 status; 136885d0a26eSJack F Vogel u16 word; 136985d0a26eSJack F Vogel u16 page_size; 137085d0a26eSJack F Vogel u16 i; 137113705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 137213705f88SJack F Vogel 137385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 13749ca4041bSJack F Vogel 137513705f88SJack F Vogel /* Prepare the EEPROM for writing */ 137613705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 137713705f88SJack F Vogel 137813705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 137913705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 138013705f88SJack F Vogel ixgbe_release_eeprom(hw); 138113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 138213705f88SJack F Vogel } 138313705f88SJack F Vogel } 138413705f88SJack F Vogel 138513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 138685d0a26eSJack F Vogel for (i = 0; i < words; i++) { 138713705f88SJack F Vogel ixgbe_standby_eeprom(hw); 138813705f88SJack F Vogel 138913705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 139085d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 139185d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 139213705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 139313705f88SJack F Vogel 139413705f88SJack F Vogel ixgbe_standby_eeprom(hw); 139513705f88SJack F Vogel 139613705f88SJack F Vogel /* 139785d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 139885d0a26eSJack F Vogel * in the opcode 139913705f88SJack F Vogel */ 140085d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 140185d0a26eSJack F Vogel ((offset + i) >= 128)) 140213705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 140313705f88SJack F Vogel 140413705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 140513705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 140613705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 140785d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 140813705f88SJack F Vogel hw->eeprom.address_bits); 140913705f88SJack F Vogel 141085d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 141113705f88SJack F Vogel 141285d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 141385d0a26eSJack F Vogel do { 141485d0a26eSJack F Vogel word = data[i]; 141585d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 141685d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 141785d0a26eSJack F Vogel 141885d0a26eSJack F Vogel if (page_size == 0) 141985d0a26eSJack F Vogel break; 142085d0a26eSJack F Vogel 142185d0a26eSJack F Vogel /* do not wrap around page */ 142285d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 142385d0a26eSJack F Vogel (page_size - 1)) 142485d0a26eSJack F Vogel break; 142585d0a26eSJack F Vogel } while (++i < words); 142685d0a26eSJack F Vogel 142785d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 142885d0a26eSJack F Vogel msec_delay(10); 142985d0a26eSJack F Vogel } 143013705f88SJack F Vogel /* Done with writing - release the EEPROM */ 143113705f88SJack F Vogel ixgbe_release_eeprom(hw); 143213705f88SJack F Vogel } 143313705f88SJack F Vogel 143485d0a26eSJack F Vogel return status; 143585d0a26eSJack F Vogel } 143685d0a26eSJack F Vogel 143785d0a26eSJack F Vogel /** 143885d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 143985d0a26eSJack F Vogel * @hw: pointer to hardware structure 144085d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 144185d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 144285d0a26eSJack F Vogel * 144385d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 144485d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 144585d0a26eSJack F Vogel **/ 144685d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 144785d0a26eSJack F Vogel { 144885d0a26eSJack F Vogel s32 status; 144985d0a26eSJack F Vogel 145085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 145185d0a26eSJack F Vogel 145285d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 145385d0a26eSJack F Vogel 145485d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 145585d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 145685d0a26eSJack F Vogel goto out; 145785d0a26eSJack F Vogel } 145885d0a26eSJack F Vogel 145985d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 146085d0a26eSJack F Vogel 14619ca4041bSJack F Vogel out: 146213705f88SJack F Vogel return status; 146313705f88SJack F Vogel } 146413705f88SJack F Vogel 146513705f88SJack F Vogel /** 146685d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 146785d0a26eSJack F Vogel * @hw: pointer to hardware structure 146885d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 146985d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 147085d0a26eSJack F Vogel * @words: number of word(s) 147185d0a26eSJack F Vogel * 147285d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 147385d0a26eSJack F Vogel **/ 147485d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147585d0a26eSJack F Vogel u16 words, u16 *data) 147685d0a26eSJack F Vogel { 147785d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 147885d0a26eSJack F Vogel u16 i, count; 147985d0a26eSJack F Vogel 148085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 148185d0a26eSJack F Vogel 148285d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 148385d0a26eSJack F Vogel 148485d0a26eSJack F Vogel if (words == 0) { 148585d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 148685d0a26eSJack F Vogel goto out; 148785d0a26eSJack F Vogel } 148885d0a26eSJack F Vogel 148985d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 149085d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 149185d0a26eSJack F Vogel goto out; 149285d0a26eSJack F Vogel } 149385d0a26eSJack F Vogel 149485d0a26eSJack F Vogel /* 149585d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 149685d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 149785d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 149885d0a26eSJack F Vogel */ 149985d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 150085d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 150185d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 150285d0a26eSJack F Vogel 150385d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 150485d0a26eSJack F Vogel count, &data[i]); 150585d0a26eSJack F Vogel 150685d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 150785d0a26eSJack F Vogel break; 150885d0a26eSJack F Vogel } 150985d0a26eSJack F Vogel 151085d0a26eSJack F Vogel out: 151185d0a26eSJack F Vogel return status; 151285d0a26eSJack F Vogel } 151385d0a26eSJack F Vogel 151485d0a26eSJack F Vogel /** 151585d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 151685d0a26eSJack F Vogel * @hw: pointer to hardware structure 151785d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 151885d0a26eSJack F Vogel * @words: number of word(s) 151985d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 152085d0a26eSJack F Vogel * 152185d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 152285d0a26eSJack F Vogel **/ 152385d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 152485d0a26eSJack F Vogel u16 words, u16 *data) 152585d0a26eSJack F Vogel { 152685d0a26eSJack F Vogel s32 status; 152785d0a26eSJack F Vogel u16 word_in; 152885d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 152985d0a26eSJack F Vogel u16 i; 153085d0a26eSJack F Vogel 153185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 153285d0a26eSJack F Vogel 153385d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 153485d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 153585d0a26eSJack F Vogel 153685d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 153785d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 153885d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 153985d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 154085d0a26eSJack F Vogel } 154185d0a26eSJack F Vogel } 154285d0a26eSJack F Vogel 154385d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 154485d0a26eSJack F Vogel for (i = 0; i < words; i++) { 154585d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 154685d0a26eSJack F Vogel /* 154785d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 154885d0a26eSJack F Vogel * in the opcode 154985d0a26eSJack F Vogel */ 155085d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 155185d0a26eSJack F Vogel ((offset + i) >= 128)) 155285d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 155385d0a26eSJack F Vogel 155485d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 155585d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 155685d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 155785d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 155885d0a26eSJack F Vogel hw->eeprom.address_bits); 155985d0a26eSJack F Vogel 156085d0a26eSJack F Vogel /* Read the data. */ 156185d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 156285d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 156385d0a26eSJack F Vogel } 156485d0a26eSJack F Vogel 156585d0a26eSJack F Vogel /* End this read operation */ 156685d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 156785d0a26eSJack F Vogel } 156885d0a26eSJack F Vogel 156985d0a26eSJack F Vogel return status; 157085d0a26eSJack F Vogel } 157185d0a26eSJack F Vogel 157285d0a26eSJack F Vogel /** 157313705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 157413705f88SJack F Vogel * @hw: pointer to hardware structure 157513705f88SJack F Vogel * @offset: offset within the EEPROM to be read 157613705f88SJack F Vogel * @data: read 16 bit value from EEPROM 157713705f88SJack F Vogel * 157813705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 157913705f88SJack F Vogel **/ 158013705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 158113705f88SJack F Vogel u16 *data) 158213705f88SJack F Vogel { 158313705f88SJack F Vogel s32 status; 158413705f88SJack F Vogel 15852969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 15862969bf0eSJack F Vogel 15879ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 15889ca4041bSJack F Vogel 15899ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 15909ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 15919ca4041bSJack F Vogel goto out; 15929ca4041bSJack F Vogel } 15939ca4041bSJack F Vogel 159485d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 159513705f88SJack F Vogel 159685d0a26eSJack F Vogel out: 159785d0a26eSJack F Vogel return status; 159885d0a26eSJack F Vogel } 159985d0a26eSJack F Vogel 160085d0a26eSJack F Vogel /** 160185d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 160285d0a26eSJack F Vogel * @hw: pointer to hardware structure 160385d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 160485d0a26eSJack F Vogel * @words: number of word(s) 160585d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 160685d0a26eSJack F Vogel * 160785d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 160885d0a26eSJack F Vogel **/ 160985d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 161085d0a26eSJack F Vogel u16 words, u16 *data) 161185d0a26eSJack F Vogel { 161285d0a26eSJack F Vogel u32 eerd; 161385d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161485d0a26eSJack F Vogel u32 i; 161585d0a26eSJack F Vogel 161685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 161785d0a26eSJack F Vogel 161885d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 161985d0a26eSJack F Vogel 162085d0a26eSJack F Vogel if (words == 0) { 162185d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1622fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162385d0a26eSJack F Vogel goto out; 162485d0a26eSJack F Vogel } 162585d0a26eSJack F Vogel 162685d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 162713705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1628fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 162985d0a26eSJack F Vogel goto out; 163013705f88SJack F Vogel } 163113705f88SJack F Vogel 163285d0a26eSJack F Vogel for (i = 0; i < words; i++) { 16330ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163485d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163585d0a26eSJack F Vogel 163685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 163785d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 163885d0a26eSJack F Vogel 163913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 164085d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 164185d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 164285d0a26eSJack F Vogel } else { 164385d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 164485d0a26eSJack F Vogel goto out; 164585d0a26eSJack F Vogel } 164685d0a26eSJack F Vogel } 164785d0a26eSJack F Vogel out: 164885d0a26eSJack F Vogel return status; 164985d0a26eSJack F Vogel } 165085d0a26eSJack F Vogel 165185d0a26eSJack F Vogel /** 165285d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 165385d0a26eSJack F Vogel * @hw: pointer to hardware structure 165485d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 165585d0a26eSJack F Vogel * 165685d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 165785d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 165885d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 165985d0a26eSJack F Vogel **/ 166085d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 166185d0a26eSJack F Vogel u16 offset) 166285d0a26eSJack F Vogel { 166385d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 166485d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 166585d0a26eSJack F Vogel u16 i; 166685d0a26eSJack F Vogel 166785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 166885d0a26eSJack F Vogel 166985d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 167085d0a26eSJack F Vogel data[i] = i; 167185d0a26eSJack F Vogel 167285d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 167385d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 167485d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 167585d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 167685d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167785d0a26eSJack F Vogel goto out; 167885d0a26eSJack F Vogel 167985d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 168085d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 168185d0a26eSJack F Vogel goto out; 168213705f88SJack F Vogel 168313705f88SJack F Vogel /* 168485d0a26eSJack F Vogel * When writing in burst more than the actual page size 168585d0a26eSJack F Vogel * EEPROM address wraps around current page. 168613705f88SJack F Vogel */ 168785d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 168813705f88SJack F Vogel 168985d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 169085d0a26eSJack F Vogel hw->eeprom.word_page_size); 16919ca4041bSJack F Vogel out: 169213705f88SJack F Vogel return status; 169313705f88SJack F Vogel } 169413705f88SJack F Vogel 169513705f88SJack F Vogel /** 16962969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 169713705f88SJack F Vogel * @hw: pointer to hardware structure 169813705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 169913705f88SJack F Vogel * @data: word read from the EEPROM 170013705f88SJack F Vogel * 170113705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 170213705f88SJack F Vogel **/ 17032969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 170413705f88SJack F Vogel { 170585d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 170685d0a26eSJack F Vogel } 170713705f88SJack F Vogel 170885d0a26eSJack F Vogel /** 170985d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 171085d0a26eSJack F Vogel * @hw: pointer to hardware structure 171185d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 171285d0a26eSJack F Vogel * @words: number of word(s) 171385d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 171485d0a26eSJack F Vogel * 171585d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 171685d0a26eSJack F Vogel **/ 171785d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 171885d0a26eSJack F Vogel u16 words, u16 *data) 171985d0a26eSJack F Vogel { 172085d0a26eSJack F Vogel u32 eewr; 172185d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 172285d0a26eSJack F Vogel u16 i; 172385d0a26eSJack F Vogel 172485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 17252969bf0eSJack F Vogel 17269ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 17279ca4041bSJack F Vogel 172885d0a26eSJack F Vogel if (words == 0) { 172985d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1730fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 173185d0a26eSJack F Vogel goto out; 173285d0a26eSJack F Vogel } 173385d0a26eSJack F Vogel 17349ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 17359ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1736fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 17379ca4041bSJack F Vogel goto out; 17389ca4041bSJack F Vogel } 17399ca4041bSJack F Vogel 174085d0a26eSJack F Vogel for (i = 0; i < words; i++) { 174185d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 174285d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 17432969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 174413705f88SJack F Vogel 174585d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 174685d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 174785d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 174885d0a26eSJack F Vogel goto out; 174985d0a26eSJack F Vogel } 175013705f88SJack F Vogel 175185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 175285d0a26eSJack F Vogel 175385d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 175485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 175585d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 175685d0a26eSJack F Vogel goto out; 175785d0a26eSJack F Vogel } 175885d0a26eSJack F Vogel } 175913705f88SJack F Vogel 17609ca4041bSJack F Vogel out: 176113705f88SJack F Vogel return status; 176213705f88SJack F Vogel } 176313705f88SJack F Vogel 176413705f88SJack F Vogel /** 17651a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 17661a4e3449SJack F Vogel * @hw: pointer to hardware structure 17671a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 17681a4e3449SJack F Vogel * @data: word write to the EEPROM 17691a4e3449SJack F Vogel * 17701a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 17711a4e3449SJack F Vogel **/ 17721a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 17731a4e3449SJack F Vogel { 177485d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 17751a4e3449SJack F Vogel } 17761a4e3449SJack F Vogel 17771a4e3449SJack F Vogel /** 17782969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 177913705f88SJack F Vogel * @hw: pointer to hardware structure 17802969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 178113705f88SJack F Vogel * 17822969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 17832969bf0eSJack F Vogel * read or write is done respectively. 178413705f88SJack F Vogel **/ 17852969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 178613705f88SJack F Vogel { 178713705f88SJack F Vogel u32 i; 178813705f88SJack F Vogel u32 reg; 178913705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 179013705f88SJack F Vogel 17912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 17922969bf0eSJack F Vogel 17932969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 17942969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 179513705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 17962969bf0eSJack F Vogel else 17972969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 17982969bf0eSJack F Vogel 17992969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 180013705f88SJack F Vogel status = IXGBE_SUCCESS; 180113705f88SJack F Vogel break; 180213705f88SJack F Vogel } 180313705f88SJack F Vogel usec_delay(5); 180413705f88SJack F Vogel } 1805fd75b91dSJack F Vogel 1806fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1807fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1808fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1809fd75b91dSJack F Vogel 181013705f88SJack F Vogel return status; 181113705f88SJack F Vogel } 181213705f88SJack F Vogel 181313705f88SJack F Vogel /** 181413705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 181513705f88SJack F Vogel * @hw: pointer to hardware structure 181613705f88SJack F Vogel * 181713705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 181813705f88SJack F Vogel * be called before issuing a command to the EEPROM. 181913705f88SJack F Vogel **/ 182013705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 182113705f88SJack F Vogel { 182213705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 182313705f88SJack F Vogel u32 eec; 182413705f88SJack F Vogel u32 i; 182513705f88SJack F Vogel 18262969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 18272969bf0eSJack F Vogel 182885d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 182985d0a26eSJack F Vogel != IXGBE_SUCCESS) 183013705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 183113705f88SJack F Vogel 183213705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 1833a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183413705f88SJack F Vogel 183513705f88SJack F Vogel /* Request EEPROM Access */ 183613705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 1837a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 183813705f88SJack F Vogel 183913705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 1840a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 184113705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 184213705f88SJack F Vogel break; 184313705f88SJack F Vogel usec_delay(5); 184413705f88SJack F Vogel } 184513705f88SJack F Vogel 18469ca4041bSJack F Vogel /* Release if grant not acquired */ 184713705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 184813705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 1849a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 185013705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 185113705f88SJack F Vogel 185285d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 185313705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 185413705f88SJack F Vogel } 185513705f88SJack F Vogel 185613705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 185713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 185813705f88SJack F Vogel /* Clear CS and SK */ 185913705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 1860a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 186113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 186213705f88SJack F Vogel usec_delay(1); 186313705f88SJack F Vogel } 18641a4e3449SJack F Vogel } 186513705f88SJack F Vogel return status; 186613705f88SJack F Vogel } 186713705f88SJack F Vogel 186813705f88SJack F Vogel /** 186913705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 187013705f88SJack F Vogel * @hw: pointer to hardware structure 187113705f88SJack F Vogel * 187213705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 187313705f88SJack F Vogel **/ 187413705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 187513705f88SJack F Vogel { 187613705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1877d8602bb9SJack F Vogel u32 timeout = 2000; 187813705f88SJack F Vogel u32 i; 187913705f88SJack F Vogel u32 swsm; 188013705f88SJack F Vogel 18812969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 18822969bf0eSJack F Vogel 18831a4e3449SJack F Vogel 188413705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 188513705f88SJack F Vogel for (i = 0; i < timeout; i++) { 188613705f88SJack F Vogel /* 188713705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 188813705f88SJack F Vogel * set and we have the semaphore 188913705f88SJack F Vogel */ 1890a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 189113705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 189213705f88SJack F Vogel status = IXGBE_SUCCESS; 189313705f88SJack F Vogel break; 189413705f88SJack F Vogel } 18950ac6dfecSJack F Vogel usec_delay(50); 189613705f88SJack F Vogel } 189713705f88SJack F Vogel 189885d0a26eSJack F Vogel if (i == timeout) { 189985d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 190085d0a26eSJack F Vogel "not granted.\n"); 190185d0a26eSJack F Vogel /* 190285d0a26eSJack F Vogel * this release is particularly important because our attempts 190385d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 190485d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 190585d0a26eSJack F Vogel * bits to free the driver to make progress 190685d0a26eSJack F Vogel */ 190785d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 190885d0a26eSJack F Vogel 190985d0a26eSJack F Vogel usec_delay(50); 191085d0a26eSJack F Vogel /* 191185d0a26eSJack F Vogel * one last try 191285d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 191385d0a26eSJack F Vogel * set and we have the semaphore 191485d0a26eSJack F Vogel */ 1915a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 191685d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 191785d0a26eSJack F Vogel status = IXGBE_SUCCESS; 191885d0a26eSJack F Vogel } 191985d0a26eSJack F Vogel 192013705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 192113705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 192213705f88SJack F Vogel for (i = 0; i < timeout; i++) { 1923a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 192413705f88SJack F Vogel 192513705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 192613705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 1927a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); 192813705f88SJack F Vogel 192913705f88SJack F Vogel /* 193013705f88SJack F Vogel * If we set the bit successfully then we got the 193113705f88SJack F Vogel * semaphore. 193213705f88SJack F Vogel */ 1933a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 193413705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 193513705f88SJack F Vogel break; 193613705f88SJack F Vogel 193713705f88SJack F Vogel usec_delay(50); 193813705f88SJack F Vogel } 193913705f88SJack F Vogel 194013705f88SJack F Vogel /* 194113705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 194213705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 194313705f88SJack F Vogel */ 194413705f88SJack F Vogel if (i >= timeout) { 1945fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1946fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 194713705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 194813705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 194913705f88SJack F Vogel } 19500ac6dfecSJack F Vogel } else { 1951fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1952fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 19530ac6dfecSJack F Vogel "not granted.\n"); 195413705f88SJack F Vogel } 195513705f88SJack F Vogel 195613705f88SJack F Vogel return status; 195713705f88SJack F Vogel } 195813705f88SJack F Vogel 195913705f88SJack F Vogel /** 196013705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 196113705f88SJack F Vogel * @hw: pointer to hardware structure 196213705f88SJack F Vogel * 196313705f88SJack F Vogel * This function clears hardware semaphore bits. 196413705f88SJack F Vogel **/ 196513705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 196613705f88SJack F Vogel { 196713705f88SJack F Vogel u32 swsm; 196813705f88SJack F Vogel 19692969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 19702969bf0eSJack F Vogel 197113705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 197213705f88SJack F Vogel 197313705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 197413705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 197513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 19769ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 197713705f88SJack F Vogel } 197813705f88SJack F Vogel 197913705f88SJack F Vogel /** 198013705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 198113705f88SJack F Vogel * @hw: pointer to hardware structure 198213705f88SJack F Vogel **/ 198313705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 198413705f88SJack F Vogel { 198513705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 198613705f88SJack F Vogel u16 i; 198713705f88SJack F Vogel u8 spi_stat_reg; 198813705f88SJack F Vogel 19892969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 19902969bf0eSJack F Vogel 199113705f88SJack F Vogel /* 199213705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 199313705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 199413705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 199513705f88SJack F Vogel * 5 milliseconds, then error out. 199613705f88SJack F Vogel */ 199713705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 199813705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 199913705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 200013705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 200113705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 200213705f88SJack F Vogel break; 200313705f88SJack F Vogel 200413705f88SJack F Vogel usec_delay(5); 200513705f88SJack F Vogel ixgbe_standby_eeprom(hw); 2006c19c7afeSEric Joyner } 200713705f88SJack F Vogel 200813705f88SJack F Vogel /* 200913705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 201013705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 201113705f88SJack F Vogel */ 201213705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 201313705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 201413705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 201513705f88SJack F Vogel } 201613705f88SJack F Vogel 201713705f88SJack F Vogel return status; 201813705f88SJack F Vogel } 201913705f88SJack F Vogel 202013705f88SJack F Vogel /** 202113705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 202213705f88SJack F Vogel * @hw: pointer to hardware structure 202313705f88SJack F Vogel **/ 202413705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 202513705f88SJack F Vogel { 202613705f88SJack F Vogel u32 eec; 202713705f88SJack F Vogel 20282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 20292969bf0eSJack F Vogel 2030a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 203113705f88SJack F Vogel 203213705f88SJack F Vogel /* Toggle CS to flush commands */ 203313705f88SJack F Vogel eec |= IXGBE_EEC_CS; 2034a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203513705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203613705f88SJack F Vogel usec_delay(1); 203713705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 2038a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203913705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 204013705f88SJack F Vogel usec_delay(1); 204113705f88SJack F Vogel } 204213705f88SJack F Vogel 204313705f88SJack F Vogel /** 204413705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 204513705f88SJack F Vogel * @hw: pointer to hardware structure 204613705f88SJack F Vogel * @data: data to send to the EEPROM 204713705f88SJack F Vogel * @count: number of bits to shift out 204813705f88SJack F Vogel **/ 204913705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 205013705f88SJack F Vogel u16 count) 205113705f88SJack F Vogel { 205213705f88SJack F Vogel u32 eec; 205313705f88SJack F Vogel u32 mask; 205413705f88SJack F Vogel u32 i; 205513705f88SJack F Vogel 20562969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 20572969bf0eSJack F Vogel 2058a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 205913705f88SJack F Vogel 206013705f88SJack F Vogel /* 206113705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 206213705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 206313705f88SJack F Vogel */ 206413705f88SJack F Vogel mask = 0x01 << (count - 1); 206513705f88SJack F Vogel 206613705f88SJack F Vogel for (i = 0; i < count; i++) { 206713705f88SJack F Vogel /* 206813705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 206913705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 207013705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 207113705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 207213705f88SJack F Vogel * raising and then lowering the clock. 207313705f88SJack F Vogel */ 207413705f88SJack F Vogel if (data & mask) 207513705f88SJack F Vogel eec |= IXGBE_EEC_DI; 207613705f88SJack F Vogel else 207713705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 207813705f88SJack F Vogel 2079a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 208013705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 208113705f88SJack F Vogel 208213705f88SJack F Vogel usec_delay(1); 208313705f88SJack F Vogel 208413705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 208513705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 208613705f88SJack F Vogel 208713705f88SJack F Vogel /* 208813705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 208913705f88SJack F Vogel * EEPROM 209013705f88SJack F Vogel */ 209113705f88SJack F Vogel mask = mask >> 1; 2092c19c7afeSEric Joyner } 209313705f88SJack F Vogel 209413705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 209513705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 2096a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 209713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 209813705f88SJack F Vogel } 209913705f88SJack F Vogel 210013705f88SJack F Vogel /** 210113705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 210213705f88SJack F Vogel * @hw: pointer to hardware structure 21037d48aa4cSEric Joyner * @count: number of bits to shift 210413705f88SJack F Vogel **/ 210513705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 210613705f88SJack F Vogel { 210713705f88SJack F Vogel u32 eec; 210813705f88SJack F Vogel u32 i; 210913705f88SJack F Vogel u16 data = 0; 211013705f88SJack F Vogel 21112969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 21122969bf0eSJack F Vogel 211313705f88SJack F Vogel /* 211413705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 211513705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 211613705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 211713705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 211813705f88SJack F Vogel * "DI" bit should always be clear. 211913705f88SJack F Vogel */ 2120a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212113705f88SJack F Vogel 212213705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 212313705f88SJack F Vogel 212413705f88SJack F Vogel for (i = 0; i < count; i++) { 212513705f88SJack F Vogel data = data << 1; 212613705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 212713705f88SJack F Vogel 2128a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212913705f88SJack F Vogel 213013705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 213113705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 213213705f88SJack F Vogel data |= 1; 213313705f88SJack F Vogel 213413705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 213513705f88SJack F Vogel } 213613705f88SJack F Vogel 213713705f88SJack F Vogel return data; 213813705f88SJack F Vogel } 213913705f88SJack F Vogel 214013705f88SJack F Vogel /** 214113705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 214213705f88SJack F Vogel * @hw: pointer to hardware structure 214313705f88SJack F Vogel * @eec: EEC register's current value 214413705f88SJack F Vogel **/ 214513705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 214613705f88SJack F Vogel { 21472969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 21482969bf0eSJack F Vogel 214913705f88SJack F Vogel /* 215013705f88SJack F Vogel * Raise the clock input to the EEPROM 215113705f88SJack F Vogel * (setting the SK bit), then delay 215213705f88SJack F Vogel */ 215313705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 2154a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 215513705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 215613705f88SJack F Vogel usec_delay(1); 215713705f88SJack F Vogel } 215813705f88SJack F Vogel 215913705f88SJack F Vogel /** 216013705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 216113705f88SJack F Vogel * @hw: pointer to hardware structure 21627d48aa4cSEric Joyner * @eec: EEC's current value 216313705f88SJack F Vogel **/ 216413705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 216513705f88SJack F Vogel { 21662969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 21672969bf0eSJack F Vogel 216813705f88SJack F Vogel /* 216913705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 217013705f88SJack F Vogel * delay 217113705f88SJack F Vogel */ 217213705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 2173a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 217413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 217513705f88SJack F Vogel usec_delay(1); 217613705f88SJack F Vogel } 217713705f88SJack F Vogel 217813705f88SJack F Vogel /** 217913705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 218013705f88SJack F Vogel * @hw: pointer to hardware structure 218113705f88SJack F Vogel **/ 218213705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 218313705f88SJack F Vogel { 218413705f88SJack F Vogel u32 eec; 218513705f88SJack F Vogel 21862969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 21872969bf0eSJack F Vogel 2188a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 218913705f88SJack F Vogel 219013705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 219113705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 219213705f88SJack F Vogel 2193a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 219513705f88SJack F Vogel 219613705f88SJack F Vogel usec_delay(1); 219713705f88SJack F Vogel 219813705f88SJack F Vogel /* Stop requesting EEPROM access */ 219913705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 2200a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 220113705f88SJack F Vogel 220285d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2203d8602bb9SJack F Vogel 2204d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2205d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 220613705f88SJack F Vogel } 220713705f88SJack F Vogel 220813705f88SJack F Vogel /** 22092969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 221013705f88SJack F Vogel * @hw: pointer to hardware structure 2211758cc3dcSJack F Vogel * 2212758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 221313705f88SJack F Vogel **/ 2214758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 221513705f88SJack F Vogel { 221613705f88SJack F Vogel u16 i; 221713705f88SJack F Vogel u16 j; 221813705f88SJack F Vogel u16 checksum = 0; 221913705f88SJack F Vogel u16 length = 0; 222013705f88SJack F Vogel u16 pointer = 0; 222113705f88SJack F Vogel u16 word = 0; 222213705f88SJack F Vogel 22232969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 22242969bf0eSJack F Vogel 222513705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 222613705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2227758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 222813705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2229758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 223013705f88SJack F Vogel } 223113705f88SJack F Vogel checksum += word; 223213705f88SJack F Vogel } 223313705f88SJack F Vogel 223413705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 223513705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2236758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2237758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2238758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2239758cc3dcSJack F Vogel } 224013705f88SJack F Vogel 2241758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2242758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2243758cc3dcSJack F Vogel continue; 224413705f88SJack F Vogel 2245758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2246758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2247758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2248758cc3dcSJack F Vogel } 2249758cc3dcSJack F Vogel 2250758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2251758cc3dcSJack F Vogel continue; 2252758cc3dcSJack F Vogel 225313705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2254758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2255758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2256758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2257758cc3dcSJack F Vogel } 225813705f88SJack F Vogel checksum += word; 225913705f88SJack F Vogel } 226013705f88SJack F Vogel } 226113705f88SJack F Vogel 226213705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 226313705f88SJack F Vogel 2264758cc3dcSJack F Vogel return (s32)checksum; 226513705f88SJack F Vogel } 226613705f88SJack F Vogel 226713705f88SJack F Vogel /** 226813705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 226913705f88SJack F Vogel * @hw: pointer to hardware structure 227013705f88SJack F Vogel * @checksum_val: calculated checksum 227113705f88SJack F Vogel * 227213705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 227313705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 227413705f88SJack F Vogel **/ 227513705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 227613705f88SJack F Vogel u16 *checksum_val) 227713705f88SJack F Vogel { 227813705f88SJack F Vogel s32 status; 227913705f88SJack F Vogel u16 checksum; 228013705f88SJack F Vogel u16 read_checksum = 0; 228113705f88SJack F Vogel 22822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 22832969bf0eSJack F Vogel 2284758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 228513705f88SJack F Vogel * not continue or we could be in for a very long wait while every 228613705f88SJack F Vogel * EEPROM read fails 228713705f88SJack F Vogel */ 22889ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2289758cc3dcSJack F Vogel if (status) { 2290758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2291758cc3dcSJack F Vogel return status; 2292758cc3dcSJack F Vogel } 229313705f88SJack F Vogel 2294758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2295758cc3dcSJack F Vogel if (status < 0) 2296758cc3dcSJack F Vogel return status; 229713705f88SJack F Vogel 2298758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 229913705f88SJack F Vogel 2300758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2301758cc3dcSJack F Vogel if (status) { 2302758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2303758cc3dcSJack F Vogel return status; 2304758cc3dcSJack F Vogel } 2305758cc3dcSJack F Vogel 2306758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 230713705f88SJack F Vogel * calculated checksum 230813705f88SJack F Vogel */ 23099ca4041bSJack F Vogel if (read_checksum != checksum) 231013705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 231113705f88SJack F Vogel 231213705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 23139ca4041bSJack F Vogel if (checksum_val) 231413705f88SJack F Vogel *checksum_val = checksum; 231513705f88SJack F Vogel 231613705f88SJack F Vogel return status; 231713705f88SJack F Vogel } 231813705f88SJack F Vogel 231913705f88SJack F Vogel /** 23209ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 232113705f88SJack F Vogel * @hw: pointer to hardware structure 232213705f88SJack F Vogel **/ 232313705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 232413705f88SJack F Vogel { 232513705f88SJack F Vogel s32 status; 232613705f88SJack F Vogel u16 checksum; 232713705f88SJack F Vogel 23282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 23292969bf0eSJack F Vogel 2330758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 233113705f88SJack F Vogel * not continue or we could be in for a very long wait while every 233213705f88SJack F Vogel * EEPROM read fails 233313705f88SJack F Vogel */ 23349ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2335758cc3dcSJack F Vogel if (status) { 233613705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2337758cc3dcSJack F Vogel return status; 233813705f88SJack F Vogel } 233913705f88SJack F Vogel 2340758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2341758cc3dcSJack F Vogel if (status < 0) 2342758cc3dcSJack F Vogel return status; 2343758cc3dcSJack F Vogel 2344758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2345758cc3dcSJack F Vogel 2346758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2347758cc3dcSJack F Vogel 234813705f88SJack F Vogel return status; 234913705f88SJack F Vogel } 235013705f88SJack F Vogel 235113705f88SJack F Vogel /** 235213705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 235313705f88SJack F Vogel * @mac_addr: pointer to MAC address. 235413705f88SJack F Vogel * 23558eb6488eSEric Joyner * Tests a MAC address to ensure it is a valid Individual Address. 235613705f88SJack F Vogel **/ 235713705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 235813705f88SJack F Vogel { 235913705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 236013705f88SJack F Vogel 23612969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 23622969bf0eSJack F Vogel 236313705f88SJack F Vogel /* Make sure it is not a multicast address */ 236413705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 236513705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236613705f88SJack F Vogel /* Not a broadcast address */ 236713705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 236813705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236913705f88SJack F Vogel /* Reject the zero address */ 237013705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 237113705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 237213705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 237313705f88SJack F Vogel } 237413705f88SJack F Vogel return status; 237513705f88SJack F Vogel } 237613705f88SJack F Vogel 237713705f88SJack F Vogel /** 23789ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 237913705f88SJack F Vogel * @hw: pointer to hardware structure 238013705f88SJack F Vogel * @index: Receive address register to write 23819ca4041bSJack F Vogel * @addr: Address to put into receive address register 23829ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 238313705f88SJack F Vogel * @enable_addr: set flag that address is active 238413705f88SJack F Vogel * 238513705f88SJack F Vogel * Puts an ethernet address into a receive address register. 238613705f88SJack F Vogel **/ 23879ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 238813705f88SJack F Vogel u32 enable_addr) 238913705f88SJack F Vogel { 239013705f88SJack F Vogel u32 rar_low, rar_high; 23919ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 239213705f88SJack F Vogel 23932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 23942969bf0eSJack F Vogel 23951a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 23961a4e3449SJack F Vogel if (index >= rar_entries) { 2397fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2398fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23991a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24001a4e3449SJack F Vogel } 24011a4e3449SJack F Vogel 24029ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 24039ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 24049ca4041bSJack F Vogel 240513705f88SJack F Vogel /* 24069ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 24079ca4041bSJack F Vogel * order from network order (big endian) to little endian 240813705f88SJack F Vogel */ 240913705f88SJack F Vogel rar_low = ((u32)addr[0] | 241013705f88SJack F Vogel ((u32)addr[1] << 8) | 241113705f88SJack F Vogel ((u32)addr[2] << 16) | 241213705f88SJack F Vogel ((u32)addr[3] << 24)); 24139ca4041bSJack F Vogel /* 24149ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24159ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 24169ca4041bSJack F Vogel * of the address and the address valid bit. 24179ca4041bSJack F Vogel */ 24189ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24199ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24209ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 242113705f88SJack F Vogel 242213705f88SJack F Vogel if (enable_addr != 0) 242313705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 242413705f88SJack F Vogel 242513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 242613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 242713705f88SJack F Vogel 242813705f88SJack F Vogel return IXGBE_SUCCESS; 242913705f88SJack F Vogel } 243013705f88SJack F Vogel 243113705f88SJack F Vogel /** 24325b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 24335b7f4cedSJack F Vogel * @hw: pointer to hardware structure 24345b7f4cedSJack F Vogel * @index: Receive address register to write 24355b7f4cedSJack F Vogel * 24365b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 24375b7f4cedSJack F Vogel **/ 24385b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 24395b7f4cedSJack F Vogel { 24405b7f4cedSJack F Vogel u32 rar_high; 24415b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24425b7f4cedSJack F Vogel 24432969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 24442969bf0eSJack F Vogel 24455b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 24461a4e3449SJack F Vogel if (index >= rar_entries) { 2447fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2448fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 24491a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24501a4e3449SJack F Vogel } 24511a4e3449SJack F Vogel 24525b7f4cedSJack F Vogel /* 24535b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24545b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 24555b7f4cedSJack F Vogel * of the address and the address valid bit. 24565b7f4cedSJack F Vogel */ 24575b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24585b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24595b7f4cedSJack F Vogel 24605b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 24615b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 24625b7f4cedSJack F Vogel 24635b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 24645b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 24655b7f4cedSJack F Vogel 24665b7f4cedSJack F Vogel return IXGBE_SUCCESS; 24675b7f4cedSJack F Vogel } 24685b7f4cedSJack F Vogel 24695b7f4cedSJack F Vogel /** 247013705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 247113705f88SJack F Vogel * @hw: pointer to hardware structure 247213705f88SJack F Vogel * 247313705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 24749ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 247513705f88SJack F Vogel * the receiver is in reset when the routine is called. 247613705f88SJack F Vogel **/ 247713705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 247813705f88SJack F Vogel { 247913705f88SJack F Vogel u32 i; 24809ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 248113705f88SJack F Vogel 24822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 24832969bf0eSJack F Vogel 248413705f88SJack F Vogel /* 248513705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 248613705f88SJack F Vogel * to the permanent address. 248713705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 248813705f88SJack F Vogel */ 248913705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 249013705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 249113705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 24929ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 249313705f88SJack F Vogel 249413705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 249513705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 249613705f88SJack F Vogel hw->mac.addr[2]); 249713705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 249813705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 249913705f88SJack F Vogel } else { 250013705f88SJack F Vogel /* Setup the receive address. */ 250113705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 250213705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 250313705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 250413705f88SJack F Vogel hw->mac.addr[2]); 250513705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 250613705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 250713705f88SJack F Vogel 25089ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 25098eb6488eSEric Joyner } 2510182b3808SJack F Vogel 2511182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2512182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 25138eb6488eSEric Joyner 25149ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 251513705f88SJack F Vogel 251613705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 251713705f88SJack F Vogel 251813705f88SJack F Vogel /* Zero out the other receive addresses. */ 25199ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 252013705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 252113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 252213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 252313705f88SJack F Vogel } 252413705f88SJack F Vogel 252513705f88SJack F Vogel /* Clear the MTA */ 252613705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 252713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 252813705f88SJack F Vogel 252913705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 25309ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 253113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 253213705f88SJack F Vogel 25335b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 25345b7f4cedSJack F Vogel 253513705f88SJack F Vogel return IXGBE_SUCCESS; 253613705f88SJack F Vogel } 253713705f88SJack F Vogel 253813705f88SJack F Vogel /** 25399ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 25409ca4041bSJack F Vogel * @hw: pointer to hardware structure 25419ca4041bSJack F Vogel * @addr: new address 25427d48aa4cSEric Joyner * @vmdq: VMDq "set" or "pool" index 25439ca4041bSJack F Vogel * 25449ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 25459ca4041bSJack F Vogel **/ 25469ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 25479ca4041bSJack F Vogel { 25489ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 25499ca4041bSJack F Vogel u32 rar; 25509ca4041bSJack F Vogel 25512969bf0eSJack F Vogel DEBUGFUNC("ixgbe_add_uc_addr"); 25522969bf0eSJack F Vogel 25539ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 25549ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 25559ca4041bSJack F Vogel 25569ca4041bSJack F Vogel /* 25579ca4041bSJack F Vogel * Place this address in the RAR if there is room, 25589ca4041bSJack F Vogel * else put the controller into promiscuous mode 25599ca4041bSJack F Vogel */ 25609ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 25610ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 25629ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 25639ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 25649ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 25659ca4041bSJack F Vogel } else { 25669ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 25679ca4041bSJack F Vogel } 25689ca4041bSJack F Vogel 25699ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 25709ca4041bSJack F Vogel } 25719ca4041bSJack F Vogel 25729ca4041bSJack F Vogel /** 25739ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 25749ca4041bSJack F Vogel * @hw: pointer to hardware structure 25759ca4041bSJack F Vogel * @addr_list: the list of new addresses 25769ca4041bSJack F Vogel * @addr_count: number of addresses 25779ca4041bSJack F Vogel * @next: iterator function to walk the address list 25789ca4041bSJack F Vogel * 25799ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 25809ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 25819ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 25829ca4041bSJack F Vogel * 25839ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 25849ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 25859ca4041bSJack F Vogel **/ 25869ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 25879ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 25889ca4041bSJack F Vogel { 25899ca4041bSJack F Vogel u8 *addr; 25909ca4041bSJack F Vogel u32 i; 25919ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 25929ca4041bSJack F Vogel u32 uc_addr_in_use; 25939ca4041bSJack F Vogel u32 fctrl; 25949ca4041bSJack F Vogel u32 vmdq; 25959ca4041bSJack F Vogel 25962969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 25972969bf0eSJack F Vogel 25989ca4041bSJack F Vogel /* 25999ca4041bSJack F Vogel * Clear accounting of old secondary address list, 26009ca4041bSJack F Vogel * don't count RAR[0] 26019ca4041bSJack F Vogel */ 26020ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 26039ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 26049ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 26059ca4041bSJack F Vogel 26069ca4041bSJack F Vogel /* Zero out the other receive addresses */ 26072969bf0eSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); 26082969bf0eSJack F Vogel for (i = 0; i < uc_addr_in_use; i++) { 26092969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); 26102969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); 26119ca4041bSJack F Vogel } 26129ca4041bSJack F Vogel 26139ca4041bSJack F Vogel /* Add the new addresses */ 26149ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 26159ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 26169ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 26179ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 26189ca4041bSJack F Vogel } 26199ca4041bSJack F Vogel 26209ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 26219ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 26229ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26239ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 26249ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26259ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 26269ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26279ca4041bSJack F Vogel } 26289ca4041bSJack F Vogel } else { 26299ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 26309ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26319ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 26329ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26339ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 26349ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26359ca4041bSJack F Vogel } 26369ca4041bSJack F Vogel } 26379ca4041bSJack F Vogel 26389ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 26399ca4041bSJack F Vogel return IXGBE_SUCCESS; 26409ca4041bSJack F Vogel } 26419ca4041bSJack F Vogel 26429ca4041bSJack F Vogel /** 264313705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 264413705f88SJack F Vogel * @hw: pointer to hardware structure 264513705f88SJack F Vogel * @mc_addr: the multicast address 264613705f88SJack F Vogel * 264713705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 264813705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 264913705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 265013705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 26519ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 265213705f88SJack F Vogel * to mc_filter_type. 265313705f88SJack F Vogel **/ 265413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 265513705f88SJack F Vogel { 265613705f88SJack F Vogel u32 vector = 0; 265713705f88SJack F Vogel 26582969bf0eSJack F Vogel DEBUGFUNC("ixgbe_mta_vector"); 26592969bf0eSJack F Vogel 266013705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 266113705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 266213705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 266313705f88SJack F Vogel break; 266413705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 266513705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 266613705f88SJack F Vogel break; 266713705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 266813705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 266913705f88SJack F Vogel break; 267013705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 267113705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 267213705f88SJack F Vogel break; 267313705f88SJack F Vogel default: /* Invalid mc_filter_type */ 267413705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 267513705f88SJack F Vogel ASSERT(0); 267613705f88SJack F Vogel break; 267713705f88SJack F Vogel } 267813705f88SJack F Vogel 267913705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 268013705f88SJack F Vogel vector &= 0xFFF; 268113705f88SJack F Vogel return vector; 268213705f88SJack F Vogel } 268313705f88SJack F Vogel 268413705f88SJack F Vogel /** 268513705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 268613705f88SJack F Vogel * @hw: pointer to hardware structure 26877d48aa4cSEric Joyner * @mc_addr: Multicast address 268813705f88SJack F Vogel * 268913705f88SJack F Vogel * Sets the bit-vector in the multicast table. 269013705f88SJack F Vogel **/ 269113705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 269213705f88SJack F Vogel { 269313705f88SJack F Vogel u32 vector; 269413705f88SJack F Vogel u32 vector_bit; 269513705f88SJack F Vogel u32 vector_reg; 269613705f88SJack F Vogel 26972969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_mta"); 26982969bf0eSJack F Vogel 269913705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 270013705f88SJack F Vogel 270113705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 270213705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 270313705f88SJack F Vogel 270413705f88SJack F Vogel /* 270513705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 270613705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 270713705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 270813705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 270913705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 271013705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 271113705f88SJack F Vogel * the value. 271213705f88SJack F Vogel */ 271313705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 271413705f88SJack F Vogel vector_bit = vector & 0x1F; 27151a4e3449SJack F Vogel hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); 271613705f88SJack F Vogel } 271713705f88SJack F Vogel 271813705f88SJack F Vogel /** 271913705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 272013705f88SJack F Vogel * @hw: pointer to hardware structure 272113705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 272213705f88SJack F Vogel * @mc_addr_count: number of addresses 27239ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 272485d0a26eSJack F Vogel * @clear: flag, when set clears the table beforehand 272513705f88SJack F Vogel * 272685d0a26eSJack F Vogel * When the clear flag is set, the given list replaces any existing list. 272785d0a26eSJack F Vogel * Hashes the given addresses into the multicast table. 272813705f88SJack F Vogel **/ 272913705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 273085d0a26eSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next, 273185d0a26eSJack F Vogel bool clear) 273213705f88SJack F Vogel { 273313705f88SJack F Vogel u32 i; 27349ca4041bSJack F Vogel u32 vmdq; 273513705f88SJack F Vogel 27362969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 27372969bf0eSJack F Vogel 273813705f88SJack F Vogel /* 273913705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 274013705f88SJack F Vogel * use. 274113705f88SJack F Vogel */ 274213705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 274313705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 274413705f88SJack F Vogel 27451a4e3449SJack F Vogel /* Clear mta_shadow */ 274685d0a26eSJack F Vogel if (clear) { 274713705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 27481a4e3449SJack F Vogel memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 274985d0a26eSJack F Vogel } 275013705f88SJack F Vogel 27511a4e3449SJack F Vogel /* Update mta_shadow */ 275213705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 275313705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 27540ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 275513705f88SJack F Vogel } 275613705f88SJack F Vogel 275713705f88SJack F Vogel /* Enable mta */ 27581a4e3449SJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 27591a4e3449SJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 27601a4e3449SJack F Vogel hw->mac.mta_shadow[i]); 27611a4e3449SJack F Vogel 276213705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 276313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 276413705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 276513705f88SJack F Vogel 276613705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 276713705f88SJack F Vogel return IXGBE_SUCCESS; 276813705f88SJack F Vogel } 276913705f88SJack F Vogel 277013705f88SJack F Vogel /** 277113705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 277213705f88SJack F Vogel * @hw: pointer to hardware structure 277313705f88SJack F Vogel * 277413705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 277513705f88SJack F Vogel **/ 277613705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 277713705f88SJack F Vogel { 277813705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 277913705f88SJack F Vogel 27802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_mc_generic"); 27812969bf0eSJack F Vogel 278213705f88SJack F Vogel if (a->mta_in_use > 0) 278313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 278413705f88SJack F Vogel hw->mac.mc_filter_type); 278513705f88SJack F Vogel 278613705f88SJack F Vogel return IXGBE_SUCCESS; 278713705f88SJack F Vogel } 278813705f88SJack F Vogel 278913705f88SJack F Vogel /** 27909ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 279113705f88SJack F Vogel * @hw: pointer to hardware structure 279213705f88SJack F Vogel * 279313705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 279413705f88SJack F Vogel **/ 279513705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 279613705f88SJack F Vogel { 279713705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 279813705f88SJack F Vogel 27992969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_mc_generic"); 28002969bf0eSJack F Vogel 280113705f88SJack F Vogel if (a->mta_in_use > 0) 280213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 280313705f88SJack F Vogel 280413705f88SJack F Vogel return IXGBE_SUCCESS; 280513705f88SJack F Vogel } 280613705f88SJack F Vogel 28071b6e0dbaSJack F Vogel /** 28080ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 28091b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 28101b6e0dbaSJack F Vogel * 28110ac6dfecSJack F Vogel * Enable flow control according to the current settings. 28121b6e0dbaSJack F Vogel **/ 2813a621e3c8SJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 28141b6e0dbaSJack F Vogel { 28151b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 28160ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 28170ac6dfecSJack F Vogel u32 reg; 28181a4e3449SJack F Vogel u32 fcrtl, fcrth; 2819a621e3c8SJack F Vogel int i; 28201b6e0dbaSJack F Vogel 28210ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 28221b6e0dbaSJack F Vogel 2823a621e3c8SJack F Vogel /* Validate the water mark configuration */ 2824a621e3c8SJack F Vogel if (!hw->fc.pause_time) { 2825a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 28260ac6dfecSJack F Vogel goto out; 2827a621e3c8SJack F Vogel } 2828a621e3c8SJack F Vogel 2829a621e3c8SJack F Vogel /* Low water mark of zero causes XOFF floods */ 2830a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2831a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2832a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2833a621e3c8SJack F Vogel if (!hw->fc.low_water[i] || 2834a621e3c8SJack F Vogel hw->fc.low_water[i] >= hw->fc.high_water[i]) { 2835a621e3c8SJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 2836a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 2837a621e3c8SJack F Vogel goto out; 2838a621e3c8SJack F Vogel } 2839a621e3c8SJack F Vogel } 2840a621e3c8SJack F Vogel } 2841a621e3c8SJack F Vogel 2842a621e3c8SJack F Vogel /* Negotiate the fc mode to use */ 28438eb6488eSEric Joyner hw->mac.ops.fc_autoneg(hw); 28440ac6dfecSJack F Vogel 28450ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 28460ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 2847a621e3c8SJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 28480ac6dfecSJack F Vogel 28490ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 28500ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 28511b6e0dbaSJack F Vogel 28521b6e0dbaSJack F Vogel /* 28531b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 28541b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 28551b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 28561b6e0dbaSJack F Vogel * but not send pause frames). 28571b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 28581b6e0dbaSJack F Vogel * we do not support receiving pause frames). 28591b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 28601b6e0dbaSJack F Vogel * other: Invalid. 28611b6e0dbaSJack F Vogel */ 28621b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 28631b6e0dbaSJack F Vogel case ixgbe_fc_none: 28641a4e3449SJack F Vogel /* 28651a4e3449SJack F Vogel * Flow control is disabled by software override or autoneg. 28660ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 28670ac6dfecSJack F Vogel */ 28681b6e0dbaSJack F Vogel break; 28691b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 28701b6e0dbaSJack F Vogel /* 28711b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 28721b6e0dbaSJack F Vogel * disabled by software override. Since there really 28731b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 28741b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 28751b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 28761b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 28771b6e0dbaSJack F Vogel */ 28780ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28791b6e0dbaSJack F Vogel break; 28801b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 28811b6e0dbaSJack F Vogel /* 28821b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 28831b6e0dbaSJack F Vogel * disabled by software override. 28841b6e0dbaSJack F Vogel */ 28850ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28861b6e0dbaSJack F Vogel break; 28871b6e0dbaSJack F Vogel case ixgbe_fc_full: 28881b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 28890ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28900ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28911b6e0dbaSJack F Vogel break; 28921b6e0dbaSJack F Vogel default: 2893fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 2894fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 28952969bf0eSJack F Vogel ret_val = IXGBE_ERR_CONFIG; 28961b6e0dbaSJack F Vogel goto out; 28971b6e0dbaSJack F Vogel break; 28981b6e0dbaSJack F Vogel } 28991b6e0dbaSJack F Vogel 29000ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 29010ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 29020ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 29030ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 29041b6e0dbaSJack F Vogel 2905d8602bb9SJack F Vogel 2906a621e3c8SJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 2907a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2908a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2909a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2910a621e3c8SJack F Vogel fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 2911a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 2912a621e3c8SJack F Vogel fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 2913a621e3c8SJack F Vogel } else { 2914a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 2915a621e3c8SJack F Vogel /* 2916a621e3c8SJack F Vogel * In order to prevent Tx hangs when the internal Tx 2917a621e3c8SJack F Vogel * switch is enabled we must set the high water mark 2918758cc3dcSJack F Vogel * to the Rx packet buffer size - 24KB. This allows 2919758cc3dcSJack F Vogel * the Tx switch to function even under heavy Rx 2920758cc3dcSJack F Vogel * workloads. 2921a621e3c8SJack F Vogel */ 2922758cc3dcSJack F Vogel fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 29231b6e0dbaSJack F Vogel } 29241b6e0dbaSJack F Vogel 2925a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 2926a621e3c8SJack F Vogel } 29270ac6dfecSJack F Vogel 29280ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 2929a621e3c8SJack F Vogel reg = hw->fc.pause_time * 0x00010001; 2930a621e3c8SJack F Vogel for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) 2931a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 29320ac6dfecSJack F Vogel 2933a621e3c8SJack F Vogel /* Configure flow control refresh threshold value */ 2934a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 29350ac6dfecSJack F Vogel 29360ac6dfecSJack F Vogel out: 29370ac6dfecSJack F Vogel return ret_val; 29380ac6dfecSJack F Vogel } 29390ac6dfecSJack F Vogel 29400ac6dfecSJack F Vogel /** 29411a4e3449SJack F Vogel * ixgbe_negotiate_fc - Negotiate flow control 29421a4e3449SJack F Vogel * @hw: pointer to hardware structure 29431a4e3449SJack F Vogel * @adv_reg: flow control advertised settings 29441a4e3449SJack F Vogel * @lp_reg: link partner's flow control settings 29451a4e3449SJack F Vogel * @adv_sym: symmetric pause bit in advertisement 29461a4e3449SJack F Vogel * @adv_asm: asymmetric pause bit in advertisement 29471a4e3449SJack F Vogel * @lp_sym: symmetric pause bit in link partner advertisement 29481a4e3449SJack F Vogel * @lp_asm: asymmetric pause bit in link partner advertisement 29491a4e3449SJack F Vogel * 29501a4e3449SJack F Vogel * Find the intersection between advertised settings and link partner's 29511a4e3449SJack F Vogel * advertised settings 29521a4e3449SJack F Vogel **/ 29538eb6488eSEric Joyner s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 29541a4e3449SJack F Vogel u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 29551a4e3449SJack F Vogel { 2956fd75b91dSJack F Vogel if ((!(adv_reg)) || (!(lp_reg))) { 2957fd75b91dSJack F Vogel ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, 2958fd75b91dSJack F Vogel "Local or link partner's advertised flow control " 2959fd75b91dSJack F Vogel "settings are NULL. Local: %x, link partner: %x\n", 2960fd75b91dSJack F Vogel adv_reg, lp_reg); 29611a4e3449SJack F Vogel return IXGBE_ERR_FC_NOT_NEGOTIATED; 2962fd75b91dSJack F Vogel } 29631a4e3449SJack F Vogel 29641a4e3449SJack F Vogel if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 29652969bf0eSJack F Vogel /* 29662969bf0eSJack F Vogel * Now we need to check if the user selected Rx ONLY 29672969bf0eSJack F Vogel * of pause frames. In this case, we had to advertise 29682969bf0eSJack F Vogel * FULL flow control because we could not advertise RX 29692969bf0eSJack F Vogel * ONLY. Hence, we must now check to see if we need to 29702969bf0eSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 29712969bf0eSJack F Vogel */ 29722969bf0eSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 29732969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 29742969bf0eSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 29752969bf0eSJack F Vogel } else { 29762969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29772969bf0eSJack F Vogel DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 29782969bf0eSJack F Vogel } 29791a4e3449SJack F Vogel } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 29801a4e3449SJack F Vogel (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29812969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 29822969bf0eSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 29831a4e3449SJack F Vogel } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 29841a4e3449SJack F Vogel !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29852969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29862969bf0eSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 29872969bf0eSJack F Vogel } else { 29882969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 29892969bf0eSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 29902969bf0eSJack F Vogel } 29911a4e3449SJack F Vogel return IXGBE_SUCCESS; 29921b6e0dbaSJack F Vogel } 29931b6e0dbaSJack F Vogel 29940ac6dfecSJack F Vogel /** 2995a621e3c8SJack F Vogel * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 29960ac6dfecSJack F Vogel * @hw: pointer to hardware structure 29970ac6dfecSJack F Vogel * 2998a621e3c8SJack F Vogel * Enable flow control according on 1 gig fiber. 29990ac6dfecSJack F Vogel **/ 3000a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 30010ac6dfecSJack F Vogel { 3002a621e3c8SJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 3003a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 30040ac6dfecSJack F Vogel 3005a621e3c8SJack F Vogel /* 3006a621e3c8SJack F Vogel * On multispeed fiber at 1g, bail out if 3007a621e3c8SJack F Vogel * - link is up but AN did not complete, or if 3008a621e3c8SJack F Vogel * - link is up and AN completed but timed out 3009a621e3c8SJack F Vogel */ 30102969bf0eSJack F Vogel 3011a621e3c8SJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 3012a621e3c8SJack F Vogel if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 3013fd75b91dSJack F Vogel (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 3014758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); 30150ac6dfecSJack F Vogel goto out; 3016fd75b91dSJack F Vogel } 30170ac6dfecSJack F Vogel 3018a621e3c8SJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 3019a621e3c8SJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 30200ac6dfecSJack F Vogel 3021a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 3022a621e3c8SJack F Vogel pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 3023a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE, 3024a621e3c8SJack F Vogel IXGBE_PCS1GANA_SYM_PAUSE, 3025a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE); 30260ac6dfecSJack F Vogel 30270ac6dfecSJack F Vogel out: 30280ac6dfecSJack F Vogel return ret_val; 30290ac6dfecSJack F Vogel } 30301b6e0dbaSJack F Vogel 303113705f88SJack F Vogel /** 3032a621e3c8SJack F Vogel * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 3033a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3034a621e3c8SJack F Vogel * 3035a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3036a621e3c8SJack F Vogel **/ 3037a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 3038a621e3c8SJack F Vogel { 3039a621e3c8SJack F Vogel u32 links2, anlp1_reg, autoc_reg, links; 3040a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3041a621e3c8SJack F Vogel 3042a621e3c8SJack F Vogel /* 3043a621e3c8SJack F Vogel * On backplane, bail out if 3044a621e3c8SJack F Vogel * - backplane autoneg was not completed, or if 3045a621e3c8SJack F Vogel * - we are 82599 and link partner is not AN enabled 3046a621e3c8SJack F Vogel */ 3047a621e3c8SJack F Vogel links = IXGBE_READ_REG(hw, IXGBE_LINKS); 3048fd75b91dSJack F Vogel if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { 3049758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete\n"); 3050a621e3c8SJack F Vogel goto out; 3051fd75b91dSJack F Vogel } 3052a621e3c8SJack F Vogel 3053a621e3c8SJack F Vogel if (hw->mac.type == ixgbe_mac_82599EB) { 3054a621e3c8SJack F Vogel links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 3055fd75b91dSJack F Vogel if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { 3056758cc3dcSJack F Vogel DEBUGOUT("Link partner is not AN enabled\n"); 3057a621e3c8SJack F Vogel goto out; 3058a621e3c8SJack F Vogel } 3059fd75b91dSJack F Vogel } 3060a621e3c8SJack F Vogel /* 3061a621e3c8SJack F Vogel * Read the 10g AN autoc and LP ability registers and resolve 3062a621e3c8SJack F Vogel * local flow control settings accordingly 3063a621e3c8SJack F Vogel */ 3064a621e3c8SJack F Vogel autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3065a621e3c8SJack F Vogel anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 3066a621e3c8SJack F Vogel 3067a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 3068a621e3c8SJack F Vogel anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 3069a621e3c8SJack F Vogel IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 3070a621e3c8SJack F Vogel 3071a621e3c8SJack F Vogel out: 3072a621e3c8SJack F Vogel return ret_val; 3073a621e3c8SJack F Vogel } 3074a621e3c8SJack F Vogel 3075a621e3c8SJack F Vogel /** 3076a621e3c8SJack F Vogel * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 3077a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3078a621e3c8SJack F Vogel * 3079a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3080a621e3c8SJack F Vogel **/ 3081a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 3082a621e3c8SJack F Vogel { 3083a621e3c8SJack F Vogel u16 technology_ability_reg = 0; 3084a621e3c8SJack F Vogel u16 lp_technology_ability_reg = 0; 3085a621e3c8SJack F Vogel 3086a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 3087a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3088a621e3c8SJack F Vogel &technology_ability_reg); 3089a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, 3090a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3091a621e3c8SJack F Vogel &lp_technology_ability_reg); 3092a621e3c8SJack F Vogel 3093a621e3c8SJack F Vogel return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 3094a621e3c8SJack F Vogel (u32)lp_technology_ability_reg, 3095a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 3096a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 3097a621e3c8SJack F Vogel } 3098a621e3c8SJack F Vogel 3099a621e3c8SJack F Vogel /** 3100a621e3c8SJack F Vogel * ixgbe_fc_autoneg - Configure flow control 3101a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3102a621e3c8SJack F Vogel * 3103a621e3c8SJack F Vogel * Compares our advertised flow control capabilities to those advertised by 3104a621e3c8SJack F Vogel * our link partner, and determines the proper flow control mode to use. 3105a621e3c8SJack F Vogel **/ 3106a621e3c8SJack F Vogel void ixgbe_fc_autoneg(struct ixgbe_hw *hw) 3107a621e3c8SJack F Vogel { 3108a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3109a621e3c8SJack F Vogel ixgbe_link_speed speed; 3110a621e3c8SJack F Vogel bool link_up; 3111a621e3c8SJack F Vogel 3112a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 3113a621e3c8SJack F Vogel 3114a621e3c8SJack F Vogel /* 3115a621e3c8SJack F Vogel * AN should have completed when the cable was plugged in. 3116a621e3c8SJack F Vogel * Look for reasons to bail out. Bail out if: 3117a621e3c8SJack F Vogel * - FC autoneg is disabled, or if 3118a621e3c8SJack F Vogel * - link is not up. 3119a621e3c8SJack F Vogel */ 3120fd75b91dSJack F Vogel if (hw->fc.disable_fc_autoneg) { 3121f511cd22SGuinan Sun /* TODO: This should be just an informative log */ 3122f511cd22SGuinan Sun ERROR_REPORT1(IXGBE_ERROR_CAUTION, 3123fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3124a621e3c8SJack F Vogel goto out; 3125fd75b91dSJack F Vogel } 3126a621e3c8SJack F Vogel 3127a621e3c8SJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3128fd75b91dSJack F Vogel if (!link_up) { 3129fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3130a621e3c8SJack F Vogel goto out; 3131fd75b91dSJack F Vogel } 3132a621e3c8SJack F Vogel 3133a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3134a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 31350ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3136758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3137a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3138a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3139a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3140a621e3c8SJack F Vogel break; 3141a621e3c8SJack F Vogel 3142a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3143a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3144a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3145a621e3c8SJack F Vogel break; 3146a621e3c8SJack F Vogel 3147a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3148a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3149fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3150a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3151a621e3c8SJack F Vogel break; 3152a621e3c8SJack F Vogel 3153a621e3c8SJack F Vogel default: 3154a621e3c8SJack F Vogel break; 3155a621e3c8SJack F Vogel } 3156a621e3c8SJack F Vogel 3157a621e3c8SJack F Vogel out: 3158a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 3159a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = TRUE; 3160a621e3c8SJack F Vogel } else { 3161a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = FALSE; 3162a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3163a621e3c8SJack F Vogel } 3164a621e3c8SJack F Vogel } 3165a621e3c8SJack F Vogel 3166fd75b91dSJack F Vogel /* 3167fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3168fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3169fd75b91dSJack F Vogel * 3170fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3171fd75b91dSJack F Vogel * 3172fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3173fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3174fd75b91dSJack F Vogel * 800 = 80 millisec. 3175fd75b91dSJack F Vogel */ 3176fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3177fd75b91dSJack F Vogel { 3178fd75b91dSJack F Vogel s16 devctl2; 3179fd75b91dSJack F Vogel u32 pollcnt; 3180fd75b91dSJack F Vogel 3181fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3182fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3183fd75b91dSJack F Vogel 3184fd75b91dSJack F Vogel switch (devctl2) { 3185fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3186fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3187fd75b91dSJack F Vogel break; 3188fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3189fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3190fd75b91dSJack F Vogel break; 3191fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3192fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3193fd75b91dSJack F Vogel break; 3194fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3195fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3196fd75b91dSJack F Vogel break; 3197fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3198fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3199fd75b91dSJack F Vogel break; 3200fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3201fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3202fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3203fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3204fd75b91dSJack F Vogel default: 3205fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3206fd75b91dSJack F Vogel break; 3207fd75b91dSJack F Vogel } 3208fd75b91dSJack F Vogel 3209fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3210fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3211fd75b91dSJack F Vogel } 3212fd75b91dSJack F Vogel 3213a621e3c8SJack F Vogel /** 321413705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 321513705f88SJack F Vogel * @hw: pointer to hardware structure 321613705f88SJack F Vogel * 321713705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 321813705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 321913705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 322013705f88SJack F Vogel * is returned signifying master requests disabled. 322113705f88SJack F Vogel **/ 322213705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 322313705f88SJack F Vogel { 3224c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3225fd75b91dSJack F Vogel u32 i, poll; 3226758cc3dcSJack F Vogel u16 value; 322713705f88SJack F Vogel 32282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_pcie_master"); 32292969bf0eSJack F Vogel 323085d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 323185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 323285d0a26eSJack F Vogel 3233fd75b91dSJack F Vogel /* Exit if master requests are blocked */ 3234758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3235758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3236c0014855SJack F Vogel goto out; 3237c0014855SJack F Vogel 323885d0a26eSJack F Vogel /* Poll for master request bit to clear */ 323913705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 324085d0a26eSJack F Vogel usec_delay(100); 3241c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3242182b3808SJack F Vogel goto out; 324385d0a26eSJack F Vogel } 3244c0014855SJack F Vogel 3245c0014855SJack F Vogel /* 3246c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 3247c0014855SJack F Vogel * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine 3248c0014855SJack F Vogel * of this need. The first reset prevents new master requests from 324985d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3250c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3251c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3252c0014855SJack F Vogel */ 325385d0a26eSJack F Vogel DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); 3254c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3255c0014855SJack F Vogel 3256a9ca1c79SSean Bruno if (hw->mac.type >= ixgbe_mac_X550) 3257a9ca1c79SSean Bruno goto out; 3258a9ca1c79SSean Bruno 325985d0a26eSJack F Vogel /* 326085d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 326185d0a26eSJack F Vogel * transactions pending. 326285d0a26eSJack F Vogel */ 3263fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3264fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 326585d0a26eSJack F Vogel usec_delay(100); 3266758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3267758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3268758cc3dcSJack F Vogel goto out; 3269758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 327085d0a26eSJack F Vogel goto out; 327185d0a26eSJack F Vogel } 327285d0a26eSJack F Vogel 3273fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3274fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 327585d0a26eSJack F Vogel status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 327685d0a26eSJack F Vogel 3277c0014855SJack F Vogel out: 327813705f88SJack F Vogel return status; 327913705f88SJack F Vogel } 328013705f88SJack F Vogel 328113705f88SJack F Vogel /** 32829ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 328313705f88SJack F Vogel * @hw: pointer to hardware structure 32849ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 328513705f88SJack F Vogel * 328685d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 328713705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 328813705f88SJack F Vogel **/ 3289758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 329013705f88SJack F Vogel { 3291fd75b91dSJack F Vogel u32 gssr = 0; 329213705f88SJack F Vogel u32 swmask = mask; 329313705f88SJack F Vogel u32 fwmask = mask << 5; 3294fd75b91dSJack F Vogel u32 timeout = 200; 3295fd75b91dSJack F Vogel u32 i; 329613705f88SJack F Vogel 32972969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 32982969bf0eSJack F Vogel 3299fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 33000ac6dfecSJack F Vogel /* 3301fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3302fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 33030ac6dfecSJack F Vogel */ 330413705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 33052969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 330613705f88SJack F Vogel 330713705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3308fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 330913705f88SJack F Vogel gssr |= swmask; 331013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 331113705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 331213705f88SJack F Vogel return IXGBE_SUCCESS; 3313fd75b91dSJack F Vogel } else { 3314fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3315fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3316fd75b91dSJack F Vogel msec_delay(5); 3317fd75b91dSJack F Vogel } 3318fd75b91dSJack F Vogel } 3319fd75b91dSJack F Vogel 3320fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3321fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3322fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3323fd75b91dSJack F Vogel 3324fd75b91dSJack F Vogel msec_delay(5); 3325fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 332613705f88SJack F Vogel } 332713705f88SJack F Vogel 332813705f88SJack F Vogel /** 332913705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 333013705f88SJack F Vogel * @hw: pointer to hardware structure 33319ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 333213705f88SJack F Vogel * 333385d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 333413705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 333513705f88SJack F Vogel **/ 3336758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 333713705f88SJack F Vogel { 333813705f88SJack F Vogel u32 gssr; 333913705f88SJack F Vogel u32 swmask = mask; 334013705f88SJack F Vogel 33412969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 33422969bf0eSJack F Vogel 334313705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 334413705f88SJack F Vogel 334513705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 334613705f88SJack F Vogel gssr &= ~swmask; 334713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 334813705f88SJack F Vogel 334913705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 33500ac6dfecSJack F Vogel } 33510ac6dfecSJack F Vogel 33520ac6dfecSJack F Vogel /** 335385d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 335485d0a26eSJack F Vogel * @hw: pointer to hardware structure 335585d0a26eSJack F Vogel * 335685d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 335785d0a26eSJack F Vogel * the Rx security block 335885d0a26eSJack F Vogel **/ 335985d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 336085d0a26eSJack F Vogel { 336185d0a26eSJack F Vogel #define IXGBE_MAX_SECRX_POLL 40 336285d0a26eSJack F Vogel 336385d0a26eSJack F Vogel int i; 336485d0a26eSJack F Vogel int secrxreg; 336585d0a26eSJack F Vogel 336685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 336785d0a26eSJack F Vogel 336885d0a26eSJack F Vogel 336985d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 337085d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 337185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 337285d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 337385d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 337485d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 337585d0a26eSJack F Vogel break; 337685d0a26eSJack F Vogel else 337785d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 337885d0a26eSJack F Vogel usec_delay(1000); 337985d0a26eSJack F Vogel } 338085d0a26eSJack F Vogel 338185d0a26eSJack F Vogel /* For informational purposes only */ 338285d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 338385d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 338485d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 338585d0a26eSJack F Vogel 338685d0a26eSJack F Vogel return IXGBE_SUCCESS; 338785d0a26eSJack F Vogel } 338885d0a26eSJack F Vogel 338985d0a26eSJack F Vogel /** 3390758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3391758cc3dcSJack F Vogel * @hw: pointer to hardware structure 33927d48aa4cSEric Joyner * @locked: bool to indicate whether the SW/FW lock was taken 3393758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3394758cc3dcSJack F Vogel * 3395758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3396758cc3dcSJack F Vogel */ 3397758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3398758cc3dcSJack F Vogel { 3399758cc3dcSJack F Vogel *locked = FALSE; 3400758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3401758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3402758cc3dcSJack F Vogel } 3403758cc3dcSJack F Vogel 3404758cc3dcSJack F Vogel /** 3405758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3406758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3407758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3408758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3409758cc3dcSJack F Vogel * previous read. 3410758cc3dcSJack F Vogel * 3411758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3412758cc3dcSJack F Vogel */ 3413758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3414758cc3dcSJack F Vogel { 3415758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3416758cc3dcSJack F Vogel 3417758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3418758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3419758cc3dcSJack F Vogel } 3420758cc3dcSJack F Vogel 3421758cc3dcSJack F Vogel /** 342285d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 342385d0a26eSJack F Vogel * @hw: pointer to hardware structure 342485d0a26eSJack F Vogel * 342585d0a26eSJack F Vogel * Enables the receive data path. 342685d0a26eSJack F Vogel **/ 342785d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 342885d0a26eSJack F Vogel { 34298eb6488eSEric Joyner u32 secrxreg; 343085d0a26eSJack F Vogel 343185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 343285d0a26eSJack F Vogel 343385d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 343485d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 343585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 343685d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 343785d0a26eSJack F Vogel 343885d0a26eSJack F Vogel return IXGBE_SUCCESS; 343985d0a26eSJack F Vogel } 344085d0a26eSJack F Vogel 344185d0a26eSJack F Vogel /** 34420ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 34430ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34440ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 34450ac6dfecSJack F Vogel * 34460ac6dfecSJack F Vogel * Enables the Rx DMA unit 34470ac6dfecSJack F Vogel **/ 34480ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 34490ac6dfecSJack F Vogel { 34502969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 34512969bf0eSJack F Vogel 3452758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3453758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3454758cc3dcSJack F Vogel else 3455758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 34560ac6dfecSJack F Vogel 34570ac6dfecSJack F Vogel return IXGBE_SUCCESS; 34580ac6dfecSJack F Vogel } 34590ac6dfecSJack F Vogel 34600ac6dfecSJack F Vogel /** 34610ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 34620ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34630ac6dfecSJack F Vogel * @index: led number to blink 34640ac6dfecSJack F Vogel **/ 34650ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 34660ac6dfecSJack F Vogel { 34670ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 34680ac6dfecSJack F Vogel bool link_up = 0; 3469758cc3dcSJack F Vogel u32 autoc_reg = 0; 34700ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34710ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3472758cc3dcSJack F Vogel bool locked = FALSE; 34730ac6dfecSJack F Vogel 34742969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 34752969bf0eSJack F Vogel 34768eb6488eSEric Joyner if (index > 3) 34778eb6488eSEric Joyner return IXGBE_ERR_PARAM; 34788eb6488eSEric Joyner 34790ac6dfecSJack F Vogel /* 34800ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 34810ac6dfecSJack F Vogel * Force it if link is down. 34820ac6dfecSJack F Vogel */ 34830ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 34840ac6dfecSJack F Vogel 34850ac6dfecSJack F Vogel if (!link_up) { 3486758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3487758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 34880ecc2ff0SJack F Vogel goto out; 34890ecc2ff0SJack F Vogel 3490d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34910ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 34920ecc2ff0SJack F Vogel 3493758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3494758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3495758cc3dcSJack F Vogel goto out; 3496758cc3dcSJack F Vogel 3497758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34980ac6dfecSJack F Vogel msec_delay(10); 34990ac6dfecSJack F Vogel } 35000ac6dfecSJack F Vogel 35010ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35020ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 35030ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35040ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35050ac6dfecSJack F Vogel 35060ecc2ff0SJack F Vogel out: 35070ecc2ff0SJack F Vogel return ret_val; 35080ac6dfecSJack F Vogel } 35090ac6dfecSJack F Vogel 35100ac6dfecSJack F Vogel /** 35110ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 35120ac6dfecSJack F Vogel * @hw: pointer to hardware structure 35130ac6dfecSJack F Vogel * @index: led number to stop blinking 35140ac6dfecSJack F Vogel **/ 35150ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 35160ac6dfecSJack F Vogel { 3517758cc3dcSJack F Vogel u32 autoc_reg = 0; 35180ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 35190ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3520758cc3dcSJack F Vogel bool locked = FALSE; 35210ac6dfecSJack F Vogel 35222969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 35232969bf0eSJack F Vogel 35248eb6488eSEric Joyner if (index > 3) 35258eb6488eSEric Joyner return IXGBE_ERR_PARAM; 35268eb6488eSEric Joyner 3527758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3528758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3529758cc3dcSJack F Vogel goto out; 3530d8602bb9SJack F Vogel 35310ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 35320ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 35330ac6dfecSJack F Vogel 3534758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3535758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3536758cc3dcSJack F Vogel goto out; 35370ecc2ff0SJack F Vogel 35380ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35390ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 35400ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 35410ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35420ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35430ac6dfecSJack F Vogel 35440ecc2ff0SJack F Vogel out: 35450ecc2ff0SJack F Vogel return ret_val; 354613705f88SJack F Vogel } 354713705f88SJack F Vogel 35482969bf0eSJack F Vogel /** 35492969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 35502969bf0eSJack F Vogel * @hw: pointer to hardware structure 35512969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 35522969bf0eSJack F Vogel * 35532969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 35542969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 35552969bf0eSJack F Vogel * get and set mac_addr routines. 35562969bf0eSJack F Vogel **/ 35572969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 35582969bf0eSJack F Vogel u16 *san_mac_offset) 35592969bf0eSJack F Vogel { 3560fd75b91dSJack F Vogel s32 ret_val; 3561fd75b91dSJack F Vogel 35622969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 35632969bf0eSJack F Vogel 35642969bf0eSJack F Vogel /* 35652969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35662969bf0eSJack F Vogel * available. 35672969bf0eSJack F Vogel */ 3568fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3569fd75b91dSJack F Vogel san_mac_offset); 3570fd75b91dSJack F Vogel if (ret_val) { 3571fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3572fd75b91dSJack F Vogel "eeprom at offset %d failed", 3573fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3574fd75b91dSJack F Vogel } 35752969bf0eSJack F Vogel 3576fd75b91dSJack F Vogel return ret_val; 35772969bf0eSJack F Vogel } 35782969bf0eSJack F Vogel 35792969bf0eSJack F Vogel /** 35802969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 35812969bf0eSJack F Vogel * @hw: pointer to hardware structure 35822969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35832969bf0eSJack F Vogel * 35842969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 35852969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 35862969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 35872969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 35882969bf0eSJack F Vogel **/ 35892969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35902969bf0eSJack F Vogel { 35912969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35922969bf0eSJack F Vogel u8 i; 3593fd75b91dSJack F Vogel s32 ret_val; 35942969bf0eSJack F Vogel 35952969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 35962969bf0eSJack F Vogel 35972969bf0eSJack F Vogel /* 35982969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35992969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 36002969bf0eSJack F Vogel */ 3601fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3602fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 36032969bf0eSJack F Vogel goto san_mac_addr_out; 36042969bf0eSJack F Vogel 36052969bf0eSJack F Vogel /* make sure we know which port we need to program */ 36062969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36072969bf0eSJack F Vogel /* apply the port offset to the address offset */ 36082969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36092969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36102969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3611fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3612fd75b91dSJack F Vogel &san_mac_data); 3613fd75b91dSJack F Vogel if (ret_val) { 3614fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3615fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3616fd75b91dSJack F Vogel san_mac_offset); 3617fd75b91dSJack F Vogel goto san_mac_addr_out; 3618fd75b91dSJack F Vogel } 36192969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 36202969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 36212969bf0eSJack F Vogel san_mac_offset++; 36222969bf0eSJack F Vogel } 3623fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36242969bf0eSJack F Vogel 36252969bf0eSJack F Vogel san_mac_addr_out: 3626fd75b91dSJack F Vogel /* 3627fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3628fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3629fd75b91dSJack F Vogel */ 3630fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3631fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 36322969bf0eSJack F Vogel return IXGBE_SUCCESS; 36332969bf0eSJack F Vogel } 36342969bf0eSJack F Vogel 36352969bf0eSJack F Vogel /** 36362969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 36372969bf0eSJack F Vogel * @hw: pointer to hardware structure 36382969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 36392969bf0eSJack F Vogel * 36402969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 36412969bf0eSJack F Vogel **/ 36422969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 36432969bf0eSJack F Vogel { 3644fd75b91dSJack F Vogel s32 ret_val; 36452969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 36462969bf0eSJack F Vogel u8 i; 36472969bf0eSJack F Vogel 36482969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 36492969bf0eSJack F Vogel 36502969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3651fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3652fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3653fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 36542969bf0eSJack F Vogel 36552969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 36562969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36572969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 36582969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36592969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36602969bf0eSJack F Vogel 36612969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 36622969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 36632969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 36642969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 36652969bf0eSJack F Vogel san_mac_offset++; 36662969bf0eSJack F Vogel } 36672969bf0eSJack F Vogel 3668fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36692969bf0eSJack F Vogel } 36702969bf0eSJack F Vogel 36712969bf0eSJack F Vogel /** 36722969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 36732969bf0eSJack F Vogel * @hw: pointer to hardware structure 36742969bf0eSJack F Vogel * 36752969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 36762969bf0eSJack F Vogel * the capabilities table. 36772969bf0eSJack F Vogel **/ 3678a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 36792969bf0eSJack F Vogel { 3680a621e3c8SJack F Vogel u16 msix_count = 1; 3681a621e3c8SJack F Vogel u16 max_msix_count; 3682a621e3c8SJack F Vogel u16 pcie_offset; 3683a621e3c8SJack F Vogel 3684a621e3c8SJack F Vogel switch (hw->mac.type) { 3685a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3686a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3687a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3688a621e3c8SJack F Vogel break; 3689a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3690a621e3c8SJack F Vogel case ixgbe_mac_X540: 3691758cc3dcSJack F Vogel case ixgbe_mac_X550: 3692758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 36938eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3694a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3695a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3696a621e3c8SJack F Vogel break; 3697a621e3c8SJack F Vogel default: 3698a621e3c8SJack F Vogel return msix_count; 3699a621e3c8SJack F Vogel } 37002969bf0eSJack F Vogel 37012969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3702a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3703758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3704758cc3dcSJack F Vogel msix_count = 0; 37052969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 37062969bf0eSJack F Vogel 3707a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 37082969bf0eSJack F Vogel msix_count++; 3709a621e3c8SJack F Vogel 3710a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3711a621e3c8SJack F Vogel msix_count = max_msix_count; 37122969bf0eSJack F Vogel 37132969bf0eSJack F Vogel return msix_count; 37142969bf0eSJack F Vogel } 37152969bf0eSJack F Vogel 37162969bf0eSJack F Vogel /** 37172969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 37182969bf0eSJack F Vogel * @hw: pointer to hardware structure 37192969bf0eSJack F Vogel * @addr: Address to put into receive address register 37202969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 37212969bf0eSJack F Vogel * 37222969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 3723c19c7afeSEric Joyner * finds the rar that it is already in; adds to the pool list 37242969bf0eSJack F Vogel **/ 37252969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 37262969bf0eSJack F Vogel { 37272969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 37282969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 37292969bf0eSJack F Vogel u32 rar; 37302969bf0eSJack F Vogel u32 rar_low, rar_high; 37312969bf0eSJack F Vogel u32 addr_low, addr_high; 37322969bf0eSJack F Vogel 37332969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 37342969bf0eSJack F Vogel 37352969bf0eSJack F Vogel /* swap bytes for HW little endian */ 37362969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 37372969bf0eSJack F Vogel | (addr[2] << 16) 37382969bf0eSJack F Vogel | (addr[3] << 24); 37392969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 37402969bf0eSJack F Vogel 37412969bf0eSJack F Vogel /* 37422969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 37432969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 37442969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 37452969bf0eSJack F Vogel * rar to the top. 37462969bf0eSJack F Vogel */ 37472969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 37482969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 37492969bf0eSJack F Vogel 37502969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 37512969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 37522969bf0eSJack F Vogel first_empty_rar = rar; 37532969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 37542969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 37552969bf0eSJack F Vogel if (rar_low == addr_low) 37562969bf0eSJack F Vogel break; /* found it already in the rars */ 37572969bf0eSJack F Vogel } 37582969bf0eSJack F Vogel } 37592969bf0eSJack F Vogel 37602969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 37612969bf0eSJack F Vogel /* already there so just add to the pool bits */ 37622969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 37632969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 37642969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 37652969bf0eSJack F Vogel rar = first_empty_rar; 37662969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37672969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 37682969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 37692969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37702969bf0eSJack F Vogel hw->mac.rar_highwater++; 37712969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 37722969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 37732969bf0eSJack F Vogel } 37742969bf0eSJack F Vogel 37752969bf0eSJack F Vogel /* 37762969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 37772969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 37782969bf0eSJack F Vogel */ 37792969bf0eSJack F Vogel if (rar == 0) 37802969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 37812969bf0eSJack F Vogel 37822969bf0eSJack F Vogel return rar; 37832969bf0eSJack F Vogel } 37842969bf0eSJack F Vogel 37852969bf0eSJack F Vogel /** 37862969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 37872969bf0eSJack F Vogel * @hw: pointer to hardware struct 37882969bf0eSJack F Vogel * @rar: receive address register index to disassociate 37892969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 37902969bf0eSJack F Vogel **/ 37912969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37922969bf0eSJack F Vogel { 37932969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 37942969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37952969bf0eSJack F Vogel 37962969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 37972969bf0eSJack F Vogel 37981a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37991a4e3449SJack F Vogel if (rar >= rar_entries) { 3800fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3801fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38021a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38031a4e3449SJack F Vogel } 38041a4e3449SJack F Vogel 38052969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38062969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38072969bf0eSJack F Vogel 3808758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3809758cc3dcSJack F Vogel goto done; 3810758cc3dcSJack F Vogel 38112969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 38122969bf0eSJack F Vogel goto done; 38132969bf0eSJack F Vogel 38142969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 38152969bf0eSJack F Vogel if (mpsar_lo) { 38162969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 38178270b717SGuinan Sun mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38182969bf0eSJack F Vogel } 38192969bf0eSJack F Vogel if (mpsar_hi) { 38202969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 38218270b717SGuinan Sun mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38222969bf0eSJack F Vogel } 38232969bf0eSJack F Vogel } else if (vmdq < 32) { 38242969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 38252969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 38262969bf0eSJack F Vogel } else { 38272969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 38282969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 38292969bf0eSJack F Vogel } 38302969bf0eSJack F Vogel 38312969bf0eSJack F Vogel /* was that the last pool using this rar? */ 38328eb6488eSEric Joyner if (mpsar_lo == 0 && mpsar_hi == 0 && 38338eb6488eSEric Joyner rar != 0 && rar != hw->mac.san_mac_rar_index) 38342969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 38352969bf0eSJack F Vogel done: 38362969bf0eSJack F Vogel return IXGBE_SUCCESS; 38372969bf0eSJack F Vogel } 38382969bf0eSJack F Vogel 38392969bf0eSJack F Vogel /** 38402969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 38412969bf0eSJack F Vogel * @hw: pointer to hardware struct 38422969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 38432969bf0eSJack F Vogel * @vmdq: VMDq pool index 38442969bf0eSJack F Vogel **/ 38452969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 38462969bf0eSJack F Vogel { 38472969bf0eSJack F Vogel u32 mpsar; 38482969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 38492969bf0eSJack F Vogel 38502969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 38512969bf0eSJack F Vogel 38521a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 38531a4e3449SJack F Vogel if (rar >= rar_entries) { 3854fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3855fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38561a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38571a4e3449SJack F Vogel } 38581a4e3449SJack F Vogel 38592969bf0eSJack F Vogel if (vmdq < 32) { 38602969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38612969bf0eSJack F Vogel mpsar |= 1 << vmdq; 38622969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 38632969bf0eSJack F Vogel } else { 38642969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38652969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 38662969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 38672969bf0eSJack F Vogel } 38682969bf0eSJack F Vogel return IXGBE_SUCCESS; 38692969bf0eSJack F Vogel } 38702969bf0eSJack F Vogel 38712969bf0eSJack F Vogel /** 3872a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3873a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3874a621e3c8SJack F Vogel * VFs advertized and not 0. 3875a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3876a621e3c8SJack F Vogel * 3877a621e3c8SJack F Vogel * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address 3878a621e3c8SJack F Vogel * @hw: pointer to hardware struct 3879a621e3c8SJack F Vogel * @vmdq: VMDq pool index 3880a621e3c8SJack F Vogel **/ 3881a621e3c8SJack F Vogel s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 3882a621e3c8SJack F Vogel { 3883a621e3c8SJack F Vogel u32 rar = hw->mac.san_mac_rar_index; 3884a621e3c8SJack F Vogel 3885a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_san_mac"); 3886a621e3c8SJack F Vogel 3887a621e3c8SJack F Vogel if (vmdq < 32) { 3888a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); 3889a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 3890a621e3c8SJack F Vogel } else { 3891a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 3892a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); 3893a621e3c8SJack F Vogel } 3894a621e3c8SJack F Vogel 3895a621e3c8SJack F Vogel return IXGBE_SUCCESS; 3896a621e3c8SJack F Vogel } 3897a621e3c8SJack F Vogel 3898a621e3c8SJack F Vogel /** 38992969bf0eSJack F Vogel * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 39002969bf0eSJack F Vogel * @hw: pointer to hardware structure 39012969bf0eSJack F Vogel **/ 39022969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 39032969bf0eSJack F Vogel { 39042969bf0eSJack F Vogel int i; 39052969bf0eSJack F Vogel 39062969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_uta_tables_generic"); 39072969bf0eSJack F Vogel DEBUGOUT(" Clearing UTA\n"); 39082969bf0eSJack F Vogel 39092969bf0eSJack F Vogel for (i = 0; i < 128; i++) 39102969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 39112969bf0eSJack F Vogel 39122969bf0eSJack F Vogel return IXGBE_SUCCESS; 39132969bf0eSJack F Vogel } 39142969bf0eSJack F Vogel 39152969bf0eSJack F Vogel /** 39162969bf0eSJack F Vogel * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 39172969bf0eSJack F Vogel * @hw: pointer to hardware structure 39182969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39197d48aa4cSEric Joyner * @vlvf_bypass: TRUE to find vlanid only, FALSE returns first empty slot if 39207d48aa4cSEric Joyner * vlanid not found 39217d48aa4cSEric Joyner * 39222969bf0eSJack F Vogel * 39232969bf0eSJack F Vogel * return the VLVF index where this VLAN id should be placed 39242969bf0eSJack F Vogel * 39252969bf0eSJack F Vogel **/ 39268eb6488eSEric Joyner s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) 39272969bf0eSJack F Vogel { 39288eb6488eSEric Joyner s32 regindex, first_empty_slot; 39298eb6488eSEric Joyner u32 bits; 39302969bf0eSJack F Vogel 3931c0014855SJack F Vogel /* short cut the special case */ 3932c0014855SJack F Vogel if (vlan == 0) 3933c0014855SJack F Vogel return 0; 3934c0014855SJack F Vogel 39358eb6488eSEric Joyner /* if vlvf_bypass is set we don't want to use an empty slot, we 39368eb6488eSEric Joyner * will simply bypass the VLVF if there are no entries present in the 39378eb6488eSEric Joyner * VLVF that contain our VLAN 39382969bf0eSJack F Vogel */ 39398eb6488eSEric Joyner first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0; 39408eb6488eSEric Joyner 39418eb6488eSEric Joyner /* add VLAN enable bit for comparison */ 39428eb6488eSEric Joyner vlan |= IXGBE_VLVF_VIEN; 39438eb6488eSEric Joyner 39448eb6488eSEric Joyner /* Search for the vlan id in the VLVF entries. Save off the first empty 39458eb6488eSEric Joyner * slot found along the way. 39468eb6488eSEric Joyner * 39478eb6488eSEric Joyner * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 39488eb6488eSEric Joyner */ 39498eb6488eSEric Joyner for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { 39502969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 39518eb6488eSEric Joyner if (bits == vlan) 39522969bf0eSJack F Vogel return regindex; 39538eb6488eSEric Joyner if (!first_empty_slot && !bits) 39548eb6488eSEric Joyner first_empty_slot = regindex; 39558eb6488eSEric Joyner } 39568eb6488eSEric Joyner 39578eb6488eSEric Joyner /* If we are here then we didn't find the VLAN. Return first empty 39588eb6488eSEric Joyner * slot we found during our search, else error. 39598eb6488eSEric Joyner */ 39608eb6488eSEric Joyner if (!first_empty_slot) 39618eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); 39628eb6488eSEric Joyner 39638eb6488eSEric Joyner return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE; 39642969bf0eSJack F Vogel } 39652969bf0eSJack F Vogel 39662969bf0eSJack F Vogel /** 39672969bf0eSJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 39682969bf0eSJack F Vogel * @hw: pointer to hardware structure 39692969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39708eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 39718eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN 39728eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 39732969bf0eSJack F Vogel * 39742969bf0eSJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 39752969bf0eSJack F Vogel **/ 39762969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 39778eb6488eSEric Joyner bool vlan_on, bool vlvf_bypass) 39782969bf0eSJack F Vogel { 39798eb6488eSEric Joyner u32 regidx, vfta_delta, vfta; 39808eb6488eSEric Joyner s32 ret_val; 39812969bf0eSJack F Vogel 39822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vfta_generic"); 39832969bf0eSJack F Vogel 39848eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 39852969bf0eSJack F Vogel return IXGBE_ERR_PARAM; 39862969bf0eSJack F Vogel 39872969bf0eSJack F Vogel /* 39882969bf0eSJack F Vogel * this is a 2 part operation - first the VFTA, then the 39892969bf0eSJack F Vogel * VLVF and VLVFB if VT Mode is set 3990c0014855SJack F Vogel * We don't write the VFTA until we know the VLVF part succeeded. 39912969bf0eSJack F Vogel */ 39922969bf0eSJack F Vogel 39932969bf0eSJack F Vogel /* Part 1 39942969bf0eSJack F Vogel * The VFTA is a bitstring made up of 128 32-bit registers 39952969bf0eSJack F Vogel * that enable the particular VLAN id, much like the MTA: 39962969bf0eSJack F Vogel * bits[11-5]: which register 39972969bf0eSJack F Vogel * bits[4-0]: which bit in the register 39982969bf0eSJack F Vogel */ 39998eb6488eSEric Joyner regidx = vlan / 32; 40008eb6488eSEric Joyner vfta_delta = 1 << (vlan % 32); 40018eb6488eSEric Joyner vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); 40022969bf0eSJack F Vogel 40038eb6488eSEric Joyner /* 40048eb6488eSEric Joyner * vfta_delta represents the difference between the current value 40058eb6488eSEric Joyner * of vfta and the value we want in the register. Since the diff 40068eb6488eSEric Joyner * is an XOR mask we can just update the vfta using an XOR 40078eb6488eSEric Joyner */ 40088eb6488eSEric Joyner vfta_delta &= vlan_on ? ~vfta : vfta; 40098eb6488eSEric Joyner vfta ^= vfta_delta; 40102969bf0eSJack F Vogel 40112969bf0eSJack F Vogel /* Part 2 401285d0a26eSJack F Vogel * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF 401385d0a26eSJack F Vogel */ 40148eb6488eSEric Joyner ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta, 40158eb6488eSEric Joyner vfta, vlvf_bypass); 40168eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS) { 40178eb6488eSEric Joyner if (vlvf_bypass) 40188eb6488eSEric Joyner goto vfta_update; 401985d0a26eSJack F Vogel return ret_val; 40208eb6488eSEric Joyner } 402185d0a26eSJack F Vogel 40228eb6488eSEric Joyner vfta_update: 40238eb6488eSEric Joyner /* Update VFTA now that we are ready for traffic */ 40248eb6488eSEric Joyner if (vfta_delta) 40258eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 402685d0a26eSJack F Vogel 402785d0a26eSJack F Vogel return IXGBE_SUCCESS; 402885d0a26eSJack F Vogel } 402985d0a26eSJack F Vogel 403085d0a26eSJack F Vogel /** 403185d0a26eSJack F Vogel * ixgbe_set_vlvf_generic - Set VLAN Pool Filter 403285d0a26eSJack F Vogel * @hw: pointer to hardware structure 403385d0a26eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 40348eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 40358eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN in VLVF 40368eb6488eSEric Joyner * @vfta_delta: pointer to the difference between the current value of VFTA 40378eb6488eSEric Joyner * and the desired value 40388eb6488eSEric Joyner * @vfta: the desired value of the VFTA 40398eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 404085d0a26eSJack F Vogel * 404185d0a26eSJack F Vogel * Turn on/off specified bit in VLVF table. 404285d0a26eSJack F Vogel **/ 404385d0a26eSJack F Vogel s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 40448eb6488eSEric Joyner bool vlan_on, u32 *vfta_delta, u32 vfta, 40458eb6488eSEric Joyner bool vlvf_bypass) 404685d0a26eSJack F Vogel { 40478eb6488eSEric Joyner u32 bits; 40488eb6488eSEric Joyner s32 vlvf_index; 404985d0a26eSJack F Vogel 405085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_vlvf_generic"); 405185d0a26eSJack F Vogel 40528eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 405385d0a26eSJack F Vogel return IXGBE_ERR_PARAM; 405485d0a26eSJack F Vogel 405585d0a26eSJack F Vogel /* If VT Mode is set 40562969bf0eSJack F Vogel * Either vlan_on 40572969bf0eSJack F Vogel * make sure the vlan is in VLVF 40582969bf0eSJack F Vogel * set the vind bit in the matching VLVFB 40592969bf0eSJack F Vogel * Or !vlan_on 40602969bf0eSJack F Vogel * clear the pool bit and possibly the vind 40612969bf0eSJack F Vogel */ 40628eb6488eSEric Joyner if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) 40638eb6488eSEric Joyner return IXGBE_SUCCESS; 4064c0014855SJack F Vogel 40658eb6488eSEric Joyner vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); 4066c0014855SJack F Vogel if (vlvf_index < 0) 4067c0014855SJack F Vogel return vlvf_index; 40682969bf0eSJack F Vogel 40698eb6488eSEric Joyner bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); 40708eb6488eSEric Joyner 40712969bf0eSJack F Vogel /* set the pool bit */ 40728eb6488eSEric Joyner bits |= 1 << (vind % 32); 40738eb6488eSEric Joyner if (vlan_on) 40748eb6488eSEric Joyner goto vlvf_update; 40758eb6488eSEric Joyner 40762969bf0eSJack F Vogel /* clear the pool bit */ 40778eb6488eSEric Joyner bits ^= 1 << (vind % 32); 40788eb6488eSEric Joyner 40798eb6488eSEric Joyner if (!bits && 40808eb6488eSEric Joyner !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { 40818eb6488eSEric Joyner /* Clear VFTA first, then disable VLVF. Otherwise 40828eb6488eSEric Joyner * we run the risk of stray packets leaking into 40838eb6488eSEric Joyner * the PF via the default pool 40848eb6488eSEric Joyner */ 40858eb6488eSEric Joyner if (*vfta_delta) 40868eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta); 40878eb6488eSEric Joyner 40888eb6488eSEric Joyner /* disable VLVF and clear remaining bit from pool */ 40898eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 40908eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); 40918eb6488eSEric Joyner 40928eb6488eSEric Joyner return IXGBE_SUCCESS; 40932969bf0eSJack F Vogel } 40942969bf0eSJack F Vogel 40958eb6488eSEric Joyner /* If there are still bits set in the VLVFB registers 4096c0014855SJack F Vogel * for the VLAN ID indicated we need to see if the 4097c0014855SJack F Vogel * caller is requesting that we clear the VFTA entry bit. 4098c0014855SJack F Vogel * If the caller has requested that we clear the VFTA 4099c0014855SJack F Vogel * entry bit but there are still pools/VFs using this VLAN 4100c0014855SJack F Vogel * ID entry then ignore the request. We're not worried 4101c0014855SJack F Vogel * about the case where we're turning the VFTA VLAN ID 4102c0014855SJack F Vogel * entry bit on, only when requested to turn it off as 4103c0014855SJack F Vogel * there may be multiple pools and/or VFs using the 4104c0014855SJack F Vogel * VLAN ID entry. In that case we cannot clear the 4105c0014855SJack F Vogel * VFTA bit until all pools/VFs using that VLAN ID have also 4106c0014855SJack F Vogel * been cleared. This will be indicated by "bits" being 4107c0014855SJack F Vogel * zero. 4108c0014855SJack F Vogel */ 41098eb6488eSEric Joyner *vfta_delta = 0; 41108eb6488eSEric Joyner 41118eb6488eSEric Joyner vlvf_update: 41128eb6488eSEric Joyner /* record pool change and enable VLAN ID if not already enabled */ 41138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); 41148eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); 4115c0014855SJack F Vogel 41162969bf0eSJack F Vogel return IXGBE_SUCCESS; 41172969bf0eSJack F Vogel } 41182969bf0eSJack F Vogel 41192969bf0eSJack F Vogel /** 41202969bf0eSJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 41212969bf0eSJack F Vogel * @hw: pointer to hardware structure 41222969bf0eSJack F Vogel * 41232969bf0eSJack F Vogel * Clears the VLAN filer table, and the VMDq index associated with the filter 41242969bf0eSJack F Vogel **/ 41252969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 41262969bf0eSJack F Vogel { 41272969bf0eSJack F Vogel u32 offset; 41282969bf0eSJack F Vogel 41292969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vfta_generic"); 41302969bf0eSJack F Vogel 41312969bf0eSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 41322969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 41332969bf0eSJack F Vogel 41342969bf0eSJack F Vogel for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 41352969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 41362969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 4137c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); 41382969bf0eSJack F Vogel } 41392969bf0eSJack F Vogel 41402969bf0eSJack F Vogel return IXGBE_SUCCESS; 41412969bf0eSJack F Vogel } 41422969bf0eSJack F Vogel 41432969bf0eSJack F Vogel /** 41448eb6488eSEric Joyner * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix 41458eb6488eSEric Joyner * @hw: pointer to hardware structure 41468eb6488eSEric Joyner * 41478eb6488eSEric Joyner * Contains the logic to identify if we need to verify link for the 41488eb6488eSEric Joyner * crosstalk fix 41498eb6488eSEric Joyner **/ 41508eb6488eSEric Joyner static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) 41518eb6488eSEric Joyner { 41528eb6488eSEric Joyner 41538eb6488eSEric Joyner /* Does FW say we need the fix */ 41548eb6488eSEric Joyner if (!hw->need_crosstalk_fix) 41558eb6488eSEric Joyner return FALSE; 41568eb6488eSEric Joyner 41578eb6488eSEric Joyner /* Only consider SFP+ PHYs i.e. media type fiber */ 41588eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 41598eb6488eSEric Joyner case ixgbe_media_type_fiber: 41608eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 41618eb6488eSEric Joyner break; 41628eb6488eSEric Joyner default: 41638eb6488eSEric Joyner return FALSE; 41648eb6488eSEric Joyner } 41658eb6488eSEric Joyner 41668eb6488eSEric Joyner return TRUE; 41678eb6488eSEric Joyner } 41688eb6488eSEric Joyner 41698eb6488eSEric Joyner /** 41702969bf0eSJack F Vogel * ixgbe_check_mac_link_generic - Determine link and speed status 41712969bf0eSJack F Vogel * @hw: pointer to hardware structure 41722969bf0eSJack F Vogel * @speed: pointer to link speed 41732969bf0eSJack F Vogel * @link_up: TRUE when link is up 41742969bf0eSJack F Vogel * @link_up_wait_to_complete: bool used to wait for link up or not 41752969bf0eSJack F Vogel * 41762969bf0eSJack F Vogel * Reads the links register to determine if link is up and the current speed 41772969bf0eSJack F Vogel **/ 41782969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 41792969bf0eSJack F Vogel bool *link_up, bool link_up_wait_to_complete) 41802969bf0eSJack F Vogel { 4181c0014855SJack F Vogel u32 links_reg, links_orig; 41822969bf0eSJack F Vogel u32 i; 41832969bf0eSJack F Vogel 41842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_check_mac_link_generic"); 41852969bf0eSJack F Vogel 41868eb6488eSEric Joyner /* If Crosstalk fix enabled do the sanity check of making sure 41878eb6488eSEric Joyner * the SFP+ cage is full. 41888eb6488eSEric Joyner */ 41898eb6488eSEric Joyner if (ixgbe_need_crosstalk_fix(hw)) { 41908eb6488eSEric Joyner u32 sfp_cage_full; 41918eb6488eSEric Joyner 41928eb6488eSEric Joyner switch (hw->mac.type) { 41938eb6488eSEric Joyner case ixgbe_mac_82599EB: 41948eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 41958eb6488eSEric Joyner IXGBE_ESDP_SDP2; 41968eb6488eSEric Joyner break; 41978eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 41988eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 41998eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 42008eb6488eSEric Joyner IXGBE_ESDP_SDP0; 42018eb6488eSEric Joyner break; 42028eb6488eSEric Joyner default: 42038eb6488eSEric Joyner /* sanity check - No SFP+ devices here */ 42048eb6488eSEric Joyner sfp_cage_full = FALSE; 42058eb6488eSEric Joyner break; 42068eb6488eSEric Joyner } 42078eb6488eSEric Joyner 42088eb6488eSEric Joyner if (!sfp_cage_full) { 42098eb6488eSEric Joyner *link_up = FALSE; 42108eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42118eb6488eSEric Joyner return IXGBE_SUCCESS; 42128eb6488eSEric Joyner } 42138eb6488eSEric Joyner } 42148eb6488eSEric Joyner 4215c0014855SJack F Vogel /* clear the old state */ 4216c0014855SJack F Vogel links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 4217c0014855SJack F Vogel 42182969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 4219c0014855SJack F Vogel 4220c0014855SJack F Vogel if (links_orig != links_reg) { 4221c0014855SJack F Vogel DEBUGOUT2("LINKS changed from %08X to %08X\n", 4222c0014855SJack F Vogel links_orig, links_reg); 4223c0014855SJack F Vogel } 4224c0014855SJack F Vogel 42252969bf0eSJack F Vogel if (link_up_wait_to_complete) { 4226a9ca1c79SSean Bruno for (i = 0; i < hw->mac.max_link_up_time; i++) { 42272969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) { 42282969bf0eSJack F Vogel *link_up = TRUE; 42292969bf0eSJack F Vogel break; 42302969bf0eSJack F Vogel } else { 42312969bf0eSJack F Vogel *link_up = FALSE; 42322969bf0eSJack F Vogel } 42332969bf0eSJack F Vogel msec_delay(100); 42342969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 42352969bf0eSJack F Vogel } 42362969bf0eSJack F Vogel } else { 42372969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) 42382969bf0eSJack F Vogel *link_up = TRUE; 42392969bf0eSJack F Vogel else 42402969bf0eSJack F Vogel *link_up = FALSE; 42412969bf0eSJack F Vogel } 42422969bf0eSJack F Vogel 4243758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4244758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 42452969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4246758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4247758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4248758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4249758cc3dcSJack F Vogel } 4250758cc3dcSJack F Vogel break; 4251758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 42522969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4253758cc3dcSJack F Vogel break; 4254758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 42552969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 42568eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550) { 4257758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4258758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4259758cc3dcSJack F Vogel } 4260758cc3dcSJack F Vogel break; 42618eb6488eSEric Joyner case IXGBE_LINKS_SPEED_10_X550EM_A: 42628eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42638eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 42647d48aa4cSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) 42658eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_10_FULL; 42668eb6488eSEric Joyner break; 4267758cc3dcSJack F Vogel default: 42681a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4269758cc3dcSJack F Vogel } 42702969bf0eSJack F Vogel 42712969bf0eSJack F Vogel return IXGBE_SUCCESS; 42722969bf0eSJack F Vogel } 42732969bf0eSJack F Vogel 42742969bf0eSJack F Vogel /** 42752969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 42762969bf0eSJack F Vogel * the EEPROM 42772969bf0eSJack F Vogel * @hw: pointer to hardware structure 42782969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 42792969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 42802969bf0eSJack F Vogel * 42812969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 42822969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 42832969bf0eSJack F Vogel **/ 42842969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 42852969bf0eSJack F Vogel u16 *wwpn_prefix) 42862969bf0eSJack F Vogel { 42872969bf0eSJack F Vogel u16 offset, caps; 42882969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 42892969bf0eSJack F Vogel 42902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 42912969bf0eSJack F Vogel 42922969bf0eSJack F Vogel /* clear output first */ 42932969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 42942969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 42952969bf0eSJack F Vogel 42962969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4297fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4298fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4299fd75b91dSJack F Vogel goto wwn_prefix_err; 43002969bf0eSJack F Vogel 43012969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 43022969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 43032969bf0eSJack F Vogel goto wwn_prefix_out; 43042969bf0eSJack F Vogel 43052969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 43062969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4307fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4308fd75b91dSJack F Vogel goto wwn_prefix_err; 43092969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 43102969bf0eSJack F Vogel goto wwn_prefix_out; 43112969bf0eSJack F Vogel 43122969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 43132969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4314fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4315fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4316fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4317fd75b91dSJack F Vogel } 43182969bf0eSJack F Vogel 43192969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4320fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4321fd75b91dSJack F Vogel goto wwn_prefix_err; 43222969bf0eSJack F Vogel 43232969bf0eSJack F Vogel wwn_prefix_out: 43242969bf0eSJack F Vogel return IXGBE_SUCCESS; 4325fd75b91dSJack F Vogel 4326fd75b91dSJack F Vogel wwn_prefix_err: 4327fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4328fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4329fd75b91dSJack F Vogel return IXGBE_SUCCESS; 43302969bf0eSJack F Vogel } 43311a4e3449SJack F Vogel 43321a4e3449SJack F Vogel /** 43331a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 43341a4e3449SJack F Vogel * @hw: pointer to hardware structure 43351a4e3449SJack F Vogel * @bs: the fcoe boot status 43361a4e3449SJack F Vogel * 43371a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 43381a4e3449SJack F Vogel **/ 43391a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 43401a4e3449SJack F Vogel { 43411a4e3449SJack F Vogel u16 offset, caps, flags; 43421a4e3449SJack F Vogel s32 status; 43431a4e3449SJack F Vogel 43441a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 43451a4e3449SJack F Vogel 43461a4e3449SJack F Vogel /* clear output first */ 43471a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 43481a4e3449SJack F Vogel 43491a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 43501a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 43511a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 43521a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43531a4e3449SJack F Vogel goto out; 43541a4e3449SJack F Vogel 43551a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 43561a4e3449SJack F Vogel goto out; 43571a4e3449SJack F Vogel 43581a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 43591a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 43601a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43611a4e3449SJack F Vogel goto out; 43621a4e3449SJack F Vogel 43631a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 43641a4e3449SJack F Vogel goto out; 43651a4e3449SJack F Vogel 43661a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 43671a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 43681a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 43691a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43701a4e3449SJack F Vogel goto out; 43711a4e3449SJack F Vogel 43721a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 43731a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 43741a4e3449SJack F Vogel else 43751a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 43761a4e3449SJack F Vogel 43771a4e3449SJack F Vogel out: 43781a4e3449SJack F Vogel return status; 43791a4e3449SJack F Vogel } 43801a4e3449SJack F Vogel 43811a4e3449SJack F Vogel /** 43821a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 43831a4e3449SJack F Vogel * @hw: pointer to hardware structure 43848eb6488eSEric Joyner * @enable: enable or disable switch for MAC anti-spoofing 43858eb6488eSEric Joyner * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 43861a4e3449SJack F Vogel * 43871a4e3449SJack F Vogel **/ 43888eb6488eSEric Joyner void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 43891a4e3449SJack F Vogel { 43908eb6488eSEric Joyner int vf_target_reg = vf >> 3; 43918eb6488eSEric Joyner int vf_target_shift = vf % 8; 43928eb6488eSEric Joyner u32 pfvfspoof; 43931a4e3449SJack F Vogel 43941a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 43951a4e3449SJack F Vogel return; 43961a4e3449SJack F Vogel 43978eb6488eSEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 43981a4e3449SJack F Vogel if (enable) 43998eb6488eSEric Joyner pfvfspoof |= (1 << vf_target_shift); 44008eb6488eSEric Joyner else 44018eb6488eSEric Joyner pfvfspoof &= ~(1 << vf_target_shift); 44028eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44031a4e3449SJack F Vogel } 44041a4e3449SJack F Vogel 44051a4e3449SJack F Vogel /** 44061a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 44071a4e3449SJack F Vogel * @hw: pointer to hardware structure 44081a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4409758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 44101a4e3449SJack F Vogel * 44111a4e3449SJack F Vogel **/ 44121a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44131a4e3449SJack F Vogel { 44141a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 44151a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 44161a4e3449SJack F Vogel u32 pfvfspoof; 44171a4e3449SJack F Vogel 44181a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44191a4e3449SJack F Vogel return; 44201a4e3449SJack F Vogel 44211a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44221a4e3449SJack F Vogel if (enable) 44231a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 44241a4e3449SJack F Vogel else 44251a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 44261a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44271a4e3449SJack F Vogel } 4428182b3808SJack F Vogel 4429182b3808SJack F Vogel /** 4430182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4431182b3808SJack F Vogel * @hw: pointer to hardware structure 4432182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4433182b3808SJack F Vogel * 4434182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4435182b3808SJack F Vogel * and return the word through device_caps. 4436182b3808SJack F Vogel **/ 4437182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4438182b3808SJack F Vogel { 4439182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4440182b3808SJack F Vogel 4441182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4442182b3808SJack F Vogel 4443182b3808SJack F Vogel return IXGBE_SUCCESS; 4444182b3808SJack F Vogel } 4445182b3808SJack F Vogel 4446182b3808SJack F Vogel /** 4447182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4448182b3808SJack F Vogel * @hw: pointer to hardware structure 4449182b3808SJack F Vogel * 4450182b3808SJack F Vogel **/ 4451182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4452182b3808SJack F Vogel { 4453182b3808SJack F Vogel u32 regval; 4454182b3808SJack F Vogel u32 i; 4455182b3808SJack F Vogel 4456182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4457182b3808SJack F Vogel 4458182b3808SJack F Vogel /* Enable relaxed ordering */ 4459182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4460182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4461a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4462182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4463182b3808SJack F Vogel } 4464182b3808SJack F Vogel 4465182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4466182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4467a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4468a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4469182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4470182b3808SJack F Vogel } 4471182b3808SJack F Vogel 4472182b3808SJack F Vogel } 447385d0a26eSJack F Vogel 447485d0a26eSJack F Vogel /** 447585d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 447685d0a26eSJack F Vogel * @buffer: pointer to EEPROM 447785d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 447885d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 447985d0a26eSJack F Vogel * checksum calculated is returned. 448085d0a26eSJack F Vogel **/ 44810ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 448285d0a26eSJack F Vogel { 448385d0a26eSJack F Vogel u32 i; 448485d0a26eSJack F Vogel u8 sum = 0; 448585d0a26eSJack F Vogel 448685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 448785d0a26eSJack F Vogel 448885d0a26eSJack F Vogel if (!buffer) 448985d0a26eSJack F Vogel return 0; 449085d0a26eSJack F Vogel 449185d0a26eSJack F Vogel for (i = 0; i < length; i++) 449285d0a26eSJack F Vogel sum += buffer[i]; 449385d0a26eSJack F Vogel 449485d0a26eSJack F Vogel return (u8) (0 - sum); 449585d0a26eSJack F Vogel } 449685d0a26eSJack F Vogel 449785d0a26eSJack F Vogel /** 44988eb6488eSEric Joyner * ixgbe_hic_unlocked - Issue command to manageability block unlocked 449985d0a26eSJack F Vogel * @hw: pointer to the HW structure 45008eb6488eSEric Joyner * @buffer: command to write and where the return status will be placed 4501a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4502758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 450385d0a26eSJack F Vogel * 450485d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 45058eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45068eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45078eb6488eSEric Joyner * 45088eb6488eSEric Joyner * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 45098eb6488eSEric Joyner * by the caller. 451085d0a26eSJack F Vogel **/ 45118eb6488eSEric Joyner s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 45128eb6488eSEric Joyner u32 timeout) 451385d0a26eSJack F Vogel { 45148eb6488eSEric Joyner u32 hicr, i, fwsts; 4515758cc3dcSJack F Vogel u16 dword_len; 451685d0a26eSJack F Vogel 45178eb6488eSEric Joyner DEBUGFUNC("ixgbe_hic_unlocked"); 451885d0a26eSJack F Vogel 45198eb6488eSEric Joyner if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4520758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4521758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 452285d0a26eSJack F Vogel } 45238eb6488eSEric Joyner 4524758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4525758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4526758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 452785d0a26eSJack F Vogel 452885d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 452985d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 45308eb6488eSEric Joyner if (!(hicr & IXGBE_HICR_EN)) { 453185d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4532758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 453385d0a26eSJack F Vogel } 453485d0a26eSJack F Vogel 4535758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 45368eb6488eSEric Joyner if (length % sizeof(u32)) { 4537758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4538758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4539758cc3dcSJack F Vogel } 4540758cc3dcSJack F Vogel 454185d0a26eSJack F Vogel dword_len = length >> 2; 454285d0a26eSJack F Vogel 4543758cc3dcSJack F Vogel /* The device driver writes the relevant command block 454485d0a26eSJack F Vogel * into the ram area. 454585d0a26eSJack F Vogel */ 454685d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 454785d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 454885d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 454985d0a26eSJack F Vogel 455085d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 455185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 455285d0a26eSJack F Vogel 4553758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 455485d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 455585d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 455685d0a26eSJack F Vogel break; 455785d0a26eSJack F Vogel msec_delay(1); 455885d0a26eSJack F Vogel } 455985d0a26eSJack F Vogel 4560c966c431SGuinan Sun /* For each command except "Apply Update" perform 4561c966c431SGuinan Sun * status checks in the HICR registry. 4562c966c431SGuinan Sun */ 4563c966c431SGuinan Sun if ((buffer[0] & IXGBE_HOST_INTERFACE_MASK_CMD) == 4564c966c431SGuinan Sun IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD) 4565c966c431SGuinan Sun return IXGBE_SUCCESS; 4566c966c431SGuinan Sun 4567758cc3dcSJack F Vogel /* Check command completion */ 45688eb6488eSEric Joyner if ((timeout && i == timeout) || 4569758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4570758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4571758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4572758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 457385d0a26eSJack F Vogel } 457485d0a26eSJack F Vogel 45758eb6488eSEric Joyner return IXGBE_SUCCESS; 45768eb6488eSEric Joyner } 45778eb6488eSEric Joyner 45788eb6488eSEric Joyner /** 45798eb6488eSEric Joyner * ixgbe_host_interface_command - Issue command to manageability block 45808eb6488eSEric Joyner * @hw: pointer to the HW structure 45818eb6488eSEric Joyner * @buffer: contains the command to write and where the return status will 45828eb6488eSEric Joyner * be placed 45838eb6488eSEric Joyner * @length: length of buffer, must be multiple of 4 bytes 45848eb6488eSEric Joyner * @timeout: time in ms to wait for command completion 45858eb6488eSEric Joyner * @return_data: read and return data from the buffer (TRUE) or not (FALSE) 45868eb6488eSEric Joyner * Needed because FW structures are big endian and decoding of 45878eb6488eSEric Joyner * these fields can be 8 bit or 16 bit based on command. Decoding 45888eb6488eSEric Joyner * is not easily understood without making a table of commands. 45898eb6488eSEric Joyner * So we will leave this up to the caller to read back the data 45908eb6488eSEric Joyner * in these cases. 45918eb6488eSEric Joyner * 45928eb6488eSEric Joyner * Communicates with the manageability block. On success return IXGBE_SUCCESS 45938eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45948eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45958eb6488eSEric Joyner **/ 45968eb6488eSEric Joyner s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 45978eb6488eSEric Joyner u32 length, u32 timeout, bool return_data) 45988eb6488eSEric Joyner { 45998eb6488eSEric Joyner u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 46007d48aa4cSEric Joyner struct ixgbe_hic_hdr *resp = (struct ixgbe_hic_hdr *)buffer; 46018eb6488eSEric Joyner u16 buf_len; 46028eb6488eSEric Joyner s32 status; 46038eb6488eSEric Joyner u32 bi; 46047d48aa4cSEric Joyner u32 dword_len; 46058eb6488eSEric Joyner 46068eb6488eSEric Joyner DEBUGFUNC("ixgbe_host_interface_command"); 46078eb6488eSEric Joyner 46088eb6488eSEric Joyner if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 46098eb6488eSEric Joyner DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 46108eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND; 46118eb6488eSEric Joyner } 46128eb6488eSEric Joyner 46138eb6488eSEric Joyner /* Take management host interface semaphore */ 46148eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46158eb6488eSEric Joyner if (status) 46168eb6488eSEric Joyner return status; 46178eb6488eSEric Joyner 46188eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 46198eb6488eSEric Joyner if (status) 46208eb6488eSEric Joyner goto rel_out; 46218eb6488eSEric Joyner 4622758cc3dcSJack F Vogel if (!return_data) 46238eb6488eSEric Joyner goto rel_out; 4624758cc3dcSJack F Vogel 462585d0a26eSJack F Vogel /* Calculate length in DWORDs */ 462685d0a26eSJack F Vogel dword_len = hdr_size >> 2; 462785d0a26eSJack F Vogel 462885d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 462985d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 463085d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 463185d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 463285d0a26eSJack F Vogel } 463385d0a26eSJack F Vogel 46347d48aa4cSEric Joyner /* 46357d48aa4cSEric Joyner * If there is any thing in data position pull it in 46367d48aa4cSEric Joyner * Read Flash command requires reading buffer length from 46377d48aa4cSEric Joyner * two byes instead of one byte 46387d48aa4cSEric Joyner */ 463931a23e3eSGuinan Sun if (resp->cmd == IXGBE_HOST_INTERFACE_FLASH_READ_CMD || 464031a23e3eSGuinan Sun resp->cmd == IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD) { 46417d48aa4cSEric Joyner for (; bi < dword_len + 2; bi++) { 46427d48aa4cSEric Joyner buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 46437d48aa4cSEric Joyner bi); 46447d48aa4cSEric Joyner IXGBE_LE32_TO_CPUS(&buffer[bi]); 46457d48aa4cSEric Joyner } 46467d48aa4cSEric Joyner buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 46477d48aa4cSEric Joyner & 0xF00) | resp->buf_len; 46487d48aa4cSEric Joyner hdr_size += (2 << 2); 46497d48aa4cSEric Joyner } else { 46507d48aa4cSEric Joyner buf_len = resp->buf_len; 46517d48aa4cSEric Joyner } 46528eb6488eSEric Joyner if (!buf_len) 46538eb6488eSEric Joyner goto rel_out; 465485d0a26eSJack F Vogel 4655758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 465685d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 46578eb6488eSEric Joyner status = IXGBE_ERR_HOST_INTERFACE_COMMAND; 46588eb6488eSEric Joyner goto rel_out; 465985d0a26eSJack F Vogel } 466085d0a26eSJack F Vogel 466185d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 466285d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 466385d0a26eSJack F Vogel 466485d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 466585d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 466685d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 466785d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 466885d0a26eSJack F Vogel } 466985d0a26eSJack F Vogel 46708eb6488eSEric Joyner rel_out: 46718eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46728eb6488eSEric Joyner 46738eb6488eSEric Joyner return status; 467485d0a26eSJack F Vogel } 467585d0a26eSJack F Vogel 467685d0a26eSJack F Vogel /** 467785d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 467885d0a26eSJack F Vogel * @hw: pointer to the HW structure 467985d0a26eSJack F Vogel * @maj: driver version major number 468085d0a26eSJack F Vogel * @min: driver version minor number 468185d0a26eSJack F Vogel * @build: driver version build number 468285d0a26eSJack F Vogel * @sub: driver version sub build number 46837d48aa4cSEric Joyner * @len: unused 46847d48aa4cSEric Joyner * @driver_ver: unused 468585d0a26eSJack F Vogel * 468685d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 468785d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 468885d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 468985d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 469085d0a26eSJack F Vogel **/ 469185d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 46928eb6488eSEric Joyner u8 build, u8 sub, u16 len, 46938eb6488eSEric Joyner const char *driver_ver) 469485d0a26eSJack F Vogel { 469585d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 469685d0a26eSJack F Vogel int i; 469785d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 469885d0a26eSJack F Vogel 469985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 47008eb6488eSEric Joyner UNREFERENCED_2PARAMETER(len, driver_ver); 470185d0a26eSJack F Vogel 470285d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 470385d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 470485d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 470585d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 470685d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 470785d0a26eSJack F Vogel fw_cmd.ver_min = min; 470885d0a26eSJack F Vogel fw_cmd.ver_build = build; 470985d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 471085d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 471185d0a26eSJack F Vogel fw_cmd.pad = 0; 471285d0a26eSJack F Vogel fw_cmd.pad2 = 0; 47137d48aa4cSEric Joyner fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 47147d48aa4cSEric Joyner (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 471585d0a26eSJack F Vogel 471685d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 471785d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4718758cc3dcSJack F Vogel sizeof(fw_cmd), 4719758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 4720758cc3dcSJack F Vogel TRUE); 472185d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 472285d0a26eSJack F Vogel continue; 472385d0a26eSJack F Vogel 472485d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 472585d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 472685d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 472785d0a26eSJack F Vogel else 472885d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 472985d0a26eSJack F Vogel 473085d0a26eSJack F Vogel break; 473185d0a26eSJack F Vogel } 473285d0a26eSJack F Vogel 473385d0a26eSJack F Vogel return ret_val; 473485d0a26eSJack F Vogel } 473585d0a26eSJack F Vogel 473685d0a26eSJack F Vogel /** 473785d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 473885d0a26eSJack F Vogel * @hw: pointer to hardware structure 473985d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 474085d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 474185d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 474285d0a26eSJack F Vogel **/ 474385d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 474485d0a26eSJack F Vogel int strategy) 474585d0a26eSJack F Vogel { 474685d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 474785d0a26eSJack F Vogel int i = 0; 474885d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 474985d0a26eSJack F Vogel 475085d0a26eSJack F Vogel /* Reserve headroom */ 475185d0a26eSJack F Vogel pbsize -= headroom; 475285d0a26eSJack F Vogel 475385d0a26eSJack F Vogel if (!num_pb) 475485d0a26eSJack F Vogel num_pb = 1; 475585d0a26eSJack F Vogel 475685d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 475785d0a26eSJack F Vogel * buffers requested using supplied strategy. 475885d0a26eSJack F Vogel */ 475985d0a26eSJack F Vogel switch (strategy) { 4760a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 476185d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 476285d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 476385d0a26eSJack F Vogel */ 4764a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 476585d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 476685d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 476785d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 476885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 4769be9f17dbSToomas Soome /* configure remaining packet buffers */ 4770be9f17dbSToomas Soome /* FALLTHROUGH */ 4771a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 477285d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 477385d0a26eSJack F Vogel for (; i < num_pb; i++) 477485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 477585d0a26eSJack F Vogel break; 477685d0a26eSJack F Vogel default: 477785d0a26eSJack F Vogel break; 477885d0a26eSJack F Vogel } 477985d0a26eSJack F Vogel 478085d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 478185d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 478285d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 478385d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 478485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 478585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 478685d0a26eSJack F Vogel } 478785d0a26eSJack F Vogel 478885d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 478985d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 479085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 479185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 479285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 479385d0a26eSJack F Vogel } 479485d0a26eSJack F Vogel } 479585d0a26eSJack F Vogel 479685d0a26eSJack F Vogel /** 479785d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 479885d0a26eSJack F Vogel * @hw: pointer to the hardware structure 479985d0a26eSJack F Vogel * 480085d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 480185d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 480285d0a26eSJack F Vogel * buffers on the system. 480385d0a26eSJack F Vogel **/ 480485d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 480585d0a26eSJack F Vogel { 4806758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4807758cc3dcSJack F Vogel u16 value; 480885d0a26eSJack F Vogel 480985d0a26eSJack F Vogel /* 481085d0a26eSJack F Vogel * If double reset is not requested then all transactions should 481185d0a26eSJack F Vogel * already be clear and as such there is no work to do 481285d0a26eSJack F Vogel */ 481385d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 481485d0a26eSJack F Vogel return; 481585d0a26eSJack F Vogel 481685d0a26eSJack F Vogel /* 481785d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 481885d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 481985d0a26eSJack F Vogel * has already been cleared. 482085d0a26eSJack F Vogel */ 482185d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 482285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 482385d0a26eSJack F Vogel 4824758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4825758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4826758cc3dcSJack F Vogel msec_delay(3); 4827758cc3dcSJack F Vogel 4828758cc3dcSJack F Vogel /* 4829758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4830758cc3dcSJack F Vogel * transactions pending. 4831758cc3dcSJack F Vogel */ 4832758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4833758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4834758cc3dcSJack F Vogel usec_delay(100); 4835758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4836758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4837758cc3dcSJack F Vogel goto out; 4838758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4839758cc3dcSJack F Vogel goto out; 4840758cc3dcSJack F Vogel } 4841758cc3dcSJack F Vogel 4842758cc3dcSJack F Vogel out: 484385d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 484485d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 484585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 484685d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 484785d0a26eSJack F Vogel 484885d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 484985d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 485085d0a26eSJack F Vogel usec_delay(20); 485185d0a26eSJack F Vogel 485285d0a26eSJack F Vogel /* restore previous register values */ 485385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 485485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 485585d0a26eSJack F Vogel } 485685d0a26eSJack F Vogel 48578eb6488eSEric Joyner /** 48588eb6488eSEric Joyner * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW 48598eb6488eSEric Joyner * 48608eb6488eSEric Joyner * @hw: pointer to hardware structure 48618eb6488eSEric Joyner * @cmd: Command we send to the FW 48628eb6488eSEric Joyner * @status: The reply from the FW 48638eb6488eSEric Joyner * 48648eb6488eSEric Joyner * Bit-bangs the cmd to the by_pass FW status points to what is returned. 48658eb6488eSEric Joyner **/ 48668eb6488eSEric Joyner #define IXGBE_BYPASS_BB_WAIT 1 48678eb6488eSEric Joyner s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) 48688eb6488eSEric Joyner { 48698eb6488eSEric Joyner int i; 48708eb6488eSEric Joyner u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; 48718eb6488eSEric Joyner u32 esdp; 48728eb6488eSEric Joyner 48738eb6488eSEric Joyner if (!status) 48748eb6488eSEric Joyner return IXGBE_ERR_PARAM; 48758eb6488eSEric Joyner 48768eb6488eSEric Joyner *status = 0; 48778eb6488eSEric Joyner 48788eb6488eSEric Joyner /* SDP vary by MAC type */ 48798eb6488eSEric Joyner switch (hw->mac.type) { 48808eb6488eSEric Joyner case ixgbe_mac_82599EB: 48818eb6488eSEric Joyner sck = IXGBE_ESDP_SDP7; 48828eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 48838eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP6; 48848eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP7_DIR; 48858eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 48868eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP6_DIR; 48878eb6488eSEric Joyner break; 48888eb6488eSEric Joyner case ixgbe_mac_X540: 48898eb6488eSEric Joyner sck = IXGBE_ESDP_SDP2; 48908eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 48918eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP1; 48928eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP2_DIR; 48938eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 48948eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP1_DIR; 48958eb6488eSEric Joyner break; 48968eb6488eSEric Joyner default: 48978eb6488eSEric Joyner return IXGBE_ERR_DEVICE_NOT_SUPPORTED; 48988eb6488eSEric Joyner } 48998eb6488eSEric Joyner 49008eb6488eSEric Joyner /* Set SDP pins direction */ 49018eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 49028eb6488eSEric Joyner esdp |= dir_sck; /* SCK as output */ 49038eb6488eSEric Joyner esdp |= dir_sdi; /* SDI as output */ 49048eb6488eSEric Joyner esdp &= ~dir_sdo; /* SDO as input */ 49058eb6488eSEric Joyner esdp |= sck; 49068eb6488eSEric Joyner esdp |= sdi; 49078eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49088eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49098eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49108eb6488eSEric Joyner 49118eb6488eSEric Joyner /* Generate start condition */ 49128eb6488eSEric Joyner esdp &= ~sdi; 49138eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49148eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49158eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49168eb6488eSEric Joyner 49178eb6488eSEric Joyner esdp &= ~sck; 49188eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49198eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49208eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49218eb6488eSEric Joyner 49228eb6488eSEric Joyner /* Clock out the new control word and clock in the status */ 49238eb6488eSEric Joyner for (i = 0; i < 32; i++) { 49248eb6488eSEric Joyner if ((cmd >> (31 - i)) & 0x01) { 49258eb6488eSEric Joyner esdp |= sdi; 49268eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49278eb6488eSEric Joyner } else { 49288eb6488eSEric Joyner esdp &= ~sdi; 49298eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49308eb6488eSEric Joyner } 49318eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49328eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49338eb6488eSEric Joyner 49348eb6488eSEric Joyner esdp |= sck; 49358eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49368eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49378eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49388eb6488eSEric Joyner 49398eb6488eSEric Joyner esdp &= ~sck; 49408eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49418eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49428eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49438eb6488eSEric Joyner 49448eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 49458eb6488eSEric Joyner if (esdp & sdo) 49468eb6488eSEric Joyner *status = (*status << 1) | 0x01; 49478eb6488eSEric Joyner else 49488eb6488eSEric Joyner *status = (*status << 1) | 0x00; 49498eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49508eb6488eSEric Joyner } 49518eb6488eSEric Joyner 49528eb6488eSEric Joyner /* stop condition */ 49538eb6488eSEric Joyner esdp |= sck; 49548eb6488eSEric Joyner esdp &= ~sdi; 49558eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49568eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49578eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49588eb6488eSEric Joyner 49598eb6488eSEric Joyner esdp |= sdi; 49608eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49618eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49628eb6488eSEric Joyner 49638eb6488eSEric Joyner /* set the page bits to match the cmd that the status it belongs to */ 49648eb6488eSEric Joyner *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); 49658eb6488eSEric Joyner 49668eb6488eSEric Joyner return IXGBE_SUCCESS; 49678eb6488eSEric Joyner } 49688eb6488eSEric Joyner 49698eb6488eSEric Joyner /** 49708eb6488eSEric Joyner * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. 49718eb6488eSEric Joyner * 49728eb6488eSEric Joyner * If we send a write we can't be sure it took until we can read back 49738eb6488eSEric Joyner * that same register. It can be a problem as some of the feilds may 49748eb6488eSEric Joyner * for valid reasons change inbetween the time wrote the register and 49758eb6488eSEric Joyner * we read it again to verify. So this function check everything we 49768eb6488eSEric Joyner * can check and then assumes it worked. 49778eb6488eSEric Joyner * 49788eb6488eSEric Joyner * @u32 in_reg - The register cmd for the bit-bang read. 49798eb6488eSEric Joyner * @u32 out_reg - The register returned from a bit-bang read. 49808eb6488eSEric Joyner **/ 49818eb6488eSEric Joyner bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) 49828eb6488eSEric Joyner { 49838eb6488eSEric Joyner u32 mask; 49848eb6488eSEric Joyner 49858eb6488eSEric Joyner /* Page must match for all control pages */ 49868eb6488eSEric Joyner if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) 49878eb6488eSEric Joyner return FALSE; 49888eb6488eSEric Joyner 49898eb6488eSEric Joyner switch (in_reg & BYPASS_PAGE_M) { 49908eb6488eSEric Joyner case BYPASS_PAGE_CTL0: 49918eb6488eSEric Joyner /* All the following can't change since the last write 49928eb6488eSEric Joyner * - All the event actions 49938eb6488eSEric Joyner * - The timeout value 49948eb6488eSEric Joyner */ 49958eb6488eSEric Joyner mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | 49968eb6488eSEric Joyner BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | 49978eb6488eSEric Joyner BYPASS_WDTIMEOUT_M | 49988eb6488eSEric Joyner BYPASS_WDT_VALUE_M; 49998eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 50008eb6488eSEric Joyner return FALSE; 50018eb6488eSEric Joyner 50028eb6488eSEric Joyner /* 0x0 is never a valid value for bypass status */ 50038eb6488eSEric Joyner if (!(out_reg & BYPASS_STATUS_OFF_M)) 50048eb6488eSEric Joyner return FALSE; 50058eb6488eSEric Joyner break; 50068eb6488eSEric Joyner case BYPASS_PAGE_CTL1: 50078eb6488eSEric Joyner /* All the following can't change since the last write 50088eb6488eSEric Joyner * - time valid bit 50098eb6488eSEric Joyner * - time we last sent 50108eb6488eSEric Joyner */ 50118eb6488eSEric Joyner mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; 50128eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 50138eb6488eSEric Joyner return FALSE; 50148eb6488eSEric Joyner break; 50158eb6488eSEric Joyner case BYPASS_PAGE_CTL2: 50168eb6488eSEric Joyner /* All we can check in this page is control number 50178eb6488eSEric Joyner * which is already done above. 50188eb6488eSEric Joyner */ 50198eb6488eSEric Joyner break; 50208eb6488eSEric Joyner } 50218eb6488eSEric Joyner 50228eb6488eSEric Joyner /* We are as sure as we can be return TRUE */ 50238eb6488eSEric Joyner return TRUE; 50248eb6488eSEric Joyner } 50258eb6488eSEric Joyner 50268eb6488eSEric Joyner /** 50278eb6488eSEric Joyner * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. 50288eb6488eSEric Joyner * 50298eb6488eSEric Joyner * @hw: pointer to hardware structure 50308eb6488eSEric Joyner * @cmd: The control word we are setting. 50318eb6488eSEric Joyner * @event: The event we are setting in the FW. This also happens to 50328eb6488eSEric Joyner * be the mask for the event we are setting (handy) 50338eb6488eSEric Joyner * @action: The action we set the event to in the FW. This is in a 50348eb6488eSEric Joyner * bit field that happens to be what we want to put in 50358eb6488eSEric Joyner * the event spot (also handy) 50368eb6488eSEric Joyner **/ 50378eb6488eSEric Joyner s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, 50388eb6488eSEric Joyner u32 action) 50398eb6488eSEric Joyner { 50408eb6488eSEric Joyner u32 by_ctl = 0; 50418eb6488eSEric Joyner u32 cmd, verify; 50428eb6488eSEric Joyner u32 count = 0; 50438eb6488eSEric Joyner 50448eb6488eSEric Joyner /* Get current values */ 50458eb6488eSEric Joyner cmd = ctrl; /* just reading only need control number */ 50468eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 50478eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50488eb6488eSEric Joyner 50498eb6488eSEric Joyner /* Set to new action */ 50508eb6488eSEric Joyner cmd = (by_ctl & ~event) | BYPASS_WE | action; 50518eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 50528eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50538eb6488eSEric Joyner 50548eb6488eSEric Joyner /* Page 0 force a FW eeprom write which is slow so verify */ 50558eb6488eSEric Joyner if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { 50568eb6488eSEric Joyner verify = BYPASS_PAGE_CTL0; 50578eb6488eSEric Joyner do { 50588eb6488eSEric Joyner if (count++ > 5) 50598eb6488eSEric Joyner return IXGBE_BYPASS_FW_WRITE_FAILURE; 50608eb6488eSEric Joyner 50618eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) 50628eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50638eb6488eSEric Joyner } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); 50648eb6488eSEric Joyner } else { 50658eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 50668eb6488eSEric Joyner msec_delay(100); 50678eb6488eSEric Joyner } 50688eb6488eSEric Joyner 50698eb6488eSEric Joyner return IXGBE_SUCCESS; 50708eb6488eSEric Joyner } 50718eb6488eSEric Joyner 50728eb6488eSEric Joyner /** 50738eb6488eSEric Joyner * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. 50748eb6488eSEric Joyner * 50758eb6488eSEric Joyner * @hw: pointer to hardware structure 50768eb6488eSEric Joyner * @addr: The bypass eeprom address to read. 50778eb6488eSEric Joyner * @value: The 8b of data at the address above. 50788eb6488eSEric Joyner **/ 50798eb6488eSEric Joyner s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) 50808eb6488eSEric Joyner { 50818eb6488eSEric Joyner u32 cmd; 50828eb6488eSEric Joyner u32 status; 50838eb6488eSEric Joyner 50848eb6488eSEric Joyner 50858eb6488eSEric Joyner /* send the request */ 50868eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 50878eb6488eSEric Joyner cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 50888eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 50898eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50908eb6488eSEric Joyner 50918eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 50928eb6488eSEric Joyner msec_delay(100); 50938eb6488eSEric Joyner 50948eb6488eSEric Joyner /* now read the results */ 50958eb6488eSEric Joyner cmd &= ~BYPASS_WE; 50968eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 50978eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50988eb6488eSEric Joyner 50998eb6488eSEric Joyner *value = status & BYPASS_CTL2_DATA_M; 51008eb6488eSEric Joyner 51018eb6488eSEric Joyner return IXGBE_SUCCESS; 51028eb6488eSEric Joyner } 51038eb6488eSEric Joyner 51047d48aa4cSEric Joyner /** 51057d48aa4cSEric Joyner * ixgbe_get_orom_version - Return option ROM from EEPROM 51067d48aa4cSEric Joyner * 51077d48aa4cSEric Joyner * @hw: pointer to hardware structure 51087d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 51097d48aa4cSEric Joyner * 51107d48aa4cSEric Joyner * if valid option ROM version, nvm_ver->or_valid set to TRUE 51117d48aa4cSEric Joyner * else nvm_ver->or_valid is FALSE. 51127d48aa4cSEric Joyner **/ 51137d48aa4cSEric Joyner void ixgbe_get_orom_version(struct ixgbe_hw *hw, 51147d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 51157d48aa4cSEric Joyner { 51167d48aa4cSEric Joyner u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl; 51177d48aa4cSEric Joyner 51187d48aa4cSEric Joyner nvm_ver->or_valid = FALSE; 51197d48aa4cSEric Joyner /* Option Rom may or may not be present. Start with pointer */ 51207d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset); 51217d48aa4cSEric Joyner 51227d48aa4cSEric Joyner /* make sure offset is valid */ 51237d48aa4cSEric Joyner if ((offset == 0x0) || (offset == NVM_INVALID_PTR)) 51247d48aa4cSEric Joyner return; 51257d48aa4cSEric Joyner 51267d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh); 51277d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl); 51287d48aa4cSEric Joyner 51297d48aa4cSEric Joyner /* option rom exists and is valid */ 51307d48aa4cSEric Joyner if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 || 51317d48aa4cSEric Joyner eeprom_cfg_blkl == NVM_VER_INVALID || 51327d48aa4cSEric Joyner eeprom_cfg_blkh == NVM_VER_INVALID) 51337d48aa4cSEric Joyner return; 51347d48aa4cSEric Joyner 51357d48aa4cSEric Joyner nvm_ver->or_valid = TRUE; 51367d48aa4cSEric Joyner nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT; 51377d48aa4cSEric Joyner nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) | 51387d48aa4cSEric Joyner (eeprom_cfg_blkh >> NVM_OROM_SHIFT); 51397d48aa4cSEric Joyner nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK; 51407d48aa4cSEric Joyner } 51417d48aa4cSEric Joyner 51427d48aa4cSEric Joyner /** 51437d48aa4cSEric Joyner * ixgbe_get_oem_prod_version - Return OEM Product version 51447d48aa4cSEric Joyner * 51457d48aa4cSEric Joyner * @hw: pointer to hardware structure 51467d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 51477d48aa4cSEric Joyner * 51487d48aa4cSEric Joyner * if valid OEM product version, nvm_ver->oem_valid set to TRUE 51497d48aa4cSEric Joyner * else nvm_ver->oem_valid is FALSE. 51507d48aa4cSEric Joyner **/ 51517d48aa4cSEric Joyner void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw, 51527d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 51537d48aa4cSEric Joyner { 51547d48aa4cSEric Joyner u16 rel_num, prod_ver, mod_len, cap, offset; 51557d48aa4cSEric Joyner 51567d48aa4cSEric Joyner nvm_ver->oem_valid = FALSE; 51577d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset); 51587d48aa4cSEric Joyner 5159ab1c54feSEric van Gyzen /* Return if offset to OEM Product Version block is invalid */ 5160ab1c54feSEric van Gyzen if (offset == 0x0 || offset == NVM_INVALID_PTR) 51617d48aa4cSEric Joyner return; 51627d48aa4cSEric Joyner 51637d48aa4cSEric Joyner /* Read product version block */ 51647d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset, &mod_len); 51657d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap); 51667d48aa4cSEric Joyner 51677d48aa4cSEric Joyner /* Return if OEM product version block is invalid */ 51687d48aa4cSEric Joyner if (mod_len != NVM_OEM_PROD_VER_MOD_LEN || 51697d48aa4cSEric Joyner (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0) 51707d48aa4cSEric Joyner return; 51717d48aa4cSEric Joyner 51727d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver); 51737d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num); 51747d48aa4cSEric Joyner 51757d48aa4cSEric Joyner /* Return if version is invalid */ 51767d48aa4cSEric Joyner if ((rel_num | prod_ver) == 0x0 || 51777d48aa4cSEric Joyner rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID) 51787d48aa4cSEric Joyner return; 51797d48aa4cSEric Joyner 51807d48aa4cSEric Joyner nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT; 51817d48aa4cSEric Joyner nvm_ver->oem_minor = prod_ver & NVM_VER_MASK; 51827d48aa4cSEric Joyner nvm_ver->oem_release = rel_num; 51837d48aa4cSEric Joyner nvm_ver->oem_valid = TRUE; 51847d48aa4cSEric Joyner } 51857d48aa4cSEric Joyner 51867d48aa4cSEric Joyner /** 51877d48aa4cSEric Joyner * ixgbe_get_etk_id - Return Etrack ID from EEPROM 51887d48aa4cSEric Joyner * 51897d48aa4cSEric Joyner * @hw: pointer to hardware structure 51907d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 51917d48aa4cSEric Joyner * 51927d48aa4cSEric Joyner * word read errors will return 0xFFFF 51937d48aa4cSEric Joyner **/ 51947d48aa4cSEric Joyner void ixgbe_get_etk_id(struct ixgbe_hw *hw, struct ixgbe_nvm_version *nvm_ver) 51957d48aa4cSEric Joyner { 51967d48aa4cSEric Joyner u16 etk_id_l, etk_id_h; 51977d48aa4cSEric Joyner 51987d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l)) 51997d48aa4cSEric Joyner etk_id_l = NVM_VER_INVALID; 52007d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h)) 52017d48aa4cSEric Joyner etk_id_h = NVM_VER_INVALID; 52027d48aa4cSEric Joyner 52037d48aa4cSEric Joyner /* The word order for the version format is determined by high order 52047d48aa4cSEric Joyner * word bit 15. 52057d48aa4cSEric Joyner */ 52067d48aa4cSEric Joyner if ((etk_id_h & NVM_ETK_VALID) == 0) { 52077d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_h; 52087d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT); 52097d48aa4cSEric Joyner } else { 52107d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_l; 52117d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT); 52127d48aa4cSEric Joyner } 52137d48aa4cSEric Joyner } 52147d48aa4cSEric Joyner 5215fd75b91dSJack F Vogel 5216fd75b91dSJack F Vogel /** 5217fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 5218fd75b91dSJack F Vogel * @hw: pointer to hardware structure 5219fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 5220fd75b91dSJack F Vogel * 5221fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 5222fd75b91dSJack F Vogel **/ 5223fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 5224fd75b91dSJack F Vogel { 5225fd75b91dSJack F Vogel u32 reg, i; 5226fd75b91dSJack F Vogel 5227fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 5228fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 5229fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 5230fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 5231fd75b91dSJack F Vogel return; 5232fd75b91dSJack F Vogel } 5233758cc3dcSJack F Vogel 5234758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 5235758cc3dcSJack F Vogel { 5236758cc3dcSJack F Vogel u32 pfdtxgswc; 5237758cc3dcSJack F Vogel u32 rxctrl; 5238758cc3dcSJack F Vogel 5239758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5240758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 5241758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5242758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5243758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 5244758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 5245758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5246758cc3dcSJack F Vogel hw->mac.set_lben = TRUE; 5247758cc3dcSJack F Vogel } else { 5248758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5249758cc3dcSJack F Vogel } 5250758cc3dcSJack F Vogel } 5251758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 5252758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 5253758cc3dcSJack F Vogel } 5254758cc3dcSJack F Vogel } 5255758cc3dcSJack F Vogel 5256758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 5257758cc3dcSJack F Vogel { 5258758cc3dcSJack F Vogel u32 pfdtxgswc; 5259758cc3dcSJack F Vogel u32 rxctrl; 5260758cc3dcSJack F Vogel 5261758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5262758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 5263758cc3dcSJack F Vogel 5264758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5265758cc3dcSJack F Vogel if (hw->mac.set_lben) { 5266758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5267758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 5268758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5269758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5270758cc3dcSJack F Vogel } 5271758cc3dcSJack F Vogel } 5272758cc3dcSJack F Vogel } 5273758cc3dcSJack F Vogel 5274758cc3dcSJack F Vogel /** 5275758cc3dcSJack F Vogel * ixgbe_mng_present - returns TRUE when management capability is present 5276758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5277758cc3dcSJack F Vogel */ 5278758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 5279758cc3dcSJack F Vogel { 5280758cc3dcSJack F Vogel u32 fwsm; 5281758cc3dcSJack F Vogel 5282758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 5283758cc3dcSJack F Vogel return FALSE; 5284758cc3dcSJack F Vogel 5285a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 52867d48aa4cSEric Joyner 52877d48aa4cSEric Joyner return !!(fwsm & IXGBE_FWSM_FW_MODE_PT); 5288758cc3dcSJack F Vogel } 5289758cc3dcSJack F Vogel 5290758cc3dcSJack F Vogel /** 5291758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 5292758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5293758cc3dcSJack F Vogel * 5294758cc3dcSJack F Vogel * Returns TRUE if the manageability engine is enabled. 5295758cc3dcSJack F Vogel **/ 5296758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 5297758cc3dcSJack F Vogel { 5298758cc3dcSJack F Vogel u32 fwsm, manc, factps; 5299758cc3dcSJack F Vogel 5300a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5301758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 5302758cc3dcSJack F Vogel return FALSE; 5303758cc3dcSJack F Vogel 5304758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 5305758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 5306758cc3dcSJack F Vogel return FALSE; 5307758cc3dcSJack F Vogel 5308758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 5309a9ca1c79SSean Bruno factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 5310758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 5311758cc3dcSJack F Vogel return FALSE; 5312758cc3dcSJack F Vogel } 5313758cc3dcSJack F Vogel 5314758cc3dcSJack F Vogel return TRUE; 5315758cc3dcSJack F Vogel } 5316758cc3dcSJack F Vogel 5317758cc3dcSJack F Vogel /** 5318758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 5319758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5320758cc3dcSJack F Vogel * @speed: new link speed 5321758cc3dcSJack F Vogel * @autoneg_wait_to_complete: TRUE when waiting for completion is needed 5322758cc3dcSJack F Vogel * 5323758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 5324758cc3dcSJack F Vogel **/ 5325758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 5326758cc3dcSJack F Vogel ixgbe_link_speed speed, 5327758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 5328758cc3dcSJack F Vogel { 5329758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5330758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5331758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 5332758cc3dcSJack F Vogel u32 speedcnt = 0; 5333758cc3dcSJack F Vogel u32 i = 0; 5334758cc3dcSJack F Vogel bool autoneg, link_up = FALSE; 5335758cc3dcSJack F Vogel 5336758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 5337758cc3dcSJack F Vogel 5338758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 5339758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 5340758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5341758cc3dcSJack F Vogel return status; 5342758cc3dcSJack F Vogel 5343758cc3dcSJack F Vogel speed &= link_speed; 5344758cc3dcSJack F Vogel 5345758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 5346758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 5347758cc3dcSJack F Vogel */ 5348758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 5349758cc3dcSJack F Vogel speedcnt++; 5350758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 5351758cc3dcSJack F Vogel 5352758cc3dcSJack F Vogel /* Set the module link speed */ 5353758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5354758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5355758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5356758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5357758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 5358758cc3dcSJack F Vogel break; 5359758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5360758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 5361758cc3dcSJack F Vogel break; 5362758cc3dcSJack F Vogel default: 5363758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5364758cc3dcSJack F Vogel break; 5365758cc3dcSJack F Vogel } 5366758cc3dcSJack F Vogel 5367758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 5368758cc3dcSJack F Vogel msec_delay(40); 5369758cc3dcSJack F Vogel 5370758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5371758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 5372758cc3dcSJack F Vogel autoneg_wait_to_complete); 5373758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5374758cc3dcSJack F Vogel return status; 5375758cc3dcSJack F Vogel 5376758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5377758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5378758cc3dcSJack F Vogel 5379758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 5380758cc3dcSJack F Vogel * Section 73.10.2, we may have to wait up to 500ms if KR is 5381758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 5382758cc3dcSJack F Vogel */ 5383*aaa3af80SMatthew Smith for (i = 0; i < 10; i++) { 5384758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5385758cc3dcSJack F Vogel msec_delay(100); 5386758cc3dcSJack F Vogel 5387758cc3dcSJack F Vogel /* If we have link, just jump out */ 5388758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 5389758cc3dcSJack F Vogel &link_up, FALSE); 5390758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5391758cc3dcSJack F Vogel return status; 5392758cc3dcSJack F Vogel 5393758cc3dcSJack F Vogel if (link_up) 5394758cc3dcSJack F Vogel goto out; 5395758cc3dcSJack F Vogel } 5396758cc3dcSJack F Vogel } 5397758cc3dcSJack F Vogel 5398758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 5399758cc3dcSJack F Vogel speedcnt++; 5400758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 5401758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 5402758cc3dcSJack F Vogel 5403758cc3dcSJack F Vogel /* Set the module link speed */ 5404758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5405758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5406758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5407758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5408758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 5409758cc3dcSJack F Vogel break; 5410758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5411758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 5412758cc3dcSJack F Vogel break; 5413758cc3dcSJack F Vogel default: 5414758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5415758cc3dcSJack F Vogel break; 5416758cc3dcSJack F Vogel } 5417758cc3dcSJack F Vogel 5418758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 5419758cc3dcSJack F Vogel msec_delay(40); 5420758cc3dcSJack F Vogel 5421758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5422758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 5423758cc3dcSJack F Vogel autoneg_wait_to_complete); 5424758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5425758cc3dcSJack F Vogel return status; 5426758cc3dcSJack F Vogel 5427758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5428758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5429758cc3dcSJack F Vogel 5430758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5431758cc3dcSJack F Vogel msec_delay(100); 5432758cc3dcSJack F Vogel 5433758cc3dcSJack F Vogel /* If we have link, just jump out */ 5434758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 5435758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5436758cc3dcSJack F Vogel return status; 5437758cc3dcSJack F Vogel 5438758cc3dcSJack F Vogel if (link_up) 5439758cc3dcSJack F Vogel goto out; 5440758cc3dcSJack F Vogel } 5441758cc3dcSJack F Vogel 5442758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 5443758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 5444758cc3dcSJack F Vogel * single highest speed that the user requested. 5445758cc3dcSJack F Vogel */ 5446758cc3dcSJack F Vogel if (speedcnt > 1) 5447758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 5448758cc3dcSJack F Vogel highest_link_speed, 5449758cc3dcSJack F Vogel autoneg_wait_to_complete); 5450758cc3dcSJack F Vogel 5451758cc3dcSJack F Vogel out: 5452758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 5453758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 5454758cc3dcSJack F Vogel 5455758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 5456758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 5457758cc3dcSJack F Vogel 5458758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 5459758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5460758cc3dcSJack F Vogel 5461758cc3dcSJack F Vogel return status; 5462758cc3dcSJack F Vogel } 5463758cc3dcSJack F Vogel 5464758cc3dcSJack F Vogel /** 5465758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 5466758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5467758cc3dcSJack F Vogel * @speed: link speed to set 5468758cc3dcSJack F Vogel * 5469758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 5470758cc3dcSJack F Vogel */ 5471758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 5472758cc3dcSJack F Vogel ixgbe_link_speed speed) 5473758cc3dcSJack F Vogel { 5474758cc3dcSJack F Vogel s32 status; 5475758cc3dcSJack F Vogel u8 rs, eeprom_data; 5476758cc3dcSJack F Vogel 5477758cc3dcSJack F Vogel switch (speed) { 5478758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 5479758cc3dcSJack F Vogel /* one bit mask same as setting on */ 5480758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 5481758cc3dcSJack F Vogel break; 5482758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 5483758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 5484758cc3dcSJack F Vogel break; 5485758cc3dcSJack F Vogel default: 5486758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 5487758cc3dcSJack F Vogel return; 5488758cc3dcSJack F Vogel } 5489758cc3dcSJack F Vogel 5490758cc3dcSJack F Vogel /* Set RS0 */ 5491758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5492758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5493758cc3dcSJack F Vogel &eeprom_data); 5494758cc3dcSJack F Vogel if (status) { 5495758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 5496758cc3dcSJack F Vogel goto out; 5497758cc3dcSJack F Vogel } 5498758cc3dcSJack F Vogel 5499758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5500758cc3dcSJack F Vogel 5501758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5502758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5503758cc3dcSJack F Vogel eeprom_data); 5504758cc3dcSJack F Vogel if (status) { 5505758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 5506758cc3dcSJack F Vogel goto out; 5507758cc3dcSJack F Vogel } 5508758cc3dcSJack F Vogel 5509758cc3dcSJack F Vogel /* Set RS1 */ 5510758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5511758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5512758cc3dcSJack F Vogel &eeprom_data); 5513758cc3dcSJack F Vogel if (status) { 5514758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 5515758cc3dcSJack F Vogel goto out; 5516758cc3dcSJack F Vogel } 5517758cc3dcSJack F Vogel 5518758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5519758cc3dcSJack F Vogel 5520758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5521758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5522758cc3dcSJack F Vogel eeprom_data); 5523758cc3dcSJack F Vogel if (status) { 5524758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 5525758cc3dcSJack F Vogel goto out; 5526758cc3dcSJack F Vogel } 5527758cc3dcSJack F Vogel out: 5528758cc3dcSJack F Vogel return; 5529758cc3dcSJack F Vogel } 5530