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); 226*c19c7afeSEric 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 2728eb6488eSEric Joyner /* fall through - only backplane uses autoc */ 273758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 274758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 275758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 276a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 277758cc3dcSJack F Vogel 278a621e3c8SJack F Vogel break; 279a621e3c8SJack F Vogel case ixgbe_media_type_copper: 280a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 281a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); 282a621e3c8SJack F Vogel break; 283a621e3c8SJack F Vogel default: 284a621e3c8SJack F Vogel break; 285a621e3c8SJack F Vogel } 286a621e3c8SJack F Vogel 287a621e3c8SJack F Vogel /* 288a621e3c8SJack F Vogel * The possible values of fc.requested_mode are: 289a621e3c8SJack F Vogel * 0: Flow control is completely disabled 290a621e3c8SJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 291a621e3c8SJack F Vogel * but not send pause frames). 292a621e3c8SJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 293a621e3c8SJack F Vogel * we do not support receiving pause frames). 294a621e3c8SJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 295a621e3c8SJack F Vogel * other: Invalid. 296a621e3c8SJack F Vogel */ 297a621e3c8SJack F Vogel switch (hw->fc.requested_mode) { 298a621e3c8SJack F Vogel case ixgbe_fc_none: 299a621e3c8SJack F Vogel /* Flow control completely disabled by software override. */ 300a621e3c8SJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 301a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 302a621e3c8SJack F Vogel reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 303a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE); 304a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 305a621e3c8SJack F Vogel reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 306a621e3c8SJack F Vogel break; 307a621e3c8SJack F Vogel case ixgbe_fc_tx_pause: 308a621e3c8SJack F Vogel /* 309a621e3c8SJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 310a621e3c8SJack F Vogel * disabled by software override. 311a621e3c8SJack F Vogel */ 312a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_ASM_PAUSE; 313a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 314a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 315a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 316a621e3c8SJack F Vogel reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 317a621e3c8SJack F Vogel } else if (hw->phy.media_type == ixgbe_media_type_copper) { 318a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_ASM_PAUSE; 319a621e3c8SJack F Vogel reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 320a621e3c8SJack F Vogel } 321a621e3c8SJack F Vogel break; 322a621e3c8SJack F Vogel case ixgbe_fc_rx_pause: 323a621e3c8SJack F Vogel /* 324a621e3c8SJack F Vogel * Rx Flow control is enabled and Tx Flow control is 325a621e3c8SJack F Vogel * disabled by software override. Since there really 326a621e3c8SJack F Vogel * isn't a way to advertise that we are capable of RX 327a621e3c8SJack F Vogel * Pause ONLY, we will advertise that we support both 328a621e3c8SJack F Vogel * symmetric and asymmetric Rx PAUSE, as such we fall 329a621e3c8SJack F Vogel * through to the fc_full statement. Later, we will 330a621e3c8SJack F Vogel * disable the adapter's ability to send PAUSE frames. 331a621e3c8SJack F Vogel */ 332a621e3c8SJack F Vogel case ixgbe_fc_full: 333a621e3c8SJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 334a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 335a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 336a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 337a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE; 338a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 339a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 340a621e3c8SJack F Vogel break; 341a621e3c8SJack F Vogel default: 342fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 343fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 344a621e3c8SJack F Vogel ret_val = IXGBE_ERR_CONFIG; 345a621e3c8SJack F Vogel goto out; 346a621e3c8SJack F Vogel break; 347a621e3c8SJack F Vogel } 348a621e3c8SJack F Vogel 349758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_X540) { 350a621e3c8SJack F Vogel /* 351a621e3c8SJack F Vogel * Enable auto-negotiation between the MAC & PHY; 352a621e3c8SJack F Vogel * the MAC will advertise clause 37 flow control. 353a621e3c8SJack F Vogel */ 354a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 355a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 356a621e3c8SJack F Vogel 357a621e3c8SJack F Vogel /* Disable AN timeout */ 358a621e3c8SJack F Vogel if (hw->fc.strict_ieee) 359a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 360a621e3c8SJack F Vogel 361a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 362a621e3c8SJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 363a621e3c8SJack F Vogel } 364a621e3c8SJack F Vogel 365a621e3c8SJack F Vogel /* 366a621e3c8SJack F Vogel * AUTOC restart handles negotiation of 1G and 10G on backplane 367a621e3c8SJack F Vogel * and copper. There is no need to set the PCS1GCTL register. 368a621e3c8SJack F Vogel * 369a621e3c8SJack F Vogel */ 370a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 371a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_AN_RESTART; 372758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 373758cc3dcSJack F Vogel if (ret_val) 3740ecc2ff0SJack F Vogel goto out; 375a621e3c8SJack F Vogel } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 376fd75b91dSJack F Vogel (ixgbe_device_supports_autoneg_fc(hw))) { 377a621e3c8SJack F Vogel hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 378a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); 379a621e3c8SJack F Vogel } 380a621e3c8SJack F Vogel 381758cc3dcSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 382a621e3c8SJack F Vogel out: 383a621e3c8SJack F Vogel return ret_val; 384a621e3c8SJack F Vogel } 385a621e3c8SJack F Vogel 386a621e3c8SJack F Vogel /** 3879ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 38813705f88SJack F Vogel * @hw: pointer to hardware structure 38913705f88SJack F Vogel * 39013705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 39113705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 39213705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 39313705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 39413705f88SJack F Vogel **/ 39513705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 39613705f88SJack F Vogel { 397a621e3c8SJack F Vogel s32 ret_val; 39813705f88SJack F Vogel u32 ctrl_ext; 3998eb6488eSEric Joyner u16 device_caps; 40013705f88SJack F Vogel 4012969bf0eSJack F Vogel DEBUGFUNC("ixgbe_start_hw_generic"); 4022969bf0eSJack F Vogel 40313705f88SJack F Vogel /* Set the media type */ 4049ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 40513705f88SJack F Vogel 4060ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 40713705f88SJack F Vogel 40813705f88SJack F Vogel /* Clear the VLAN filter table */ 4099ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 41013705f88SJack F Vogel 41113705f88SJack F Vogel /* Clear statistics registers */ 4129ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 41313705f88SJack F Vogel 41413705f88SJack F Vogel /* Set No Snoop Disable */ 41513705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 41613705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 41713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 4189ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 41913705f88SJack F Vogel 4200ac6dfecSJack F Vogel /* Setup flow control */ 421a621e3c8SJack F Vogel ret_val = ixgbe_setup_fc(hw); 4228eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) { 4238eb6488eSEric Joyner DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val); 4248eb6488eSEric Joyner return ret_val; 4258eb6488eSEric Joyner } 4268eb6488eSEric Joyner 4278eb6488eSEric Joyner /* Cache bit indicating need for crosstalk fix */ 4288eb6488eSEric Joyner switch (hw->mac.type) { 4298eb6488eSEric Joyner case ixgbe_mac_82599EB: 4308eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4318eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4328eb6488eSEric Joyner hw->mac.ops.get_device_caps(hw, &device_caps); 4338eb6488eSEric Joyner if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) 4348eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 4358eb6488eSEric Joyner else 4368eb6488eSEric Joyner hw->need_crosstalk_fix = TRUE; 4378eb6488eSEric Joyner break; 4388eb6488eSEric Joyner default: 4398eb6488eSEric Joyner hw->need_crosstalk_fix = FALSE; 4408eb6488eSEric Joyner break; 4418eb6488eSEric Joyner } 4420ac6dfecSJack F Vogel 44313705f88SJack F Vogel /* Clear adapter stopped flag */ 44413705f88SJack F Vogel hw->adapter_stopped = FALSE; 44513705f88SJack F Vogel 4468eb6488eSEric Joyner return IXGBE_SUCCESS; 4471a4e3449SJack F Vogel } 4481a4e3449SJack F Vogel 4491a4e3449SJack F Vogel /** 4501a4e3449SJack F Vogel * ixgbe_start_hw_gen2 - Init sequence for common device family 4511a4e3449SJack F Vogel * @hw: pointer to hw structure 4521a4e3449SJack F Vogel * 4531a4e3449SJack F Vogel * Performs the init sequence common to the second generation 4541a4e3449SJack F Vogel * of 10 GbE devices. 4551a4e3449SJack F Vogel * Devices in the second generation: 4561a4e3449SJack F Vogel * 82599 457182b3808SJack F Vogel * X540 4581a4e3449SJack F Vogel **/ 4591a4e3449SJack F Vogel s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 4601a4e3449SJack F Vogel { 4611a4e3449SJack F Vogel u32 i; 4621a4e3449SJack F Vogel u32 regval; 4631a4e3449SJack F Vogel 4641a4e3449SJack F Vogel /* Clear the rate limiters */ 4651a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4661a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 4671a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 4681a4e3449SJack F Vogel } 4691a4e3449SJack F Vogel IXGBE_WRITE_FLUSH(hw); 4701a4e3449SJack F Vogel 4711a4e3449SJack F Vogel /* Disable relaxed ordering */ 4721a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4731a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 474a621e3c8SJack F Vogel regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4751a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4761a4e3449SJack F Vogel } 4771a4e3449SJack F Vogel 4781a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4791a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 480a621e3c8SJack F Vogel regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | 481a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN); 4821a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4831a4e3449SJack F Vogel } 4841a4e3449SJack F Vogel 4851a4e3449SJack F Vogel return IXGBE_SUCCESS; 48613705f88SJack F Vogel } 48713705f88SJack F Vogel 48813705f88SJack F Vogel /** 48913705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 49013705f88SJack F Vogel * @hw: pointer to hardware structure 49113705f88SJack F Vogel * 4929ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 49313705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 49413705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 49513705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 49613705f88SJack F Vogel * disabled and uninitialized 49713705f88SJack F Vogel **/ 49813705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 49913705f88SJack F Vogel { 5001a4e3449SJack F Vogel s32 status; 5010ac6dfecSJack F Vogel 5022969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 5032969bf0eSJack F Vogel 50413705f88SJack F Vogel /* Reset the hardware */ 5050ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 50613705f88SJack F Vogel 5078eb6488eSEric Joyner if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { 50813705f88SJack F Vogel /* Start the HW */ 5090ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 5100ac6dfecSJack F Vogel } 51113705f88SJack F Vogel 5128eb6488eSEric Joyner /* Initialize the LED link active for LED blink support */ 5138eb6488eSEric Joyner if (hw->mac.ops.init_led_link_act) 5148eb6488eSEric Joyner hw->mac.ops.init_led_link_act(hw); 5158eb6488eSEric Joyner 5168eb6488eSEric Joyner if (status != IXGBE_SUCCESS) 5178eb6488eSEric Joyner DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); 5188eb6488eSEric Joyner 5190ac6dfecSJack F Vogel return status; 52013705f88SJack F Vogel } 52113705f88SJack F Vogel 52213705f88SJack F Vogel /** 52313705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 52413705f88SJack F Vogel * @hw: pointer to hardware structure 52513705f88SJack F Vogel * 52613705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 52713705f88SJack F Vogel * Statistics counters are clear on read. 52813705f88SJack F Vogel **/ 52913705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 53013705f88SJack F Vogel { 53113705f88SJack F Vogel u16 i = 0; 53213705f88SJack F Vogel 5332969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 5342969bf0eSJack F Vogel 53513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 53713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 53813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 53913705f88SJack F Vogel for (i = 0; i < 8; i++) 54013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 54113705f88SJack F Vogel 54213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 54513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 54613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 5470ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5480ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5490ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5500ac6dfecSJack F Vogel } else { 5511b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 55213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5530ac6dfecSJack F Vogel } 55413705f88SJack F Vogel 55513705f88SJack F Vogel for (i = 0; i < 8; i++) { 55613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 55713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5580ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5590ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5600ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5610ac6dfecSJack F Vogel } else { 5621b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 56313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 56413705f88SJack F Vogel } 5650ac6dfecSJack F Vogel } 5660ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5670ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5680ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 56913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 57013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 57113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 57213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 57313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 57413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 57513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 57613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 57713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 57813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 57913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 58013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 58113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 58213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 58385d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 58413705f88SJack F Vogel for (i = 0; i < 8; i++) 58513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 58613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 58713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 58813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 58913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 59013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 59113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 59213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 59313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 59413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 59513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 59613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 59713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 59813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 59913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 60013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 60113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 60213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 60313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 60413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 60513705f88SJack F Vogel for (i = 0; i < 16; i++) { 60613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 60713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 6081a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 6091a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 6101a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 6111a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 6121a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 6131a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 6141a4e3449SJack F Vogel } else { 6151a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 61613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 61713705f88SJack F Vogel } 6181a4e3449SJack F Vogel } 6191a4e3449SJack F Vogel 620758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 62185d0a26eSJack F Vogel if (hw->phy.id == 0) 62285d0a26eSJack F Vogel ixgbe_identify_phy(hw); 62385d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 62485d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62585d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 62685d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62785d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 62885d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62985d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 63085d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 63185d0a26eSJack F Vogel } 63285d0a26eSJack F Vogel 6331a4e3449SJack F Vogel return IXGBE_SUCCESS; 6341a4e3449SJack F Vogel } 6351a4e3449SJack F Vogel 6361a4e3449SJack F Vogel /** 6371a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 6381a4e3449SJack F Vogel * @hw: pointer to hardware structure 6391a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 6401a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 6411a4e3449SJack F Vogel * 6421a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 6431a4e3449SJack F Vogel **/ 6441a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 6451a4e3449SJack F Vogel u32 pba_num_size) 6461a4e3449SJack F Vogel { 6471a4e3449SJack F Vogel s32 ret_val; 6481a4e3449SJack F Vogel u16 data; 6491a4e3449SJack F Vogel u16 pba_ptr; 6501a4e3449SJack F Vogel u16 offset; 6511a4e3449SJack F Vogel u16 length; 6521a4e3449SJack F Vogel 6531a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6541a4e3449SJack F Vogel 6551a4e3449SJack F Vogel if (pba_num == NULL) { 6561a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6571a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6581a4e3449SJack F Vogel } 6591a4e3449SJack F Vogel 6601a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6611a4e3449SJack F Vogel if (ret_val) { 6621a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6631a4e3449SJack F Vogel return ret_val; 6641a4e3449SJack F Vogel } 6651a4e3449SJack F Vogel 6661a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6671a4e3449SJack F Vogel if (ret_val) { 6681a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6691a4e3449SJack F Vogel return ret_val; 6701a4e3449SJack F Vogel } 6711a4e3449SJack F Vogel 6721a4e3449SJack F Vogel /* 6731a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6741a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6751a4e3449SJack F Vogel * and we can decode it into an ascii string 6761a4e3449SJack F Vogel */ 6771a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6781a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6791a4e3449SJack F Vogel 6801a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6811a4e3449SJack F Vogel if (pba_num_size < 11) { 6821a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6831a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6841a4e3449SJack F Vogel } 6851a4e3449SJack F Vogel 6861a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6871a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6881a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6891a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6901a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6911a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6921a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6931a4e3449SJack F Vogel pba_num[6] = '-'; 6941a4e3449SJack F Vogel pba_num[7] = 0; 6951a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6961a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6971a4e3449SJack F Vogel 6981a4e3449SJack F Vogel /* put a null character on the end of our string */ 6991a4e3449SJack F Vogel pba_num[10] = '\0'; 7001a4e3449SJack F Vogel 7011a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 7021a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 7031a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 7041a4e3449SJack F Vogel pba_num[offset] += '0'; 7051a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 7061a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 7071a4e3449SJack F Vogel } 7081a4e3449SJack F Vogel 7091a4e3449SJack F Vogel return IXGBE_SUCCESS; 7101a4e3449SJack F Vogel } 7111a4e3449SJack F Vogel 7121a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 7131a4e3449SJack F Vogel if (ret_val) { 7141a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7151a4e3449SJack F Vogel return ret_val; 7161a4e3449SJack F Vogel } 7171a4e3449SJack F Vogel 7181a4e3449SJack F Vogel if (length == 0xFFFF || length == 0) { 7191a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 7201a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 7211a4e3449SJack F Vogel } 7221a4e3449SJack F Vogel 7231a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 7241a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 7251a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 7261a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 7271a4e3449SJack F Vogel } 7281a4e3449SJack F Vogel 7291a4e3449SJack F Vogel /* trim pba length from start of string */ 7301a4e3449SJack F Vogel pba_ptr++; 7311a4e3449SJack F Vogel length--; 7321a4e3449SJack F Vogel 7331a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 7341a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 7351a4e3449SJack F Vogel if (ret_val) { 7361a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7371a4e3449SJack F Vogel return ret_val; 7381a4e3449SJack F Vogel } 7391a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 7401a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 7411a4e3449SJack F Vogel } 7421a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 7431a4e3449SJack F Vogel 7441a4e3449SJack F Vogel return IXGBE_SUCCESS; 7451a4e3449SJack F Vogel } 7461a4e3449SJack F Vogel 7471a4e3449SJack F Vogel /** 7481b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7499ca4041bSJack F Vogel * @hw: pointer to hardware structure 7509ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7519ca4041bSJack F Vogel * 7529ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7539ca4041bSJack F Vogel **/ 7549ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7559ca4041bSJack F Vogel { 7569ca4041bSJack F Vogel s32 ret_val; 7579ca4041bSJack F Vogel u16 data; 7589ca4041bSJack F Vogel 7599ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7609ca4041bSJack F Vogel 7619ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7629ca4041bSJack F Vogel if (ret_val) { 7639ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7649ca4041bSJack F Vogel return ret_val; 7651a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7661a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7671a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7689ca4041bSJack F Vogel } 7699ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7709ca4041bSJack F Vogel 7719ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7729ca4041bSJack F Vogel if (ret_val) { 7739ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7749ca4041bSJack F Vogel return ret_val; 7759ca4041bSJack F Vogel } 7769ca4041bSJack F Vogel *pba_num |= data; 7779ca4041bSJack F Vogel 7789ca4041bSJack F Vogel return IXGBE_SUCCESS; 7799ca4041bSJack F Vogel } 7809ca4041bSJack F Vogel 7819ca4041bSJack F Vogel /** 7820ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7830ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7840ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7850ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7860ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7870ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7880ecc2ff0SJack F Vogel * 7890ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7900ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7910ecc2ff0SJack F Vogel * 7920ecc2ff0SJack F Vogel **/ 7930ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7940ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7950ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7960ecc2ff0SJack F Vogel { 7970ecc2ff0SJack F Vogel s32 ret_val; 7980ecc2ff0SJack F Vogel u16 pba_block_size; 7990ecc2ff0SJack F Vogel 8000ecc2ff0SJack F Vogel if (pba == NULL) 8010ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8020ecc2ff0SJack F Vogel 8030ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8040ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8050ecc2ff0SJack F Vogel &pba->word[0]); 8060ecc2ff0SJack F Vogel if (ret_val) 8070ecc2ff0SJack F Vogel return ret_val; 8080ecc2ff0SJack F Vogel } else { 8090ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8100ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8110ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8120ecc2ff0SJack F Vogel } else { 8130ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8140ecc2ff0SJack F Vogel } 8150ecc2ff0SJack F Vogel } 8160ecc2ff0SJack F Vogel 8170ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8180ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8190ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8200ecc2ff0SJack F Vogel 8210ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 8220ecc2ff0SJack F Vogel eeprom_buf_size, 8230ecc2ff0SJack F Vogel &pba_block_size); 8240ecc2ff0SJack F Vogel if (ret_val) 8250ecc2ff0SJack F Vogel return ret_val; 8260ecc2ff0SJack F Vogel 8270ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 8280ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8290ecc2ff0SJack F Vogel 8300ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8310ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 8320ecc2ff0SJack F Vogel pba_block_size, 8330ecc2ff0SJack F Vogel pba->pba_block); 8340ecc2ff0SJack F Vogel if (ret_val) 8350ecc2ff0SJack F Vogel return ret_val; 8360ecc2ff0SJack F Vogel } else { 8370ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 838758cc3dcSJack F Vogel pba_block_size)) { 8390ecc2ff0SJack F Vogel memcpy(pba->pba_block, 8400ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 8410ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 8420ecc2ff0SJack F Vogel } else { 8430ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8440ecc2ff0SJack F Vogel } 8450ecc2ff0SJack F Vogel } 8460ecc2ff0SJack F Vogel } 8470ecc2ff0SJack F Vogel 8480ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8490ecc2ff0SJack F Vogel } 8500ecc2ff0SJack F Vogel 8510ecc2ff0SJack F Vogel /** 8520ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8530ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8540ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8550ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8560ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8570ecc2ff0SJack F Vogel * 8580ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8590ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8600ecc2ff0SJack F Vogel * 8610ecc2ff0SJack F Vogel **/ 8620ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8630ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8640ecc2ff0SJack F Vogel { 8650ecc2ff0SJack F Vogel s32 ret_val; 8660ecc2ff0SJack F Vogel 8670ecc2ff0SJack F Vogel if (pba == NULL) 8680ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8690ecc2ff0SJack F Vogel 8700ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8710ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8720ecc2ff0SJack F Vogel &pba->word[0]); 8730ecc2ff0SJack F Vogel if (ret_val) 8740ecc2ff0SJack F Vogel return ret_val; 8750ecc2ff0SJack F Vogel } else { 8760ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8770ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8780ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8790ecc2ff0SJack F Vogel } else { 8800ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8810ecc2ff0SJack F Vogel } 8820ecc2ff0SJack F Vogel } 8830ecc2ff0SJack F Vogel 8840ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8850ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8860ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8870ecc2ff0SJack F Vogel 8880ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8890ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8900ecc2ff0SJack F Vogel pba->pba_block[0], 8910ecc2ff0SJack F Vogel pba->pba_block); 8920ecc2ff0SJack F Vogel if (ret_val) 8930ecc2ff0SJack F Vogel return ret_val; 8940ecc2ff0SJack F Vogel } else { 8950ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8960ecc2ff0SJack F Vogel pba->pba_block[0])) { 8970ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8980ecc2ff0SJack F Vogel pba->pba_block, 8990ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 9000ecc2ff0SJack F Vogel } else { 9010ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9020ecc2ff0SJack F Vogel } 9030ecc2ff0SJack F Vogel } 9040ecc2ff0SJack F Vogel } 9050ecc2ff0SJack F Vogel 9060ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9070ecc2ff0SJack F Vogel } 9080ecc2ff0SJack F Vogel 9090ecc2ff0SJack F Vogel /** 9100ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 9110ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 9120ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 9130ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 9140ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 9150ecc2ff0SJack F Vogel * 9160ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 9170ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 9180ecc2ff0SJack F Vogel * EEPROM device. 9190ecc2ff0SJack F Vogel * 9200ecc2ff0SJack F Vogel **/ 9210ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 9220ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 9230ecc2ff0SJack F Vogel { 9240ecc2ff0SJack F Vogel s32 ret_val; 9250ecc2ff0SJack F Vogel u16 pba_word[2]; 9260ecc2ff0SJack F Vogel u16 length; 9270ecc2ff0SJack F Vogel 9280ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 9290ecc2ff0SJack F Vogel 9300ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9310ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 9320ecc2ff0SJack F Vogel &pba_word[0]); 9330ecc2ff0SJack F Vogel if (ret_val) 9340ecc2ff0SJack F Vogel return ret_val; 9350ecc2ff0SJack F Vogel } else { 9360ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 9370ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 9380ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 9390ecc2ff0SJack F Vogel } else { 9400ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9410ecc2ff0SJack F Vogel } 9420ecc2ff0SJack F Vogel } 9430ecc2ff0SJack F Vogel 9440ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 9450ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9460ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 9470ecc2ff0SJack F Vogel &length); 9480ecc2ff0SJack F Vogel if (ret_val) 9490ecc2ff0SJack F Vogel return ret_val; 9500ecc2ff0SJack F Vogel } else { 9510ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9520ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9530ecc2ff0SJack F Vogel else 9540ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9550ecc2ff0SJack F Vogel } 9560ecc2ff0SJack F Vogel 9570ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9580ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9590ecc2ff0SJack F Vogel } else { 9600ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9610ecc2ff0SJack F Vogel length = 0; 9620ecc2ff0SJack F Vogel } 9630ecc2ff0SJack F Vogel 9640ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9650ecc2ff0SJack F Vogel *pba_block_size = length; 9660ecc2ff0SJack F Vogel 9670ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9680ecc2ff0SJack F Vogel } 9690ecc2ff0SJack F Vogel 9700ecc2ff0SJack F Vogel /** 97113705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 97213705f88SJack F Vogel * @hw: pointer to hardware structure 97313705f88SJack F Vogel * @mac_addr: Adapter MAC address 97413705f88SJack F Vogel * 97513705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 97613705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 97713705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 97813705f88SJack F Vogel **/ 97913705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 98013705f88SJack F Vogel { 98113705f88SJack F Vogel u32 rar_high; 98213705f88SJack F Vogel u32 rar_low; 98313705f88SJack F Vogel u16 i; 98413705f88SJack F Vogel 9852969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9862969bf0eSJack F Vogel 98713705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 98813705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 98913705f88SJack F Vogel 99013705f88SJack F Vogel for (i = 0; i < 4; i++) 99113705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 99213705f88SJack F Vogel 99313705f88SJack F Vogel for (i = 0; i < 2; i++) 99413705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 99513705f88SJack F Vogel 99613705f88SJack F Vogel return IXGBE_SUCCESS; 99713705f88SJack F Vogel } 99813705f88SJack F Vogel 99913705f88SJack F Vogel /** 1000fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 100113705f88SJack F Vogel * @hw: pointer to hardware structure 1002fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 100313705f88SJack F Vogel * 1004fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 100513705f88SJack F Vogel **/ 1006fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 100713705f88SJack F Vogel { 10081b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 10092969bf0eSJack F Vogel 1010758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 101113705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 101213705f88SJack F Vogel 101313705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 101413705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 101513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 101613705f88SJack F Vogel break; 101713705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 101813705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 101913705f88SJack F Vogel break; 102013705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 102113705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 102213705f88SJack F Vogel break; 102313705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 102413705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 102513705f88SJack F Vogel break; 102613705f88SJack F Vogel default: 102713705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 102813705f88SJack F Vogel break; 102913705f88SJack F Vogel } 103013705f88SJack F Vogel 103113705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 103213705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 103313705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 103413705f88SJack F Vogel break; 103513705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 103613705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 103713705f88SJack F Vogel break; 1038a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 1039a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 1040a621e3c8SJack F Vogel break; 104113705f88SJack F Vogel default: 104213705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 104313705f88SJack F Vogel break; 104413705f88SJack F Vogel } 104513705f88SJack F Vogel 10461b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 1047fd75b91dSJack F Vogel } 1048fd75b91dSJack F Vogel 1049fd75b91dSJack F Vogel /** 1050fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1051fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1052fd75b91dSJack F Vogel * 1053fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1054fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1055fd75b91dSJack F Vogel **/ 1056fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1057fd75b91dSJack F Vogel { 1058fd75b91dSJack F Vogel u16 link_status; 1059fd75b91dSJack F Vogel 1060fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1061fd75b91dSJack F Vogel 1062fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1063fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1064fd75b91dSJack F Vogel 1065fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10661b6e0dbaSJack F Vogel 106713705f88SJack F Vogel return IXGBE_SUCCESS; 106813705f88SJack F Vogel } 106913705f88SJack F Vogel 107013705f88SJack F Vogel /** 10711b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10721b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10731b6e0dbaSJack F Vogel * 10748eb6488eSEric Joyner * Determines the LAN function id by reading memory-mapped registers and swaps 10758eb6488eSEric Joyner * the port value if requested, and set MAC instance for devices that share 10768eb6488eSEric Joyner * CS4227. 10771b6e0dbaSJack F Vogel **/ 10781b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10791b6e0dbaSJack F Vogel { 10801b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10811b6e0dbaSJack F Vogel u32 reg; 10828eb6488eSEric Joyner u16 ee_ctrl_4; 10831b6e0dbaSJack F Vogel 10842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10852969bf0eSJack F Vogel 10861b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10871b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 10888eb6488eSEric Joyner bus->lan_id = (u8)bus->func; 10891b6e0dbaSJack F Vogel 10901b6e0dbaSJack F Vogel /* check for a port swap */ 1091a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 10921b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10931b6e0dbaSJack F Vogel bus->func ^= 0x1; 10948eb6488eSEric Joyner 10958eb6488eSEric Joyner /* Get MAC instance from EEPROM for configuring CS4227 */ 10968eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 10978eb6488eSEric Joyner hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 10988eb6488eSEric Joyner bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 10998eb6488eSEric Joyner IXGBE_EE_CTRL_4_INST_ID_SHIFT; 11008eb6488eSEric Joyner } 11011b6e0dbaSJack F Vogel } 11021b6e0dbaSJack F Vogel 11031b6e0dbaSJack F Vogel /** 11049ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 110513705f88SJack F Vogel * @hw: pointer to hardware structure 110613705f88SJack F Vogel * 110713705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 110813705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 110913705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 111013705f88SJack F Vogel * state and should not touch the hardware. 111113705f88SJack F Vogel **/ 111213705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 111313705f88SJack F Vogel { 111413705f88SJack F Vogel u32 reg_val; 111513705f88SJack F Vogel u16 i; 111613705f88SJack F Vogel 11172969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 11182969bf0eSJack F Vogel 111913705f88SJack F Vogel /* 112013705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 112113705f88SJack F Vogel * the hardware 112213705f88SJack F Vogel */ 112313705f88SJack F Vogel hw->adapter_stopped = TRUE; 112413705f88SJack F Vogel 112513705f88SJack F Vogel /* Disable the receive unit */ 1126758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 112713705f88SJack F Vogel 112885d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 112913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 113013705f88SJack F Vogel 113185d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 113213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 113313705f88SJack F Vogel 113413705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 113585d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 113685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 113785d0a26eSJack F Vogel 113885d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 113985d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 114085d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 114185d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 114285d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 114385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 114413705f88SJack F Vogel } 114585d0a26eSJack F Vogel 114685d0a26eSJack F Vogel /* flush all queues disables */ 114785d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 114885d0a26eSJack F Vogel msec_delay(2); 114913705f88SJack F Vogel 11509ca4041bSJack F Vogel /* 11516f37f232SEric Joyner * Prevent the PCI-E bus from hanging by disabling PCI-E master 11529ca4041bSJack F Vogel * access and verify no pending requests 11539ca4041bSJack F Vogel */ 115485d0a26eSJack F Vogel return ixgbe_disable_pcie_master(hw); 115513705f88SJack F Vogel } 115613705f88SJack F Vogel 115713705f88SJack F Vogel /** 11588eb6488eSEric Joyner * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 11598eb6488eSEric Joyner * @hw: pointer to hardware structure 11608eb6488eSEric Joyner * 11618eb6488eSEric Joyner * Store the index for the link active LED. This will be used to support 11628eb6488eSEric Joyner * blinking the LED. 11638eb6488eSEric Joyner **/ 11648eb6488eSEric Joyner s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 11658eb6488eSEric Joyner { 11668eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac; 11678eb6488eSEric Joyner u32 led_reg, led_mode; 11688eb6488eSEric Joyner u8 i; 11698eb6488eSEric Joyner 11708eb6488eSEric Joyner led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 11718eb6488eSEric Joyner 11728eb6488eSEric Joyner /* Get LED link active from the LEDCTL register */ 11738eb6488eSEric Joyner for (i = 0; i < 4; i++) { 11748eb6488eSEric Joyner led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 11758eb6488eSEric Joyner 11768eb6488eSEric Joyner if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 11778eb6488eSEric Joyner IXGBE_LED_LINK_ACTIVE) { 11788eb6488eSEric Joyner mac->led_link_act = i; 11798eb6488eSEric Joyner return IXGBE_SUCCESS; 11808eb6488eSEric Joyner } 11818eb6488eSEric Joyner } 11828eb6488eSEric Joyner 11838eb6488eSEric Joyner /* 11848eb6488eSEric Joyner * If LEDCTL register does not have the LED link active set, then use 11858eb6488eSEric Joyner * known MAC defaults. 11868eb6488eSEric Joyner */ 11878eb6488eSEric Joyner switch (hw->mac.type) { 11888eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 11898eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 11908eb6488eSEric Joyner mac->led_link_act = 1; 11918eb6488eSEric Joyner break; 11928eb6488eSEric Joyner default: 11938eb6488eSEric Joyner mac->led_link_act = 2; 11948eb6488eSEric Joyner } 11958eb6488eSEric Joyner return IXGBE_SUCCESS; 11968eb6488eSEric Joyner } 11978eb6488eSEric Joyner 11988eb6488eSEric Joyner /** 119913705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 120013705f88SJack F Vogel * @hw: pointer to hardware structure 120113705f88SJack F Vogel * @index: led number to turn on 120213705f88SJack F Vogel **/ 120313705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 120413705f88SJack F Vogel { 120513705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 120613705f88SJack F Vogel 12072969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 12082969bf0eSJack F Vogel 12098eb6488eSEric Joyner if (index > 3) 12108eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12118eb6488eSEric Joyner 121213705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 121313705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 121413705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 121513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12169ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 121713705f88SJack F Vogel 121813705f88SJack F Vogel return IXGBE_SUCCESS; 121913705f88SJack F Vogel } 122013705f88SJack F Vogel 122113705f88SJack F Vogel /** 122213705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 122313705f88SJack F Vogel * @hw: pointer to hardware structure 122413705f88SJack F Vogel * @index: led number to turn off 122513705f88SJack F Vogel **/ 122613705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 122713705f88SJack F Vogel { 122813705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 122913705f88SJack F Vogel 12302969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 12312969bf0eSJack F Vogel 12328eb6488eSEric Joyner if (index > 3) 12338eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12348eb6488eSEric Joyner 123513705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 123613705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 123713705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 123813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12399ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 124013705f88SJack F Vogel 124113705f88SJack F Vogel return IXGBE_SUCCESS; 124213705f88SJack F Vogel } 124313705f88SJack F Vogel 124413705f88SJack F Vogel /** 124513705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 124613705f88SJack F Vogel * @hw: pointer to hardware structure 124713705f88SJack F Vogel * 124813705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 124913705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 125013705f88SJack F Vogel **/ 125113705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 125213705f88SJack F Vogel { 125313705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 125413705f88SJack F Vogel u32 eec; 125513705f88SJack F Vogel u16 eeprom_size; 125613705f88SJack F Vogel 12572969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 12582969bf0eSJack F Vogel 125913705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 126013705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 12615b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 12625b7f4cedSJack F Vogel * tested value */ 12635b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 126485d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 126585d0a26eSJack F Vogel eeprom->word_page_size = 0; 126613705f88SJack F Vogel 126713705f88SJack F Vogel /* 126813705f88SJack F Vogel * Check for EEPROM present first. 126913705f88SJack F Vogel * If not present leave as none 127013705f88SJack F Vogel */ 1271a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 127213705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 127313705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 127413705f88SJack F Vogel 127513705f88SJack F Vogel /* 127613705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 127713705f88SJack F Vogel * change if a future EEPROM is not SPI. 127813705f88SJack F Vogel */ 127913705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 128013705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 128113705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 128285d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 128313705f88SJack F Vogel } 128413705f88SJack F Vogel 128513705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 128613705f88SJack F Vogel eeprom->address_bits = 16; 128713705f88SJack F Vogel else 128813705f88SJack F Vogel eeprom->address_bits = 8; 128913705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 129013705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 129113705f88SJack F Vogel eeprom->address_bits); 129213705f88SJack F Vogel } 129313705f88SJack F Vogel 129413705f88SJack F Vogel return IXGBE_SUCCESS; 129513705f88SJack F Vogel } 129613705f88SJack F Vogel 129713705f88SJack F Vogel /** 129885d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 129985d0a26eSJack F Vogel * @hw: pointer to hardware structure 130085d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 130185d0a26eSJack F Vogel * @words: number of word(s) 130285d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 130385d0a26eSJack F Vogel * 130485d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 130585d0a26eSJack F Vogel **/ 130685d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 130785d0a26eSJack F Vogel u16 words, u16 *data) 130885d0a26eSJack F Vogel { 130985d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 131085d0a26eSJack F Vogel u16 i, count; 131185d0a26eSJack F Vogel 131285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 131385d0a26eSJack F Vogel 131485d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 131585d0a26eSJack F Vogel 131685d0a26eSJack F Vogel if (words == 0) { 131785d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 131885d0a26eSJack F Vogel goto out; 131985d0a26eSJack F Vogel } 132085d0a26eSJack F Vogel 132185d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 132285d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 132385d0a26eSJack F Vogel goto out; 132485d0a26eSJack F Vogel } 132585d0a26eSJack F Vogel 132685d0a26eSJack F Vogel /* 132785d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 132885d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 132985d0a26eSJack F Vogel */ 133085d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 133185d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 133285d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 133385d0a26eSJack F Vogel 133485d0a26eSJack F Vogel /* 133585d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 133685d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 133785d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 133885d0a26eSJack F Vogel */ 133985d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 134085d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 134185d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 134285d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 134385d0a26eSJack F Vogel count, &data[i]); 134485d0a26eSJack F Vogel 134585d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 134685d0a26eSJack F Vogel break; 134785d0a26eSJack F Vogel } 134885d0a26eSJack F Vogel 134985d0a26eSJack F Vogel out: 135085d0a26eSJack F Vogel return status; 135185d0a26eSJack F Vogel } 135285d0a26eSJack F Vogel 135385d0a26eSJack F Vogel /** 135485d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 135513705f88SJack F Vogel * @hw: pointer to hardware structure 135613705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 135785d0a26eSJack F Vogel * @words: number of word(s) 135885d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 135913705f88SJack F Vogel * 136013705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 136113705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 136213705f88SJack F Vogel **/ 136385d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 136485d0a26eSJack F Vogel u16 words, u16 *data) 136513705f88SJack F Vogel { 136613705f88SJack F Vogel s32 status; 136785d0a26eSJack F Vogel u16 word; 136885d0a26eSJack F Vogel u16 page_size; 136985d0a26eSJack F Vogel u16 i; 137013705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 137113705f88SJack F Vogel 137285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 13739ca4041bSJack F Vogel 137413705f88SJack F Vogel /* Prepare the EEPROM for writing */ 137513705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 137613705f88SJack F Vogel 137713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 137813705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 137913705f88SJack F Vogel ixgbe_release_eeprom(hw); 138013705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 138113705f88SJack F Vogel } 138213705f88SJack F Vogel } 138313705f88SJack F Vogel 138413705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 138585d0a26eSJack F Vogel for (i = 0; i < words; i++) { 138613705f88SJack F Vogel ixgbe_standby_eeprom(hw); 138713705f88SJack F Vogel 138813705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 138985d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 139085d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 139113705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 139213705f88SJack F Vogel 139313705f88SJack F Vogel ixgbe_standby_eeprom(hw); 139413705f88SJack F Vogel 139513705f88SJack F Vogel /* 139685d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 139785d0a26eSJack F Vogel * in the opcode 139813705f88SJack F Vogel */ 139985d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 140085d0a26eSJack F Vogel ((offset + i) >= 128)) 140113705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 140213705f88SJack F Vogel 140313705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 140413705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 140513705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 140685d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 140713705f88SJack F Vogel hw->eeprom.address_bits); 140813705f88SJack F Vogel 140985d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 141013705f88SJack F Vogel 141185d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 141285d0a26eSJack F Vogel do { 141385d0a26eSJack F Vogel word = data[i]; 141485d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 141585d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 141685d0a26eSJack F Vogel 141785d0a26eSJack F Vogel if (page_size == 0) 141885d0a26eSJack F Vogel break; 141985d0a26eSJack F Vogel 142085d0a26eSJack F Vogel /* do not wrap around page */ 142185d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 142285d0a26eSJack F Vogel (page_size - 1)) 142385d0a26eSJack F Vogel break; 142485d0a26eSJack F Vogel } while (++i < words); 142585d0a26eSJack F Vogel 142685d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 142785d0a26eSJack F Vogel msec_delay(10); 142885d0a26eSJack F Vogel } 142913705f88SJack F Vogel /* Done with writing - release the EEPROM */ 143013705f88SJack F Vogel ixgbe_release_eeprom(hw); 143113705f88SJack F Vogel } 143213705f88SJack F Vogel 143385d0a26eSJack F Vogel return status; 143485d0a26eSJack F Vogel } 143585d0a26eSJack F Vogel 143685d0a26eSJack F Vogel /** 143785d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 143885d0a26eSJack F Vogel * @hw: pointer to hardware structure 143985d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 144085d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 144185d0a26eSJack F Vogel * 144285d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 144385d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 144485d0a26eSJack F Vogel **/ 144585d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 144685d0a26eSJack F Vogel { 144785d0a26eSJack F Vogel s32 status; 144885d0a26eSJack F Vogel 144985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 145085d0a26eSJack F Vogel 145185d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 145285d0a26eSJack F Vogel 145385d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 145485d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 145585d0a26eSJack F Vogel goto out; 145685d0a26eSJack F Vogel } 145785d0a26eSJack F Vogel 145885d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 145985d0a26eSJack F Vogel 14609ca4041bSJack F Vogel out: 146113705f88SJack F Vogel return status; 146213705f88SJack F Vogel } 146313705f88SJack F Vogel 146413705f88SJack F Vogel /** 146585d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 146685d0a26eSJack F Vogel * @hw: pointer to hardware structure 146785d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 146885d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 146985d0a26eSJack F Vogel * @words: number of word(s) 147085d0a26eSJack F Vogel * 147185d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 147285d0a26eSJack F Vogel **/ 147385d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147485d0a26eSJack F Vogel u16 words, u16 *data) 147585d0a26eSJack F Vogel { 147685d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 147785d0a26eSJack F Vogel u16 i, count; 147885d0a26eSJack F Vogel 147985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 148085d0a26eSJack F Vogel 148185d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 148285d0a26eSJack F Vogel 148385d0a26eSJack F Vogel if (words == 0) { 148485d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 148585d0a26eSJack F Vogel goto out; 148685d0a26eSJack F Vogel } 148785d0a26eSJack F Vogel 148885d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 148985d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 149085d0a26eSJack F Vogel goto out; 149185d0a26eSJack F Vogel } 149285d0a26eSJack F Vogel 149385d0a26eSJack F Vogel /* 149485d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 149585d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 149685d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 149785d0a26eSJack F Vogel */ 149885d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 149985d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 150085d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 150185d0a26eSJack F Vogel 150285d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 150385d0a26eSJack F Vogel count, &data[i]); 150485d0a26eSJack F Vogel 150585d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 150685d0a26eSJack F Vogel break; 150785d0a26eSJack F Vogel } 150885d0a26eSJack F Vogel 150985d0a26eSJack F Vogel out: 151085d0a26eSJack F Vogel return status; 151185d0a26eSJack F Vogel } 151285d0a26eSJack F Vogel 151385d0a26eSJack F Vogel /** 151485d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 151585d0a26eSJack F Vogel * @hw: pointer to hardware structure 151685d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 151785d0a26eSJack F Vogel * @words: number of word(s) 151885d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 151985d0a26eSJack F Vogel * 152085d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 152185d0a26eSJack F Vogel **/ 152285d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 152385d0a26eSJack F Vogel u16 words, u16 *data) 152485d0a26eSJack F Vogel { 152585d0a26eSJack F Vogel s32 status; 152685d0a26eSJack F Vogel u16 word_in; 152785d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 152885d0a26eSJack F Vogel u16 i; 152985d0a26eSJack F Vogel 153085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 153185d0a26eSJack F Vogel 153285d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 153385d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 153485d0a26eSJack F Vogel 153585d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 153685d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 153785d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 153885d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 153985d0a26eSJack F Vogel } 154085d0a26eSJack F Vogel } 154185d0a26eSJack F Vogel 154285d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 154385d0a26eSJack F Vogel for (i = 0; i < words; i++) { 154485d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 154585d0a26eSJack F Vogel /* 154685d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 154785d0a26eSJack F Vogel * in the opcode 154885d0a26eSJack F Vogel */ 154985d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 155085d0a26eSJack F Vogel ((offset + i) >= 128)) 155185d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 155285d0a26eSJack F Vogel 155385d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 155485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 155585d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 155685d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 155785d0a26eSJack F Vogel hw->eeprom.address_bits); 155885d0a26eSJack F Vogel 155985d0a26eSJack F Vogel /* Read the data. */ 156085d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 156185d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 156285d0a26eSJack F Vogel } 156385d0a26eSJack F Vogel 156485d0a26eSJack F Vogel /* End this read operation */ 156585d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 156685d0a26eSJack F Vogel } 156785d0a26eSJack F Vogel 156885d0a26eSJack F Vogel return status; 156985d0a26eSJack F Vogel } 157085d0a26eSJack F Vogel 157185d0a26eSJack F Vogel /** 157213705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 157313705f88SJack F Vogel * @hw: pointer to hardware structure 157413705f88SJack F Vogel * @offset: offset within the EEPROM to be read 157513705f88SJack F Vogel * @data: read 16 bit value from EEPROM 157613705f88SJack F Vogel * 157713705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 157813705f88SJack F Vogel **/ 157913705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 158013705f88SJack F Vogel u16 *data) 158113705f88SJack F Vogel { 158213705f88SJack F Vogel s32 status; 158313705f88SJack F Vogel 15842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 15852969bf0eSJack F Vogel 15869ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 15879ca4041bSJack F Vogel 15889ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 15899ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 15909ca4041bSJack F Vogel goto out; 15919ca4041bSJack F Vogel } 15929ca4041bSJack F Vogel 159385d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 159413705f88SJack F Vogel 159585d0a26eSJack F Vogel out: 159685d0a26eSJack F Vogel return status; 159785d0a26eSJack F Vogel } 159885d0a26eSJack F Vogel 159985d0a26eSJack F Vogel /** 160085d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 160185d0a26eSJack F Vogel * @hw: pointer to hardware structure 160285d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 160385d0a26eSJack F Vogel * @words: number of word(s) 160485d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 160585d0a26eSJack F Vogel * 160685d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 160785d0a26eSJack F Vogel **/ 160885d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 160985d0a26eSJack F Vogel u16 words, u16 *data) 161085d0a26eSJack F Vogel { 161185d0a26eSJack F Vogel u32 eerd; 161285d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161385d0a26eSJack F Vogel u32 i; 161485d0a26eSJack F Vogel 161585d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 161685d0a26eSJack F Vogel 161785d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 161885d0a26eSJack F Vogel 161985d0a26eSJack F Vogel if (words == 0) { 162085d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1621fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162285d0a26eSJack F Vogel goto out; 162385d0a26eSJack F Vogel } 162485d0a26eSJack F Vogel 162585d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 162613705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1627fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 162885d0a26eSJack F Vogel goto out; 162913705f88SJack F Vogel } 163013705f88SJack F Vogel 163185d0a26eSJack F Vogel for (i = 0; i < words; i++) { 16320ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163385d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163485d0a26eSJack F Vogel 163585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 163685d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 163785d0a26eSJack F Vogel 163813705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 163985d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 164085d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 164185d0a26eSJack F Vogel } else { 164285d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 164385d0a26eSJack F Vogel goto out; 164485d0a26eSJack F Vogel } 164585d0a26eSJack F Vogel } 164685d0a26eSJack F Vogel out: 164785d0a26eSJack F Vogel return status; 164885d0a26eSJack F Vogel } 164985d0a26eSJack F Vogel 165085d0a26eSJack F Vogel /** 165185d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 165285d0a26eSJack F Vogel * @hw: pointer to hardware structure 165385d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 165485d0a26eSJack F Vogel * 165585d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 165685d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 165785d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 165885d0a26eSJack F Vogel **/ 165985d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 166085d0a26eSJack F Vogel u16 offset) 166185d0a26eSJack F Vogel { 166285d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 166385d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 166485d0a26eSJack F Vogel u16 i; 166585d0a26eSJack F Vogel 166685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 166785d0a26eSJack F Vogel 166885d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 166985d0a26eSJack F Vogel data[i] = i; 167085d0a26eSJack F Vogel 167185d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 167285d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 167385d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 167485d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 167585d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167685d0a26eSJack F Vogel goto out; 167785d0a26eSJack F Vogel 167885d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 167985d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 168085d0a26eSJack F Vogel goto out; 168113705f88SJack F Vogel 168213705f88SJack F Vogel /* 168385d0a26eSJack F Vogel * When writing in burst more than the actual page size 168485d0a26eSJack F Vogel * EEPROM address wraps around current page. 168513705f88SJack F Vogel */ 168685d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 168713705f88SJack F Vogel 168885d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 168985d0a26eSJack F Vogel hw->eeprom.word_page_size); 16909ca4041bSJack F Vogel out: 169113705f88SJack F Vogel return status; 169213705f88SJack F Vogel } 169313705f88SJack F Vogel 169413705f88SJack F Vogel /** 16952969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 169613705f88SJack F Vogel * @hw: pointer to hardware structure 169713705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 169813705f88SJack F Vogel * @data: word read from the EEPROM 169913705f88SJack F Vogel * 170013705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 170113705f88SJack F Vogel **/ 17022969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 170313705f88SJack F Vogel { 170485d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 170585d0a26eSJack F Vogel } 170613705f88SJack F Vogel 170785d0a26eSJack F Vogel /** 170885d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 170985d0a26eSJack F Vogel * @hw: pointer to hardware structure 171085d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 171185d0a26eSJack F Vogel * @words: number of word(s) 171285d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 171385d0a26eSJack F Vogel * 171485d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 171585d0a26eSJack F Vogel **/ 171685d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 171785d0a26eSJack F Vogel u16 words, u16 *data) 171885d0a26eSJack F Vogel { 171985d0a26eSJack F Vogel u32 eewr; 172085d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 172185d0a26eSJack F Vogel u16 i; 172285d0a26eSJack F Vogel 172385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 17242969bf0eSJack F Vogel 17259ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 17269ca4041bSJack F Vogel 172785d0a26eSJack F Vogel if (words == 0) { 172885d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1729fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 173085d0a26eSJack F Vogel goto out; 173185d0a26eSJack F Vogel } 173285d0a26eSJack F Vogel 17339ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 17349ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1735fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 17369ca4041bSJack F Vogel goto out; 17379ca4041bSJack F Vogel } 17389ca4041bSJack F Vogel 173985d0a26eSJack F Vogel for (i = 0; i < words; i++) { 174085d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 174185d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 17422969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 174313705f88SJack F Vogel 174485d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 174585d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 174685d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 174785d0a26eSJack F Vogel goto out; 174885d0a26eSJack F Vogel } 174913705f88SJack F Vogel 175085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 175185d0a26eSJack F Vogel 175285d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 175385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 175485d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 175585d0a26eSJack F Vogel goto out; 175685d0a26eSJack F Vogel } 175785d0a26eSJack F Vogel } 175813705f88SJack F Vogel 17599ca4041bSJack F Vogel out: 176013705f88SJack F Vogel return status; 176113705f88SJack F Vogel } 176213705f88SJack F Vogel 176313705f88SJack F Vogel /** 17641a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 17651a4e3449SJack F Vogel * @hw: pointer to hardware structure 17661a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 17671a4e3449SJack F Vogel * @data: word write to the EEPROM 17681a4e3449SJack F Vogel * 17691a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 17701a4e3449SJack F Vogel **/ 17711a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 17721a4e3449SJack F Vogel { 177385d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 17741a4e3449SJack F Vogel } 17751a4e3449SJack F Vogel 17761a4e3449SJack F Vogel /** 17772969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 177813705f88SJack F Vogel * @hw: pointer to hardware structure 17792969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 178013705f88SJack F Vogel * 17812969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 17822969bf0eSJack F Vogel * read or write is done respectively. 178313705f88SJack F Vogel **/ 17842969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 178513705f88SJack F Vogel { 178613705f88SJack F Vogel u32 i; 178713705f88SJack F Vogel u32 reg; 178813705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 178913705f88SJack F Vogel 17902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 17912969bf0eSJack F Vogel 17922969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 17932969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 179413705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 17952969bf0eSJack F Vogel else 17962969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 17972969bf0eSJack F Vogel 17982969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 179913705f88SJack F Vogel status = IXGBE_SUCCESS; 180013705f88SJack F Vogel break; 180113705f88SJack F Vogel } 180213705f88SJack F Vogel usec_delay(5); 180313705f88SJack F Vogel } 1804fd75b91dSJack F Vogel 1805fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1806fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1807fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1808fd75b91dSJack F Vogel 180913705f88SJack F Vogel return status; 181013705f88SJack F Vogel } 181113705f88SJack F Vogel 181213705f88SJack F Vogel /** 181313705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 181413705f88SJack F Vogel * @hw: pointer to hardware structure 181513705f88SJack F Vogel * 181613705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 181713705f88SJack F Vogel * be called before issuing a command to the EEPROM. 181813705f88SJack F Vogel **/ 181913705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 182013705f88SJack F Vogel { 182113705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 182213705f88SJack F Vogel u32 eec; 182313705f88SJack F Vogel u32 i; 182413705f88SJack F Vogel 18252969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 18262969bf0eSJack F Vogel 182785d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 182885d0a26eSJack F Vogel != IXGBE_SUCCESS) 182913705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 183013705f88SJack F Vogel 183113705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 1832a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183313705f88SJack F Vogel 183413705f88SJack F Vogel /* Request EEPROM Access */ 183513705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 1836a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 183713705f88SJack F Vogel 183813705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 1839a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 184013705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 184113705f88SJack F Vogel break; 184213705f88SJack F Vogel usec_delay(5); 184313705f88SJack F Vogel } 184413705f88SJack F Vogel 18459ca4041bSJack F Vogel /* Release if grant not acquired */ 184613705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 184713705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 1848a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 184913705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 185013705f88SJack F Vogel 185185d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 185213705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 185313705f88SJack F Vogel } 185413705f88SJack F Vogel 185513705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 185613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 185713705f88SJack F Vogel /* Clear CS and SK */ 185813705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 1859a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 186013705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 186113705f88SJack F Vogel usec_delay(1); 186213705f88SJack F Vogel } 18631a4e3449SJack F Vogel } 186413705f88SJack F Vogel return status; 186513705f88SJack F Vogel } 186613705f88SJack F Vogel 186713705f88SJack F Vogel /** 186813705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 186913705f88SJack F Vogel * @hw: pointer to hardware structure 187013705f88SJack F Vogel * 187113705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 187213705f88SJack F Vogel **/ 187313705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 187413705f88SJack F Vogel { 187513705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1876d8602bb9SJack F Vogel u32 timeout = 2000; 187713705f88SJack F Vogel u32 i; 187813705f88SJack F Vogel u32 swsm; 187913705f88SJack F Vogel 18802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 18812969bf0eSJack F Vogel 18821a4e3449SJack F Vogel 188313705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 188413705f88SJack F Vogel for (i = 0; i < timeout; i++) { 188513705f88SJack F Vogel /* 188613705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 188713705f88SJack F Vogel * set and we have the semaphore 188813705f88SJack F Vogel */ 1889a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 189013705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 189113705f88SJack F Vogel status = IXGBE_SUCCESS; 189213705f88SJack F Vogel break; 189313705f88SJack F Vogel } 18940ac6dfecSJack F Vogel usec_delay(50); 189513705f88SJack F Vogel } 189613705f88SJack F Vogel 189785d0a26eSJack F Vogel if (i == timeout) { 189885d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 189985d0a26eSJack F Vogel "not granted.\n"); 190085d0a26eSJack F Vogel /* 190185d0a26eSJack F Vogel * this release is particularly important because our attempts 190285d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 190385d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 190485d0a26eSJack F Vogel * bits to free the driver to make progress 190585d0a26eSJack F Vogel */ 190685d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 190785d0a26eSJack F Vogel 190885d0a26eSJack F Vogel usec_delay(50); 190985d0a26eSJack F Vogel /* 191085d0a26eSJack F Vogel * one last try 191185d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 191285d0a26eSJack F Vogel * set and we have the semaphore 191385d0a26eSJack F Vogel */ 1914a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 191585d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 191685d0a26eSJack F Vogel status = IXGBE_SUCCESS; 191785d0a26eSJack F Vogel } 191885d0a26eSJack F Vogel 191913705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 192013705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 192113705f88SJack F Vogel for (i = 0; i < timeout; i++) { 1922a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 192313705f88SJack F Vogel 192413705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 192513705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 1926a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); 192713705f88SJack F Vogel 192813705f88SJack F Vogel /* 192913705f88SJack F Vogel * If we set the bit successfully then we got the 193013705f88SJack F Vogel * semaphore. 193113705f88SJack F Vogel */ 1932a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 193313705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 193413705f88SJack F Vogel break; 193513705f88SJack F Vogel 193613705f88SJack F Vogel usec_delay(50); 193713705f88SJack F Vogel } 193813705f88SJack F Vogel 193913705f88SJack F Vogel /* 194013705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 194113705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 194213705f88SJack F Vogel */ 194313705f88SJack F Vogel if (i >= timeout) { 1944fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1945fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 194613705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 194713705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 194813705f88SJack F Vogel } 19490ac6dfecSJack F Vogel } else { 1950fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1951fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 19520ac6dfecSJack F Vogel "not granted.\n"); 195313705f88SJack F Vogel } 195413705f88SJack F Vogel 195513705f88SJack F Vogel return status; 195613705f88SJack F Vogel } 195713705f88SJack F Vogel 195813705f88SJack F Vogel /** 195913705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 196013705f88SJack F Vogel * @hw: pointer to hardware structure 196113705f88SJack F Vogel * 196213705f88SJack F Vogel * This function clears hardware semaphore bits. 196313705f88SJack F Vogel **/ 196413705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 196513705f88SJack F Vogel { 196613705f88SJack F Vogel u32 swsm; 196713705f88SJack F Vogel 19682969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 19692969bf0eSJack F Vogel 197013705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 197113705f88SJack F Vogel 197213705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 197313705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 197413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 19759ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 197613705f88SJack F Vogel } 197713705f88SJack F Vogel 197813705f88SJack F Vogel /** 197913705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 198013705f88SJack F Vogel * @hw: pointer to hardware structure 198113705f88SJack F Vogel **/ 198213705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 198313705f88SJack F Vogel { 198413705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 198513705f88SJack F Vogel u16 i; 198613705f88SJack F Vogel u8 spi_stat_reg; 198713705f88SJack F Vogel 19882969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 19892969bf0eSJack F Vogel 199013705f88SJack F Vogel /* 199113705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 199213705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 199313705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 199413705f88SJack F Vogel * 5 milliseconds, then error out. 199513705f88SJack F Vogel */ 199613705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 199713705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 199813705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 199913705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 200013705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 200113705f88SJack F Vogel break; 200213705f88SJack F Vogel 200313705f88SJack F Vogel usec_delay(5); 200413705f88SJack F Vogel ixgbe_standby_eeprom(hw); 2005*c19c7afeSEric Joyner } 200613705f88SJack F Vogel 200713705f88SJack F Vogel /* 200813705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 200913705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 201013705f88SJack F Vogel */ 201113705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 201213705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 201313705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 201413705f88SJack F Vogel } 201513705f88SJack F Vogel 201613705f88SJack F Vogel return status; 201713705f88SJack F Vogel } 201813705f88SJack F Vogel 201913705f88SJack F Vogel /** 202013705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 202113705f88SJack F Vogel * @hw: pointer to hardware structure 202213705f88SJack F Vogel **/ 202313705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 202413705f88SJack F Vogel { 202513705f88SJack F Vogel u32 eec; 202613705f88SJack F Vogel 20272969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 20282969bf0eSJack F Vogel 2029a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 203013705f88SJack F Vogel 203113705f88SJack F Vogel /* Toggle CS to flush commands */ 203213705f88SJack F Vogel eec |= IXGBE_EEC_CS; 2033a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203513705f88SJack F Vogel usec_delay(1); 203613705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 2037a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203913705f88SJack F Vogel usec_delay(1); 204013705f88SJack F Vogel } 204113705f88SJack F Vogel 204213705f88SJack F Vogel /** 204313705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 204413705f88SJack F Vogel * @hw: pointer to hardware structure 204513705f88SJack F Vogel * @data: data to send to the EEPROM 204613705f88SJack F Vogel * @count: number of bits to shift out 204713705f88SJack F Vogel **/ 204813705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 204913705f88SJack F Vogel u16 count) 205013705f88SJack F Vogel { 205113705f88SJack F Vogel u32 eec; 205213705f88SJack F Vogel u32 mask; 205313705f88SJack F Vogel u32 i; 205413705f88SJack F Vogel 20552969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 20562969bf0eSJack F Vogel 2057a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 205813705f88SJack F Vogel 205913705f88SJack F Vogel /* 206013705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 206113705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 206213705f88SJack F Vogel */ 206313705f88SJack F Vogel mask = 0x01 << (count - 1); 206413705f88SJack F Vogel 206513705f88SJack F Vogel for (i = 0; i < count; i++) { 206613705f88SJack F Vogel /* 206713705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 206813705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 206913705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 207013705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 207113705f88SJack F Vogel * raising and then lowering the clock. 207213705f88SJack F Vogel */ 207313705f88SJack F Vogel if (data & mask) 207413705f88SJack F Vogel eec |= IXGBE_EEC_DI; 207513705f88SJack F Vogel else 207613705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 207713705f88SJack F Vogel 2078a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 207913705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 208013705f88SJack F Vogel 208113705f88SJack F Vogel usec_delay(1); 208213705f88SJack F Vogel 208313705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 208413705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 208513705f88SJack F Vogel 208613705f88SJack F Vogel /* 208713705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 208813705f88SJack F Vogel * EEPROM 208913705f88SJack F Vogel */ 209013705f88SJack F Vogel mask = mask >> 1; 2091*c19c7afeSEric Joyner } 209213705f88SJack F Vogel 209313705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 209413705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 2095a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 209613705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 209713705f88SJack F Vogel } 209813705f88SJack F Vogel 209913705f88SJack F Vogel /** 210013705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 210113705f88SJack F Vogel * @hw: pointer to hardware structure 210213705f88SJack F Vogel **/ 210313705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 210413705f88SJack F Vogel { 210513705f88SJack F Vogel u32 eec; 210613705f88SJack F Vogel u32 i; 210713705f88SJack F Vogel u16 data = 0; 210813705f88SJack F Vogel 21092969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 21102969bf0eSJack F Vogel 211113705f88SJack F Vogel /* 211213705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 211313705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 211413705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 211513705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 211613705f88SJack F Vogel * "DI" bit should always be clear. 211713705f88SJack F Vogel */ 2118a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 211913705f88SJack F Vogel 212013705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 212113705f88SJack F Vogel 212213705f88SJack F Vogel for (i = 0; i < count; i++) { 212313705f88SJack F Vogel data = data << 1; 212413705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 212513705f88SJack F Vogel 2126a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212713705f88SJack F Vogel 212813705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 212913705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 213013705f88SJack F Vogel data |= 1; 213113705f88SJack F Vogel 213213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 213313705f88SJack F Vogel } 213413705f88SJack F Vogel 213513705f88SJack F Vogel return data; 213613705f88SJack F Vogel } 213713705f88SJack F Vogel 213813705f88SJack F Vogel /** 213913705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 214013705f88SJack F Vogel * @hw: pointer to hardware structure 214113705f88SJack F Vogel * @eec: EEC register's current value 214213705f88SJack F Vogel **/ 214313705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 214413705f88SJack F Vogel { 21452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 21462969bf0eSJack F Vogel 214713705f88SJack F Vogel /* 214813705f88SJack F Vogel * Raise the clock input to the EEPROM 214913705f88SJack F Vogel * (setting the SK bit), then delay 215013705f88SJack F Vogel */ 215113705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 2152a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 215313705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 215413705f88SJack F Vogel usec_delay(1); 215513705f88SJack F Vogel } 215613705f88SJack F Vogel 215713705f88SJack F Vogel /** 215813705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 215913705f88SJack F Vogel * @hw: pointer to hardware structure 216013705f88SJack F Vogel * @eecd: EECD's current value 216113705f88SJack F Vogel **/ 216213705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 216313705f88SJack F Vogel { 21642969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 21652969bf0eSJack F Vogel 216613705f88SJack F Vogel /* 216713705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 216813705f88SJack F Vogel * delay 216913705f88SJack F Vogel */ 217013705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 2171a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 217213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 217313705f88SJack F Vogel usec_delay(1); 217413705f88SJack F Vogel } 217513705f88SJack F Vogel 217613705f88SJack F Vogel /** 217713705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 217813705f88SJack F Vogel * @hw: pointer to hardware structure 217913705f88SJack F Vogel **/ 218013705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 218113705f88SJack F Vogel { 218213705f88SJack F Vogel u32 eec; 218313705f88SJack F Vogel 21842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 21852969bf0eSJack F Vogel 2186a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 218713705f88SJack F Vogel 218813705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 218913705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 219013705f88SJack F Vogel 2191a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 219313705f88SJack F Vogel 219413705f88SJack F Vogel usec_delay(1); 219513705f88SJack F Vogel 219613705f88SJack F Vogel /* Stop requesting EEPROM access */ 219713705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 2198a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219913705f88SJack F Vogel 220085d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2201d8602bb9SJack F Vogel 2202d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2203d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 220413705f88SJack F Vogel } 220513705f88SJack F Vogel 220613705f88SJack F Vogel /** 22072969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 220813705f88SJack F Vogel * @hw: pointer to hardware structure 2209758cc3dcSJack F Vogel * 2210758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 221113705f88SJack F Vogel **/ 2212758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 221313705f88SJack F Vogel { 221413705f88SJack F Vogel u16 i; 221513705f88SJack F Vogel u16 j; 221613705f88SJack F Vogel u16 checksum = 0; 221713705f88SJack F Vogel u16 length = 0; 221813705f88SJack F Vogel u16 pointer = 0; 221913705f88SJack F Vogel u16 word = 0; 222013705f88SJack F Vogel 22212969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 22222969bf0eSJack F Vogel 222313705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 222413705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2225758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 222613705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2227758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 222813705f88SJack F Vogel } 222913705f88SJack F Vogel checksum += word; 223013705f88SJack F Vogel } 223113705f88SJack F Vogel 223213705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 223313705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2234758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2235758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2236758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2237758cc3dcSJack F Vogel } 223813705f88SJack F Vogel 2239758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2240758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2241758cc3dcSJack F Vogel continue; 224213705f88SJack F Vogel 2243758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2244758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2245758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2246758cc3dcSJack F Vogel } 2247758cc3dcSJack F Vogel 2248758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2249758cc3dcSJack F Vogel continue; 2250758cc3dcSJack F Vogel 225113705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2252758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2253758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2254758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2255758cc3dcSJack F Vogel } 225613705f88SJack F Vogel checksum += word; 225713705f88SJack F Vogel } 225813705f88SJack F Vogel } 225913705f88SJack F Vogel 226013705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 226113705f88SJack F Vogel 2262758cc3dcSJack F Vogel return (s32)checksum; 226313705f88SJack F Vogel } 226413705f88SJack F Vogel 226513705f88SJack F Vogel /** 226613705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 226713705f88SJack F Vogel * @hw: pointer to hardware structure 226813705f88SJack F Vogel * @checksum_val: calculated checksum 226913705f88SJack F Vogel * 227013705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 227113705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 227213705f88SJack F Vogel **/ 227313705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 227413705f88SJack F Vogel u16 *checksum_val) 227513705f88SJack F Vogel { 227613705f88SJack F Vogel s32 status; 227713705f88SJack F Vogel u16 checksum; 227813705f88SJack F Vogel u16 read_checksum = 0; 227913705f88SJack F Vogel 22802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 22812969bf0eSJack F Vogel 2282758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 228313705f88SJack F Vogel * not continue or we could be in for a very long wait while every 228413705f88SJack F Vogel * EEPROM read fails 228513705f88SJack F Vogel */ 22869ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2287758cc3dcSJack F Vogel if (status) { 2288758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2289758cc3dcSJack F Vogel return status; 2290758cc3dcSJack F Vogel } 229113705f88SJack F Vogel 2292758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2293758cc3dcSJack F Vogel if (status < 0) 2294758cc3dcSJack F Vogel return status; 229513705f88SJack F Vogel 2296758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 229713705f88SJack F Vogel 2298758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2299758cc3dcSJack F Vogel if (status) { 2300758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2301758cc3dcSJack F Vogel return status; 2302758cc3dcSJack F Vogel } 2303758cc3dcSJack F Vogel 2304758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 230513705f88SJack F Vogel * calculated checksum 230613705f88SJack F Vogel */ 23079ca4041bSJack F Vogel if (read_checksum != checksum) 230813705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 230913705f88SJack F Vogel 231013705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 23119ca4041bSJack F Vogel if (checksum_val) 231213705f88SJack F Vogel *checksum_val = checksum; 231313705f88SJack F Vogel 231413705f88SJack F Vogel return status; 231513705f88SJack F Vogel } 231613705f88SJack F Vogel 231713705f88SJack F Vogel /** 23189ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 231913705f88SJack F Vogel * @hw: pointer to hardware structure 232013705f88SJack F Vogel **/ 232113705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 232213705f88SJack F Vogel { 232313705f88SJack F Vogel s32 status; 232413705f88SJack F Vogel u16 checksum; 232513705f88SJack F Vogel 23262969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 23272969bf0eSJack F Vogel 2328758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 232913705f88SJack F Vogel * not continue or we could be in for a very long wait while every 233013705f88SJack F Vogel * EEPROM read fails 233113705f88SJack F Vogel */ 23329ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2333758cc3dcSJack F Vogel if (status) { 233413705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2335758cc3dcSJack F Vogel return status; 233613705f88SJack F Vogel } 233713705f88SJack F Vogel 2338758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2339758cc3dcSJack F Vogel if (status < 0) 2340758cc3dcSJack F Vogel return status; 2341758cc3dcSJack F Vogel 2342758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2343758cc3dcSJack F Vogel 2344758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2345758cc3dcSJack F Vogel 234613705f88SJack F Vogel return status; 234713705f88SJack F Vogel } 234813705f88SJack F Vogel 234913705f88SJack F Vogel /** 235013705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 235113705f88SJack F Vogel * @mac_addr: pointer to MAC address. 235213705f88SJack F Vogel * 23538eb6488eSEric Joyner * Tests a MAC address to ensure it is a valid Individual Address. 235413705f88SJack F Vogel **/ 235513705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 235613705f88SJack F Vogel { 235713705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 235813705f88SJack F Vogel 23592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 23602969bf0eSJack F Vogel 236113705f88SJack F Vogel /* Make sure it is not a multicast address */ 236213705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 236313705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236413705f88SJack F Vogel /* Not a broadcast address */ 236513705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 236613705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236713705f88SJack F Vogel /* Reject the zero address */ 236813705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 236913705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 237013705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 237113705f88SJack F Vogel } 237213705f88SJack F Vogel return status; 237313705f88SJack F Vogel } 237413705f88SJack F Vogel 237513705f88SJack F Vogel /** 23769ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 237713705f88SJack F Vogel * @hw: pointer to hardware structure 237813705f88SJack F Vogel * @index: Receive address register to write 23799ca4041bSJack F Vogel * @addr: Address to put into receive address register 23809ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 238113705f88SJack F Vogel * @enable_addr: set flag that address is active 238213705f88SJack F Vogel * 238313705f88SJack F Vogel * Puts an ethernet address into a receive address register. 238413705f88SJack F Vogel **/ 23859ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 238613705f88SJack F Vogel u32 enable_addr) 238713705f88SJack F Vogel { 238813705f88SJack F Vogel u32 rar_low, rar_high; 23899ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 239013705f88SJack F Vogel 23912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 23922969bf0eSJack F Vogel 23931a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 23941a4e3449SJack F Vogel if (index >= rar_entries) { 2395fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2396fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23971a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 23981a4e3449SJack F Vogel } 23991a4e3449SJack F Vogel 24009ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 24019ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 24029ca4041bSJack F Vogel 240313705f88SJack F Vogel /* 24049ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 24059ca4041bSJack F Vogel * order from network order (big endian) to little endian 240613705f88SJack F Vogel */ 240713705f88SJack F Vogel rar_low = ((u32)addr[0] | 240813705f88SJack F Vogel ((u32)addr[1] << 8) | 240913705f88SJack F Vogel ((u32)addr[2] << 16) | 241013705f88SJack F Vogel ((u32)addr[3] << 24)); 24119ca4041bSJack F Vogel /* 24129ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24139ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 24149ca4041bSJack F Vogel * of the address and the address valid bit. 24159ca4041bSJack F Vogel */ 24169ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24179ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24189ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 241913705f88SJack F Vogel 242013705f88SJack F Vogel if (enable_addr != 0) 242113705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 242213705f88SJack F Vogel 242313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 242413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 242513705f88SJack F Vogel 242613705f88SJack F Vogel return IXGBE_SUCCESS; 242713705f88SJack F Vogel } 242813705f88SJack F Vogel 242913705f88SJack F Vogel /** 24305b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 24315b7f4cedSJack F Vogel * @hw: pointer to hardware structure 24325b7f4cedSJack F Vogel * @index: Receive address register to write 24335b7f4cedSJack F Vogel * 24345b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 24355b7f4cedSJack F Vogel **/ 24365b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 24375b7f4cedSJack F Vogel { 24385b7f4cedSJack F Vogel u32 rar_high; 24395b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24405b7f4cedSJack F Vogel 24412969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 24422969bf0eSJack F Vogel 24435b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 24441a4e3449SJack F Vogel if (index >= rar_entries) { 2445fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2446fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 24471a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24481a4e3449SJack F Vogel } 24491a4e3449SJack F Vogel 24505b7f4cedSJack F Vogel /* 24515b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24525b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 24535b7f4cedSJack F Vogel * of the address and the address valid bit. 24545b7f4cedSJack F Vogel */ 24555b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24565b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24575b7f4cedSJack F Vogel 24585b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 24595b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 24605b7f4cedSJack F Vogel 24615b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 24625b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 24635b7f4cedSJack F Vogel 24645b7f4cedSJack F Vogel return IXGBE_SUCCESS; 24655b7f4cedSJack F Vogel } 24665b7f4cedSJack F Vogel 24675b7f4cedSJack F Vogel /** 246813705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 246913705f88SJack F Vogel * @hw: pointer to hardware structure 247013705f88SJack F Vogel * 247113705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 24729ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 247313705f88SJack F Vogel * the receiver is in reset when the routine is called. 247413705f88SJack F Vogel **/ 247513705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 247613705f88SJack F Vogel { 247713705f88SJack F Vogel u32 i; 24789ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 247913705f88SJack F Vogel 24802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 24812969bf0eSJack F Vogel 248213705f88SJack F Vogel /* 248313705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 248413705f88SJack F Vogel * to the permanent address. 248513705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 248613705f88SJack F Vogel */ 248713705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 248813705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 248913705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 24909ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 249113705f88SJack F Vogel 249213705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 249313705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 249413705f88SJack F Vogel hw->mac.addr[2]); 249513705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 249613705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 249713705f88SJack F Vogel } else { 249813705f88SJack F Vogel /* Setup the receive address. */ 249913705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 250013705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 250113705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 250213705f88SJack F Vogel hw->mac.addr[2]); 250313705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 250413705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 250513705f88SJack F Vogel 25069ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 25078eb6488eSEric Joyner } 2508182b3808SJack F Vogel 2509182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2510182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 25118eb6488eSEric Joyner 25129ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 251313705f88SJack F Vogel 251413705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 251513705f88SJack F Vogel 251613705f88SJack F Vogel /* Zero out the other receive addresses. */ 25179ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 251813705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 251913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 252013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 252113705f88SJack F Vogel } 252213705f88SJack F Vogel 252313705f88SJack F Vogel /* Clear the MTA */ 252413705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 252513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 252613705f88SJack F Vogel 252713705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 25289ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 252913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 253013705f88SJack F Vogel 25315b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 25325b7f4cedSJack F Vogel 253313705f88SJack F Vogel return IXGBE_SUCCESS; 253413705f88SJack F Vogel } 253513705f88SJack F Vogel 253613705f88SJack F Vogel /** 25379ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 25389ca4041bSJack F Vogel * @hw: pointer to hardware structure 25399ca4041bSJack F Vogel * @addr: new address 25409ca4041bSJack F Vogel * 25419ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 25429ca4041bSJack F Vogel **/ 25439ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 25449ca4041bSJack F Vogel { 25459ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 25469ca4041bSJack F Vogel u32 rar; 25479ca4041bSJack F Vogel 25482969bf0eSJack F Vogel DEBUGFUNC("ixgbe_add_uc_addr"); 25492969bf0eSJack F Vogel 25509ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 25519ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 25529ca4041bSJack F Vogel 25539ca4041bSJack F Vogel /* 25549ca4041bSJack F Vogel * Place this address in the RAR if there is room, 25559ca4041bSJack F Vogel * else put the controller into promiscuous mode 25569ca4041bSJack F Vogel */ 25579ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 25580ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 25599ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 25609ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 25619ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 25629ca4041bSJack F Vogel } else { 25639ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 25649ca4041bSJack F Vogel } 25659ca4041bSJack F Vogel 25669ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 25679ca4041bSJack F Vogel } 25689ca4041bSJack F Vogel 25699ca4041bSJack F Vogel /** 25709ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 25719ca4041bSJack F Vogel * @hw: pointer to hardware structure 25729ca4041bSJack F Vogel * @addr_list: the list of new addresses 25739ca4041bSJack F Vogel * @addr_count: number of addresses 25749ca4041bSJack F Vogel * @next: iterator function to walk the address list 25759ca4041bSJack F Vogel * 25769ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 25779ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 25789ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 25799ca4041bSJack F Vogel * 25809ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 25819ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 25829ca4041bSJack F Vogel **/ 25839ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 25849ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 25859ca4041bSJack F Vogel { 25869ca4041bSJack F Vogel u8 *addr; 25879ca4041bSJack F Vogel u32 i; 25889ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 25899ca4041bSJack F Vogel u32 uc_addr_in_use; 25909ca4041bSJack F Vogel u32 fctrl; 25919ca4041bSJack F Vogel u32 vmdq; 25929ca4041bSJack F Vogel 25932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 25942969bf0eSJack F Vogel 25959ca4041bSJack F Vogel /* 25969ca4041bSJack F Vogel * Clear accounting of old secondary address list, 25979ca4041bSJack F Vogel * don't count RAR[0] 25989ca4041bSJack F Vogel */ 25990ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 26009ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 26019ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 26029ca4041bSJack F Vogel 26039ca4041bSJack F Vogel /* Zero out the other receive addresses */ 26042969bf0eSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); 26052969bf0eSJack F Vogel for (i = 0; i < uc_addr_in_use; i++) { 26062969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); 26072969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); 26089ca4041bSJack F Vogel } 26099ca4041bSJack F Vogel 26109ca4041bSJack F Vogel /* Add the new addresses */ 26119ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 26129ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 26139ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 26149ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 26159ca4041bSJack F Vogel } 26169ca4041bSJack F Vogel 26179ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 26189ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 26199ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26209ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 26219ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26229ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 26239ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26249ca4041bSJack F Vogel } 26259ca4041bSJack F Vogel } else { 26269ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 26279ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26289ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 26299ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26309ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 26319ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26329ca4041bSJack F Vogel } 26339ca4041bSJack F Vogel } 26349ca4041bSJack F Vogel 26359ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 26369ca4041bSJack F Vogel return IXGBE_SUCCESS; 26379ca4041bSJack F Vogel } 26389ca4041bSJack F Vogel 26399ca4041bSJack F Vogel /** 264013705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 264113705f88SJack F Vogel * @hw: pointer to hardware structure 264213705f88SJack F Vogel * @mc_addr: the multicast address 264313705f88SJack F Vogel * 264413705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 264513705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 264613705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 264713705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 26489ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 264913705f88SJack F Vogel * to mc_filter_type. 265013705f88SJack F Vogel **/ 265113705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 265213705f88SJack F Vogel { 265313705f88SJack F Vogel u32 vector = 0; 265413705f88SJack F Vogel 26552969bf0eSJack F Vogel DEBUGFUNC("ixgbe_mta_vector"); 26562969bf0eSJack F Vogel 265713705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 265813705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 265913705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 266013705f88SJack F Vogel break; 266113705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 266213705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 266313705f88SJack F Vogel break; 266413705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 266513705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 266613705f88SJack F Vogel break; 266713705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 266813705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 266913705f88SJack F Vogel break; 267013705f88SJack F Vogel default: /* Invalid mc_filter_type */ 267113705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 267213705f88SJack F Vogel ASSERT(0); 267313705f88SJack F Vogel break; 267413705f88SJack F Vogel } 267513705f88SJack F Vogel 267613705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 267713705f88SJack F Vogel vector &= 0xFFF; 267813705f88SJack F Vogel return vector; 267913705f88SJack F Vogel } 268013705f88SJack F Vogel 268113705f88SJack F Vogel /** 268213705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 268313705f88SJack F Vogel * @hw: pointer to hardware structure 268413705f88SJack F Vogel * @hash_value: Multicast address hash value 268513705f88SJack F Vogel * 268613705f88SJack F Vogel * Sets the bit-vector in the multicast table. 268713705f88SJack F Vogel **/ 268813705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 268913705f88SJack F Vogel { 269013705f88SJack F Vogel u32 vector; 269113705f88SJack F Vogel u32 vector_bit; 269213705f88SJack F Vogel u32 vector_reg; 269313705f88SJack F Vogel 26942969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_mta"); 26952969bf0eSJack F Vogel 269613705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 269713705f88SJack F Vogel 269813705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 269913705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 270013705f88SJack F Vogel 270113705f88SJack F Vogel /* 270213705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 270313705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 270413705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 270513705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 270613705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 270713705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 270813705f88SJack F Vogel * the value. 270913705f88SJack F Vogel */ 271013705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 271113705f88SJack F Vogel vector_bit = vector & 0x1F; 27121a4e3449SJack F Vogel hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); 271313705f88SJack F Vogel } 271413705f88SJack F Vogel 271513705f88SJack F Vogel /** 271613705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 271713705f88SJack F Vogel * @hw: pointer to hardware structure 271813705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 271913705f88SJack F Vogel * @mc_addr_count: number of addresses 27209ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 272185d0a26eSJack F Vogel * @clear: flag, when set clears the table beforehand 272213705f88SJack F Vogel * 272385d0a26eSJack F Vogel * When the clear flag is set, the given list replaces any existing list. 272485d0a26eSJack F Vogel * Hashes the given addresses into the multicast table. 272513705f88SJack F Vogel **/ 272613705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 272785d0a26eSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next, 272885d0a26eSJack F Vogel bool clear) 272913705f88SJack F Vogel { 273013705f88SJack F Vogel u32 i; 27319ca4041bSJack F Vogel u32 vmdq; 273213705f88SJack F Vogel 27332969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 27342969bf0eSJack F Vogel 273513705f88SJack F Vogel /* 273613705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 273713705f88SJack F Vogel * use. 273813705f88SJack F Vogel */ 273913705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 274013705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 274113705f88SJack F Vogel 27421a4e3449SJack F Vogel /* Clear mta_shadow */ 274385d0a26eSJack F Vogel if (clear) { 274413705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 27451a4e3449SJack F Vogel memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 274685d0a26eSJack F Vogel } 274713705f88SJack F Vogel 27481a4e3449SJack F Vogel /* Update mta_shadow */ 274913705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 275013705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 27510ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 275213705f88SJack F Vogel } 275313705f88SJack F Vogel 275413705f88SJack F Vogel /* Enable mta */ 27551a4e3449SJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 27561a4e3449SJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 27571a4e3449SJack F Vogel hw->mac.mta_shadow[i]); 27581a4e3449SJack F Vogel 275913705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 276013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 276113705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 276213705f88SJack F Vogel 276313705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 276413705f88SJack F Vogel return IXGBE_SUCCESS; 276513705f88SJack F Vogel } 276613705f88SJack F Vogel 276713705f88SJack F Vogel /** 276813705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 276913705f88SJack F Vogel * @hw: pointer to hardware structure 277013705f88SJack F Vogel * 277113705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 277213705f88SJack F Vogel **/ 277313705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 277413705f88SJack F Vogel { 277513705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 277613705f88SJack F Vogel 27772969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_mc_generic"); 27782969bf0eSJack F Vogel 277913705f88SJack F Vogel if (a->mta_in_use > 0) 278013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 278113705f88SJack F Vogel hw->mac.mc_filter_type); 278213705f88SJack F Vogel 278313705f88SJack F Vogel return IXGBE_SUCCESS; 278413705f88SJack F Vogel } 278513705f88SJack F Vogel 278613705f88SJack F Vogel /** 27879ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 278813705f88SJack F Vogel * @hw: pointer to hardware structure 278913705f88SJack F Vogel * 279013705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 279113705f88SJack F Vogel **/ 279213705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 279313705f88SJack F Vogel { 279413705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 279513705f88SJack F Vogel 27962969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_mc_generic"); 27972969bf0eSJack F Vogel 279813705f88SJack F Vogel if (a->mta_in_use > 0) 279913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 280013705f88SJack F Vogel 280113705f88SJack F Vogel return IXGBE_SUCCESS; 280213705f88SJack F Vogel } 280313705f88SJack F Vogel 28041b6e0dbaSJack F Vogel /** 28050ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 28061b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 28071b6e0dbaSJack F Vogel * 28080ac6dfecSJack F Vogel * Enable flow control according to the current settings. 28091b6e0dbaSJack F Vogel **/ 2810a621e3c8SJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 28111b6e0dbaSJack F Vogel { 28121b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 28130ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 28140ac6dfecSJack F Vogel u32 reg; 28151a4e3449SJack F Vogel u32 fcrtl, fcrth; 2816a621e3c8SJack F Vogel int i; 28171b6e0dbaSJack F Vogel 28180ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 28191b6e0dbaSJack F Vogel 2820a621e3c8SJack F Vogel /* Validate the water mark configuration */ 2821a621e3c8SJack F Vogel if (!hw->fc.pause_time) { 2822a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 28230ac6dfecSJack F Vogel goto out; 2824a621e3c8SJack F Vogel } 2825a621e3c8SJack F Vogel 2826a621e3c8SJack F Vogel /* Low water mark of zero causes XOFF floods */ 2827a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2828a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2829a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2830a621e3c8SJack F Vogel if (!hw->fc.low_water[i] || 2831a621e3c8SJack F Vogel hw->fc.low_water[i] >= hw->fc.high_water[i]) { 2832a621e3c8SJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 2833a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 2834a621e3c8SJack F Vogel goto out; 2835a621e3c8SJack F Vogel } 2836a621e3c8SJack F Vogel } 2837a621e3c8SJack F Vogel } 2838a621e3c8SJack F Vogel 2839a621e3c8SJack F Vogel /* Negotiate the fc mode to use */ 28408eb6488eSEric Joyner hw->mac.ops.fc_autoneg(hw); 28410ac6dfecSJack F Vogel 28420ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 28430ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 2844a621e3c8SJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 28450ac6dfecSJack F Vogel 28460ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 28470ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 28481b6e0dbaSJack F Vogel 28491b6e0dbaSJack F Vogel /* 28501b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 28511b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 28521b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 28531b6e0dbaSJack F Vogel * but not send pause frames). 28541b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 28551b6e0dbaSJack F Vogel * we do not support receiving pause frames). 28561b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 28571b6e0dbaSJack F Vogel * other: Invalid. 28581b6e0dbaSJack F Vogel */ 28591b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 28601b6e0dbaSJack F Vogel case ixgbe_fc_none: 28611a4e3449SJack F Vogel /* 28621a4e3449SJack F Vogel * Flow control is disabled by software override or autoneg. 28630ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 28640ac6dfecSJack F Vogel */ 28651b6e0dbaSJack F Vogel break; 28661b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 28671b6e0dbaSJack F Vogel /* 28681b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 28691b6e0dbaSJack F Vogel * disabled by software override. Since there really 28701b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 28711b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 28721b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 28731b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 28741b6e0dbaSJack F Vogel */ 28750ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28761b6e0dbaSJack F Vogel break; 28771b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 28781b6e0dbaSJack F Vogel /* 28791b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 28801b6e0dbaSJack F Vogel * disabled by software override. 28811b6e0dbaSJack F Vogel */ 28820ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28831b6e0dbaSJack F Vogel break; 28841b6e0dbaSJack F Vogel case ixgbe_fc_full: 28851b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 28860ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28870ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28881b6e0dbaSJack F Vogel break; 28891b6e0dbaSJack F Vogel default: 2890fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 2891fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 28922969bf0eSJack F Vogel ret_val = IXGBE_ERR_CONFIG; 28931b6e0dbaSJack F Vogel goto out; 28941b6e0dbaSJack F Vogel break; 28951b6e0dbaSJack F Vogel } 28961b6e0dbaSJack F Vogel 28970ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 28980ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 28990ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 29000ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 29011b6e0dbaSJack F Vogel 2902d8602bb9SJack F Vogel 2903a621e3c8SJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 2904a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2905a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2906a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2907a621e3c8SJack F Vogel fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 2908a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 2909a621e3c8SJack F Vogel fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 2910a621e3c8SJack F Vogel } else { 2911a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 2912a621e3c8SJack F Vogel /* 2913a621e3c8SJack F Vogel * In order to prevent Tx hangs when the internal Tx 2914a621e3c8SJack F Vogel * switch is enabled we must set the high water mark 2915758cc3dcSJack F Vogel * to the Rx packet buffer size - 24KB. This allows 2916758cc3dcSJack F Vogel * the Tx switch to function even under heavy Rx 2917758cc3dcSJack F Vogel * workloads. 2918a621e3c8SJack F Vogel */ 2919758cc3dcSJack F Vogel fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 29201b6e0dbaSJack F Vogel } 29211b6e0dbaSJack F Vogel 2922a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 2923a621e3c8SJack F Vogel } 29240ac6dfecSJack F Vogel 29250ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 2926a621e3c8SJack F Vogel reg = hw->fc.pause_time * 0x00010001; 2927a621e3c8SJack F Vogel for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) 2928a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 29290ac6dfecSJack F Vogel 2930a621e3c8SJack F Vogel /* Configure flow control refresh threshold value */ 2931a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 29320ac6dfecSJack F Vogel 29330ac6dfecSJack F Vogel out: 29340ac6dfecSJack F Vogel return ret_val; 29350ac6dfecSJack F Vogel } 29360ac6dfecSJack F Vogel 29370ac6dfecSJack F Vogel /** 29381a4e3449SJack F Vogel * ixgbe_negotiate_fc - Negotiate flow control 29391a4e3449SJack F Vogel * @hw: pointer to hardware structure 29401a4e3449SJack F Vogel * @adv_reg: flow control advertised settings 29411a4e3449SJack F Vogel * @lp_reg: link partner's flow control settings 29421a4e3449SJack F Vogel * @adv_sym: symmetric pause bit in advertisement 29431a4e3449SJack F Vogel * @adv_asm: asymmetric pause bit in advertisement 29441a4e3449SJack F Vogel * @lp_sym: symmetric pause bit in link partner advertisement 29451a4e3449SJack F Vogel * @lp_asm: asymmetric pause bit in link partner advertisement 29461a4e3449SJack F Vogel * 29471a4e3449SJack F Vogel * Find the intersection between advertised settings and link partner's 29481a4e3449SJack F Vogel * advertised settings 29491a4e3449SJack F Vogel **/ 29508eb6488eSEric Joyner s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 29511a4e3449SJack F Vogel u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 29521a4e3449SJack F Vogel { 2953fd75b91dSJack F Vogel if ((!(adv_reg)) || (!(lp_reg))) { 2954fd75b91dSJack F Vogel ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, 2955fd75b91dSJack F Vogel "Local or link partner's advertised flow control " 2956fd75b91dSJack F Vogel "settings are NULL. Local: %x, link partner: %x\n", 2957fd75b91dSJack F Vogel adv_reg, lp_reg); 29581a4e3449SJack F Vogel return IXGBE_ERR_FC_NOT_NEGOTIATED; 2959fd75b91dSJack F Vogel } 29601a4e3449SJack F Vogel 29611a4e3449SJack F Vogel if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 29622969bf0eSJack F Vogel /* 29632969bf0eSJack F Vogel * Now we need to check if the user selected Rx ONLY 29642969bf0eSJack F Vogel * of pause frames. In this case, we had to advertise 29652969bf0eSJack F Vogel * FULL flow control because we could not advertise RX 29662969bf0eSJack F Vogel * ONLY. Hence, we must now check to see if we need to 29672969bf0eSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 29682969bf0eSJack F Vogel */ 29692969bf0eSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 29702969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 29712969bf0eSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 29722969bf0eSJack F Vogel } else { 29732969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29742969bf0eSJack F Vogel DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 29752969bf0eSJack F Vogel } 29761a4e3449SJack F Vogel } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 29771a4e3449SJack F Vogel (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29782969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 29792969bf0eSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 29801a4e3449SJack F Vogel } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 29811a4e3449SJack F Vogel !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29822969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29832969bf0eSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 29842969bf0eSJack F Vogel } else { 29852969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 29862969bf0eSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 29872969bf0eSJack F Vogel } 29881a4e3449SJack F Vogel return IXGBE_SUCCESS; 29891b6e0dbaSJack F Vogel } 29901b6e0dbaSJack F Vogel 29910ac6dfecSJack F Vogel /** 2992a621e3c8SJack F Vogel * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 29930ac6dfecSJack F Vogel * @hw: pointer to hardware structure 29940ac6dfecSJack F Vogel * 2995a621e3c8SJack F Vogel * Enable flow control according on 1 gig fiber. 29960ac6dfecSJack F Vogel **/ 2997a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 29980ac6dfecSJack F Vogel { 2999a621e3c8SJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 3000a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 30010ac6dfecSJack F Vogel 3002a621e3c8SJack F Vogel /* 3003a621e3c8SJack F Vogel * On multispeed fiber at 1g, bail out if 3004a621e3c8SJack F Vogel * - link is up but AN did not complete, or if 3005a621e3c8SJack F Vogel * - link is up and AN completed but timed out 3006a621e3c8SJack F Vogel */ 30072969bf0eSJack F Vogel 3008a621e3c8SJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 3009a621e3c8SJack F Vogel if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 3010fd75b91dSJack F Vogel (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 3011758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); 30120ac6dfecSJack F Vogel goto out; 3013fd75b91dSJack F Vogel } 30140ac6dfecSJack F Vogel 3015a621e3c8SJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 3016a621e3c8SJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 30170ac6dfecSJack F Vogel 3018a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 3019a621e3c8SJack F Vogel pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 3020a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE, 3021a621e3c8SJack F Vogel IXGBE_PCS1GANA_SYM_PAUSE, 3022a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE); 30230ac6dfecSJack F Vogel 30240ac6dfecSJack F Vogel out: 30250ac6dfecSJack F Vogel return ret_val; 30260ac6dfecSJack F Vogel } 30271b6e0dbaSJack F Vogel 302813705f88SJack F Vogel /** 3029a621e3c8SJack F Vogel * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 3030a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3031a621e3c8SJack F Vogel * 3032a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3033a621e3c8SJack F Vogel **/ 3034a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 3035a621e3c8SJack F Vogel { 3036a621e3c8SJack F Vogel u32 links2, anlp1_reg, autoc_reg, links; 3037a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3038a621e3c8SJack F Vogel 3039a621e3c8SJack F Vogel /* 3040a621e3c8SJack F Vogel * On backplane, bail out if 3041a621e3c8SJack F Vogel * - backplane autoneg was not completed, or if 3042a621e3c8SJack F Vogel * - we are 82599 and link partner is not AN enabled 3043a621e3c8SJack F Vogel */ 3044a621e3c8SJack F Vogel links = IXGBE_READ_REG(hw, IXGBE_LINKS); 3045fd75b91dSJack F Vogel if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { 3046758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete\n"); 3047a621e3c8SJack F Vogel goto out; 3048fd75b91dSJack F Vogel } 3049a621e3c8SJack F Vogel 3050a621e3c8SJack F Vogel if (hw->mac.type == ixgbe_mac_82599EB) { 3051a621e3c8SJack F Vogel links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 3052fd75b91dSJack F Vogel if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { 3053758cc3dcSJack F Vogel DEBUGOUT("Link partner is not AN enabled\n"); 3054a621e3c8SJack F Vogel goto out; 3055a621e3c8SJack F Vogel } 3056fd75b91dSJack F Vogel } 3057a621e3c8SJack F Vogel /* 3058a621e3c8SJack F Vogel * Read the 10g AN autoc and LP ability registers and resolve 3059a621e3c8SJack F Vogel * local flow control settings accordingly 3060a621e3c8SJack F Vogel */ 3061a621e3c8SJack F Vogel autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3062a621e3c8SJack F Vogel anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 3063a621e3c8SJack F Vogel 3064a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 3065a621e3c8SJack F Vogel anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 3066a621e3c8SJack F Vogel IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 3067a621e3c8SJack F Vogel 3068a621e3c8SJack F Vogel out: 3069a621e3c8SJack F Vogel return ret_val; 3070a621e3c8SJack F Vogel } 3071a621e3c8SJack F Vogel 3072a621e3c8SJack F Vogel /** 3073a621e3c8SJack F Vogel * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 3074a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3075a621e3c8SJack F Vogel * 3076a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3077a621e3c8SJack F Vogel **/ 3078a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 3079a621e3c8SJack F Vogel { 3080a621e3c8SJack F Vogel u16 technology_ability_reg = 0; 3081a621e3c8SJack F Vogel u16 lp_technology_ability_reg = 0; 3082a621e3c8SJack F Vogel 3083a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 3084a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3085a621e3c8SJack F Vogel &technology_ability_reg); 3086a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, 3087a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3088a621e3c8SJack F Vogel &lp_technology_ability_reg); 3089a621e3c8SJack F Vogel 3090a621e3c8SJack F Vogel return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 3091a621e3c8SJack F Vogel (u32)lp_technology_ability_reg, 3092a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 3093a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 3094a621e3c8SJack F Vogel } 3095a621e3c8SJack F Vogel 3096a621e3c8SJack F Vogel /** 3097a621e3c8SJack F Vogel * ixgbe_fc_autoneg - Configure flow control 3098a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3099a621e3c8SJack F Vogel * 3100a621e3c8SJack F Vogel * Compares our advertised flow control capabilities to those advertised by 3101a621e3c8SJack F Vogel * our link partner, and determines the proper flow control mode to use. 3102a621e3c8SJack F Vogel **/ 3103a621e3c8SJack F Vogel void ixgbe_fc_autoneg(struct ixgbe_hw *hw) 3104a621e3c8SJack F Vogel { 3105a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3106a621e3c8SJack F Vogel ixgbe_link_speed speed; 3107a621e3c8SJack F Vogel bool link_up; 3108a621e3c8SJack F Vogel 3109a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 3110a621e3c8SJack F Vogel 3111a621e3c8SJack F Vogel /* 3112a621e3c8SJack F Vogel * AN should have completed when the cable was plugged in. 3113a621e3c8SJack F Vogel * Look for reasons to bail out. Bail out if: 3114a621e3c8SJack F Vogel * - FC autoneg is disabled, or if 3115a621e3c8SJack F Vogel * - link is not up. 3116a621e3c8SJack F Vogel */ 3117fd75b91dSJack F Vogel if (hw->fc.disable_fc_autoneg) { 3118fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 3119fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3120a621e3c8SJack F Vogel goto out; 3121fd75b91dSJack F Vogel } 3122a621e3c8SJack F Vogel 3123a621e3c8SJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 3124fd75b91dSJack F Vogel if (!link_up) { 3125fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3126a621e3c8SJack F Vogel goto out; 3127fd75b91dSJack F Vogel } 3128a621e3c8SJack F Vogel 3129a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3130a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 31310ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3132758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3133a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3134a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3135a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3136a621e3c8SJack F Vogel break; 3137a621e3c8SJack F Vogel 3138a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3139a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3140a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3141a621e3c8SJack F Vogel break; 3142a621e3c8SJack F Vogel 3143a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3144a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3145fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3146a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3147a621e3c8SJack F Vogel break; 3148a621e3c8SJack F Vogel 3149a621e3c8SJack F Vogel default: 3150a621e3c8SJack F Vogel break; 3151a621e3c8SJack F Vogel } 3152a621e3c8SJack F Vogel 3153a621e3c8SJack F Vogel out: 3154a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 3155a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = TRUE; 3156a621e3c8SJack F Vogel } else { 3157a621e3c8SJack F Vogel hw->fc.fc_was_autonegged = FALSE; 3158a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3159a621e3c8SJack F Vogel } 3160a621e3c8SJack F Vogel } 3161a621e3c8SJack F Vogel 3162fd75b91dSJack F Vogel /* 3163fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3164fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3165fd75b91dSJack F Vogel * 3166fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3167fd75b91dSJack F Vogel * 3168fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3169fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3170fd75b91dSJack F Vogel * 800 = 80 millisec. 3171fd75b91dSJack F Vogel */ 3172fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3173fd75b91dSJack F Vogel { 3174fd75b91dSJack F Vogel s16 devctl2; 3175fd75b91dSJack F Vogel u32 pollcnt; 3176fd75b91dSJack F Vogel 3177fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3178fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3179fd75b91dSJack F Vogel 3180fd75b91dSJack F Vogel switch (devctl2) { 3181fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3182fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3183fd75b91dSJack F Vogel break; 3184fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3185fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3186fd75b91dSJack F Vogel break; 3187fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3188fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3189fd75b91dSJack F Vogel break; 3190fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3191fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3192fd75b91dSJack F Vogel break; 3193fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3194fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3195fd75b91dSJack F Vogel break; 3196fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3197fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3198fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3199fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3200fd75b91dSJack F Vogel default: 3201fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3202fd75b91dSJack F Vogel break; 3203fd75b91dSJack F Vogel } 3204fd75b91dSJack F Vogel 3205fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3206fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3207fd75b91dSJack F Vogel } 3208fd75b91dSJack F Vogel 3209a621e3c8SJack F Vogel /** 321013705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 321113705f88SJack F Vogel * @hw: pointer to hardware structure 321213705f88SJack F Vogel * 321313705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 321413705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 321513705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 321613705f88SJack F Vogel * is returned signifying master requests disabled. 321713705f88SJack F Vogel **/ 321813705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 321913705f88SJack F Vogel { 3220c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3221fd75b91dSJack F Vogel u32 i, poll; 3222758cc3dcSJack F Vogel u16 value; 322313705f88SJack F Vogel 32242969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_pcie_master"); 32252969bf0eSJack F Vogel 322685d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 322785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 322885d0a26eSJack F Vogel 3229fd75b91dSJack F Vogel /* Exit if master requests are blocked */ 3230758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3231758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3232c0014855SJack F Vogel goto out; 3233c0014855SJack F Vogel 323485d0a26eSJack F Vogel /* Poll for master request bit to clear */ 323513705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 323685d0a26eSJack F Vogel usec_delay(100); 3237c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3238182b3808SJack F Vogel goto out; 323985d0a26eSJack F Vogel } 3240c0014855SJack F Vogel 3241c0014855SJack F Vogel /* 3242c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 3243c0014855SJack F Vogel * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine 3244c0014855SJack F Vogel * of this need. The first reset prevents new master requests from 324585d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3246c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3247c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3248c0014855SJack F Vogel */ 324985d0a26eSJack F Vogel DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); 3250c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3251c0014855SJack F Vogel 3252a9ca1c79SSean Bruno if (hw->mac.type >= ixgbe_mac_X550) 3253a9ca1c79SSean Bruno goto out; 3254a9ca1c79SSean Bruno 325585d0a26eSJack F Vogel /* 325685d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 325785d0a26eSJack F Vogel * transactions pending. 325885d0a26eSJack F Vogel */ 3259fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3260fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 326185d0a26eSJack F Vogel usec_delay(100); 3262758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3263758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3264758cc3dcSJack F Vogel goto out; 3265758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 326685d0a26eSJack F Vogel goto out; 326785d0a26eSJack F Vogel } 326885d0a26eSJack F Vogel 3269fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3270fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 327185d0a26eSJack F Vogel status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 327285d0a26eSJack F Vogel 3273c0014855SJack F Vogel out: 327413705f88SJack F Vogel return status; 327513705f88SJack F Vogel } 327613705f88SJack F Vogel 327713705f88SJack F Vogel /** 32789ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 327913705f88SJack F Vogel * @hw: pointer to hardware structure 32809ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 328113705f88SJack F Vogel * 328285d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 328313705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 328413705f88SJack F Vogel **/ 3285758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 328613705f88SJack F Vogel { 3287fd75b91dSJack F Vogel u32 gssr = 0; 328813705f88SJack F Vogel u32 swmask = mask; 328913705f88SJack F Vogel u32 fwmask = mask << 5; 3290fd75b91dSJack F Vogel u32 timeout = 200; 3291fd75b91dSJack F Vogel u32 i; 329213705f88SJack F Vogel 32932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 32942969bf0eSJack F Vogel 3295fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 32960ac6dfecSJack F Vogel /* 3297fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3298fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 32990ac6dfecSJack F Vogel */ 330013705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 33012969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 330213705f88SJack F Vogel 330313705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3304fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 330513705f88SJack F Vogel gssr |= swmask; 330613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 330713705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 330813705f88SJack F Vogel return IXGBE_SUCCESS; 3309fd75b91dSJack F Vogel } else { 3310fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3311fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3312fd75b91dSJack F Vogel msec_delay(5); 3313fd75b91dSJack F Vogel } 3314fd75b91dSJack F Vogel } 3315fd75b91dSJack F Vogel 3316fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3317fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3318fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3319fd75b91dSJack F Vogel 3320fd75b91dSJack F Vogel msec_delay(5); 3321fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 332213705f88SJack F Vogel } 332313705f88SJack F Vogel 332413705f88SJack F Vogel /** 332513705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 332613705f88SJack F Vogel * @hw: pointer to hardware structure 33279ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 332813705f88SJack F Vogel * 332985d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 333013705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 333113705f88SJack F Vogel **/ 3332758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 333313705f88SJack F Vogel { 333413705f88SJack F Vogel u32 gssr; 333513705f88SJack F Vogel u32 swmask = mask; 333613705f88SJack F Vogel 33372969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 33382969bf0eSJack F Vogel 333913705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 334013705f88SJack F Vogel 334113705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 334213705f88SJack F Vogel gssr &= ~swmask; 334313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 334413705f88SJack F Vogel 334513705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 33460ac6dfecSJack F Vogel } 33470ac6dfecSJack F Vogel 33480ac6dfecSJack F Vogel /** 334985d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 335085d0a26eSJack F Vogel * @hw: pointer to hardware structure 335185d0a26eSJack F Vogel * 335285d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 335385d0a26eSJack F Vogel * the Rx security block 335485d0a26eSJack F Vogel **/ 335585d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 335685d0a26eSJack F Vogel { 335785d0a26eSJack F Vogel #define IXGBE_MAX_SECRX_POLL 40 335885d0a26eSJack F Vogel 335985d0a26eSJack F Vogel int i; 336085d0a26eSJack F Vogel int secrxreg; 336185d0a26eSJack F Vogel 336285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 336385d0a26eSJack F Vogel 336485d0a26eSJack F Vogel 336585d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 336685d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 336785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 336885d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 336985d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 337085d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 337185d0a26eSJack F Vogel break; 337285d0a26eSJack F Vogel else 337385d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 337485d0a26eSJack F Vogel usec_delay(1000); 337585d0a26eSJack F Vogel } 337685d0a26eSJack F Vogel 337785d0a26eSJack F Vogel /* For informational purposes only */ 337885d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 337985d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 338085d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 338185d0a26eSJack F Vogel 338285d0a26eSJack F Vogel return IXGBE_SUCCESS; 338385d0a26eSJack F Vogel } 338485d0a26eSJack F Vogel 338585d0a26eSJack F Vogel /** 3386758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3387758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3388758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3389758cc3dcSJack F Vogel * 3390758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3391758cc3dcSJack F Vogel */ 3392758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3393758cc3dcSJack F Vogel { 3394758cc3dcSJack F Vogel *locked = FALSE; 3395758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3396758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3397758cc3dcSJack F Vogel } 3398758cc3dcSJack F Vogel 3399758cc3dcSJack F Vogel /** 3400758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3401758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3402758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3403758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3404758cc3dcSJack F Vogel * previous read. 3405758cc3dcSJack F Vogel * 3406758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3407758cc3dcSJack F Vogel */ 3408758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3409758cc3dcSJack F Vogel { 3410758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3411758cc3dcSJack F Vogel 3412758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3413758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3414758cc3dcSJack F Vogel } 3415758cc3dcSJack F Vogel 3416758cc3dcSJack F Vogel /** 341785d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 341885d0a26eSJack F Vogel * @hw: pointer to hardware structure 341985d0a26eSJack F Vogel * 342085d0a26eSJack F Vogel * Enables the receive data path. 342185d0a26eSJack F Vogel **/ 342285d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 342385d0a26eSJack F Vogel { 34248eb6488eSEric Joyner u32 secrxreg; 342585d0a26eSJack F Vogel 342685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 342785d0a26eSJack F Vogel 342885d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 342985d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 343085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 343185d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 343285d0a26eSJack F Vogel 343385d0a26eSJack F Vogel return IXGBE_SUCCESS; 343485d0a26eSJack F Vogel } 343585d0a26eSJack F Vogel 343685d0a26eSJack F Vogel /** 34370ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 34380ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34390ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 34400ac6dfecSJack F Vogel * 34410ac6dfecSJack F Vogel * Enables the Rx DMA unit 34420ac6dfecSJack F Vogel **/ 34430ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 34440ac6dfecSJack F Vogel { 34452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 34462969bf0eSJack F Vogel 3447758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3448758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3449758cc3dcSJack F Vogel else 3450758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 34510ac6dfecSJack F Vogel 34520ac6dfecSJack F Vogel return IXGBE_SUCCESS; 34530ac6dfecSJack F Vogel } 34540ac6dfecSJack F Vogel 34550ac6dfecSJack F Vogel /** 34560ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 34570ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34580ac6dfecSJack F Vogel * @index: led number to blink 34590ac6dfecSJack F Vogel **/ 34600ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 34610ac6dfecSJack F Vogel { 34620ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 34630ac6dfecSJack F Vogel bool link_up = 0; 3464758cc3dcSJack F Vogel u32 autoc_reg = 0; 34650ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34660ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3467758cc3dcSJack F Vogel bool locked = FALSE; 34680ac6dfecSJack F Vogel 34692969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 34702969bf0eSJack F Vogel 34718eb6488eSEric Joyner if (index > 3) 34728eb6488eSEric Joyner return IXGBE_ERR_PARAM; 34738eb6488eSEric Joyner 34740ac6dfecSJack F Vogel /* 34750ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 34760ac6dfecSJack F Vogel * Force it if link is down. 34770ac6dfecSJack F Vogel */ 34780ac6dfecSJack F Vogel hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); 34790ac6dfecSJack F Vogel 34800ac6dfecSJack F Vogel if (!link_up) { 3481758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3482758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 34830ecc2ff0SJack F Vogel goto out; 34840ecc2ff0SJack F Vogel 3485d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34860ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 34870ecc2ff0SJack F Vogel 3488758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3489758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3490758cc3dcSJack F Vogel goto out; 3491758cc3dcSJack F Vogel 3492758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34930ac6dfecSJack F Vogel msec_delay(10); 34940ac6dfecSJack F Vogel } 34950ac6dfecSJack F Vogel 34960ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 34970ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 34980ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 34990ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35000ac6dfecSJack F Vogel 35010ecc2ff0SJack F Vogel out: 35020ecc2ff0SJack F Vogel return ret_val; 35030ac6dfecSJack F Vogel } 35040ac6dfecSJack F Vogel 35050ac6dfecSJack F Vogel /** 35060ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 35070ac6dfecSJack F Vogel * @hw: pointer to hardware structure 35080ac6dfecSJack F Vogel * @index: led number to stop blinking 35090ac6dfecSJack F Vogel **/ 35100ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 35110ac6dfecSJack F Vogel { 3512758cc3dcSJack F Vogel u32 autoc_reg = 0; 35130ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 35140ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 3515758cc3dcSJack F Vogel bool locked = FALSE; 35160ac6dfecSJack F Vogel 35172969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 35182969bf0eSJack F Vogel 35198eb6488eSEric Joyner if (index > 3) 35208eb6488eSEric Joyner return IXGBE_ERR_PARAM; 35218eb6488eSEric Joyner 3522758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3523758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3524758cc3dcSJack F Vogel goto out; 3525d8602bb9SJack F Vogel 35260ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 35270ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 35280ac6dfecSJack F Vogel 3529758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3530758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3531758cc3dcSJack F Vogel goto out; 35320ecc2ff0SJack F Vogel 35330ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35340ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 35350ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 35360ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35370ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35380ac6dfecSJack F Vogel 35390ecc2ff0SJack F Vogel out: 35400ecc2ff0SJack F Vogel return ret_val; 354113705f88SJack F Vogel } 354213705f88SJack F Vogel 35432969bf0eSJack F Vogel /** 35442969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 35452969bf0eSJack F Vogel * @hw: pointer to hardware structure 35462969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 35472969bf0eSJack F Vogel * 35482969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 35492969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 35502969bf0eSJack F Vogel * get and set mac_addr routines. 35512969bf0eSJack F Vogel **/ 35522969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 35532969bf0eSJack F Vogel u16 *san_mac_offset) 35542969bf0eSJack F Vogel { 3555fd75b91dSJack F Vogel s32 ret_val; 3556fd75b91dSJack F Vogel 35572969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 35582969bf0eSJack F Vogel 35592969bf0eSJack F Vogel /* 35602969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35612969bf0eSJack F Vogel * available. 35622969bf0eSJack F Vogel */ 3563fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3564fd75b91dSJack F Vogel san_mac_offset); 3565fd75b91dSJack F Vogel if (ret_val) { 3566fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3567fd75b91dSJack F Vogel "eeprom at offset %d failed", 3568fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3569fd75b91dSJack F Vogel } 35702969bf0eSJack F Vogel 3571fd75b91dSJack F Vogel return ret_val; 35722969bf0eSJack F Vogel } 35732969bf0eSJack F Vogel 35742969bf0eSJack F Vogel /** 35752969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 35762969bf0eSJack F Vogel * @hw: pointer to hardware structure 35772969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35782969bf0eSJack F Vogel * 35792969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 35802969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 35812969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 35822969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 35832969bf0eSJack F Vogel **/ 35842969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35852969bf0eSJack F Vogel { 35862969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35872969bf0eSJack F Vogel u8 i; 3588fd75b91dSJack F Vogel s32 ret_val; 35892969bf0eSJack F Vogel 35902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 35912969bf0eSJack F Vogel 35922969bf0eSJack F Vogel /* 35932969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35942969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 35952969bf0eSJack F Vogel */ 3596fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3597fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 35982969bf0eSJack F Vogel goto san_mac_addr_out; 35992969bf0eSJack F Vogel 36002969bf0eSJack F Vogel /* make sure we know which port we need to program */ 36012969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36022969bf0eSJack F Vogel /* apply the port offset to the address offset */ 36032969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36042969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36052969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3606fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3607fd75b91dSJack F Vogel &san_mac_data); 3608fd75b91dSJack F Vogel if (ret_val) { 3609fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3610fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3611fd75b91dSJack F Vogel san_mac_offset); 3612fd75b91dSJack F Vogel goto san_mac_addr_out; 3613fd75b91dSJack F Vogel } 36142969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 36152969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 36162969bf0eSJack F Vogel san_mac_offset++; 36172969bf0eSJack F Vogel } 3618fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36192969bf0eSJack F Vogel 36202969bf0eSJack F Vogel san_mac_addr_out: 3621fd75b91dSJack F Vogel /* 3622fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3623fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3624fd75b91dSJack F Vogel */ 3625fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3626fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 36272969bf0eSJack F Vogel return IXGBE_SUCCESS; 36282969bf0eSJack F Vogel } 36292969bf0eSJack F Vogel 36302969bf0eSJack F Vogel /** 36312969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 36322969bf0eSJack F Vogel * @hw: pointer to hardware structure 36332969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 36342969bf0eSJack F Vogel * 36352969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 36362969bf0eSJack F Vogel **/ 36372969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 36382969bf0eSJack F Vogel { 3639fd75b91dSJack F Vogel s32 ret_val; 36402969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 36412969bf0eSJack F Vogel u8 i; 36422969bf0eSJack F Vogel 36432969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 36442969bf0eSJack F Vogel 36452969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3646fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3647fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3648fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 36492969bf0eSJack F Vogel 36502969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 36512969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36522969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 36532969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36542969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36552969bf0eSJack F Vogel 36562969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 36572969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 36582969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 36592969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 36602969bf0eSJack F Vogel san_mac_offset++; 36612969bf0eSJack F Vogel } 36622969bf0eSJack F Vogel 3663fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36642969bf0eSJack F Vogel } 36652969bf0eSJack F Vogel 36662969bf0eSJack F Vogel /** 36672969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 36682969bf0eSJack F Vogel * @hw: pointer to hardware structure 36692969bf0eSJack F Vogel * 36702969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 36712969bf0eSJack F Vogel * the capabilities table. 36722969bf0eSJack F Vogel **/ 3673a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 36742969bf0eSJack F Vogel { 3675a621e3c8SJack F Vogel u16 msix_count = 1; 3676a621e3c8SJack F Vogel u16 max_msix_count; 3677a621e3c8SJack F Vogel u16 pcie_offset; 3678a621e3c8SJack F Vogel 3679a621e3c8SJack F Vogel switch (hw->mac.type) { 3680a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3681a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3682a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3683a621e3c8SJack F Vogel break; 3684a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3685a621e3c8SJack F Vogel case ixgbe_mac_X540: 3686758cc3dcSJack F Vogel case ixgbe_mac_X550: 3687758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 36888eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3689a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3690a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3691a621e3c8SJack F Vogel break; 3692a621e3c8SJack F Vogel default: 3693a621e3c8SJack F Vogel return msix_count; 3694a621e3c8SJack F Vogel } 36952969bf0eSJack F Vogel 36962969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3697a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3698758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3699758cc3dcSJack F Vogel msix_count = 0; 37002969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 37012969bf0eSJack F Vogel 3702a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 37032969bf0eSJack F Vogel msix_count++; 3704a621e3c8SJack F Vogel 3705a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3706a621e3c8SJack F Vogel msix_count = max_msix_count; 37072969bf0eSJack F Vogel 37082969bf0eSJack F Vogel return msix_count; 37092969bf0eSJack F Vogel } 37102969bf0eSJack F Vogel 37112969bf0eSJack F Vogel /** 37122969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 37132969bf0eSJack F Vogel * @hw: pointer to hardware structure 37142969bf0eSJack F Vogel * @addr: Address to put into receive address register 37152969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 37162969bf0eSJack F Vogel * 37172969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 3718*c19c7afeSEric Joyner * finds the rar that it is already in; adds to the pool list 37192969bf0eSJack F Vogel **/ 37202969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 37212969bf0eSJack F Vogel { 37222969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 37232969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 37242969bf0eSJack F Vogel u32 rar; 37252969bf0eSJack F Vogel u32 rar_low, rar_high; 37262969bf0eSJack F Vogel u32 addr_low, addr_high; 37272969bf0eSJack F Vogel 37282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 37292969bf0eSJack F Vogel 37302969bf0eSJack F Vogel /* swap bytes for HW little endian */ 37312969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 37322969bf0eSJack F Vogel | (addr[2] << 16) 37332969bf0eSJack F Vogel | (addr[3] << 24); 37342969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 37352969bf0eSJack F Vogel 37362969bf0eSJack F Vogel /* 37372969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 37382969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 37392969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 37402969bf0eSJack F Vogel * rar to the top. 37412969bf0eSJack F Vogel */ 37422969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 37432969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 37442969bf0eSJack F Vogel 37452969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 37462969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 37472969bf0eSJack F Vogel first_empty_rar = rar; 37482969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 37492969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 37502969bf0eSJack F Vogel if (rar_low == addr_low) 37512969bf0eSJack F Vogel break; /* found it already in the rars */ 37522969bf0eSJack F Vogel } 37532969bf0eSJack F Vogel } 37542969bf0eSJack F Vogel 37552969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 37562969bf0eSJack F Vogel /* already there so just add to the pool bits */ 37572969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 37582969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 37592969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 37602969bf0eSJack F Vogel rar = first_empty_rar; 37612969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37622969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 37632969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 37642969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37652969bf0eSJack F Vogel hw->mac.rar_highwater++; 37662969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 37672969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 37682969bf0eSJack F Vogel } 37692969bf0eSJack F Vogel 37702969bf0eSJack F Vogel /* 37712969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 37722969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 37732969bf0eSJack F Vogel */ 37742969bf0eSJack F Vogel if (rar == 0) 37752969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 37762969bf0eSJack F Vogel 37772969bf0eSJack F Vogel return rar; 37782969bf0eSJack F Vogel } 37792969bf0eSJack F Vogel 37802969bf0eSJack F Vogel /** 37812969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 37822969bf0eSJack F Vogel * @hw: pointer to hardware struct 37832969bf0eSJack F Vogel * @rar: receive address register index to disassociate 37842969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 37852969bf0eSJack F Vogel **/ 37862969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37872969bf0eSJack F Vogel { 37882969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 37892969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37902969bf0eSJack F Vogel 37912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 37922969bf0eSJack F Vogel 37931a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37941a4e3449SJack F Vogel if (rar >= rar_entries) { 3795fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3796fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 37971a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 37981a4e3449SJack F Vogel } 37991a4e3449SJack F Vogel 38002969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38012969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38022969bf0eSJack F Vogel 3803758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3804758cc3dcSJack F Vogel goto done; 3805758cc3dcSJack F Vogel 38062969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 38072969bf0eSJack F Vogel goto done; 38082969bf0eSJack F Vogel 38092969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 38102969bf0eSJack F Vogel if (mpsar_lo) { 38112969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 38122969bf0eSJack F Vogel mpsar_lo = 0; 38132969bf0eSJack F Vogel } 38142969bf0eSJack F Vogel if (mpsar_hi) { 38152969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 38162969bf0eSJack F Vogel mpsar_hi = 0; 38172969bf0eSJack F Vogel } 38182969bf0eSJack F Vogel } else if (vmdq < 32) { 38192969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 38202969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 38212969bf0eSJack F Vogel } else { 38222969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 38232969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 38242969bf0eSJack F Vogel } 38252969bf0eSJack F Vogel 38262969bf0eSJack F Vogel /* was that the last pool using this rar? */ 38278eb6488eSEric Joyner if (mpsar_lo == 0 && mpsar_hi == 0 && 38288eb6488eSEric Joyner rar != 0 && rar != hw->mac.san_mac_rar_index) 38292969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 38302969bf0eSJack F Vogel done: 38312969bf0eSJack F Vogel return IXGBE_SUCCESS; 38322969bf0eSJack F Vogel } 38332969bf0eSJack F Vogel 38342969bf0eSJack F Vogel /** 38352969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 38362969bf0eSJack F Vogel * @hw: pointer to hardware struct 38372969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 38382969bf0eSJack F Vogel * @vmdq: VMDq pool index 38392969bf0eSJack F Vogel **/ 38402969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 38412969bf0eSJack F Vogel { 38422969bf0eSJack F Vogel u32 mpsar; 38432969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 38442969bf0eSJack F Vogel 38452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 38462969bf0eSJack F Vogel 38471a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 38481a4e3449SJack F Vogel if (rar >= rar_entries) { 3849fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3850fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38511a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38521a4e3449SJack F Vogel } 38531a4e3449SJack F Vogel 38542969bf0eSJack F Vogel if (vmdq < 32) { 38552969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38562969bf0eSJack F Vogel mpsar |= 1 << vmdq; 38572969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 38582969bf0eSJack F Vogel } else { 38592969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38602969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 38612969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 38622969bf0eSJack F Vogel } 38632969bf0eSJack F Vogel return IXGBE_SUCCESS; 38642969bf0eSJack F Vogel } 38652969bf0eSJack F Vogel 38662969bf0eSJack F Vogel /** 3867a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3868a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3869a621e3c8SJack F Vogel * VFs advertized and not 0. 3870a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3871a621e3c8SJack F Vogel * 3872a621e3c8SJack F Vogel * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address 3873a621e3c8SJack F Vogel * @hw: pointer to hardware struct 3874a621e3c8SJack F Vogel * @vmdq: VMDq pool index 3875a621e3c8SJack F Vogel **/ 3876a621e3c8SJack F Vogel s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 3877a621e3c8SJack F Vogel { 3878a621e3c8SJack F Vogel u32 rar = hw->mac.san_mac_rar_index; 3879a621e3c8SJack F Vogel 3880a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_san_mac"); 3881a621e3c8SJack F Vogel 3882a621e3c8SJack F Vogel if (vmdq < 32) { 3883a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); 3884a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 3885a621e3c8SJack F Vogel } else { 3886a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 3887a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); 3888a621e3c8SJack F Vogel } 3889a621e3c8SJack F Vogel 3890a621e3c8SJack F Vogel return IXGBE_SUCCESS; 3891a621e3c8SJack F Vogel } 3892a621e3c8SJack F Vogel 3893a621e3c8SJack F Vogel /** 38942969bf0eSJack F Vogel * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 38952969bf0eSJack F Vogel * @hw: pointer to hardware structure 38962969bf0eSJack F Vogel **/ 38972969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 38982969bf0eSJack F Vogel { 38992969bf0eSJack F Vogel int i; 39002969bf0eSJack F Vogel 39012969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_uta_tables_generic"); 39022969bf0eSJack F Vogel DEBUGOUT(" Clearing UTA\n"); 39032969bf0eSJack F Vogel 39042969bf0eSJack F Vogel for (i = 0; i < 128; i++) 39052969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 39062969bf0eSJack F Vogel 39072969bf0eSJack F Vogel return IXGBE_SUCCESS; 39082969bf0eSJack F Vogel } 39092969bf0eSJack F Vogel 39102969bf0eSJack F Vogel /** 39112969bf0eSJack F Vogel * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 39122969bf0eSJack F Vogel * @hw: pointer to hardware structure 39132969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39142969bf0eSJack F Vogel * 39152969bf0eSJack F Vogel * return the VLVF index where this VLAN id should be placed 39162969bf0eSJack F Vogel * 39172969bf0eSJack F Vogel **/ 39188eb6488eSEric Joyner s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) 39192969bf0eSJack F Vogel { 39208eb6488eSEric Joyner s32 regindex, first_empty_slot; 39218eb6488eSEric Joyner u32 bits; 39222969bf0eSJack F Vogel 3923c0014855SJack F Vogel /* short cut the special case */ 3924c0014855SJack F Vogel if (vlan == 0) 3925c0014855SJack F Vogel return 0; 3926c0014855SJack F Vogel 39278eb6488eSEric Joyner /* if vlvf_bypass is set we don't want to use an empty slot, we 39288eb6488eSEric Joyner * will simply bypass the VLVF if there are no entries present in the 39298eb6488eSEric Joyner * VLVF that contain our VLAN 39302969bf0eSJack F Vogel */ 39318eb6488eSEric Joyner first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0; 39328eb6488eSEric Joyner 39338eb6488eSEric Joyner /* add VLAN enable bit for comparison */ 39348eb6488eSEric Joyner vlan |= IXGBE_VLVF_VIEN; 39358eb6488eSEric Joyner 39368eb6488eSEric Joyner /* Search for the vlan id in the VLVF entries. Save off the first empty 39378eb6488eSEric Joyner * slot found along the way. 39388eb6488eSEric Joyner * 39398eb6488eSEric Joyner * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 39408eb6488eSEric Joyner */ 39418eb6488eSEric Joyner for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { 39422969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 39438eb6488eSEric Joyner if (bits == vlan) 39442969bf0eSJack F Vogel return regindex; 39458eb6488eSEric Joyner if (!first_empty_slot && !bits) 39468eb6488eSEric Joyner first_empty_slot = regindex; 39478eb6488eSEric Joyner } 39488eb6488eSEric Joyner 39498eb6488eSEric Joyner /* If we are here then we didn't find the VLAN. Return first empty 39508eb6488eSEric Joyner * slot we found during our search, else error. 39518eb6488eSEric Joyner */ 39528eb6488eSEric Joyner if (!first_empty_slot) 39538eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); 39548eb6488eSEric Joyner 39558eb6488eSEric Joyner return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE; 39562969bf0eSJack F Vogel } 39572969bf0eSJack F Vogel 39582969bf0eSJack F Vogel /** 39592969bf0eSJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 39602969bf0eSJack F Vogel * @hw: pointer to hardware structure 39612969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39628eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 39638eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN 39648eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 39652969bf0eSJack F Vogel * 39662969bf0eSJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 39672969bf0eSJack F Vogel **/ 39682969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 39698eb6488eSEric Joyner bool vlan_on, bool vlvf_bypass) 39702969bf0eSJack F Vogel { 39718eb6488eSEric Joyner u32 regidx, vfta_delta, vfta; 39728eb6488eSEric Joyner s32 ret_val; 39732969bf0eSJack F Vogel 39742969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vfta_generic"); 39752969bf0eSJack F Vogel 39768eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 39772969bf0eSJack F Vogel return IXGBE_ERR_PARAM; 39782969bf0eSJack F Vogel 39792969bf0eSJack F Vogel /* 39802969bf0eSJack F Vogel * this is a 2 part operation - first the VFTA, then the 39812969bf0eSJack F Vogel * VLVF and VLVFB if VT Mode is set 3982c0014855SJack F Vogel * We don't write the VFTA until we know the VLVF part succeeded. 39832969bf0eSJack F Vogel */ 39842969bf0eSJack F Vogel 39852969bf0eSJack F Vogel /* Part 1 39862969bf0eSJack F Vogel * The VFTA is a bitstring made up of 128 32-bit registers 39872969bf0eSJack F Vogel * that enable the particular VLAN id, much like the MTA: 39882969bf0eSJack F Vogel * bits[11-5]: which register 39892969bf0eSJack F Vogel * bits[4-0]: which bit in the register 39902969bf0eSJack F Vogel */ 39918eb6488eSEric Joyner regidx = vlan / 32; 39928eb6488eSEric Joyner vfta_delta = 1 << (vlan % 32); 39938eb6488eSEric Joyner vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); 39942969bf0eSJack F Vogel 39958eb6488eSEric Joyner /* 39968eb6488eSEric Joyner * vfta_delta represents the difference between the current value 39978eb6488eSEric Joyner * of vfta and the value we want in the register. Since the diff 39988eb6488eSEric Joyner * is an XOR mask we can just update the vfta using an XOR 39998eb6488eSEric Joyner */ 40008eb6488eSEric Joyner vfta_delta &= vlan_on ? ~vfta : vfta; 40018eb6488eSEric Joyner vfta ^= vfta_delta; 40022969bf0eSJack F Vogel 40032969bf0eSJack F Vogel /* Part 2 400485d0a26eSJack F Vogel * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF 400585d0a26eSJack F Vogel */ 40068eb6488eSEric Joyner ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta, 40078eb6488eSEric Joyner vfta, vlvf_bypass); 40088eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS) { 40098eb6488eSEric Joyner if (vlvf_bypass) 40108eb6488eSEric Joyner goto vfta_update; 401185d0a26eSJack F Vogel return ret_val; 40128eb6488eSEric Joyner } 401385d0a26eSJack F Vogel 40148eb6488eSEric Joyner vfta_update: 40158eb6488eSEric Joyner /* Update VFTA now that we are ready for traffic */ 40168eb6488eSEric Joyner if (vfta_delta) 40178eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 401885d0a26eSJack F Vogel 401985d0a26eSJack F Vogel return IXGBE_SUCCESS; 402085d0a26eSJack F Vogel } 402185d0a26eSJack F Vogel 402285d0a26eSJack F Vogel /** 402385d0a26eSJack F Vogel * ixgbe_set_vlvf_generic - Set VLAN Pool Filter 402485d0a26eSJack F Vogel * @hw: pointer to hardware structure 402585d0a26eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 40268eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 40278eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN in VLVF 40288eb6488eSEric Joyner * @vfta_delta: pointer to the difference between the current value of VFTA 40298eb6488eSEric Joyner * and the desired value 40308eb6488eSEric Joyner * @vfta: the desired value of the VFTA 40318eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 403285d0a26eSJack F Vogel * 403385d0a26eSJack F Vogel * Turn on/off specified bit in VLVF table. 403485d0a26eSJack F Vogel **/ 403585d0a26eSJack F Vogel s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 40368eb6488eSEric Joyner bool vlan_on, u32 *vfta_delta, u32 vfta, 40378eb6488eSEric Joyner bool vlvf_bypass) 403885d0a26eSJack F Vogel { 40398eb6488eSEric Joyner u32 bits; 40408eb6488eSEric Joyner s32 vlvf_index; 404185d0a26eSJack F Vogel 404285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_vlvf_generic"); 404385d0a26eSJack F Vogel 40448eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 404585d0a26eSJack F Vogel return IXGBE_ERR_PARAM; 404685d0a26eSJack F Vogel 404785d0a26eSJack F Vogel /* If VT Mode is set 40482969bf0eSJack F Vogel * Either vlan_on 40492969bf0eSJack F Vogel * make sure the vlan is in VLVF 40502969bf0eSJack F Vogel * set the vind bit in the matching VLVFB 40512969bf0eSJack F Vogel * Or !vlan_on 40522969bf0eSJack F Vogel * clear the pool bit and possibly the vind 40532969bf0eSJack F Vogel */ 40548eb6488eSEric Joyner if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) 40558eb6488eSEric Joyner return IXGBE_SUCCESS; 4056c0014855SJack F Vogel 40578eb6488eSEric Joyner vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); 4058c0014855SJack F Vogel if (vlvf_index < 0) 4059c0014855SJack F Vogel return vlvf_index; 40602969bf0eSJack F Vogel 40618eb6488eSEric Joyner bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); 40628eb6488eSEric Joyner 40632969bf0eSJack F Vogel /* set the pool bit */ 40648eb6488eSEric Joyner bits |= 1 << (vind % 32); 40658eb6488eSEric Joyner if (vlan_on) 40668eb6488eSEric Joyner goto vlvf_update; 40678eb6488eSEric Joyner 40682969bf0eSJack F Vogel /* clear the pool bit */ 40698eb6488eSEric Joyner bits ^= 1 << (vind % 32); 40708eb6488eSEric Joyner 40718eb6488eSEric Joyner if (!bits && 40728eb6488eSEric Joyner !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { 40738eb6488eSEric Joyner /* Clear VFTA first, then disable VLVF. Otherwise 40748eb6488eSEric Joyner * we run the risk of stray packets leaking into 40758eb6488eSEric Joyner * the PF via the default pool 40768eb6488eSEric Joyner */ 40778eb6488eSEric Joyner if (*vfta_delta) 40788eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta); 40798eb6488eSEric Joyner 40808eb6488eSEric Joyner /* disable VLVF and clear remaining bit from pool */ 40818eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 40828eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); 40838eb6488eSEric Joyner 40848eb6488eSEric Joyner return IXGBE_SUCCESS; 40852969bf0eSJack F Vogel } 40862969bf0eSJack F Vogel 40878eb6488eSEric Joyner /* If there are still bits set in the VLVFB registers 4088c0014855SJack F Vogel * for the VLAN ID indicated we need to see if the 4089c0014855SJack F Vogel * caller is requesting that we clear the VFTA entry bit. 4090c0014855SJack F Vogel * If the caller has requested that we clear the VFTA 4091c0014855SJack F Vogel * entry bit but there are still pools/VFs using this VLAN 4092c0014855SJack F Vogel * ID entry then ignore the request. We're not worried 4093c0014855SJack F Vogel * about the case where we're turning the VFTA VLAN ID 4094c0014855SJack F Vogel * entry bit on, only when requested to turn it off as 4095c0014855SJack F Vogel * there may be multiple pools and/or VFs using the 4096c0014855SJack F Vogel * VLAN ID entry. In that case we cannot clear the 4097c0014855SJack F Vogel * VFTA bit until all pools/VFs using that VLAN ID have also 4098c0014855SJack F Vogel * been cleared. This will be indicated by "bits" being 4099c0014855SJack F Vogel * zero. 4100c0014855SJack F Vogel */ 41018eb6488eSEric Joyner *vfta_delta = 0; 41028eb6488eSEric Joyner 41038eb6488eSEric Joyner vlvf_update: 41048eb6488eSEric Joyner /* record pool change and enable VLAN ID if not already enabled */ 41058eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); 41068eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); 4107c0014855SJack F Vogel 41082969bf0eSJack F Vogel return IXGBE_SUCCESS; 41092969bf0eSJack F Vogel } 41102969bf0eSJack F Vogel 41112969bf0eSJack F Vogel /** 41122969bf0eSJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 41132969bf0eSJack F Vogel * @hw: pointer to hardware structure 41142969bf0eSJack F Vogel * 41152969bf0eSJack F Vogel * Clears the VLAN filer table, and the VMDq index associated with the filter 41162969bf0eSJack F Vogel **/ 41172969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 41182969bf0eSJack F Vogel { 41192969bf0eSJack F Vogel u32 offset; 41202969bf0eSJack F Vogel 41212969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vfta_generic"); 41222969bf0eSJack F Vogel 41232969bf0eSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 41242969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 41252969bf0eSJack F Vogel 41262969bf0eSJack F Vogel for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 41272969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 41282969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 4129*c19c7afeSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); 41302969bf0eSJack F Vogel } 41312969bf0eSJack F Vogel 41322969bf0eSJack F Vogel return IXGBE_SUCCESS; 41332969bf0eSJack F Vogel } 41342969bf0eSJack F Vogel 41352969bf0eSJack F Vogel /** 41368eb6488eSEric Joyner * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix 41378eb6488eSEric Joyner * @hw: pointer to hardware structure 41388eb6488eSEric Joyner * 41398eb6488eSEric Joyner * Contains the logic to identify if we need to verify link for the 41408eb6488eSEric Joyner * crosstalk fix 41418eb6488eSEric Joyner **/ 41428eb6488eSEric Joyner static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) 41438eb6488eSEric Joyner { 41448eb6488eSEric Joyner 41458eb6488eSEric Joyner /* Does FW say we need the fix */ 41468eb6488eSEric Joyner if (!hw->need_crosstalk_fix) 41478eb6488eSEric Joyner return FALSE; 41488eb6488eSEric Joyner 41498eb6488eSEric Joyner /* Only consider SFP+ PHYs i.e. media type fiber */ 41508eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 41518eb6488eSEric Joyner case ixgbe_media_type_fiber: 41528eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 41538eb6488eSEric Joyner break; 41548eb6488eSEric Joyner default: 41558eb6488eSEric Joyner return FALSE; 41568eb6488eSEric Joyner } 41578eb6488eSEric Joyner 41588eb6488eSEric Joyner return TRUE; 41598eb6488eSEric Joyner } 41608eb6488eSEric Joyner 41618eb6488eSEric Joyner /** 41622969bf0eSJack F Vogel * ixgbe_check_mac_link_generic - Determine link and speed status 41632969bf0eSJack F Vogel * @hw: pointer to hardware structure 41642969bf0eSJack F Vogel * @speed: pointer to link speed 41652969bf0eSJack F Vogel * @link_up: TRUE when link is up 41662969bf0eSJack F Vogel * @link_up_wait_to_complete: bool used to wait for link up or not 41672969bf0eSJack F Vogel * 41682969bf0eSJack F Vogel * Reads the links register to determine if link is up and the current speed 41692969bf0eSJack F Vogel **/ 41702969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 41712969bf0eSJack F Vogel bool *link_up, bool link_up_wait_to_complete) 41722969bf0eSJack F Vogel { 4173c0014855SJack F Vogel u32 links_reg, links_orig; 41742969bf0eSJack F Vogel u32 i; 41752969bf0eSJack F Vogel 41762969bf0eSJack F Vogel DEBUGFUNC("ixgbe_check_mac_link_generic"); 41772969bf0eSJack F Vogel 41788eb6488eSEric Joyner /* If Crosstalk fix enabled do the sanity check of making sure 41798eb6488eSEric Joyner * the SFP+ cage is full. 41808eb6488eSEric Joyner */ 41818eb6488eSEric Joyner if (ixgbe_need_crosstalk_fix(hw)) { 41828eb6488eSEric Joyner u32 sfp_cage_full; 41838eb6488eSEric Joyner 41848eb6488eSEric Joyner switch (hw->mac.type) { 41858eb6488eSEric Joyner case ixgbe_mac_82599EB: 41868eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 41878eb6488eSEric Joyner IXGBE_ESDP_SDP2; 41888eb6488eSEric Joyner break; 41898eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 41908eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 41918eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 41928eb6488eSEric Joyner IXGBE_ESDP_SDP0; 41938eb6488eSEric Joyner break; 41948eb6488eSEric Joyner default: 41958eb6488eSEric Joyner /* sanity check - No SFP+ devices here */ 41968eb6488eSEric Joyner sfp_cage_full = FALSE; 41978eb6488eSEric Joyner break; 41988eb6488eSEric Joyner } 41998eb6488eSEric Joyner 42008eb6488eSEric Joyner if (!sfp_cage_full) { 42018eb6488eSEric Joyner *link_up = FALSE; 42028eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42038eb6488eSEric Joyner return IXGBE_SUCCESS; 42048eb6488eSEric Joyner } 42058eb6488eSEric Joyner } 42068eb6488eSEric Joyner 4207c0014855SJack F Vogel /* clear the old state */ 4208c0014855SJack F Vogel links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 4209c0014855SJack F Vogel 42102969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 4211c0014855SJack F Vogel 4212c0014855SJack F Vogel if (links_orig != links_reg) { 4213c0014855SJack F Vogel DEBUGOUT2("LINKS changed from %08X to %08X\n", 4214c0014855SJack F Vogel links_orig, links_reg); 4215c0014855SJack F Vogel } 4216c0014855SJack F Vogel 42172969bf0eSJack F Vogel if (link_up_wait_to_complete) { 4218a9ca1c79SSean Bruno for (i = 0; i < hw->mac.max_link_up_time; i++) { 42192969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) { 42202969bf0eSJack F Vogel *link_up = TRUE; 42212969bf0eSJack F Vogel break; 42222969bf0eSJack F Vogel } else { 42232969bf0eSJack F Vogel *link_up = FALSE; 42242969bf0eSJack F Vogel } 42252969bf0eSJack F Vogel msec_delay(100); 42262969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 42272969bf0eSJack F Vogel } 42282969bf0eSJack F Vogel } else { 42292969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) 42302969bf0eSJack F Vogel *link_up = TRUE; 42312969bf0eSJack F Vogel else 42322969bf0eSJack F Vogel *link_up = FALSE; 42332969bf0eSJack F Vogel } 42342969bf0eSJack F Vogel 4235758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4236758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 42372969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4238758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4239758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4240758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4241758cc3dcSJack F Vogel } 4242758cc3dcSJack F Vogel break; 4243758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 42442969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4245758cc3dcSJack F Vogel break; 4246758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 42472969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 42488eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550) { 4249758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4250758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4251758cc3dcSJack F Vogel } 4252758cc3dcSJack F Vogel break; 42538eb6488eSEric Joyner case IXGBE_LINKS_SPEED_10_X550EM_A: 42548eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42558eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 42568eb6488eSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { 42578eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_10_FULL; 42588eb6488eSEric Joyner } 42598eb6488eSEric Joyner break; 4260758cc3dcSJack F Vogel default: 42611a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4262758cc3dcSJack F Vogel } 42632969bf0eSJack F Vogel 42642969bf0eSJack F Vogel return IXGBE_SUCCESS; 42652969bf0eSJack F Vogel } 42662969bf0eSJack F Vogel 42672969bf0eSJack F Vogel /** 42682969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 42692969bf0eSJack F Vogel * the EEPROM 42702969bf0eSJack F Vogel * @hw: pointer to hardware structure 42712969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 42722969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 42732969bf0eSJack F Vogel * 42742969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 42752969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 42762969bf0eSJack F Vogel **/ 42772969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 42782969bf0eSJack F Vogel u16 *wwpn_prefix) 42792969bf0eSJack F Vogel { 42802969bf0eSJack F Vogel u16 offset, caps; 42812969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 42822969bf0eSJack F Vogel 42832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 42842969bf0eSJack F Vogel 42852969bf0eSJack F Vogel /* clear output first */ 42862969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 42872969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 42882969bf0eSJack F Vogel 42892969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4290fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4291fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4292fd75b91dSJack F Vogel goto wwn_prefix_err; 42932969bf0eSJack F Vogel 42942969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 42952969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 42962969bf0eSJack F Vogel goto wwn_prefix_out; 42972969bf0eSJack F Vogel 42982969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 42992969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4300fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4301fd75b91dSJack F Vogel goto wwn_prefix_err; 43022969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 43032969bf0eSJack F Vogel goto wwn_prefix_out; 43042969bf0eSJack F Vogel 43052969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 43062969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4307fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4308fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4309fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4310fd75b91dSJack F Vogel } 43112969bf0eSJack F Vogel 43122969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4313fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4314fd75b91dSJack F Vogel goto wwn_prefix_err; 43152969bf0eSJack F Vogel 43162969bf0eSJack F Vogel wwn_prefix_out: 43172969bf0eSJack F Vogel return IXGBE_SUCCESS; 4318fd75b91dSJack F Vogel 4319fd75b91dSJack F Vogel wwn_prefix_err: 4320fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4321fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4322fd75b91dSJack F Vogel return IXGBE_SUCCESS; 43232969bf0eSJack F Vogel } 43241a4e3449SJack F Vogel 43251a4e3449SJack F Vogel /** 43261a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 43271a4e3449SJack F Vogel * @hw: pointer to hardware structure 43281a4e3449SJack F Vogel * @bs: the fcoe boot status 43291a4e3449SJack F Vogel * 43301a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 43311a4e3449SJack F Vogel **/ 43321a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 43331a4e3449SJack F Vogel { 43341a4e3449SJack F Vogel u16 offset, caps, flags; 43351a4e3449SJack F Vogel s32 status; 43361a4e3449SJack F Vogel 43371a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 43381a4e3449SJack F Vogel 43391a4e3449SJack F Vogel /* clear output first */ 43401a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 43411a4e3449SJack F Vogel 43421a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 43431a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 43441a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 43451a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43461a4e3449SJack F Vogel goto out; 43471a4e3449SJack F Vogel 43481a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 43491a4e3449SJack F Vogel goto out; 43501a4e3449SJack F Vogel 43511a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 43521a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 43531a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43541a4e3449SJack F Vogel goto out; 43551a4e3449SJack F Vogel 43561a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 43571a4e3449SJack F Vogel goto out; 43581a4e3449SJack F Vogel 43591a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 43601a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 43611a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 43621a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43631a4e3449SJack F Vogel goto out; 43641a4e3449SJack F Vogel 43651a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 43661a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 43671a4e3449SJack F Vogel else 43681a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 43691a4e3449SJack F Vogel 43701a4e3449SJack F Vogel out: 43711a4e3449SJack F Vogel return status; 43721a4e3449SJack F Vogel } 43731a4e3449SJack F Vogel 43741a4e3449SJack F Vogel /** 43751a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 43761a4e3449SJack F Vogel * @hw: pointer to hardware structure 43778eb6488eSEric Joyner * @enable: enable or disable switch for MAC anti-spoofing 43788eb6488eSEric Joyner * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 43791a4e3449SJack F Vogel * 43801a4e3449SJack F Vogel **/ 43818eb6488eSEric Joyner void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 43821a4e3449SJack F Vogel { 43838eb6488eSEric Joyner int vf_target_reg = vf >> 3; 43848eb6488eSEric Joyner int vf_target_shift = vf % 8; 43858eb6488eSEric Joyner u32 pfvfspoof; 43861a4e3449SJack F Vogel 43871a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 43881a4e3449SJack F Vogel return; 43891a4e3449SJack F Vogel 43908eb6488eSEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 43911a4e3449SJack F Vogel if (enable) 43928eb6488eSEric Joyner pfvfspoof |= (1 << vf_target_shift); 43938eb6488eSEric Joyner else 43948eb6488eSEric Joyner pfvfspoof &= ~(1 << vf_target_shift); 43958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 43961a4e3449SJack F Vogel } 43971a4e3449SJack F Vogel 43981a4e3449SJack F Vogel /** 43991a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 44001a4e3449SJack F Vogel * @hw: pointer to hardware structure 44011a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4402758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 44031a4e3449SJack F Vogel * 44041a4e3449SJack F Vogel **/ 44051a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44061a4e3449SJack F Vogel { 44071a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 44081a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 44091a4e3449SJack F Vogel u32 pfvfspoof; 44101a4e3449SJack F Vogel 44111a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44121a4e3449SJack F Vogel return; 44131a4e3449SJack F Vogel 44141a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44151a4e3449SJack F Vogel if (enable) 44161a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 44171a4e3449SJack F Vogel else 44181a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 44191a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44201a4e3449SJack F Vogel } 4421182b3808SJack F Vogel 4422182b3808SJack F Vogel /** 4423182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4424182b3808SJack F Vogel * @hw: pointer to hardware structure 4425182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4426182b3808SJack F Vogel * 4427182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4428182b3808SJack F Vogel * and return the word through device_caps. 4429182b3808SJack F Vogel **/ 4430182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4431182b3808SJack F Vogel { 4432182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4433182b3808SJack F Vogel 4434182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4435182b3808SJack F Vogel 4436182b3808SJack F Vogel return IXGBE_SUCCESS; 4437182b3808SJack F Vogel } 4438182b3808SJack F Vogel 4439182b3808SJack F Vogel /** 4440182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4441182b3808SJack F Vogel * @hw: pointer to hardware structure 4442182b3808SJack F Vogel * 4443182b3808SJack F Vogel **/ 4444182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4445182b3808SJack F Vogel { 4446182b3808SJack F Vogel u32 regval; 4447182b3808SJack F Vogel u32 i; 4448182b3808SJack F Vogel 4449182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4450182b3808SJack F Vogel 4451182b3808SJack F Vogel /* Enable relaxed ordering */ 4452182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4453182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4454a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4455182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4456182b3808SJack F Vogel } 4457182b3808SJack F Vogel 4458182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4459182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4460a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4461a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4462182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4463182b3808SJack F Vogel } 4464182b3808SJack F Vogel 4465182b3808SJack F Vogel } 446685d0a26eSJack F Vogel 446785d0a26eSJack F Vogel /** 446885d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 446985d0a26eSJack F Vogel * @buffer: pointer to EEPROM 447085d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 447185d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 447285d0a26eSJack F Vogel * checksum calculated is returned. 447385d0a26eSJack F Vogel **/ 44740ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 447585d0a26eSJack F Vogel { 447685d0a26eSJack F Vogel u32 i; 447785d0a26eSJack F Vogel u8 sum = 0; 447885d0a26eSJack F Vogel 447985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 448085d0a26eSJack F Vogel 448185d0a26eSJack F Vogel if (!buffer) 448285d0a26eSJack F Vogel return 0; 448385d0a26eSJack F Vogel 448485d0a26eSJack F Vogel for (i = 0; i < length; i++) 448585d0a26eSJack F Vogel sum += buffer[i]; 448685d0a26eSJack F Vogel 448785d0a26eSJack F Vogel return (u8) (0 - sum); 448885d0a26eSJack F Vogel } 448985d0a26eSJack F Vogel 449085d0a26eSJack F Vogel /** 44918eb6488eSEric Joyner * ixgbe_hic_unlocked - Issue command to manageability block unlocked 449285d0a26eSJack F Vogel * @hw: pointer to the HW structure 44938eb6488eSEric Joyner * @buffer: command to write and where the return status will be placed 4494a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4495758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 449685d0a26eSJack F Vogel * 449785d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 44988eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 44998eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45008eb6488eSEric Joyner * 45018eb6488eSEric Joyner * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 45028eb6488eSEric Joyner * by the caller. 450385d0a26eSJack F Vogel **/ 45048eb6488eSEric Joyner s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 45058eb6488eSEric Joyner u32 timeout) 450685d0a26eSJack F Vogel { 45078eb6488eSEric Joyner u32 hicr, i, fwsts; 4508758cc3dcSJack F Vogel u16 dword_len; 450985d0a26eSJack F Vogel 45108eb6488eSEric Joyner DEBUGFUNC("ixgbe_hic_unlocked"); 451185d0a26eSJack F Vogel 45128eb6488eSEric Joyner if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4513758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4514758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 451585d0a26eSJack F Vogel } 45168eb6488eSEric Joyner 4517758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4518758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4519758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 452085d0a26eSJack F Vogel 452185d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 452285d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 45238eb6488eSEric Joyner if (!(hicr & IXGBE_HICR_EN)) { 452485d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4525758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 452685d0a26eSJack F Vogel } 452785d0a26eSJack F Vogel 4528758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 45298eb6488eSEric Joyner if (length % sizeof(u32)) { 4530758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4531758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4532758cc3dcSJack F Vogel } 4533758cc3dcSJack F Vogel 453485d0a26eSJack F Vogel dword_len = length >> 2; 453585d0a26eSJack F Vogel 4536758cc3dcSJack F Vogel /* The device driver writes the relevant command block 453785d0a26eSJack F Vogel * into the ram area. 453885d0a26eSJack F Vogel */ 453985d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 454085d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 454185d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 454285d0a26eSJack F Vogel 454385d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 454485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 454585d0a26eSJack F Vogel 4546758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 454785d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 454885d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 454985d0a26eSJack F Vogel break; 455085d0a26eSJack F Vogel msec_delay(1); 455185d0a26eSJack F Vogel } 455285d0a26eSJack F Vogel 4553758cc3dcSJack F Vogel /* Check command completion */ 45548eb6488eSEric Joyner if ((timeout && i == timeout) || 4555758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4556758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4557758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4558758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 455985d0a26eSJack F Vogel } 456085d0a26eSJack F Vogel 45618eb6488eSEric Joyner return IXGBE_SUCCESS; 45628eb6488eSEric Joyner } 45638eb6488eSEric Joyner 45648eb6488eSEric Joyner /** 45658eb6488eSEric Joyner * ixgbe_host_interface_command - Issue command to manageability block 45668eb6488eSEric Joyner * @hw: pointer to the HW structure 45678eb6488eSEric Joyner * @buffer: contains the command to write and where the return status will 45688eb6488eSEric Joyner * be placed 45698eb6488eSEric Joyner * @length: length of buffer, must be multiple of 4 bytes 45708eb6488eSEric Joyner * @timeout: time in ms to wait for command completion 45718eb6488eSEric Joyner * @return_data: read and return data from the buffer (TRUE) or not (FALSE) 45728eb6488eSEric Joyner * Needed because FW structures are big endian and decoding of 45738eb6488eSEric Joyner * these fields can be 8 bit or 16 bit based on command. Decoding 45748eb6488eSEric Joyner * is not easily understood without making a table of commands. 45758eb6488eSEric Joyner * So we will leave this up to the caller to read back the data 45768eb6488eSEric Joyner * in these cases. 45778eb6488eSEric Joyner * 45788eb6488eSEric Joyner * Communicates with the manageability block. On success return IXGBE_SUCCESS 45798eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45808eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45818eb6488eSEric Joyner **/ 45828eb6488eSEric Joyner s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 45838eb6488eSEric Joyner u32 length, u32 timeout, bool return_data) 45848eb6488eSEric Joyner { 45858eb6488eSEric Joyner u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 45868eb6488eSEric Joyner u16 dword_len; 45878eb6488eSEric Joyner u16 buf_len; 45888eb6488eSEric Joyner s32 status; 45898eb6488eSEric Joyner u32 bi; 45908eb6488eSEric Joyner 45918eb6488eSEric Joyner DEBUGFUNC("ixgbe_host_interface_command"); 45928eb6488eSEric Joyner 45938eb6488eSEric Joyner if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 45948eb6488eSEric Joyner DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 45958eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND; 45968eb6488eSEric Joyner } 45978eb6488eSEric Joyner 45988eb6488eSEric Joyner /* Take management host interface semaphore */ 45998eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46008eb6488eSEric Joyner if (status) 46018eb6488eSEric Joyner return status; 46028eb6488eSEric Joyner 46038eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 46048eb6488eSEric Joyner if (status) 46058eb6488eSEric Joyner goto rel_out; 46068eb6488eSEric Joyner 4607758cc3dcSJack F Vogel if (!return_data) 46088eb6488eSEric Joyner goto rel_out; 4609758cc3dcSJack F Vogel 461085d0a26eSJack F Vogel /* Calculate length in DWORDs */ 461185d0a26eSJack F Vogel dword_len = hdr_size >> 2; 461285d0a26eSJack F Vogel 461385d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 461485d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 461585d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 461685d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 461785d0a26eSJack F Vogel } 461885d0a26eSJack F Vogel 461985d0a26eSJack F Vogel /* If there is any thing in data position pull it in */ 462085d0a26eSJack F Vogel buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; 46218eb6488eSEric Joyner if (!buf_len) 46228eb6488eSEric Joyner goto rel_out; 462385d0a26eSJack F Vogel 4624758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 462585d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 46268eb6488eSEric Joyner status = IXGBE_ERR_HOST_INTERFACE_COMMAND; 46278eb6488eSEric Joyner goto rel_out; 462885d0a26eSJack F Vogel } 462985d0a26eSJack F Vogel 463085d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 463185d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 463285d0a26eSJack F Vogel 463385d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 463485d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 463585d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 463685d0a26eSJack F Vogel IXGBE_LE32_TO_CPUS(&buffer[bi]); 463785d0a26eSJack F Vogel } 463885d0a26eSJack F Vogel 46398eb6488eSEric Joyner rel_out: 46408eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46418eb6488eSEric Joyner 46428eb6488eSEric Joyner return status; 464385d0a26eSJack F Vogel } 464485d0a26eSJack F Vogel 464585d0a26eSJack F Vogel /** 464685d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 464785d0a26eSJack F Vogel * @hw: pointer to the HW structure 464885d0a26eSJack F Vogel * @maj: driver version major number 464985d0a26eSJack F Vogel * @min: driver version minor number 465085d0a26eSJack F Vogel * @build: driver version build number 465185d0a26eSJack F Vogel * @sub: driver version sub build number 465285d0a26eSJack F Vogel * 465385d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 465485d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 465585d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 465685d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 465785d0a26eSJack F Vogel **/ 465885d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 46598eb6488eSEric Joyner u8 build, u8 sub, u16 len, 46608eb6488eSEric Joyner const char *driver_ver) 466185d0a26eSJack F Vogel { 466285d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 466385d0a26eSJack F Vogel int i; 466485d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 466585d0a26eSJack F Vogel 466685d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 46678eb6488eSEric Joyner UNREFERENCED_2PARAMETER(len, driver_ver); 466885d0a26eSJack F Vogel 466985d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 467085d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 467185d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 467285d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 467385d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 467485d0a26eSJack F Vogel fw_cmd.ver_min = min; 467585d0a26eSJack F Vogel fw_cmd.ver_build = build; 467685d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 467785d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 467885d0a26eSJack F Vogel fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 467985d0a26eSJack F Vogel (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 468085d0a26eSJack F Vogel fw_cmd.pad = 0; 468185d0a26eSJack F Vogel fw_cmd.pad2 = 0; 468285d0a26eSJack F Vogel 468385d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 468485d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4685758cc3dcSJack F Vogel sizeof(fw_cmd), 4686758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 4687758cc3dcSJack F Vogel TRUE); 468885d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 468985d0a26eSJack F Vogel continue; 469085d0a26eSJack F Vogel 469185d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 469285d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 469385d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 469485d0a26eSJack F Vogel else 469585d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 469685d0a26eSJack F Vogel 469785d0a26eSJack F Vogel break; 469885d0a26eSJack F Vogel } 469985d0a26eSJack F Vogel 470085d0a26eSJack F Vogel return ret_val; 470185d0a26eSJack F Vogel } 470285d0a26eSJack F Vogel 470385d0a26eSJack F Vogel /** 470485d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 470585d0a26eSJack F Vogel * @hw: pointer to hardware structure 470685d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 470785d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 470885d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 470985d0a26eSJack F Vogel **/ 471085d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 471185d0a26eSJack F Vogel int strategy) 471285d0a26eSJack F Vogel { 471385d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 471485d0a26eSJack F Vogel int i = 0; 471585d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 471685d0a26eSJack F Vogel 471785d0a26eSJack F Vogel /* Reserve headroom */ 471885d0a26eSJack F Vogel pbsize -= headroom; 471985d0a26eSJack F Vogel 472085d0a26eSJack F Vogel if (!num_pb) 472185d0a26eSJack F Vogel num_pb = 1; 472285d0a26eSJack F Vogel 472385d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 472485d0a26eSJack F Vogel * buffers requested using supplied strategy. 472585d0a26eSJack F Vogel */ 472685d0a26eSJack F Vogel switch (strategy) { 4727a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 472885d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 472985d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 473085d0a26eSJack F Vogel */ 4731a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 473285d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 473385d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 473485d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 473585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 47368eb6488eSEric Joyner /* fall through - configure remaining packet buffers */ 4737a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 473885d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 473985d0a26eSJack F Vogel for (; i < num_pb; i++) 474085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 474185d0a26eSJack F Vogel break; 474285d0a26eSJack F Vogel default: 474385d0a26eSJack F Vogel break; 474485d0a26eSJack F Vogel } 474585d0a26eSJack F Vogel 474685d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 474785d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 474885d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 474985d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 475085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 475185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 475285d0a26eSJack F Vogel } 475385d0a26eSJack F Vogel 475485d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 475585d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 475685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 475785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 475885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 475985d0a26eSJack F Vogel } 476085d0a26eSJack F Vogel } 476185d0a26eSJack F Vogel 476285d0a26eSJack F Vogel /** 476385d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 476485d0a26eSJack F Vogel * @hw: pointer to the hardware structure 476585d0a26eSJack F Vogel * 476685d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 476785d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 476885d0a26eSJack F Vogel * buffers on the system. 476985d0a26eSJack F Vogel **/ 477085d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 477185d0a26eSJack F Vogel { 4772758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4773758cc3dcSJack F Vogel u16 value; 477485d0a26eSJack F Vogel 477585d0a26eSJack F Vogel /* 477685d0a26eSJack F Vogel * If double reset is not requested then all transactions should 477785d0a26eSJack F Vogel * already be clear and as such there is no work to do 477885d0a26eSJack F Vogel */ 477985d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 478085d0a26eSJack F Vogel return; 478185d0a26eSJack F Vogel 478285d0a26eSJack F Vogel /* 478385d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 478485d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 478585d0a26eSJack F Vogel * has already been cleared. 478685d0a26eSJack F Vogel */ 478785d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 478885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 478985d0a26eSJack F Vogel 4790758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4791758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4792758cc3dcSJack F Vogel msec_delay(3); 4793758cc3dcSJack F Vogel 4794758cc3dcSJack F Vogel /* 4795758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4796758cc3dcSJack F Vogel * transactions pending. 4797758cc3dcSJack F Vogel */ 4798758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4799758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4800758cc3dcSJack F Vogel usec_delay(100); 4801758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4802758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4803758cc3dcSJack F Vogel goto out; 4804758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4805758cc3dcSJack F Vogel goto out; 4806758cc3dcSJack F Vogel } 4807758cc3dcSJack F Vogel 4808758cc3dcSJack F Vogel out: 480985d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 481085d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 481185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 481285d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 481385d0a26eSJack F Vogel 481485d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 481585d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 481685d0a26eSJack F Vogel usec_delay(20); 481785d0a26eSJack F Vogel 481885d0a26eSJack F Vogel /* restore previous register values */ 481985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 482085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 482185d0a26eSJack F Vogel } 482285d0a26eSJack F Vogel 48238eb6488eSEric Joyner /** 48248eb6488eSEric Joyner * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW 48258eb6488eSEric Joyner * 48268eb6488eSEric Joyner * @hw: pointer to hardware structure 48278eb6488eSEric Joyner * @cmd: Command we send to the FW 48288eb6488eSEric Joyner * @status: The reply from the FW 48298eb6488eSEric Joyner * 48308eb6488eSEric Joyner * Bit-bangs the cmd to the by_pass FW status points to what is returned. 48318eb6488eSEric Joyner **/ 48328eb6488eSEric Joyner #define IXGBE_BYPASS_BB_WAIT 1 48338eb6488eSEric Joyner s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) 48348eb6488eSEric Joyner { 48358eb6488eSEric Joyner int i; 48368eb6488eSEric Joyner u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; 48378eb6488eSEric Joyner u32 esdp; 48388eb6488eSEric Joyner 48398eb6488eSEric Joyner if (!status) 48408eb6488eSEric Joyner return IXGBE_ERR_PARAM; 48418eb6488eSEric Joyner 48428eb6488eSEric Joyner *status = 0; 48438eb6488eSEric Joyner 48448eb6488eSEric Joyner /* SDP vary by MAC type */ 48458eb6488eSEric Joyner switch (hw->mac.type) { 48468eb6488eSEric Joyner case ixgbe_mac_82599EB: 48478eb6488eSEric Joyner sck = IXGBE_ESDP_SDP7; 48488eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 48498eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP6; 48508eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP7_DIR; 48518eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 48528eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP6_DIR; 48538eb6488eSEric Joyner break; 48548eb6488eSEric Joyner case ixgbe_mac_X540: 48558eb6488eSEric Joyner sck = IXGBE_ESDP_SDP2; 48568eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 48578eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP1; 48588eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP2_DIR; 48598eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 48608eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP1_DIR; 48618eb6488eSEric Joyner break; 48628eb6488eSEric Joyner default: 48638eb6488eSEric Joyner return IXGBE_ERR_DEVICE_NOT_SUPPORTED; 48648eb6488eSEric Joyner } 48658eb6488eSEric Joyner 48668eb6488eSEric Joyner /* Set SDP pins direction */ 48678eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 48688eb6488eSEric Joyner esdp |= dir_sck; /* SCK as output */ 48698eb6488eSEric Joyner esdp |= dir_sdi; /* SDI as output */ 48708eb6488eSEric Joyner esdp &= ~dir_sdo; /* SDO as input */ 48718eb6488eSEric Joyner esdp |= sck; 48728eb6488eSEric Joyner esdp |= sdi; 48738eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 48748eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 48758eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 48768eb6488eSEric Joyner 48778eb6488eSEric Joyner /* Generate start condition */ 48788eb6488eSEric Joyner esdp &= ~sdi; 48798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 48808eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 48818eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 48828eb6488eSEric Joyner 48838eb6488eSEric Joyner esdp &= ~sck; 48848eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 48858eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 48868eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 48878eb6488eSEric Joyner 48888eb6488eSEric Joyner /* Clock out the new control word and clock in the status */ 48898eb6488eSEric Joyner for (i = 0; i < 32; i++) { 48908eb6488eSEric Joyner if ((cmd >> (31 - i)) & 0x01) { 48918eb6488eSEric Joyner esdp |= sdi; 48928eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 48938eb6488eSEric Joyner } else { 48948eb6488eSEric Joyner esdp &= ~sdi; 48958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 48968eb6488eSEric Joyner } 48978eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 48988eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 48998eb6488eSEric Joyner 49008eb6488eSEric Joyner esdp |= sck; 49018eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49028eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49038eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49048eb6488eSEric Joyner 49058eb6488eSEric Joyner esdp &= ~sck; 49068eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49078eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49088eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49098eb6488eSEric Joyner 49108eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 49118eb6488eSEric Joyner if (esdp & sdo) 49128eb6488eSEric Joyner *status = (*status << 1) | 0x01; 49138eb6488eSEric Joyner else 49148eb6488eSEric Joyner *status = (*status << 1) | 0x00; 49158eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49168eb6488eSEric Joyner } 49178eb6488eSEric Joyner 49188eb6488eSEric Joyner /* stop condition */ 49198eb6488eSEric Joyner esdp |= sck; 49208eb6488eSEric Joyner esdp &= ~sdi; 49218eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49228eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49238eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 49248eb6488eSEric Joyner 49258eb6488eSEric Joyner esdp |= sdi; 49268eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 49278eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 49288eb6488eSEric Joyner 49298eb6488eSEric Joyner /* set the page bits to match the cmd that the status it belongs to */ 49308eb6488eSEric Joyner *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); 49318eb6488eSEric Joyner 49328eb6488eSEric Joyner return IXGBE_SUCCESS; 49338eb6488eSEric Joyner } 49348eb6488eSEric Joyner 49358eb6488eSEric Joyner /** 49368eb6488eSEric Joyner * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. 49378eb6488eSEric Joyner * 49388eb6488eSEric Joyner * If we send a write we can't be sure it took until we can read back 49398eb6488eSEric Joyner * that same register. It can be a problem as some of the feilds may 49408eb6488eSEric Joyner * for valid reasons change inbetween the time wrote the register and 49418eb6488eSEric Joyner * we read it again to verify. So this function check everything we 49428eb6488eSEric Joyner * can check and then assumes it worked. 49438eb6488eSEric Joyner * 49448eb6488eSEric Joyner * @u32 in_reg - The register cmd for the bit-bang read. 49458eb6488eSEric Joyner * @u32 out_reg - The register returned from a bit-bang read. 49468eb6488eSEric Joyner **/ 49478eb6488eSEric Joyner bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) 49488eb6488eSEric Joyner { 49498eb6488eSEric Joyner u32 mask; 49508eb6488eSEric Joyner 49518eb6488eSEric Joyner /* Page must match for all control pages */ 49528eb6488eSEric Joyner if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) 49538eb6488eSEric Joyner return FALSE; 49548eb6488eSEric Joyner 49558eb6488eSEric Joyner switch (in_reg & BYPASS_PAGE_M) { 49568eb6488eSEric Joyner case BYPASS_PAGE_CTL0: 49578eb6488eSEric Joyner /* All the following can't change since the last write 49588eb6488eSEric Joyner * - All the event actions 49598eb6488eSEric Joyner * - The timeout value 49608eb6488eSEric Joyner */ 49618eb6488eSEric Joyner mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | 49628eb6488eSEric Joyner BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | 49638eb6488eSEric Joyner BYPASS_WDTIMEOUT_M | 49648eb6488eSEric Joyner BYPASS_WDT_VALUE_M; 49658eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 49668eb6488eSEric Joyner return FALSE; 49678eb6488eSEric Joyner 49688eb6488eSEric Joyner /* 0x0 is never a valid value for bypass status */ 49698eb6488eSEric Joyner if (!(out_reg & BYPASS_STATUS_OFF_M)) 49708eb6488eSEric Joyner return FALSE; 49718eb6488eSEric Joyner break; 49728eb6488eSEric Joyner case BYPASS_PAGE_CTL1: 49738eb6488eSEric Joyner /* All the following can't change since the last write 49748eb6488eSEric Joyner * - time valid bit 49758eb6488eSEric Joyner * - time we last sent 49768eb6488eSEric Joyner */ 49778eb6488eSEric Joyner mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; 49788eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 49798eb6488eSEric Joyner return FALSE; 49808eb6488eSEric Joyner break; 49818eb6488eSEric Joyner case BYPASS_PAGE_CTL2: 49828eb6488eSEric Joyner /* All we can check in this page is control number 49838eb6488eSEric Joyner * which is already done above. 49848eb6488eSEric Joyner */ 49858eb6488eSEric Joyner break; 49868eb6488eSEric Joyner } 49878eb6488eSEric Joyner 49888eb6488eSEric Joyner /* We are as sure as we can be return TRUE */ 49898eb6488eSEric Joyner return TRUE; 49908eb6488eSEric Joyner } 49918eb6488eSEric Joyner 49928eb6488eSEric Joyner /** 49938eb6488eSEric Joyner * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. 49948eb6488eSEric Joyner * 49958eb6488eSEric Joyner * @hw: pointer to hardware structure 49968eb6488eSEric Joyner * @cmd: The control word we are setting. 49978eb6488eSEric Joyner * @event: The event we are setting in the FW. This also happens to 49988eb6488eSEric Joyner * be the mask for the event we are setting (handy) 49998eb6488eSEric Joyner * @action: The action we set the event to in the FW. This is in a 50008eb6488eSEric Joyner * bit field that happens to be what we want to put in 50018eb6488eSEric Joyner * the event spot (also handy) 50028eb6488eSEric Joyner **/ 50038eb6488eSEric Joyner s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, 50048eb6488eSEric Joyner u32 action) 50058eb6488eSEric Joyner { 50068eb6488eSEric Joyner u32 by_ctl = 0; 50078eb6488eSEric Joyner u32 cmd, verify; 50088eb6488eSEric Joyner u32 count = 0; 50098eb6488eSEric Joyner 50108eb6488eSEric Joyner /* Get current values */ 50118eb6488eSEric Joyner cmd = ctrl; /* just reading only need control number */ 50128eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 50138eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50148eb6488eSEric Joyner 50158eb6488eSEric Joyner /* Set to new action */ 50168eb6488eSEric Joyner cmd = (by_ctl & ~event) | BYPASS_WE | action; 50178eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 50188eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50198eb6488eSEric Joyner 50208eb6488eSEric Joyner /* Page 0 force a FW eeprom write which is slow so verify */ 50218eb6488eSEric Joyner if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { 50228eb6488eSEric Joyner verify = BYPASS_PAGE_CTL0; 50238eb6488eSEric Joyner do { 50248eb6488eSEric Joyner if (count++ > 5) 50258eb6488eSEric Joyner return IXGBE_BYPASS_FW_WRITE_FAILURE; 50268eb6488eSEric Joyner 50278eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) 50288eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50298eb6488eSEric Joyner } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); 50308eb6488eSEric Joyner } else { 50318eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 50328eb6488eSEric Joyner msec_delay(100); 50338eb6488eSEric Joyner } 50348eb6488eSEric Joyner 50358eb6488eSEric Joyner return IXGBE_SUCCESS; 50368eb6488eSEric Joyner } 50378eb6488eSEric Joyner 50388eb6488eSEric Joyner /** 50398eb6488eSEric Joyner * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. 50408eb6488eSEric Joyner * 50418eb6488eSEric Joyner * @hw: pointer to hardware structure 50428eb6488eSEric Joyner * @addr: The bypass eeprom address to read. 50438eb6488eSEric Joyner * @value: The 8b of data at the address above. 50448eb6488eSEric Joyner **/ 50458eb6488eSEric Joyner s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) 50468eb6488eSEric Joyner { 50478eb6488eSEric Joyner u32 cmd; 50488eb6488eSEric Joyner u32 status; 50498eb6488eSEric Joyner 50508eb6488eSEric Joyner 50518eb6488eSEric Joyner /* send the request */ 50528eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 50538eb6488eSEric Joyner cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 50548eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 50558eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50568eb6488eSEric Joyner 50578eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 50588eb6488eSEric Joyner msec_delay(100); 50598eb6488eSEric Joyner 50608eb6488eSEric Joyner /* now read the results */ 50618eb6488eSEric Joyner cmd &= ~BYPASS_WE; 50628eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 50638eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 50648eb6488eSEric Joyner 50658eb6488eSEric Joyner *value = status & BYPASS_CTL2_DATA_M; 50668eb6488eSEric Joyner 50678eb6488eSEric Joyner return IXGBE_SUCCESS; 50688eb6488eSEric Joyner } 50698eb6488eSEric Joyner 5070fd75b91dSJack F Vogel 5071fd75b91dSJack F Vogel /** 5072fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 5073fd75b91dSJack F Vogel * @hw: pointer to hardware structure 5074fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 5075fd75b91dSJack F Vogel * 5076fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 5077fd75b91dSJack F Vogel **/ 5078fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 5079fd75b91dSJack F Vogel { 5080fd75b91dSJack F Vogel u32 reg, i; 5081fd75b91dSJack F Vogel 5082fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 5083fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 5084fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 5085fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 5086fd75b91dSJack F Vogel return; 5087fd75b91dSJack F Vogel } 5088758cc3dcSJack F Vogel 5089758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 5090758cc3dcSJack F Vogel { 5091758cc3dcSJack F Vogel u32 pfdtxgswc; 5092758cc3dcSJack F Vogel u32 rxctrl; 5093758cc3dcSJack F Vogel 5094758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5095758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 5096758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5097758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5098758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 5099758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 5100758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5101758cc3dcSJack F Vogel hw->mac.set_lben = TRUE; 5102758cc3dcSJack F Vogel } else { 5103758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5104758cc3dcSJack F Vogel } 5105758cc3dcSJack F Vogel } 5106758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 5107758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 5108758cc3dcSJack F Vogel } 5109758cc3dcSJack F Vogel } 5110758cc3dcSJack F Vogel 5111758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 5112758cc3dcSJack F Vogel { 5113758cc3dcSJack F Vogel u32 pfdtxgswc; 5114758cc3dcSJack F Vogel u32 rxctrl; 5115758cc3dcSJack F Vogel 5116758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5117758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 5118758cc3dcSJack F Vogel 5119758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5120758cc3dcSJack F Vogel if (hw->mac.set_lben) { 5121758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5122758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 5123758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 5124758cc3dcSJack F Vogel hw->mac.set_lben = FALSE; 5125758cc3dcSJack F Vogel } 5126758cc3dcSJack F Vogel } 5127758cc3dcSJack F Vogel } 5128758cc3dcSJack F Vogel 5129758cc3dcSJack F Vogel /** 5130758cc3dcSJack F Vogel * ixgbe_mng_present - returns TRUE when management capability is present 5131758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5132758cc3dcSJack F Vogel */ 5133758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 5134758cc3dcSJack F Vogel { 5135758cc3dcSJack F Vogel u32 fwsm; 5136758cc3dcSJack F Vogel 5137758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 5138758cc3dcSJack F Vogel return FALSE; 5139758cc3dcSJack F Vogel 5140a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5141758cc3dcSJack F Vogel fwsm &= IXGBE_FWSM_MODE_MASK; 5142758cc3dcSJack F Vogel return fwsm == IXGBE_FWSM_FW_MODE_PT; 5143758cc3dcSJack F Vogel } 5144758cc3dcSJack F Vogel 5145758cc3dcSJack F Vogel /** 5146758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 5147758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5148758cc3dcSJack F Vogel * 5149758cc3dcSJack F Vogel * Returns TRUE if the manageability engine is enabled. 5150758cc3dcSJack F Vogel **/ 5151758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 5152758cc3dcSJack F Vogel { 5153758cc3dcSJack F Vogel u32 fwsm, manc, factps; 5154758cc3dcSJack F Vogel 5155a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5156758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 5157758cc3dcSJack F Vogel return FALSE; 5158758cc3dcSJack F Vogel 5159758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 5160758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 5161758cc3dcSJack F Vogel return FALSE; 5162758cc3dcSJack F Vogel 5163758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 5164a9ca1c79SSean Bruno factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 5165758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 5166758cc3dcSJack F Vogel return FALSE; 5167758cc3dcSJack F Vogel } 5168758cc3dcSJack F Vogel 5169758cc3dcSJack F Vogel return TRUE; 5170758cc3dcSJack F Vogel } 5171758cc3dcSJack F Vogel 5172758cc3dcSJack F Vogel /** 5173758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 5174758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5175758cc3dcSJack F Vogel * @speed: new link speed 5176758cc3dcSJack F Vogel * @autoneg_wait_to_complete: TRUE when waiting for completion is needed 5177758cc3dcSJack F Vogel * 5178758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 5179758cc3dcSJack F Vogel **/ 5180758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 5181758cc3dcSJack F Vogel ixgbe_link_speed speed, 5182758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 5183758cc3dcSJack F Vogel { 5184758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5185758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5186758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 5187758cc3dcSJack F Vogel u32 speedcnt = 0; 5188758cc3dcSJack F Vogel u32 i = 0; 5189758cc3dcSJack F Vogel bool autoneg, link_up = FALSE; 5190758cc3dcSJack F Vogel 5191758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 5192758cc3dcSJack F Vogel 5193758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 5194758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 5195758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5196758cc3dcSJack F Vogel return status; 5197758cc3dcSJack F Vogel 5198758cc3dcSJack F Vogel speed &= link_speed; 5199758cc3dcSJack F Vogel 5200758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 5201758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 5202758cc3dcSJack F Vogel */ 5203758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 5204758cc3dcSJack F Vogel speedcnt++; 5205758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 5206758cc3dcSJack F Vogel 5207758cc3dcSJack F Vogel /* Set the module link speed */ 5208758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5209758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5210758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5211758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5212758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 5213758cc3dcSJack F Vogel break; 5214758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5215758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 5216758cc3dcSJack F Vogel break; 5217758cc3dcSJack F Vogel default: 5218758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5219758cc3dcSJack F Vogel break; 5220758cc3dcSJack F Vogel } 5221758cc3dcSJack F Vogel 5222758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 5223758cc3dcSJack F Vogel msec_delay(40); 5224758cc3dcSJack F Vogel 5225758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5226758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 5227758cc3dcSJack F Vogel autoneg_wait_to_complete); 5228758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5229758cc3dcSJack F Vogel return status; 5230758cc3dcSJack F Vogel 5231758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5232758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5233758cc3dcSJack F Vogel 5234758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 5235758cc3dcSJack F Vogel * Section 73.10.2, we may have to wait up to 500ms if KR is 5236758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 5237758cc3dcSJack F Vogel */ 5238758cc3dcSJack F Vogel for (i = 0; i < 5; i++) { 5239758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5240758cc3dcSJack F Vogel msec_delay(100); 5241758cc3dcSJack F Vogel 5242758cc3dcSJack F Vogel /* If we have link, just jump out */ 5243758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 5244758cc3dcSJack F Vogel &link_up, FALSE); 5245758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5246758cc3dcSJack F Vogel return status; 5247758cc3dcSJack F Vogel 5248758cc3dcSJack F Vogel if (link_up) 5249758cc3dcSJack F Vogel goto out; 5250758cc3dcSJack F Vogel } 5251758cc3dcSJack F Vogel } 5252758cc3dcSJack F Vogel 5253758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 5254758cc3dcSJack F Vogel speedcnt++; 5255758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 5256758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 5257758cc3dcSJack F Vogel 5258758cc3dcSJack F Vogel /* Set the module link speed */ 5259758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5260758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5261758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5262758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5263758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 5264758cc3dcSJack F Vogel break; 5265758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5266758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 5267758cc3dcSJack F Vogel break; 5268758cc3dcSJack F Vogel default: 5269758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5270758cc3dcSJack F Vogel break; 5271758cc3dcSJack F Vogel } 5272758cc3dcSJack F Vogel 5273758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 5274758cc3dcSJack F Vogel msec_delay(40); 5275758cc3dcSJack F Vogel 5276758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5277758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 5278758cc3dcSJack F Vogel autoneg_wait_to_complete); 5279758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5280758cc3dcSJack F Vogel return status; 5281758cc3dcSJack F Vogel 5282758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5283758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5284758cc3dcSJack F Vogel 5285758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5286758cc3dcSJack F Vogel msec_delay(100); 5287758cc3dcSJack F Vogel 5288758cc3dcSJack F Vogel /* If we have link, just jump out */ 5289758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); 5290758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5291758cc3dcSJack F Vogel return status; 5292758cc3dcSJack F Vogel 5293758cc3dcSJack F Vogel if (link_up) 5294758cc3dcSJack F Vogel goto out; 5295758cc3dcSJack F Vogel } 5296758cc3dcSJack F Vogel 5297758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 5298758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 5299758cc3dcSJack F Vogel * single highest speed that the user requested. 5300758cc3dcSJack F Vogel */ 5301758cc3dcSJack F Vogel if (speedcnt > 1) 5302758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 5303758cc3dcSJack F Vogel highest_link_speed, 5304758cc3dcSJack F Vogel autoneg_wait_to_complete); 5305758cc3dcSJack F Vogel 5306758cc3dcSJack F Vogel out: 5307758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 5308758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 5309758cc3dcSJack F Vogel 5310758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 5311758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 5312758cc3dcSJack F Vogel 5313758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 5314758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5315758cc3dcSJack F Vogel 5316758cc3dcSJack F Vogel return status; 5317758cc3dcSJack F Vogel } 5318758cc3dcSJack F Vogel 5319758cc3dcSJack F Vogel /** 5320758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 5321758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5322758cc3dcSJack F Vogel * @speed: link speed to set 5323758cc3dcSJack F Vogel * 5324758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 5325758cc3dcSJack F Vogel */ 5326758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 5327758cc3dcSJack F Vogel ixgbe_link_speed speed) 5328758cc3dcSJack F Vogel { 5329758cc3dcSJack F Vogel s32 status; 5330758cc3dcSJack F Vogel u8 rs, eeprom_data; 5331758cc3dcSJack F Vogel 5332758cc3dcSJack F Vogel switch (speed) { 5333758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 5334758cc3dcSJack F Vogel /* one bit mask same as setting on */ 5335758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 5336758cc3dcSJack F Vogel break; 5337758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 5338758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 5339758cc3dcSJack F Vogel break; 5340758cc3dcSJack F Vogel default: 5341758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 5342758cc3dcSJack F Vogel return; 5343758cc3dcSJack F Vogel } 5344758cc3dcSJack F Vogel 5345758cc3dcSJack F Vogel /* Set RS0 */ 5346758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5347758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5348758cc3dcSJack F Vogel &eeprom_data); 5349758cc3dcSJack F Vogel if (status) { 5350758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 5351758cc3dcSJack F Vogel goto out; 5352758cc3dcSJack F Vogel } 5353758cc3dcSJack F Vogel 5354758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5355758cc3dcSJack F Vogel 5356758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5357758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5358758cc3dcSJack F Vogel eeprom_data); 5359758cc3dcSJack F Vogel if (status) { 5360758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 5361758cc3dcSJack F Vogel goto out; 5362758cc3dcSJack F Vogel } 5363758cc3dcSJack F Vogel 5364758cc3dcSJack F Vogel /* Set RS1 */ 5365758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5366758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5367758cc3dcSJack F Vogel &eeprom_data); 5368758cc3dcSJack F Vogel if (status) { 5369758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 5370758cc3dcSJack F Vogel goto out; 5371758cc3dcSJack F Vogel } 5372758cc3dcSJack F Vogel 5373758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5374758cc3dcSJack F Vogel 5375758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5376758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5377758cc3dcSJack F Vogel eeprom_data); 5378758cc3dcSJack F Vogel if (status) { 5379758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 5380758cc3dcSJack F Vogel goto out; 5381758cc3dcSJack F Vogel } 5382758cc3dcSJack F Vogel out: 5383758cc3dcSJack F Vogel return; 5384758cc3dcSJack F Vogel } 5385