19ca4041bSJack F Vogel /****************************************************************************** 27282444bSPedro F. Giffuni SPDX-License-Identifier: BSD-3-Clause 313705f88SJack F Vogel 48455e365SKevin Bowling Copyright (c) 2001-2020, 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 3513705f88SJack F Vogel #include "ixgbe_common.h" 361a4e3449SJack F Vogel #include "ixgbe_phy.h" 37fd75b91dSJack F Vogel #include "ixgbe_dcb.h" 38fd75b91dSJack F Vogel #include "ixgbe_dcb_82599.h" 3913705f88SJack F Vogel #include "ixgbe_api.h" 4013705f88SJack F Vogel 4113705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 4213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 4313705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 4413705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 4513705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 4613705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 4713705f88SJack F Vogel u16 count); 4813705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 4913705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5013705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5113705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 5213705f88SJack F Vogel 5313705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 542969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 552969bf0eSJack F Vogel u16 *san_mac_offset); 5685d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5785d0a26eSJack F Vogel u16 words, u16 *data); 5885d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5985d0a26eSJack F Vogel u16 words, u16 *data); 6085d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 6185d0a26eSJack F Vogel u16 offset); 6213705f88SJack F Vogel 6313705f88SJack F Vogel /** 649ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 659ca4041bSJack F Vogel * @hw: pointer to the hardware structure 6613705f88SJack F Vogel * 679ca4041bSJack F Vogel * Initialize the function pointers. 6813705f88SJack F Vogel **/ 699ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 7013705f88SJack F Vogel { 719ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 729ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 73a9ca1c79SSean Bruno u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 7413705f88SJack F Vogel 752969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_ops_generic"); 762969bf0eSJack F Vogel 7713705f88SJack F Vogel /* EEPROM */ 78758cc3dcSJack F Vogel eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; 799ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 8085d0a26eSJack F Vogel if (eec & IXGBE_EEC_PRES) { 81758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eerd_generic; 82758cc3dcSJack F Vogel eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; 8385d0a26eSJack F Vogel } else { 84758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; 8585d0a26eSJack F Vogel eeprom->ops.read_buffer = 86758cc3dcSJack F Vogel ixgbe_read_eeprom_buffer_bit_bang_generic; 8785d0a26eSJack F Vogel } 88758cc3dcSJack F Vogel eeprom->ops.write = ixgbe_write_eeprom_generic; 89758cc3dcSJack F Vogel eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; 909ca4041bSJack F Vogel eeprom->ops.validate_checksum = 91758cc3dcSJack F Vogel ixgbe_validate_eeprom_checksum_generic; 92758cc3dcSJack F Vogel eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; 93758cc3dcSJack F Vogel eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; 949ca4041bSJack F Vogel 959ca4041bSJack F Vogel /* MAC */ 96758cc3dcSJack F Vogel mac->ops.init_hw = ixgbe_init_hw_generic; 979ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 98758cc3dcSJack F Vogel mac->ops.start_hw = ixgbe_start_hw_generic; 99758cc3dcSJack F Vogel mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; 1009ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 1011b6e0dbaSJack F Vogel mac->ops.get_supported_physical_layer = NULL; 102758cc3dcSJack F Vogel mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; 103758cc3dcSJack F Vogel mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; 104758cc3dcSJack F Vogel mac->ops.stop_adapter = ixgbe_stop_adapter_generic; 105758cc3dcSJack F Vogel mac->ops.get_bus_info = ixgbe_get_bus_info_generic; 106758cc3dcSJack F Vogel mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; 107758cc3dcSJack F Vogel mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; 108758cc3dcSJack F Vogel mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; 109758cc3dcSJack F Vogel mac->ops.prot_autoc_read = prot_autoc_read_generic; 110758cc3dcSJack F Vogel mac->ops.prot_autoc_write = prot_autoc_write_generic; 1119ca4041bSJack F Vogel 1129ca4041bSJack F Vogel /* LEDs */ 113758cc3dcSJack F Vogel mac->ops.led_on = ixgbe_led_on_generic; 114758cc3dcSJack F Vogel mac->ops.led_off = ixgbe_led_off_generic; 115758cc3dcSJack F Vogel mac->ops.blink_led_start = ixgbe_blink_led_start_generic; 116758cc3dcSJack F Vogel mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; 1178eb6488eSEric Joyner mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic; 1189ca4041bSJack F Vogel 11913705f88SJack F Vogel /* RAR, Multicast, VLAN */ 120758cc3dcSJack F Vogel mac->ops.set_rar = ixgbe_set_rar_generic; 121758cc3dcSJack F Vogel mac->ops.clear_rar = ixgbe_clear_rar_generic; 1220ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1239ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1245b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 125758cc3dcSJack F Vogel mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; 126758cc3dcSJack F Vogel mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; 127758cc3dcSJack F Vogel mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; 128758cc3dcSJack F Vogel mac->ops.enable_mc = ixgbe_enable_mc_generic; 129758cc3dcSJack F Vogel mac->ops.disable_mc = ixgbe_disable_mc_generic; 1305b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1315b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 13285d0a26eSJack F Vogel mac->ops.set_vlvf = NULL; 1335b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 134758cc3dcSJack F Vogel mac->ops.enable_rx = ixgbe_enable_rx_generic; 135758cc3dcSJack F Vogel mac->ops.disable_rx = ixgbe_disable_rx_generic; 1369ca4041bSJack F Vogel 1370ac6dfecSJack F Vogel /* Flow Control */ 138758cc3dcSJack F Vogel mac->ops.fc_enable = ixgbe_fc_enable_generic; 139758cc3dcSJack F Vogel mac->ops.setup_fc = ixgbe_setup_fc_generic; 1408eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg; 1419ca4041bSJack F Vogel 1429ca4041bSJack F Vogel /* Link */ 1439ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1449ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1459ca4041bSJack F Vogel mac->ops.check_link = NULL; 146fd75b91dSJack F Vogel mac->ops.dmac_config = NULL; 147fd75b91dSJack F Vogel mac->ops.dmac_update_tcs = NULL; 148fd75b91dSJack F Vogel mac->ops.dmac_config_tcs = NULL; 14913705f88SJack F Vogel 15013705f88SJack F Vogel return IXGBE_SUCCESS; 15113705f88SJack F Vogel } 15213705f88SJack F Vogel 15313705f88SJack F Vogel /** 154fd75b91dSJack F Vogel * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation 155fd75b91dSJack F Vogel * of flow control 156a621e3c8SJack F Vogel * @hw: pointer to hardware structure 157a621e3c8SJack F Vogel * 15879b36ec9SKevin Bowling * This function returns true if the device supports flow control 15979b36ec9SKevin Bowling * autonegotiation, and false if it does not. 160fd75b91dSJack F Vogel * 161a621e3c8SJack F Vogel **/ 162fd75b91dSJack F Vogel bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 163a621e3c8SJack F Vogel { 16479b36ec9SKevin Bowling bool supported = false; 165fd75b91dSJack F Vogel ixgbe_link_speed speed; 166fd75b91dSJack F Vogel bool link_up; 167a621e3c8SJack F Vogel 168a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); 169a621e3c8SJack F Vogel 170fd75b91dSJack F Vogel switch (hw->phy.media_type) { 171fd75b91dSJack F Vogel case ixgbe_media_type_fiber_fixed: 172758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 173fd75b91dSJack F Vogel case ixgbe_media_type_fiber: 1744530d49eSMarcin Jurczak /* flow control autoneg block list */ 1758eb6488eSEric Joyner switch (hw->device_id) { 1768eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP: 1778eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N: 1788eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP: 1798eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP_N: 18079b36ec9SKevin Bowling supported = false; 1818eb6488eSEric Joyner break; 1828eb6488eSEric Joyner default: 18379b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 184fd75b91dSJack F Vogel /* if link is down, assume supported */ 185fd75b91dSJack F Vogel if (link_up) 186fd75b91dSJack F Vogel supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? 18779b36ec9SKevin Bowling true : false; 188fd75b91dSJack F Vogel else 18979b36ec9SKevin Bowling supported = true; 1908eb6488eSEric Joyner } 1918eb6488eSEric Joyner 192fd75b91dSJack F Vogel break; 193fd75b91dSJack F Vogel case ixgbe_media_type_backplane: 1948eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) 19579b36ec9SKevin Bowling supported = false; 1968eb6488eSEric Joyner else 19779b36ec9SKevin Bowling supported = true; 198fd75b91dSJack F Vogel break; 199fd75b91dSJack F Vogel case ixgbe_media_type_copper: 200fd75b91dSJack F Vogel /* only some copper devices support flow control autoneg */ 201a621e3c8SJack F Vogel switch (hw->device_id) { 202a621e3c8SJack F Vogel case IXGBE_DEV_ID_82599_T3_LOM: 2030ecc2ff0SJack F Vogel case IXGBE_DEV_ID_X540T: 204758cc3dcSJack F Vogel case IXGBE_DEV_ID_X540T1: 205fd75b91dSJack F Vogel case IXGBE_DEV_ID_X540_BYPASS: 206758cc3dcSJack F Vogel case IXGBE_DEV_ID_X550T: 207a9ca1c79SSean Bruno case IXGBE_DEV_ID_X550T1: 2086f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T: 2098eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T: 2108eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T: 2118eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L: 21279b36ec9SKevin Bowling supported = true; 213fd75b91dSJack F Vogel break; 214a621e3c8SJack F Vogel default: 21579b36ec9SKevin Bowling supported = false; 216a621e3c8SJack F Vogel } 217fd75b91dSJack F Vogel default: 218fd75b91dSJack F Vogel break; 219fd75b91dSJack F Vogel } 220fd75b91dSJack F Vogel 2218eb6488eSEric Joyner if (!supported) 222fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, 223fd75b91dSJack F Vogel "Device %x does not support flow control autoneg", 224fd75b91dSJack F Vogel hw->device_id); 225c19c7afeSEric Joyner 226fd75b91dSJack F Vogel return supported; 227a621e3c8SJack F Vogel } 228a621e3c8SJack F Vogel 229a621e3c8SJack F Vogel /** 230758cc3dcSJack F Vogel * ixgbe_setup_fc_generic - Set up flow control 231a621e3c8SJack F Vogel * @hw: pointer to hardware structure 232a621e3c8SJack F Vogel * 233a621e3c8SJack F Vogel * Called at init time to set up flow control. 234a621e3c8SJack F Vogel **/ 235758cc3dcSJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 236a621e3c8SJack F Vogel { 237a621e3c8SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 238a621e3c8SJack F Vogel u32 reg = 0, reg_bp = 0; 239a621e3c8SJack F Vogel u16 reg_cu = 0; 24079b36ec9SKevin Bowling bool locked = false; 241a621e3c8SJack F Vogel 242758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_fc_generic"); 243a621e3c8SJack F Vogel 244758cc3dcSJack F Vogel /* Validate the requested mode */ 245a621e3c8SJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 246fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 247fd75b91dSJack F Vogel "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 248a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 249a621e3c8SJack F Vogel goto out; 250a621e3c8SJack F Vogel } 251a621e3c8SJack F Vogel 252a621e3c8SJack F Vogel /* 253a621e3c8SJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 254a621e3c8SJack F Vogel * default flow control setting, so we explicitly set it to full. 255a621e3c8SJack F Vogel */ 256a621e3c8SJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 257a621e3c8SJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 258a621e3c8SJack F Vogel 259a621e3c8SJack F Vogel /* 260a621e3c8SJack F Vogel * Set up the 1G and 10G flow control advertisement registers so the 261a621e3c8SJack F Vogel * HW will be able to do fc autoneg once the cable is plugged in. If 262a621e3c8SJack F Vogel * we link at 10G, the 1G advertisement is harmless and vice versa. 263a621e3c8SJack F Vogel */ 264a621e3c8SJack F Vogel switch (hw->phy.media_type) { 265a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 266758cc3dcSJack F Vogel /* some MAC's need RMW protection on AUTOC */ 267758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 268758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 269758cc3dcSJack F Vogel goto out; 270758cc3dcSJack F Vogel 27150455f73SPiotr Skajewski reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 27250455f73SPiotr Skajewski break; 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) 43479b36ec9SKevin Bowling hw->need_crosstalk_fix = false; 4358eb6488eSEric Joyner else 43679b36ec9SKevin Bowling hw->need_crosstalk_fix = true; 4378eb6488eSEric Joyner break; 4388eb6488eSEric Joyner default: 43979b36ec9SKevin Bowling hw->need_crosstalk_fix = false; 4408eb6488eSEric Joyner break; 4418eb6488eSEric Joyner } 4420ac6dfecSJack F Vogel 44313705f88SJack F Vogel /* Clear adapter stopped flag */ 44479b36ec9SKevin Bowling 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 **/ 4593a890053SGuinan Sun void 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 } 48413705f88SJack F Vogel } 48513705f88SJack F Vogel 48613705f88SJack F Vogel /** 48713705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 48813705f88SJack F Vogel * @hw: pointer to hardware structure 48913705f88SJack F Vogel * 4909ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 49113705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 49213705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 49313705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 49413705f88SJack F Vogel * disabled and uninitialized 49513705f88SJack F Vogel **/ 49613705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 49713705f88SJack F Vogel { 4981a4e3449SJack F Vogel s32 status; 4990ac6dfecSJack F Vogel 5002969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 5012969bf0eSJack F Vogel 50213705f88SJack F Vogel /* Reset the hardware */ 5030ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 50413705f88SJack F Vogel 5058eb6488eSEric Joyner if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { 50613705f88SJack F Vogel /* Start the HW */ 5070ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 5080ac6dfecSJack F Vogel } 50913705f88SJack F Vogel 5108eb6488eSEric Joyner /* Initialize the LED link active for LED blink support */ 5118eb6488eSEric Joyner if (hw->mac.ops.init_led_link_act) 5128eb6488eSEric Joyner hw->mac.ops.init_led_link_act(hw); 5138eb6488eSEric Joyner 5148eb6488eSEric Joyner if (status != IXGBE_SUCCESS) 5158eb6488eSEric Joyner DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); 5168eb6488eSEric Joyner 5170ac6dfecSJack F Vogel return status; 51813705f88SJack F Vogel } 51913705f88SJack F Vogel 52013705f88SJack F Vogel /** 52113705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 52213705f88SJack F Vogel * @hw: pointer to hardware structure 52313705f88SJack F Vogel * 52413705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 52513705f88SJack F Vogel * Statistics counters are clear on read. 52613705f88SJack F Vogel **/ 52713705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 52813705f88SJack F Vogel { 52913705f88SJack F Vogel u16 i = 0; 53013705f88SJack F Vogel 5312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 5322969bf0eSJack F Vogel 53313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 53413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 53513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 53713705f88SJack F Vogel for (i = 0; i < 8; i++) 53813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 53913705f88SJack F Vogel 54013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 54113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 54213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 5450ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5460ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5470ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5480ac6dfecSJack F Vogel } else { 5491b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 55013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5510ac6dfecSJack F Vogel } 55213705f88SJack F Vogel 55313705f88SJack F Vogel for (i = 0; i < 8; i++) { 55413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 55513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5560ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5570ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5580ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5590ac6dfecSJack F Vogel } else { 5601b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 56113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 56213705f88SJack F Vogel } 5630ac6dfecSJack F Vogel } 5640ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5650ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5660ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 56713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 56813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 56913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 57013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 57113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 57213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 57313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 57413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 57513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 57613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 57713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 57813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 57913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 58013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 58185d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 58213705f88SJack F Vogel for (i = 0; i < 8; i++) 58313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 58413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 58513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 58613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 58713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 58813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 58913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 59013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 59113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 59213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 59313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 59413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 59513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 59613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 59713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 59813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 59913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 60013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 60113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 60213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 60313705f88SJack F Vogel for (i = 0; i < 16; i++) { 60413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 60513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 6061a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 6071a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 6081a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 6091a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 6101a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 6111a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 6121a4e3449SJack F Vogel } else { 6131a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 61413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 61513705f88SJack F Vogel } 6161a4e3449SJack F Vogel } 6171a4e3449SJack F Vogel 618758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 61985d0a26eSJack F Vogel if (hw->phy.id == 0) 62085d0a26eSJack F Vogel ixgbe_identify_phy(hw); 62185d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 62285d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62385d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 62485d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62585d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 62685d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62785d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 62885d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62985d0a26eSJack F Vogel } 63085d0a26eSJack F Vogel 6311a4e3449SJack F Vogel return IXGBE_SUCCESS; 6321a4e3449SJack F Vogel } 6331a4e3449SJack F Vogel 6341a4e3449SJack F Vogel /** 6351a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 6361a4e3449SJack F Vogel * @hw: pointer to hardware structure 6371a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 6381a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 6391a4e3449SJack F Vogel * 6401a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 6411a4e3449SJack F Vogel **/ 6421a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 6431a4e3449SJack F Vogel u32 pba_num_size) 6441a4e3449SJack F Vogel { 6451a4e3449SJack F Vogel s32 ret_val; 6461a4e3449SJack F Vogel u16 data; 6471a4e3449SJack F Vogel u16 pba_ptr; 6481a4e3449SJack F Vogel u16 offset; 6491a4e3449SJack F Vogel u16 length; 6501a4e3449SJack F Vogel 6511a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6521a4e3449SJack F Vogel 6531a4e3449SJack F Vogel if (pba_num == NULL) { 6541a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6551a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6561a4e3449SJack F Vogel } 6571a4e3449SJack F Vogel 6581a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6591a4e3449SJack F Vogel if (ret_val) { 6601a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6611a4e3449SJack F Vogel return ret_val; 6621a4e3449SJack F Vogel } 6631a4e3449SJack F Vogel 6641a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6651a4e3449SJack F Vogel if (ret_val) { 6661a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6671a4e3449SJack F Vogel return ret_val; 6681a4e3449SJack F Vogel } 6691a4e3449SJack F Vogel 6701a4e3449SJack F Vogel /* 6711a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6721a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6731a4e3449SJack F Vogel * and we can decode it into an ascii string 6741a4e3449SJack F Vogel */ 6751a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6761a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6771a4e3449SJack F Vogel 6781a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6791a4e3449SJack F Vogel if (pba_num_size < 11) { 6801a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6811a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6821a4e3449SJack F Vogel } 6831a4e3449SJack F Vogel 6841a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6851a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6861a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6871a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6881a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6891a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6901a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6911a4e3449SJack F Vogel pba_num[6] = '-'; 6921a4e3449SJack F Vogel pba_num[7] = 0; 6931a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6941a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6951a4e3449SJack F Vogel 6961a4e3449SJack F Vogel /* put a null character on the end of our string */ 6971a4e3449SJack F Vogel pba_num[10] = '\0'; 6981a4e3449SJack F Vogel 6991a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 7001a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 7011a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 7021a4e3449SJack F Vogel pba_num[offset] += '0'; 7031a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 7041a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 7051a4e3449SJack F Vogel } 7061a4e3449SJack F Vogel 7071a4e3449SJack F Vogel return IXGBE_SUCCESS; 7081a4e3449SJack F Vogel } 7091a4e3449SJack F Vogel 7101a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 7111a4e3449SJack F Vogel if (ret_val) { 7121a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7131a4e3449SJack F Vogel return ret_val; 7141a4e3449SJack F Vogel } 7151a4e3449SJack F Vogel 716*25771c8cSDawid Zielinski if (length == 0xFFFF || length == 0 || length > hw->eeprom.word_size) { 7171a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 7181a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 7191a4e3449SJack F Vogel } 7201a4e3449SJack F Vogel 7211a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 7221a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 7231a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 7241a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 7251a4e3449SJack F Vogel } 7261a4e3449SJack F Vogel 7271a4e3449SJack F Vogel /* trim pba length from start of string */ 7281a4e3449SJack F Vogel pba_ptr++; 7291a4e3449SJack F Vogel length--; 7301a4e3449SJack F Vogel 7311a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 7321a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 7331a4e3449SJack F Vogel if (ret_val) { 7341a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7351a4e3449SJack F Vogel return ret_val; 7361a4e3449SJack F Vogel } 7371a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 7381a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 7391a4e3449SJack F Vogel } 7401a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 7411a4e3449SJack F Vogel 7421a4e3449SJack F Vogel return IXGBE_SUCCESS; 7431a4e3449SJack F Vogel } 7441a4e3449SJack F Vogel 7451a4e3449SJack F Vogel /** 7461b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7479ca4041bSJack F Vogel * @hw: pointer to hardware structure 7489ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7499ca4041bSJack F Vogel * 7509ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7519ca4041bSJack F Vogel **/ 7529ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7539ca4041bSJack F Vogel { 7549ca4041bSJack F Vogel s32 ret_val; 7559ca4041bSJack F Vogel u16 data; 7569ca4041bSJack F Vogel 7579ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7589ca4041bSJack F Vogel 7599ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7609ca4041bSJack F Vogel if (ret_val) { 7619ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7629ca4041bSJack F Vogel return ret_val; 7631a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7641a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7651a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7669ca4041bSJack F Vogel } 7679ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7689ca4041bSJack F Vogel 7699ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7709ca4041bSJack F Vogel if (ret_val) { 7719ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7729ca4041bSJack F Vogel return ret_val; 7739ca4041bSJack F Vogel } 774994dd632SGuinan Sun *pba_num |= (u32)data; 7759ca4041bSJack F Vogel 7769ca4041bSJack F Vogel return IXGBE_SUCCESS; 7779ca4041bSJack F Vogel } 7789ca4041bSJack F Vogel 7799ca4041bSJack F Vogel /** 7800ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7810ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7820ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7830ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7840ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7850ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7860ecc2ff0SJack F Vogel * 7870ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7880ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7890ecc2ff0SJack F Vogel * 7900ecc2ff0SJack F Vogel **/ 7910ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7920ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7930ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7940ecc2ff0SJack F Vogel { 7950ecc2ff0SJack F Vogel s32 ret_val; 7960ecc2ff0SJack F Vogel u16 pba_block_size; 7970ecc2ff0SJack F Vogel 7980ecc2ff0SJack F Vogel if (pba == NULL) 7990ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8000ecc2ff0SJack F Vogel 8010ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8020ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8030ecc2ff0SJack F Vogel &pba->word[0]); 8040ecc2ff0SJack F Vogel if (ret_val) 8050ecc2ff0SJack F Vogel return ret_val; 8060ecc2ff0SJack F Vogel } else { 8070ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8080ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8090ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8100ecc2ff0SJack F Vogel } else { 8110ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8120ecc2ff0SJack F Vogel } 8130ecc2ff0SJack F Vogel } 8140ecc2ff0SJack F Vogel 8150ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8160ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8170ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8180ecc2ff0SJack F Vogel 8190ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 8200ecc2ff0SJack F Vogel eeprom_buf_size, 8210ecc2ff0SJack F Vogel &pba_block_size); 8220ecc2ff0SJack F Vogel if (ret_val) 8230ecc2ff0SJack F Vogel return ret_val; 8240ecc2ff0SJack F Vogel 8250ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 8260ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8270ecc2ff0SJack F Vogel 8280ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8290ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 8300ecc2ff0SJack F Vogel pba_block_size, 8310ecc2ff0SJack F Vogel pba->pba_block); 8320ecc2ff0SJack F Vogel if (ret_val) 8330ecc2ff0SJack F Vogel return ret_val; 8340ecc2ff0SJack F Vogel } else { 8350ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 836758cc3dcSJack F Vogel pba_block_size)) { 8370ecc2ff0SJack F Vogel memcpy(pba->pba_block, 8380ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 8390ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 8400ecc2ff0SJack F Vogel } else { 8410ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8420ecc2ff0SJack F Vogel } 8430ecc2ff0SJack F Vogel } 8440ecc2ff0SJack F Vogel } 8450ecc2ff0SJack F Vogel 8460ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8470ecc2ff0SJack F Vogel } 8480ecc2ff0SJack F Vogel 8490ecc2ff0SJack F Vogel /** 8500ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8510ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8520ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8530ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8540ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8550ecc2ff0SJack F Vogel * 8560ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8570ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8580ecc2ff0SJack F Vogel * 8590ecc2ff0SJack F Vogel **/ 8600ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8610ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8620ecc2ff0SJack F Vogel { 8630ecc2ff0SJack F Vogel s32 ret_val; 8640ecc2ff0SJack F Vogel 8650ecc2ff0SJack F Vogel if (pba == NULL) 8660ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8670ecc2ff0SJack F Vogel 8680ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8690ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8700ecc2ff0SJack F Vogel &pba->word[0]); 8710ecc2ff0SJack F Vogel if (ret_val) 8720ecc2ff0SJack F Vogel return ret_val; 8730ecc2ff0SJack F Vogel } else { 8740ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8750ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8760ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8770ecc2ff0SJack F Vogel } else { 8780ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8790ecc2ff0SJack F Vogel } 8800ecc2ff0SJack F Vogel } 8810ecc2ff0SJack F Vogel 8820ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8830ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8840ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8850ecc2ff0SJack F Vogel 8860ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8870ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8880ecc2ff0SJack F Vogel pba->pba_block[0], 8890ecc2ff0SJack F Vogel pba->pba_block); 8900ecc2ff0SJack F Vogel if (ret_val) 8910ecc2ff0SJack F Vogel return ret_val; 8920ecc2ff0SJack F Vogel } else { 8930ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8940ecc2ff0SJack F Vogel pba->pba_block[0])) { 8950ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8960ecc2ff0SJack F Vogel pba->pba_block, 8970ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 8980ecc2ff0SJack F Vogel } else { 8990ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9000ecc2ff0SJack F Vogel } 9010ecc2ff0SJack F Vogel } 9020ecc2ff0SJack F Vogel } 9030ecc2ff0SJack F Vogel 9040ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9050ecc2ff0SJack F Vogel } 9060ecc2ff0SJack F Vogel 9070ecc2ff0SJack F Vogel /** 9080ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 9090ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 9100ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 9110ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 9120ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 9130ecc2ff0SJack F Vogel * 9140ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 9150ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 9160ecc2ff0SJack F Vogel * EEPROM device. 9170ecc2ff0SJack F Vogel * 9180ecc2ff0SJack F Vogel **/ 9190ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 9200ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 9210ecc2ff0SJack F Vogel { 9220ecc2ff0SJack F Vogel s32 ret_val; 9230ecc2ff0SJack F Vogel u16 pba_word[2]; 9240ecc2ff0SJack F Vogel u16 length; 9250ecc2ff0SJack F Vogel 9260ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 9270ecc2ff0SJack F Vogel 9280ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9290ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 9300ecc2ff0SJack F Vogel &pba_word[0]); 9310ecc2ff0SJack F Vogel if (ret_val) 9320ecc2ff0SJack F Vogel return ret_val; 9330ecc2ff0SJack F Vogel } else { 9340ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 9350ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 9360ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 9370ecc2ff0SJack F Vogel } else { 9380ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9390ecc2ff0SJack F Vogel } 9400ecc2ff0SJack F Vogel } 9410ecc2ff0SJack F Vogel 9420ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 9430ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9440ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 9450ecc2ff0SJack F Vogel &length); 9460ecc2ff0SJack F Vogel if (ret_val) 9470ecc2ff0SJack F Vogel return ret_val; 9480ecc2ff0SJack F Vogel } else { 9490ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9500ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9510ecc2ff0SJack F Vogel else 9520ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9530ecc2ff0SJack F Vogel } 9540ecc2ff0SJack F Vogel 9550ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9560ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9570ecc2ff0SJack F Vogel } else { 9580ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9590ecc2ff0SJack F Vogel length = 0; 9600ecc2ff0SJack F Vogel } 9610ecc2ff0SJack F Vogel 9620ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9630ecc2ff0SJack F Vogel *pba_block_size = length; 9640ecc2ff0SJack F Vogel 9650ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9660ecc2ff0SJack F Vogel } 9670ecc2ff0SJack F Vogel 9680ecc2ff0SJack F Vogel /** 96913705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 97013705f88SJack F Vogel * @hw: pointer to hardware structure 97113705f88SJack F Vogel * @mac_addr: Adapter MAC address 97213705f88SJack F Vogel * 97313705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 97413705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 97513705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 97613705f88SJack F Vogel **/ 97713705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 97813705f88SJack F Vogel { 97913705f88SJack F Vogel u32 rar_high; 98013705f88SJack F Vogel u32 rar_low; 98113705f88SJack F Vogel u16 i; 98213705f88SJack F Vogel 9832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9842969bf0eSJack F Vogel 98513705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 98613705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 98713705f88SJack F Vogel 98813705f88SJack F Vogel for (i = 0; i < 4; i++) 98913705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 99013705f88SJack F Vogel 99113705f88SJack F Vogel for (i = 0; i < 2; i++) 99213705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 99313705f88SJack F Vogel 99413705f88SJack F Vogel return IXGBE_SUCCESS; 99513705f88SJack F Vogel } 99613705f88SJack F Vogel 99713705f88SJack F Vogel /** 998fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 99913705f88SJack F Vogel * @hw: pointer to hardware structure 1000fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 100113705f88SJack F Vogel * 1002fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 100313705f88SJack F Vogel **/ 1004fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 100513705f88SJack F Vogel { 10061b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 10072969bf0eSJack F Vogel 1008758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 100913705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 101013705f88SJack F Vogel 101113705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 101213705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 101313705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 101413705f88SJack F Vogel break; 101513705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 101613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 101713705f88SJack F Vogel break; 101813705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 101913705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 102013705f88SJack F Vogel break; 102113705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 102213705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 102313705f88SJack F Vogel break; 102413705f88SJack F Vogel default: 102513705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 102613705f88SJack F Vogel break; 102713705f88SJack F Vogel } 102813705f88SJack F Vogel 102913705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 103013705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 103113705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 103213705f88SJack F Vogel break; 103313705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 103413705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 103513705f88SJack F Vogel break; 1036a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 1037a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 1038a621e3c8SJack F Vogel break; 103913705f88SJack F Vogel default: 104013705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 104113705f88SJack F Vogel break; 104213705f88SJack F Vogel } 104313705f88SJack F Vogel 10441b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 1045fd75b91dSJack F Vogel } 1046fd75b91dSJack F Vogel 1047fd75b91dSJack F Vogel /** 1048fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1049fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1050fd75b91dSJack F Vogel * 1051fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1052fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1053fd75b91dSJack F Vogel **/ 1054fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1055fd75b91dSJack F Vogel { 1056fd75b91dSJack F Vogel u16 link_status; 1057fd75b91dSJack F Vogel 1058fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1059fd75b91dSJack F Vogel 1060fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1061fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1062fd75b91dSJack F Vogel 1063fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10641b6e0dbaSJack F Vogel 106513705f88SJack F Vogel return IXGBE_SUCCESS; 106613705f88SJack F Vogel } 106713705f88SJack F Vogel 106813705f88SJack F Vogel /** 10691b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10701b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10711b6e0dbaSJack F Vogel * 10728eb6488eSEric Joyner * Determines the LAN function id by reading memory-mapped registers and swaps 10738eb6488eSEric Joyner * the port value if requested, and set MAC instance for devices that share 10748eb6488eSEric Joyner * CS4227. 10751b6e0dbaSJack F Vogel **/ 10761b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10771b6e0dbaSJack F Vogel { 10781b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10791b6e0dbaSJack F Vogel u32 reg; 10808eb6488eSEric Joyner u16 ee_ctrl_4; 10811b6e0dbaSJack F Vogel 10822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10832969bf0eSJack F Vogel 10841b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10851b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 10868eb6488eSEric Joyner bus->lan_id = (u8)bus->func; 10871b6e0dbaSJack F Vogel 10881b6e0dbaSJack F Vogel /* check for a port swap */ 1089a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 10901b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10911b6e0dbaSJack F Vogel bus->func ^= 0x1; 10928eb6488eSEric Joyner 10938eb6488eSEric Joyner /* Get MAC instance from EEPROM for configuring CS4227 */ 10948eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 10958eb6488eSEric Joyner hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 10968eb6488eSEric Joyner bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 10978eb6488eSEric Joyner IXGBE_EE_CTRL_4_INST_ID_SHIFT; 10988eb6488eSEric Joyner } 10991b6e0dbaSJack F Vogel } 11001b6e0dbaSJack F Vogel 11011b6e0dbaSJack F Vogel /** 11029ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 110313705f88SJack F Vogel * @hw: pointer to hardware structure 110413705f88SJack F Vogel * 110513705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 110613705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 110713705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 110813705f88SJack F Vogel * state and should not touch the hardware. 110913705f88SJack F Vogel **/ 111013705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 111113705f88SJack F Vogel { 111213705f88SJack F Vogel u32 reg_val; 111313705f88SJack F Vogel u16 i; 111413705f88SJack F Vogel 11152969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 11162969bf0eSJack F Vogel 111713705f88SJack F Vogel /* 111813705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 111913705f88SJack F Vogel * the hardware 112013705f88SJack F Vogel */ 112179b36ec9SKevin Bowling hw->adapter_stopped = true; 112213705f88SJack F Vogel 112313705f88SJack F Vogel /* Disable the receive unit */ 1124758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 112513705f88SJack F Vogel 112685d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 112713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 112813705f88SJack F Vogel 112985d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 113013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 113113705f88SJack F Vogel 113213705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 113385d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 113485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 113585d0a26eSJack F Vogel 113685d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 113785d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 113885d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 113985d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 114085d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 114185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 114213705f88SJack F Vogel } 114385d0a26eSJack F Vogel 114485d0a26eSJack F Vogel /* flush all queues disables */ 114585d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 114685d0a26eSJack F Vogel msec_delay(2); 114713705f88SJack F Vogel 11489ca4041bSJack F Vogel /* 11494530d49eSMarcin Jurczak * Prevent the PCI-E bus from hanging by disabling PCI-E primary 11509ca4041bSJack F Vogel * access and verify no pending requests 11519ca4041bSJack F Vogel */ 11524530d49eSMarcin Jurczak return ixgbe_disable_pcie_primary(hw); 115313705f88SJack F Vogel } 115413705f88SJack F Vogel 115513705f88SJack F Vogel /** 11568eb6488eSEric Joyner * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 11578eb6488eSEric Joyner * @hw: pointer to hardware structure 11588eb6488eSEric Joyner * 11598eb6488eSEric Joyner * Store the index for the link active LED. This will be used to support 11608eb6488eSEric Joyner * blinking the LED. 11618eb6488eSEric Joyner **/ 11628eb6488eSEric Joyner s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 11638eb6488eSEric Joyner { 11648eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac; 11658eb6488eSEric Joyner u32 led_reg, led_mode; 11668eb6488eSEric Joyner u8 i; 11678eb6488eSEric Joyner 11688eb6488eSEric Joyner led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 11698eb6488eSEric Joyner 11708eb6488eSEric Joyner /* Get LED link active from the LEDCTL register */ 11718eb6488eSEric Joyner for (i = 0; i < 4; i++) { 11728eb6488eSEric Joyner led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 11738eb6488eSEric Joyner 11748eb6488eSEric Joyner if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 11758eb6488eSEric Joyner IXGBE_LED_LINK_ACTIVE) { 11768eb6488eSEric Joyner mac->led_link_act = i; 11778eb6488eSEric Joyner return IXGBE_SUCCESS; 11788eb6488eSEric Joyner } 11798eb6488eSEric Joyner } 11808eb6488eSEric Joyner 11818eb6488eSEric Joyner /* 11828eb6488eSEric Joyner * If LEDCTL register does not have the LED link active set, then use 11838eb6488eSEric Joyner * known MAC defaults. 11848eb6488eSEric Joyner */ 11858eb6488eSEric Joyner switch (hw->mac.type) { 11868eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 11878eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 11888eb6488eSEric Joyner mac->led_link_act = 1; 11898eb6488eSEric Joyner break; 11908eb6488eSEric Joyner default: 11918eb6488eSEric Joyner mac->led_link_act = 2; 11928eb6488eSEric Joyner } 11938eb6488eSEric Joyner return IXGBE_SUCCESS; 11948eb6488eSEric Joyner } 11958eb6488eSEric Joyner 11968eb6488eSEric Joyner /** 119713705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 119813705f88SJack F Vogel * @hw: pointer to hardware structure 119913705f88SJack F Vogel * @index: led number to turn on 120013705f88SJack F Vogel **/ 120113705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 120213705f88SJack F Vogel { 120313705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 120413705f88SJack F Vogel 12052969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 12062969bf0eSJack F Vogel 12078eb6488eSEric Joyner if (index > 3) 12088eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12098eb6488eSEric Joyner 121013705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 121113705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 121213705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 121313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12149ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 121513705f88SJack F Vogel 121613705f88SJack F Vogel return IXGBE_SUCCESS; 121713705f88SJack F Vogel } 121813705f88SJack F Vogel 121913705f88SJack F Vogel /** 122013705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 122113705f88SJack F Vogel * @hw: pointer to hardware structure 122213705f88SJack F Vogel * @index: led number to turn off 122313705f88SJack F Vogel **/ 122413705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 122513705f88SJack F Vogel { 122613705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 122713705f88SJack F Vogel 12282969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 12292969bf0eSJack F Vogel 12308eb6488eSEric Joyner if (index > 3) 12318eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12328eb6488eSEric Joyner 123313705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 123413705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 123513705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 123613705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12379ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 123813705f88SJack F Vogel 123913705f88SJack F Vogel return IXGBE_SUCCESS; 124013705f88SJack F Vogel } 124113705f88SJack F Vogel 124213705f88SJack F Vogel /** 124313705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 124413705f88SJack F Vogel * @hw: pointer to hardware structure 124513705f88SJack F Vogel * 124613705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 124713705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 124813705f88SJack F Vogel **/ 124913705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 125013705f88SJack F Vogel { 125113705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 125213705f88SJack F Vogel u32 eec; 125313705f88SJack F Vogel u16 eeprom_size; 125413705f88SJack F Vogel 12552969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 12562969bf0eSJack F Vogel 125713705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 125813705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 12595b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 12605b7f4cedSJack F Vogel * tested value */ 12615b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 126285d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 126385d0a26eSJack F Vogel eeprom->word_page_size = 0; 126413705f88SJack F Vogel 126513705f88SJack F Vogel /* 126613705f88SJack F Vogel * Check for EEPROM present first. 126713705f88SJack F Vogel * If not present leave as none 126813705f88SJack F Vogel */ 1269a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 127013705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 127113705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 127213705f88SJack F Vogel 127313705f88SJack F Vogel /* 127413705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 127513705f88SJack F Vogel * change if a future EEPROM is not SPI. 127613705f88SJack F Vogel */ 127713705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 127813705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 127913705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 128085d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 128113705f88SJack F Vogel } 128213705f88SJack F Vogel 128313705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 128413705f88SJack F Vogel eeprom->address_bits = 16; 128513705f88SJack F Vogel else 128613705f88SJack F Vogel eeprom->address_bits = 8; 128713705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 128813705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 128913705f88SJack F Vogel eeprom->address_bits); 129013705f88SJack F Vogel } 129113705f88SJack F Vogel 129213705f88SJack F Vogel return IXGBE_SUCCESS; 129313705f88SJack F Vogel } 129413705f88SJack F Vogel 129513705f88SJack F Vogel /** 129685d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 129785d0a26eSJack F Vogel * @hw: pointer to hardware structure 129885d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 129985d0a26eSJack F Vogel * @words: number of word(s) 130085d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 130185d0a26eSJack F Vogel * 130285d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 130385d0a26eSJack F Vogel **/ 130485d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 130585d0a26eSJack F Vogel u16 words, u16 *data) 130685d0a26eSJack F Vogel { 130785d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 130885d0a26eSJack F Vogel u16 i, count; 130985d0a26eSJack F Vogel 131085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 131185d0a26eSJack F Vogel 131285d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 131385d0a26eSJack F Vogel 131485d0a26eSJack F Vogel if (words == 0) { 131585d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 131685d0a26eSJack F Vogel goto out; 131785d0a26eSJack F Vogel } 131885d0a26eSJack F Vogel 131985d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 132085d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 132185d0a26eSJack F Vogel goto out; 132285d0a26eSJack F Vogel } 132385d0a26eSJack F Vogel 132485d0a26eSJack F Vogel /* 132585d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 132685d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 132785d0a26eSJack F Vogel */ 132885d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 132985d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 133085d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 133185d0a26eSJack F Vogel 133285d0a26eSJack F Vogel /* 133385d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 133485d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 133585d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 133685d0a26eSJack F Vogel */ 133785d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 133885d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 133985d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 134085d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 134185d0a26eSJack F Vogel count, &data[i]); 134285d0a26eSJack F Vogel 134385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 134485d0a26eSJack F Vogel break; 134585d0a26eSJack F Vogel } 134685d0a26eSJack F Vogel 134785d0a26eSJack F Vogel out: 134885d0a26eSJack F Vogel return status; 134985d0a26eSJack F Vogel } 135085d0a26eSJack F Vogel 135185d0a26eSJack F Vogel /** 135285d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 135313705f88SJack F Vogel * @hw: pointer to hardware structure 135413705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 135585d0a26eSJack F Vogel * @words: number of word(s) 135685d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 135713705f88SJack F Vogel * 135813705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 135913705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 136013705f88SJack F Vogel **/ 136185d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 136285d0a26eSJack F Vogel u16 words, u16 *data) 136313705f88SJack F Vogel { 136413705f88SJack F Vogel s32 status; 136585d0a26eSJack F Vogel u16 word; 136685d0a26eSJack F Vogel u16 page_size; 136785d0a26eSJack F Vogel u16 i; 136813705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 136913705f88SJack F Vogel 137085d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 13719ca4041bSJack F Vogel 137213705f88SJack F Vogel /* Prepare the EEPROM for writing */ 137313705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 137413705f88SJack F Vogel 137513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 137613705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 137713705f88SJack F Vogel ixgbe_release_eeprom(hw); 137813705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 137913705f88SJack F Vogel } 138013705f88SJack F Vogel } 138113705f88SJack F Vogel 138213705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 138385d0a26eSJack F Vogel for (i = 0; i < words; i++) { 138413705f88SJack F Vogel ixgbe_standby_eeprom(hw); 138513705f88SJack F Vogel 138613705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 138785d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 138885d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 138913705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 139013705f88SJack F Vogel 139113705f88SJack F Vogel ixgbe_standby_eeprom(hw); 139213705f88SJack F Vogel 139313705f88SJack F Vogel /* 139485d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 139585d0a26eSJack F Vogel * in the opcode 139613705f88SJack F Vogel */ 139785d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 139885d0a26eSJack F Vogel ((offset + i) >= 128)) 139913705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 140013705f88SJack F Vogel 140113705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 140213705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 140313705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 140485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 140513705f88SJack F Vogel hw->eeprom.address_bits); 140613705f88SJack F Vogel 140785d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 140813705f88SJack F Vogel 140985d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 141085d0a26eSJack F Vogel do { 141185d0a26eSJack F Vogel word = data[i]; 141285d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 141385d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 141485d0a26eSJack F Vogel 141585d0a26eSJack F Vogel if (page_size == 0) 141685d0a26eSJack F Vogel break; 141785d0a26eSJack F Vogel 141885d0a26eSJack F Vogel /* do not wrap around page */ 141985d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 142085d0a26eSJack F Vogel (page_size - 1)) 142185d0a26eSJack F Vogel break; 142285d0a26eSJack F Vogel } while (++i < words); 142385d0a26eSJack F Vogel 142485d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 142585d0a26eSJack F Vogel msec_delay(10); 142685d0a26eSJack F Vogel } 142713705f88SJack F Vogel /* Done with writing - release the EEPROM */ 142813705f88SJack F Vogel ixgbe_release_eeprom(hw); 142913705f88SJack F Vogel } 143013705f88SJack F Vogel 143185d0a26eSJack F Vogel return status; 143285d0a26eSJack F Vogel } 143385d0a26eSJack F Vogel 143485d0a26eSJack F Vogel /** 143585d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 143685d0a26eSJack F Vogel * @hw: pointer to hardware structure 143785d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 143885d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 143985d0a26eSJack F Vogel * 144085d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 144185d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 144285d0a26eSJack F Vogel **/ 144385d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 144485d0a26eSJack F Vogel { 144585d0a26eSJack F Vogel s32 status; 144685d0a26eSJack F Vogel 144785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 144885d0a26eSJack F Vogel 144985d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 145085d0a26eSJack F Vogel 145185d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 145285d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 145385d0a26eSJack F Vogel goto out; 145485d0a26eSJack F Vogel } 145585d0a26eSJack F Vogel 145685d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 145785d0a26eSJack F Vogel 14589ca4041bSJack F Vogel out: 145913705f88SJack F Vogel return status; 146013705f88SJack F Vogel } 146113705f88SJack F Vogel 146213705f88SJack F Vogel /** 146385d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 146485d0a26eSJack F Vogel * @hw: pointer to hardware structure 146585d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 146685d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 146785d0a26eSJack F Vogel * @words: number of word(s) 146885d0a26eSJack F Vogel * 146985d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 147085d0a26eSJack F Vogel **/ 147185d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147285d0a26eSJack F Vogel u16 words, u16 *data) 147385d0a26eSJack F Vogel { 147485d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 147585d0a26eSJack F Vogel u16 i, count; 147685d0a26eSJack F Vogel 147785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 147885d0a26eSJack F Vogel 147985d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 148085d0a26eSJack F Vogel 148185d0a26eSJack F Vogel if (words == 0) { 148285d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 148385d0a26eSJack F Vogel goto out; 148485d0a26eSJack F Vogel } 148585d0a26eSJack F Vogel 148685d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 148785d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 148885d0a26eSJack F Vogel goto out; 148985d0a26eSJack F Vogel } 149085d0a26eSJack F Vogel 149185d0a26eSJack F Vogel /* 149285d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 149385d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 149485d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 149585d0a26eSJack F Vogel */ 149685d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 149785d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 149885d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 149985d0a26eSJack F Vogel 150085d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 150185d0a26eSJack F Vogel count, &data[i]); 150285d0a26eSJack F Vogel 150385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 150485d0a26eSJack F Vogel break; 150585d0a26eSJack F Vogel } 150685d0a26eSJack F Vogel 150785d0a26eSJack F Vogel out: 150885d0a26eSJack F Vogel return status; 150985d0a26eSJack F Vogel } 151085d0a26eSJack F Vogel 151185d0a26eSJack F Vogel /** 151285d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 151385d0a26eSJack F Vogel * @hw: pointer to hardware structure 151485d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 151585d0a26eSJack F Vogel * @words: number of word(s) 151685d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 151785d0a26eSJack F Vogel * 151885d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 151985d0a26eSJack F Vogel **/ 152085d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 152185d0a26eSJack F Vogel u16 words, u16 *data) 152285d0a26eSJack F Vogel { 152385d0a26eSJack F Vogel s32 status; 152485d0a26eSJack F Vogel u16 word_in; 152585d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 152685d0a26eSJack F Vogel u16 i; 152785d0a26eSJack F Vogel 152885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 152985d0a26eSJack F Vogel 153085d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 153185d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 153285d0a26eSJack F Vogel 153385d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 153485d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 153585d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 153685d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 153785d0a26eSJack F Vogel } 153885d0a26eSJack F Vogel } 153985d0a26eSJack F Vogel 154085d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 154185d0a26eSJack F Vogel for (i = 0; i < words; i++) { 154285d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 154385d0a26eSJack F Vogel /* 154485d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 154585d0a26eSJack F Vogel * in the opcode 154685d0a26eSJack F Vogel */ 154785d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 154885d0a26eSJack F Vogel ((offset + i) >= 128)) 154985d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 155085d0a26eSJack F Vogel 155185d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 155285d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 155385d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 155485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 155585d0a26eSJack F Vogel hw->eeprom.address_bits); 155685d0a26eSJack F Vogel 155785d0a26eSJack F Vogel /* Read the data. */ 155885d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 155985d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 156085d0a26eSJack F Vogel } 156185d0a26eSJack F Vogel 156285d0a26eSJack F Vogel /* End this read operation */ 156385d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 156485d0a26eSJack F Vogel } 156585d0a26eSJack F Vogel 156685d0a26eSJack F Vogel return status; 156785d0a26eSJack F Vogel } 156885d0a26eSJack F Vogel 156985d0a26eSJack F Vogel /** 157013705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 157113705f88SJack F Vogel * @hw: pointer to hardware structure 157213705f88SJack F Vogel * @offset: offset within the EEPROM to be read 157313705f88SJack F Vogel * @data: read 16 bit value from EEPROM 157413705f88SJack F Vogel * 157513705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 157613705f88SJack F Vogel **/ 157713705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 157813705f88SJack F Vogel u16 *data) 157913705f88SJack F Vogel { 158013705f88SJack F Vogel s32 status; 158113705f88SJack F Vogel 15822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 15832969bf0eSJack F Vogel 15849ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 15859ca4041bSJack F Vogel 15869ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 15879ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 15889ca4041bSJack F Vogel goto out; 15899ca4041bSJack F Vogel } 15909ca4041bSJack F Vogel 159185d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 159213705f88SJack F Vogel 159385d0a26eSJack F Vogel out: 159485d0a26eSJack F Vogel return status; 159585d0a26eSJack F Vogel } 159685d0a26eSJack F Vogel 159785d0a26eSJack F Vogel /** 159885d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 159985d0a26eSJack F Vogel * @hw: pointer to hardware structure 160085d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 160185d0a26eSJack F Vogel * @words: number of word(s) 160285d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 160385d0a26eSJack F Vogel * 160485d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 160585d0a26eSJack F Vogel **/ 160685d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 160785d0a26eSJack F Vogel u16 words, u16 *data) 160885d0a26eSJack F Vogel { 160985d0a26eSJack F Vogel u32 eerd; 161085d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161185d0a26eSJack F Vogel u32 i; 161285d0a26eSJack F Vogel 161385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 161485d0a26eSJack F Vogel 161585d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 161685d0a26eSJack F Vogel 161785d0a26eSJack F Vogel if (words == 0) { 161885d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1619fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162085d0a26eSJack F Vogel goto out; 162185d0a26eSJack F Vogel } 162285d0a26eSJack F Vogel 162385d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 162413705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1625fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 162685d0a26eSJack F Vogel goto out; 162713705f88SJack F Vogel } 162813705f88SJack F Vogel 162985d0a26eSJack F Vogel for (i = 0; i < words; i++) { 16300ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163185d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163285d0a26eSJack F Vogel 163385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 163485d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 163585d0a26eSJack F Vogel 163613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 163785d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 163885d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 163985d0a26eSJack F Vogel } else { 164085d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 164185d0a26eSJack F Vogel goto out; 164285d0a26eSJack F Vogel } 164385d0a26eSJack F Vogel } 164485d0a26eSJack F Vogel out: 164585d0a26eSJack F Vogel return status; 164685d0a26eSJack F Vogel } 164785d0a26eSJack F Vogel 164885d0a26eSJack F Vogel /** 164985d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 165085d0a26eSJack F Vogel * @hw: pointer to hardware structure 165185d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 165285d0a26eSJack F Vogel * 165385d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 165485d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 165585d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 165685d0a26eSJack F Vogel **/ 165785d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 165885d0a26eSJack F Vogel u16 offset) 165985d0a26eSJack F Vogel { 166085d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 166185d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 166285d0a26eSJack F Vogel u16 i; 166385d0a26eSJack F Vogel 166485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 166585d0a26eSJack F Vogel 166685d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 166785d0a26eSJack F Vogel data[i] = i; 166885d0a26eSJack F Vogel 166985d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 167085d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 167185d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 167285d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 167385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167485d0a26eSJack F Vogel goto out; 167585d0a26eSJack F Vogel 167685d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 167785d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167885d0a26eSJack F Vogel goto out; 167913705f88SJack F Vogel 168013705f88SJack F Vogel /* 168185d0a26eSJack F Vogel * When writing in burst more than the actual page size 168285d0a26eSJack F Vogel * EEPROM address wraps around current page. 168313705f88SJack F Vogel */ 168485d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 168513705f88SJack F Vogel 168685d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 168785d0a26eSJack F Vogel hw->eeprom.word_page_size); 16889ca4041bSJack F Vogel out: 168913705f88SJack F Vogel return status; 169013705f88SJack F Vogel } 169113705f88SJack F Vogel 169213705f88SJack F Vogel /** 16932969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 169413705f88SJack F Vogel * @hw: pointer to hardware structure 169513705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 169613705f88SJack F Vogel * @data: word read from the EEPROM 169713705f88SJack F Vogel * 169813705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 169913705f88SJack F Vogel **/ 17002969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 170113705f88SJack F Vogel { 170285d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 170385d0a26eSJack F Vogel } 170413705f88SJack F Vogel 170585d0a26eSJack F Vogel /** 170685d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 170785d0a26eSJack F Vogel * @hw: pointer to hardware structure 170885d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 170985d0a26eSJack F Vogel * @words: number of word(s) 171085d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 171185d0a26eSJack F Vogel * 171285d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 171385d0a26eSJack F Vogel **/ 171485d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 171585d0a26eSJack F Vogel u16 words, u16 *data) 171685d0a26eSJack F Vogel { 171785d0a26eSJack F Vogel u32 eewr; 171885d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 171985d0a26eSJack F Vogel u16 i; 172085d0a26eSJack F Vogel 172185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 17222969bf0eSJack F Vogel 17239ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 17249ca4041bSJack F Vogel 172585d0a26eSJack F Vogel if (words == 0) { 172685d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1727fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 172885d0a26eSJack F Vogel goto out; 172985d0a26eSJack F Vogel } 173085d0a26eSJack F Vogel 17319ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 17329ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1733fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 17349ca4041bSJack F Vogel goto out; 17359ca4041bSJack F Vogel } 17369ca4041bSJack F Vogel 173785d0a26eSJack F Vogel for (i = 0; i < words; i++) { 173885d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 173985d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 17402969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 174113705f88SJack F Vogel 174285d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 174385d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 174485d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 174585d0a26eSJack F Vogel goto out; 174685d0a26eSJack F Vogel } 174713705f88SJack F Vogel 174885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 174985d0a26eSJack F Vogel 175085d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 175185d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 175285d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 175385d0a26eSJack F Vogel goto out; 175485d0a26eSJack F Vogel } 175585d0a26eSJack F Vogel } 175613705f88SJack F Vogel 17579ca4041bSJack F Vogel out: 175813705f88SJack F Vogel return status; 175913705f88SJack F Vogel } 176013705f88SJack F Vogel 176113705f88SJack F Vogel /** 17621a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 17631a4e3449SJack F Vogel * @hw: pointer to hardware structure 17641a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 17651a4e3449SJack F Vogel * @data: word write to the EEPROM 17661a4e3449SJack F Vogel * 17671a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 17681a4e3449SJack F Vogel **/ 17691a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 17701a4e3449SJack F Vogel { 177185d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 17721a4e3449SJack F Vogel } 17731a4e3449SJack F Vogel 17741a4e3449SJack F Vogel /** 17752969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 177613705f88SJack F Vogel * @hw: pointer to hardware structure 17772969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 177813705f88SJack F Vogel * 17792969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 17802969bf0eSJack F Vogel * read or write is done respectively. 178113705f88SJack F Vogel **/ 17822969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 178313705f88SJack F Vogel { 178413705f88SJack F Vogel u32 i; 178513705f88SJack F Vogel u32 reg; 178613705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 178713705f88SJack F Vogel 17882969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 17892969bf0eSJack F Vogel 17902969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 17912969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 179213705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 17932969bf0eSJack F Vogel else 17942969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 17952969bf0eSJack F Vogel 17962969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 179713705f88SJack F Vogel status = IXGBE_SUCCESS; 179813705f88SJack F Vogel break; 179913705f88SJack F Vogel } 180013705f88SJack F Vogel usec_delay(5); 180113705f88SJack F Vogel } 1802fd75b91dSJack F Vogel 1803fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1804fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1805fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1806fd75b91dSJack F Vogel 180713705f88SJack F Vogel return status; 180813705f88SJack F Vogel } 180913705f88SJack F Vogel 181013705f88SJack F Vogel /** 181113705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 181213705f88SJack F Vogel * @hw: pointer to hardware structure 181313705f88SJack F Vogel * 181413705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 181513705f88SJack F Vogel * be called before issuing a command to the EEPROM. 181613705f88SJack F Vogel **/ 181713705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 181813705f88SJack F Vogel { 181913705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 182013705f88SJack F Vogel u32 eec; 182113705f88SJack F Vogel u32 i; 182213705f88SJack F Vogel 18232969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 18242969bf0eSJack F Vogel 182585d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 182685d0a26eSJack F Vogel != IXGBE_SUCCESS) 182713705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 182813705f88SJack F Vogel 182913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 1830a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183113705f88SJack F Vogel 183213705f88SJack F Vogel /* Request EEPROM Access */ 183313705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 1834a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 183513705f88SJack F Vogel 183613705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 1837a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183813705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 183913705f88SJack F Vogel break; 184013705f88SJack F Vogel usec_delay(5); 184113705f88SJack F Vogel } 184213705f88SJack F Vogel 18439ca4041bSJack F Vogel /* Release if grant not acquired */ 184413705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 184513705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 1846a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 184713705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 184813705f88SJack F Vogel 184985d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 185013705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 185113705f88SJack F Vogel } 185213705f88SJack F Vogel 185313705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 185413705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 185513705f88SJack F Vogel /* Clear CS and SK */ 185613705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 1857a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 185813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 185913705f88SJack F Vogel usec_delay(1); 186013705f88SJack F Vogel } 18611a4e3449SJack F Vogel } 186213705f88SJack F Vogel return status; 186313705f88SJack F Vogel } 186413705f88SJack F Vogel 186513705f88SJack F Vogel /** 186613705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 186713705f88SJack F Vogel * @hw: pointer to hardware structure 186813705f88SJack F Vogel * 186913705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 187013705f88SJack F Vogel **/ 187113705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 187213705f88SJack F Vogel { 187313705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1874d8602bb9SJack F Vogel u32 timeout = 2000; 187513705f88SJack F Vogel u32 i; 187613705f88SJack F Vogel u32 swsm; 187713705f88SJack F Vogel 18782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 18792969bf0eSJack F Vogel 18801a4e3449SJack F Vogel 188113705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 188213705f88SJack F Vogel for (i = 0; i < timeout; i++) { 188313705f88SJack F Vogel /* 188413705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 188513705f88SJack F Vogel * set and we have the semaphore 188613705f88SJack F Vogel */ 1887a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 188813705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 188913705f88SJack F Vogel status = IXGBE_SUCCESS; 189013705f88SJack F Vogel break; 189113705f88SJack F Vogel } 18920ac6dfecSJack F Vogel usec_delay(50); 189313705f88SJack F Vogel } 189413705f88SJack F Vogel 189585d0a26eSJack F Vogel if (i == timeout) { 189685d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 189785d0a26eSJack F Vogel "not granted.\n"); 189885d0a26eSJack F Vogel /* 189985d0a26eSJack F Vogel * this release is particularly important because our attempts 190085d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 190185d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 190285d0a26eSJack F Vogel * bits to free the driver to make progress 190385d0a26eSJack F Vogel */ 190485d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 190585d0a26eSJack F Vogel 190685d0a26eSJack F Vogel usec_delay(50); 190785d0a26eSJack F Vogel /* 190885d0a26eSJack F Vogel * one last try 190985d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 191085d0a26eSJack F Vogel * set and we have the semaphore 191185d0a26eSJack F Vogel */ 1912a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 191385d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 191485d0a26eSJack F Vogel status = IXGBE_SUCCESS; 191585d0a26eSJack F Vogel } 191685d0a26eSJack F Vogel 191713705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 191813705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 191913705f88SJack F Vogel for (i = 0; i < timeout; i++) { 1920a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 192113705f88SJack F Vogel 192213705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 192313705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 1924a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); 192513705f88SJack F Vogel 192613705f88SJack F Vogel /* 192713705f88SJack F Vogel * If we set the bit successfully then we got the 192813705f88SJack F Vogel * semaphore. 192913705f88SJack F Vogel */ 1930a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 193113705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 193213705f88SJack F Vogel break; 193313705f88SJack F Vogel 193413705f88SJack F Vogel usec_delay(50); 193513705f88SJack F Vogel } 193613705f88SJack F Vogel 193713705f88SJack F Vogel /* 193813705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 193913705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 194013705f88SJack F Vogel */ 194113705f88SJack F Vogel if (i >= timeout) { 1942fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1943fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 194413705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 194513705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 194613705f88SJack F Vogel } 19470ac6dfecSJack F Vogel } else { 1948fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1949fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 19500ac6dfecSJack F Vogel "not granted.\n"); 195113705f88SJack F Vogel } 195213705f88SJack F Vogel 195313705f88SJack F Vogel return status; 195413705f88SJack F Vogel } 195513705f88SJack F Vogel 195613705f88SJack F Vogel /** 195713705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 195813705f88SJack F Vogel * @hw: pointer to hardware structure 195913705f88SJack F Vogel * 196013705f88SJack F Vogel * This function clears hardware semaphore bits. 196113705f88SJack F Vogel **/ 196213705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 196313705f88SJack F Vogel { 196413705f88SJack F Vogel u32 swsm; 196513705f88SJack F Vogel 19662969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 19672969bf0eSJack F Vogel 196813705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 196913705f88SJack F Vogel 197013705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 197113705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 197213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 19739ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 197413705f88SJack F Vogel } 197513705f88SJack F Vogel 197613705f88SJack F Vogel /** 197713705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 197813705f88SJack F Vogel * @hw: pointer to hardware structure 197913705f88SJack F Vogel **/ 198013705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 198113705f88SJack F Vogel { 198213705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 198313705f88SJack F Vogel u16 i; 198413705f88SJack F Vogel u8 spi_stat_reg; 198513705f88SJack F Vogel 19862969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 19872969bf0eSJack F Vogel 198813705f88SJack F Vogel /* 198913705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 199013705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 199113705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 199213705f88SJack F Vogel * 5 milliseconds, then error out. 199313705f88SJack F Vogel */ 199413705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 199513705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 199613705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 199713705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 199813705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 199913705f88SJack F Vogel break; 200013705f88SJack F Vogel 200113705f88SJack F Vogel usec_delay(5); 200213705f88SJack F Vogel ixgbe_standby_eeprom(hw); 2003c19c7afeSEric Joyner } 200413705f88SJack F Vogel 200513705f88SJack F Vogel /* 200613705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 200713705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 200813705f88SJack F Vogel */ 200913705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 201013705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 201113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 201213705f88SJack F Vogel } 201313705f88SJack F Vogel 201413705f88SJack F Vogel return status; 201513705f88SJack F Vogel } 201613705f88SJack F Vogel 201713705f88SJack F Vogel /** 201813705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 201913705f88SJack F Vogel * @hw: pointer to hardware structure 202013705f88SJack F Vogel **/ 202113705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 202213705f88SJack F Vogel { 202313705f88SJack F Vogel u32 eec; 202413705f88SJack F Vogel 20252969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 20262969bf0eSJack F Vogel 2027a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 202813705f88SJack F Vogel 202913705f88SJack F Vogel /* Toggle CS to flush commands */ 203013705f88SJack F Vogel eec |= IXGBE_EEC_CS; 2031a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203313705f88SJack F Vogel usec_delay(1); 203413705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 2035a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203613705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203713705f88SJack F Vogel usec_delay(1); 203813705f88SJack F Vogel } 203913705f88SJack F Vogel 204013705f88SJack F Vogel /** 204113705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 204213705f88SJack F Vogel * @hw: pointer to hardware structure 204313705f88SJack F Vogel * @data: data to send to the EEPROM 204413705f88SJack F Vogel * @count: number of bits to shift out 204513705f88SJack F Vogel **/ 204613705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 204713705f88SJack F Vogel u16 count) 204813705f88SJack F Vogel { 204913705f88SJack F Vogel u32 eec; 205013705f88SJack F Vogel u32 mask; 205113705f88SJack F Vogel u32 i; 205213705f88SJack F Vogel 20532969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 20542969bf0eSJack F Vogel 2055a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 205613705f88SJack F Vogel 205713705f88SJack F Vogel /* 205813705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 205913705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 206013705f88SJack F Vogel */ 206113705f88SJack F Vogel mask = 0x01 << (count - 1); 206213705f88SJack F Vogel 206313705f88SJack F Vogel for (i = 0; i < count; i++) { 206413705f88SJack F Vogel /* 206513705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 206613705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 206713705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 206813705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 206913705f88SJack F Vogel * raising and then lowering the clock. 207013705f88SJack F Vogel */ 207113705f88SJack F Vogel if (data & mask) 207213705f88SJack F Vogel eec |= IXGBE_EEC_DI; 207313705f88SJack F Vogel else 207413705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 207513705f88SJack F Vogel 2076a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 207713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 207813705f88SJack F Vogel 207913705f88SJack F Vogel usec_delay(1); 208013705f88SJack F Vogel 208113705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 208213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 208313705f88SJack F Vogel 208413705f88SJack F Vogel /* 208513705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 208613705f88SJack F Vogel * EEPROM 208713705f88SJack F Vogel */ 208813705f88SJack F Vogel mask = mask >> 1; 2089c19c7afeSEric Joyner } 209013705f88SJack F Vogel 209113705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 209213705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 2093a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 209413705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 209513705f88SJack F Vogel } 209613705f88SJack F Vogel 209713705f88SJack F Vogel /** 209813705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 209913705f88SJack F Vogel * @hw: pointer to hardware structure 21007d48aa4cSEric Joyner * @count: number of bits to shift 210113705f88SJack F Vogel **/ 210213705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 210313705f88SJack F Vogel { 210413705f88SJack F Vogel u32 eec; 210513705f88SJack F Vogel u32 i; 210613705f88SJack F Vogel u16 data = 0; 210713705f88SJack F Vogel 21082969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 21092969bf0eSJack F Vogel 211013705f88SJack F Vogel /* 211113705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 211213705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 211313705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 211413705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 211513705f88SJack F Vogel * "DI" bit should always be clear. 211613705f88SJack F Vogel */ 2117a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 211813705f88SJack F Vogel 211913705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 212013705f88SJack F Vogel 212113705f88SJack F Vogel for (i = 0; i < count; i++) { 212213705f88SJack F Vogel data = data << 1; 212313705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 212413705f88SJack F Vogel 2125a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212613705f88SJack F Vogel 212713705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 212813705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 212913705f88SJack F Vogel data |= 1; 213013705f88SJack F Vogel 213113705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 213213705f88SJack F Vogel } 213313705f88SJack F Vogel 213413705f88SJack F Vogel return data; 213513705f88SJack F Vogel } 213613705f88SJack F Vogel 213713705f88SJack F Vogel /** 213813705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 213913705f88SJack F Vogel * @hw: pointer to hardware structure 214013705f88SJack F Vogel * @eec: EEC register's current value 214113705f88SJack F Vogel **/ 214213705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 214313705f88SJack F Vogel { 21442969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 21452969bf0eSJack F Vogel 214613705f88SJack F Vogel /* 214713705f88SJack F Vogel * Raise the clock input to the EEPROM 214813705f88SJack F Vogel * (setting the SK bit), then delay 214913705f88SJack F Vogel */ 215013705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 2151a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 215213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 215313705f88SJack F Vogel usec_delay(1); 215413705f88SJack F Vogel } 215513705f88SJack F Vogel 215613705f88SJack F Vogel /** 215713705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 215813705f88SJack F Vogel * @hw: pointer to hardware structure 21597d48aa4cSEric Joyner * @eec: EEC's current value 216013705f88SJack F Vogel **/ 216113705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 216213705f88SJack F Vogel { 21632969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 21642969bf0eSJack F Vogel 216513705f88SJack F Vogel /* 216613705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 216713705f88SJack F Vogel * delay 216813705f88SJack F Vogel */ 216913705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 2170a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 217113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 217213705f88SJack F Vogel usec_delay(1); 217313705f88SJack F Vogel } 217413705f88SJack F Vogel 217513705f88SJack F Vogel /** 217613705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 217713705f88SJack F Vogel * @hw: pointer to hardware structure 217813705f88SJack F Vogel **/ 217913705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 218013705f88SJack F Vogel { 218113705f88SJack F Vogel u32 eec; 218213705f88SJack F Vogel 21832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 21842969bf0eSJack F Vogel 2185a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 218613705f88SJack F Vogel 218713705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 218813705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 218913705f88SJack F Vogel 2190a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219113705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 219213705f88SJack F Vogel 219313705f88SJack F Vogel usec_delay(1); 219413705f88SJack F Vogel 219513705f88SJack F Vogel /* Stop requesting EEPROM access */ 219613705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 2197a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219813705f88SJack F Vogel 219985d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2200d8602bb9SJack F Vogel 2201d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2202d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 220313705f88SJack F Vogel } 220413705f88SJack F Vogel 220513705f88SJack F Vogel /** 22062969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 220713705f88SJack F Vogel * @hw: pointer to hardware structure 2208758cc3dcSJack F Vogel * 2209758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 221013705f88SJack F Vogel **/ 2211758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 221213705f88SJack F Vogel { 221313705f88SJack F Vogel u16 i; 221413705f88SJack F Vogel u16 j; 221513705f88SJack F Vogel u16 checksum = 0; 221613705f88SJack F Vogel u16 length = 0; 221713705f88SJack F Vogel u16 pointer = 0; 221813705f88SJack F Vogel u16 word = 0; 221913705f88SJack F Vogel 22202969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 22212969bf0eSJack F Vogel 222213705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 222313705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2224758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 222513705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2226758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 222713705f88SJack F Vogel } 222813705f88SJack F Vogel checksum += word; 222913705f88SJack F Vogel } 223013705f88SJack F Vogel 223113705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 223213705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2233758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2234758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2235758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2236758cc3dcSJack F Vogel } 223713705f88SJack F Vogel 2238758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2239758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2240758cc3dcSJack F Vogel continue; 224113705f88SJack F Vogel 2242758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2243758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2244758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2245758cc3dcSJack F Vogel } 2246758cc3dcSJack F Vogel 2247758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2248758cc3dcSJack F Vogel continue; 2249758cc3dcSJack F Vogel 225013705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2251758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2252758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2253758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2254758cc3dcSJack F Vogel } 225513705f88SJack F Vogel checksum += word; 225613705f88SJack F Vogel } 225713705f88SJack F Vogel } 225813705f88SJack F Vogel 225913705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 226013705f88SJack F Vogel 2261758cc3dcSJack F Vogel return (s32)checksum; 226213705f88SJack F Vogel } 226313705f88SJack F Vogel 226413705f88SJack F Vogel /** 226513705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 226613705f88SJack F Vogel * @hw: pointer to hardware structure 226713705f88SJack F Vogel * @checksum_val: calculated checksum 226813705f88SJack F Vogel * 226913705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 227013705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 227113705f88SJack F Vogel **/ 227213705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 227313705f88SJack F Vogel u16 *checksum_val) 227413705f88SJack F Vogel { 227513705f88SJack F Vogel s32 status; 227613705f88SJack F Vogel u16 checksum; 227713705f88SJack F Vogel u16 read_checksum = 0; 227813705f88SJack F Vogel 22792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 22802969bf0eSJack F Vogel 2281758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 228213705f88SJack F Vogel * not continue or we could be in for a very long wait while every 228313705f88SJack F Vogel * EEPROM read fails 228413705f88SJack F Vogel */ 22859ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2286758cc3dcSJack F Vogel if (status) { 2287758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2288758cc3dcSJack F Vogel return status; 2289758cc3dcSJack F Vogel } 229013705f88SJack F Vogel 2291758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2292758cc3dcSJack F Vogel if (status < 0) 2293758cc3dcSJack F Vogel return status; 229413705f88SJack F Vogel 2295758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 229613705f88SJack F Vogel 2297758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2298758cc3dcSJack F Vogel if (status) { 2299758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2300758cc3dcSJack F Vogel return status; 2301758cc3dcSJack F Vogel } 2302758cc3dcSJack F Vogel 2303758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 230413705f88SJack F Vogel * calculated checksum 230513705f88SJack F Vogel */ 23069ca4041bSJack F Vogel if (read_checksum != checksum) 230713705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 230813705f88SJack F Vogel 230913705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 23109ca4041bSJack F Vogel if (checksum_val) 231113705f88SJack F Vogel *checksum_val = checksum; 231213705f88SJack F Vogel 231313705f88SJack F Vogel return status; 231413705f88SJack F Vogel } 231513705f88SJack F Vogel 231613705f88SJack F Vogel /** 23179ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 231813705f88SJack F Vogel * @hw: pointer to hardware structure 231913705f88SJack F Vogel **/ 232013705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 232113705f88SJack F Vogel { 232213705f88SJack F Vogel s32 status; 232313705f88SJack F Vogel u16 checksum; 232413705f88SJack F Vogel 23252969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 23262969bf0eSJack F Vogel 2327758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 232813705f88SJack F Vogel * not continue or we could be in for a very long wait while every 232913705f88SJack F Vogel * EEPROM read fails 233013705f88SJack F Vogel */ 23319ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2332758cc3dcSJack F Vogel if (status) { 233313705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2334758cc3dcSJack F Vogel return status; 233513705f88SJack F Vogel } 233613705f88SJack F Vogel 2337758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2338758cc3dcSJack F Vogel if (status < 0) 2339758cc3dcSJack F Vogel return status; 2340758cc3dcSJack F Vogel 2341758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2342758cc3dcSJack F Vogel 2343758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2344758cc3dcSJack F Vogel 234513705f88SJack F Vogel return status; 234613705f88SJack F Vogel } 234713705f88SJack F Vogel 234813705f88SJack F Vogel /** 234913705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 235013705f88SJack F Vogel * @mac_addr: pointer to MAC address. 235113705f88SJack F Vogel * 23528eb6488eSEric Joyner * Tests a MAC address to ensure it is a valid Individual Address. 235313705f88SJack F Vogel **/ 235413705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 235513705f88SJack F Vogel { 235613705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 235713705f88SJack F Vogel 23582969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 23592969bf0eSJack F Vogel 236013705f88SJack F Vogel /* Make sure it is not a multicast address */ 236113705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 236213705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236313705f88SJack F Vogel /* Not a broadcast address */ 236413705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 236513705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236613705f88SJack F Vogel /* Reject the zero address */ 236713705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 236813705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 236913705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 237013705f88SJack F Vogel } 237113705f88SJack F Vogel return status; 237213705f88SJack F Vogel } 237313705f88SJack F Vogel 237413705f88SJack F Vogel /** 23759ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 237613705f88SJack F Vogel * @hw: pointer to hardware structure 237713705f88SJack F Vogel * @index: Receive address register to write 23789ca4041bSJack F Vogel * @addr: Address to put into receive address register 23799ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 238013705f88SJack F Vogel * @enable_addr: set flag that address is active 238113705f88SJack F Vogel * 238213705f88SJack F Vogel * Puts an ethernet address into a receive address register. 238313705f88SJack F Vogel **/ 23849ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 238513705f88SJack F Vogel u32 enable_addr) 238613705f88SJack F Vogel { 238713705f88SJack F Vogel u32 rar_low, rar_high; 23889ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 238913705f88SJack F Vogel 23902969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 23912969bf0eSJack F Vogel 23921a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 23931a4e3449SJack F Vogel if (index >= rar_entries) { 2394fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2395fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23961a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 23971a4e3449SJack F Vogel } 23981a4e3449SJack F Vogel 23999ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 24009ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 24019ca4041bSJack F Vogel 240213705f88SJack F Vogel /* 24039ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 24049ca4041bSJack F Vogel * order from network order (big endian) to little endian 240513705f88SJack F Vogel */ 240613705f88SJack F Vogel rar_low = ((u32)addr[0] | 240713705f88SJack F Vogel ((u32)addr[1] << 8) | 240813705f88SJack F Vogel ((u32)addr[2] << 16) | 240913705f88SJack F Vogel ((u32)addr[3] << 24)); 24109ca4041bSJack F Vogel /* 24119ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24129ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 24139ca4041bSJack F Vogel * of the address and the address valid bit. 24149ca4041bSJack F Vogel */ 24159ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24169ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24179ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 241813705f88SJack F Vogel 241913705f88SJack F Vogel if (enable_addr != 0) 242013705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 242113705f88SJack F Vogel 242213705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 242313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 242413705f88SJack F Vogel 242513705f88SJack F Vogel return IXGBE_SUCCESS; 242613705f88SJack F Vogel } 242713705f88SJack F Vogel 242813705f88SJack F Vogel /** 24295b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 24305b7f4cedSJack F Vogel * @hw: pointer to hardware structure 24315b7f4cedSJack F Vogel * @index: Receive address register to write 24325b7f4cedSJack F Vogel * 24335b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 24345b7f4cedSJack F Vogel **/ 24355b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 24365b7f4cedSJack F Vogel { 24375b7f4cedSJack F Vogel u32 rar_high; 24385b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24395b7f4cedSJack F Vogel 24402969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 24412969bf0eSJack F Vogel 24425b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 24431a4e3449SJack F Vogel if (index >= rar_entries) { 2444fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2445fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 24461a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24471a4e3449SJack F Vogel } 24481a4e3449SJack F Vogel 24495b7f4cedSJack F Vogel /* 24505b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24515b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 24525b7f4cedSJack F Vogel * of the address and the address valid bit. 24535b7f4cedSJack F Vogel */ 24545b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24555b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24565b7f4cedSJack F Vogel 24575b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 24585b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 24595b7f4cedSJack F Vogel 24605b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 24615b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 24625b7f4cedSJack F Vogel 24635b7f4cedSJack F Vogel return IXGBE_SUCCESS; 24645b7f4cedSJack F Vogel } 24655b7f4cedSJack F Vogel 24665b7f4cedSJack F Vogel /** 246713705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 246813705f88SJack F Vogel * @hw: pointer to hardware structure 246913705f88SJack F Vogel * 247013705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 24719ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 247213705f88SJack F Vogel * the receiver is in reset when the routine is called. 247313705f88SJack F Vogel **/ 247413705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 247513705f88SJack F Vogel { 247613705f88SJack F Vogel u32 i; 24779ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 247813705f88SJack F Vogel 24792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 24802969bf0eSJack F Vogel 248113705f88SJack F Vogel /* 248213705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 248313705f88SJack F Vogel * to the permanent address. 248413705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 248513705f88SJack F Vogel */ 248613705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 248713705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 248813705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 24899ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 249013705f88SJack F Vogel 249113705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 249213705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 249313705f88SJack F Vogel hw->mac.addr[2]); 249413705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 249513705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 249613705f88SJack F Vogel } else { 249713705f88SJack F Vogel /* Setup the receive address. */ 249813705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 249913705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 250013705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 250113705f88SJack F Vogel hw->mac.addr[2]); 250213705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 250313705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 250413705f88SJack F Vogel 25059ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 25068eb6488eSEric Joyner } 2507182b3808SJack F Vogel 2508182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2509182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 25108eb6488eSEric Joyner 25119ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 251213705f88SJack F Vogel 251313705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 251413705f88SJack F Vogel 251513705f88SJack F Vogel /* Zero out the other receive addresses. */ 25169ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 251713705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 251813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 251913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 252013705f88SJack F Vogel } 252113705f88SJack F Vogel 252213705f88SJack F Vogel /* Clear the MTA */ 252313705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 252413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 252513705f88SJack F Vogel 252613705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 25279ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 252813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 252913705f88SJack F Vogel 25305b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 25315b7f4cedSJack F Vogel 253213705f88SJack F Vogel return IXGBE_SUCCESS; 253313705f88SJack F Vogel } 253413705f88SJack F Vogel 253513705f88SJack F Vogel /** 25369ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 25379ca4041bSJack F Vogel * @hw: pointer to hardware structure 25389ca4041bSJack F Vogel * @addr: new address 25397d48aa4cSEric Joyner * @vmdq: VMDq "set" or "pool" index 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 26847d48aa4cSEric Joyner * @mc_addr: Multicast address 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) { 3118f511cd22SGuinan Sun /* TODO: This should be just an informative log */ 3119f511cd22SGuinan Sun ERROR_REPORT1(IXGBE_ERROR_CAUTION, 3120fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3121a621e3c8SJack F Vogel goto out; 3122fd75b91dSJack F Vogel } 3123a621e3c8SJack F Vogel 312479b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 3125fd75b91dSJack F Vogel if (!link_up) { 3126fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3127a621e3c8SJack F Vogel goto out; 3128fd75b91dSJack F Vogel } 3129a621e3c8SJack F Vogel 3130a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3131a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 31320ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3133758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3134a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3135a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3136a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3137a621e3c8SJack F Vogel break; 3138a621e3c8SJack F Vogel 3139a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3140a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3141a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3142a621e3c8SJack F Vogel break; 3143a621e3c8SJack F Vogel 3144a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3145a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3146fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3147a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3148a621e3c8SJack F Vogel break; 3149a621e3c8SJack F Vogel 3150a621e3c8SJack F Vogel default: 3151a621e3c8SJack F Vogel break; 3152a621e3c8SJack F Vogel } 3153a621e3c8SJack F Vogel 3154a621e3c8SJack F Vogel out: 3155a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 315679b36ec9SKevin Bowling hw->fc.fc_was_autonegged = true; 3157a621e3c8SJack F Vogel } else { 315879b36ec9SKevin Bowling hw->fc.fc_was_autonegged = false; 3159a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3160a621e3c8SJack F Vogel } 3161a621e3c8SJack F Vogel } 3162a621e3c8SJack F Vogel 3163fd75b91dSJack F Vogel /* 3164fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3165fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3166fd75b91dSJack F Vogel * 3167fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3168fd75b91dSJack F Vogel * 3169fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3170fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3171fd75b91dSJack F Vogel * 800 = 80 millisec. 3172fd75b91dSJack F Vogel */ 3173fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3174fd75b91dSJack F Vogel { 3175fd75b91dSJack F Vogel s16 devctl2; 3176fd75b91dSJack F Vogel u32 pollcnt; 3177fd75b91dSJack F Vogel 3178fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3179fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3180fd75b91dSJack F Vogel 3181fd75b91dSJack F Vogel switch (devctl2) { 3182fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3183fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3184fd75b91dSJack F Vogel break; 3185fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3186fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3187fd75b91dSJack F Vogel break; 3188fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3189fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3190fd75b91dSJack F Vogel break; 3191fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3192fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3193fd75b91dSJack F Vogel break; 3194fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3195fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3196fd75b91dSJack F Vogel break; 3197fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3198fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3199fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3200fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3201fd75b91dSJack F Vogel default: 3202fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3203fd75b91dSJack F Vogel break; 3204fd75b91dSJack F Vogel } 3205fd75b91dSJack F Vogel 3206fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3207fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3208fd75b91dSJack F Vogel } 3209fd75b91dSJack F Vogel 3210a621e3c8SJack F Vogel /** 32114530d49eSMarcin Jurczak * ixgbe_disable_pcie_primary - Disable PCI-express primary access 321213705f88SJack F Vogel * @hw: pointer to hardware structure 321313705f88SJack F Vogel * 32144530d49eSMarcin Jurczak * Disables PCI-Express primary access and verifies there are no pending 32154530d49eSMarcin Jurczak * requests. IXGBE_ERR_PRIMARY_REQUESTS_PENDING is returned if primary disable 32164530d49eSMarcin Jurczak * bit hasn't caused the primary requests to be disabled, else IXGBE_SUCCESS 32174530d49eSMarcin Jurczak * is returned signifying primary requests disabled. 321813705f88SJack F Vogel **/ 32194530d49eSMarcin Jurczak s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw) 322013705f88SJack F Vogel { 3221c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3222fd75b91dSJack F Vogel u32 i, poll; 3223758cc3dcSJack F Vogel u16 value; 322413705f88SJack F Vogel 32254530d49eSMarcin Jurczak DEBUGFUNC("ixgbe_disable_pcie_primary"); 32262969bf0eSJack F Vogel 322785d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 322885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 322985d0a26eSJack F Vogel 32304530d49eSMarcin Jurczak /* Exit if primary requests are blocked */ 3231758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3232758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3233c0014855SJack F Vogel goto out; 3234c0014855SJack F Vogel 32354530d49eSMarcin Jurczak /* Poll for primary request bit to clear */ 32364530d49eSMarcin Jurczak for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) { 323785d0a26eSJack F Vogel usec_delay(100); 3238c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3239182b3808SJack F Vogel goto out; 324085d0a26eSJack F Vogel } 3241c0014855SJack F Vogel 3242c0014855SJack F Vogel /* 3243c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 32444530d49eSMarcin Jurczak * 5.2.5.3.2 Primary Disable. We set a flag to inform the reset routine 32454530d49eSMarcin Jurczak * of this need. The first reset prevents new primary requests from 324685d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3247c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3248c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3249c0014855SJack F Vogel */ 32504530d49eSMarcin Jurczak DEBUGOUT("GIO Primary Disable bit didn't clear - requesting resets\n"); 3251c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3252c0014855SJack F Vogel 3253a9ca1c79SSean Bruno if (hw->mac.type >= ixgbe_mac_X550) 3254a9ca1c79SSean Bruno goto out; 3255a9ca1c79SSean Bruno 325685d0a26eSJack F Vogel /* 325785d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 325885d0a26eSJack F Vogel * transactions pending. 325985d0a26eSJack F Vogel */ 3260fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3261fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 326285d0a26eSJack F Vogel usec_delay(100); 3263758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3264758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3265758cc3dcSJack F Vogel goto out; 3266758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 326785d0a26eSJack F Vogel goto out; 326885d0a26eSJack F Vogel } 326985d0a26eSJack F Vogel 3270fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3271fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 32724530d49eSMarcin Jurczak status = IXGBE_ERR_PRIMARY_REQUESTS_PENDING; 327385d0a26eSJack F Vogel 3274c0014855SJack F Vogel out: 327513705f88SJack F Vogel return status; 327613705f88SJack F Vogel } 327713705f88SJack F Vogel 327813705f88SJack F Vogel /** 32799ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 328013705f88SJack F Vogel * @hw: pointer to hardware structure 32819ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 328213705f88SJack F Vogel * 328385d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 328413705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 328513705f88SJack F Vogel **/ 3286758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 328713705f88SJack F Vogel { 3288fd75b91dSJack F Vogel u32 gssr = 0; 328913705f88SJack F Vogel u32 swmask = mask; 329013705f88SJack F Vogel u32 fwmask = mask << 5; 3291fd75b91dSJack F Vogel u32 timeout = 200; 3292fd75b91dSJack F Vogel u32 i; 329313705f88SJack F Vogel 32942969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 32952969bf0eSJack F Vogel 3296fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 32970ac6dfecSJack F Vogel /* 3298fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3299fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 33000ac6dfecSJack F Vogel */ 330113705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 33022969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 330313705f88SJack F Vogel 330413705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3305fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 330613705f88SJack F Vogel gssr |= swmask; 330713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 330813705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 330913705f88SJack F Vogel return IXGBE_SUCCESS; 3310fd75b91dSJack F Vogel } else { 3311fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3312fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3313fd75b91dSJack F Vogel msec_delay(5); 3314fd75b91dSJack F Vogel } 3315fd75b91dSJack F Vogel } 3316fd75b91dSJack F Vogel 3317fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3318fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3319fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3320fd75b91dSJack F Vogel 3321fd75b91dSJack F Vogel msec_delay(5); 3322fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 332313705f88SJack F Vogel } 332413705f88SJack F Vogel 332513705f88SJack F Vogel /** 332613705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 332713705f88SJack F Vogel * @hw: pointer to hardware structure 33289ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 332913705f88SJack F Vogel * 333085d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 333113705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 333213705f88SJack F Vogel **/ 3333758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 333413705f88SJack F Vogel { 333513705f88SJack F Vogel u32 gssr; 333613705f88SJack F Vogel u32 swmask = mask; 333713705f88SJack F Vogel 33382969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 33392969bf0eSJack F Vogel 334013705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 334113705f88SJack F Vogel 334213705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 334313705f88SJack F Vogel gssr &= ~swmask; 334413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 334513705f88SJack F Vogel 334613705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 33470ac6dfecSJack F Vogel } 33480ac6dfecSJack F Vogel 33490ac6dfecSJack F Vogel /** 335085d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 335185d0a26eSJack F Vogel * @hw: pointer to hardware structure 335285d0a26eSJack F Vogel * 335385d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 335485d0a26eSJack F Vogel * the Rx security block 335585d0a26eSJack F Vogel **/ 335685d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 335785d0a26eSJack F Vogel { 33585fd1f4beSQiming Yang #define IXGBE_MAX_SECRX_POLL 4000 335985d0a26eSJack F Vogel 336085d0a26eSJack F Vogel int i; 336185d0a26eSJack F Vogel int secrxreg; 336285d0a26eSJack F Vogel 336385d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 336485d0a26eSJack F Vogel 336585d0a26eSJack F Vogel 336685d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 336785d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 336885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 336985d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 337085d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 337185d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 337285d0a26eSJack F Vogel break; 337385d0a26eSJack F Vogel else 337485d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 33755fd1f4beSQiming Yang usec_delay(10); 337685d0a26eSJack F Vogel } 337785d0a26eSJack F Vogel 337885d0a26eSJack F Vogel /* For informational purposes only */ 337985d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 338085d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 338185d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 338285d0a26eSJack F Vogel 338385d0a26eSJack F Vogel return IXGBE_SUCCESS; 338485d0a26eSJack F Vogel } 338585d0a26eSJack F Vogel 338685d0a26eSJack F Vogel /** 3387758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3388758cc3dcSJack F Vogel * @hw: pointer to hardware structure 33897d48aa4cSEric Joyner * @locked: bool to indicate whether the SW/FW lock was taken 3390758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3391758cc3dcSJack F Vogel * 3392758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3393758cc3dcSJack F Vogel */ 3394758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3395758cc3dcSJack F Vogel { 339679b36ec9SKevin Bowling *locked = false; 3397758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3398758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3399758cc3dcSJack F Vogel } 3400758cc3dcSJack F Vogel 3401758cc3dcSJack F Vogel /** 3402758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3403758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3404758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3405758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3406758cc3dcSJack F Vogel * previous read. 3407758cc3dcSJack F Vogel * 3408758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3409758cc3dcSJack F Vogel */ 3410758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3411758cc3dcSJack F Vogel { 3412758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3413758cc3dcSJack F Vogel 3414758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3415758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3416758cc3dcSJack F Vogel } 3417758cc3dcSJack F Vogel 3418758cc3dcSJack F Vogel /** 341985d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 342085d0a26eSJack F Vogel * @hw: pointer to hardware structure 342185d0a26eSJack F Vogel * 342285d0a26eSJack F Vogel * Enables the receive data path. 342385d0a26eSJack F Vogel **/ 342485d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 342585d0a26eSJack F Vogel { 34268eb6488eSEric Joyner u32 secrxreg; 342785d0a26eSJack F Vogel 342885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 342985d0a26eSJack F Vogel 343085d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 343185d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 343285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 343385d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 343485d0a26eSJack F Vogel 343585d0a26eSJack F Vogel return IXGBE_SUCCESS; 343685d0a26eSJack F Vogel } 343785d0a26eSJack F Vogel 343885d0a26eSJack F Vogel /** 34390ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 34400ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34410ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 34420ac6dfecSJack F Vogel * 34430ac6dfecSJack F Vogel * Enables the Rx DMA unit 34440ac6dfecSJack F Vogel **/ 34450ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 34460ac6dfecSJack F Vogel { 34472969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 34482969bf0eSJack F Vogel 3449758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3450758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3451758cc3dcSJack F Vogel else 3452758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 34530ac6dfecSJack F Vogel 34540ac6dfecSJack F Vogel return IXGBE_SUCCESS; 34550ac6dfecSJack F Vogel } 34560ac6dfecSJack F Vogel 34570ac6dfecSJack F Vogel /** 34580ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 34590ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34600ac6dfecSJack F Vogel * @index: led number to blink 34610ac6dfecSJack F Vogel **/ 34620ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 34630ac6dfecSJack F Vogel { 34640ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 34650ac6dfecSJack F Vogel bool link_up = 0; 3466758cc3dcSJack F Vogel u32 autoc_reg = 0; 34670ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34680ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 346979b36ec9SKevin Bowling bool locked = false; 34700ac6dfecSJack F Vogel 34712969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 34722969bf0eSJack F Vogel 34738eb6488eSEric Joyner if (index > 3) 34748eb6488eSEric Joyner return IXGBE_ERR_PARAM; 34758eb6488eSEric Joyner 34760ac6dfecSJack F Vogel /* 34770ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 34780ac6dfecSJack F Vogel * Force it if link is down. 34790ac6dfecSJack F Vogel */ 348079b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 34810ac6dfecSJack F Vogel 34820ac6dfecSJack F Vogel if (!link_up) { 3483758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3484758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 34850ecc2ff0SJack F Vogel goto out; 34860ecc2ff0SJack F Vogel 3487d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34880ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 34890ecc2ff0SJack F Vogel 3490758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3491758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3492758cc3dcSJack F Vogel goto out; 3493758cc3dcSJack F Vogel 3494758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34950ac6dfecSJack F Vogel msec_delay(10); 34960ac6dfecSJack F Vogel } 34970ac6dfecSJack F Vogel 34980ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 34990ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 35000ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35010ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35020ac6dfecSJack F Vogel 35030ecc2ff0SJack F Vogel out: 35040ecc2ff0SJack F Vogel return ret_val; 35050ac6dfecSJack F Vogel } 35060ac6dfecSJack F Vogel 35070ac6dfecSJack F Vogel /** 35080ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 35090ac6dfecSJack F Vogel * @hw: pointer to hardware structure 35100ac6dfecSJack F Vogel * @index: led number to stop blinking 35110ac6dfecSJack F Vogel **/ 35120ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 35130ac6dfecSJack F Vogel { 3514758cc3dcSJack F Vogel u32 autoc_reg = 0; 35150ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 35160ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 351779b36ec9SKevin Bowling bool locked = false; 35180ac6dfecSJack F Vogel 35192969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 35202969bf0eSJack F Vogel 35218eb6488eSEric Joyner if (index > 3) 35228eb6488eSEric Joyner return IXGBE_ERR_PARAM; 35238eb6488eSEric Joyner 3524758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3525758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3526758cc3dcSJack F Vogel goto out; 3527d8602bb9SJack F Vogel 35280ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 35290ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 35300ac6dfecSJack F Vogel 3531758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3532758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3533758cc3dcSJack F Vogel goto out; 35340ecc2ff0SJack F Vogel 35350ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35360ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 35370ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 35380ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35390ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35400ac6dfecSJack F Vogel 35410ecc2ff0SJack F Vogel out: 35420ecc2ff0SJack F Vogel return ret_val; 354313705f88SJack F Vogel } 354413705f88SJack F Vogel 35452969bf0eSJack F Vogel /** 35462969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 35472969bf0eSJack F Vogel * @hw: pointer to hardware structure 35482969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 35492969bf0eSJack F Vogel * 35502969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 35512969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 35522969bf0eSJack F Vogel * get and set mac_addr routines. 35532969bf0eSJack F Vogel **/ 35542969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 35552969bf0eSJack F Vogel u16 *san_mac_offset) 35562969bf0eSJack F Vogel { 3557fd75b91dSJack F Vogel s32 ret_val; 3558fd75b91dSJack F Vogel 35592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 35602969bf0eSJack F Vogel 35612969bf0eSJack F Vogel /* 35622969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35632969bf0eSJack F Vogel * available. 35642969bf0eSJack F Vogel */ 3565fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3566fd75b91dSJack F Vogel san_mac_offset); 3567fd75b91dSJack F Vogel if (ret_val) { 3568fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3569fd75b91dSJack F Vogel "eeprom at offset %d failed", 3570fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3571fd75b91dSJack F Vogel } 35722969bf0eSJack F Vogel 3573fd75b91dSJack F Vogel return ret_val; 35742969bf0eSJack F Vogel } 35752969bf0eSJack F Vogel 35762969bf0eSJack F Vogel /** 35772969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 35782969bf0eSJack F Vogel * @hw: pointer to hardware structure 35792969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35802969bf0eSJack F Vogel * 35812969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 35822969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 35832969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 35842969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 35852969bf0eSJack F Vogel **/ 35862969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35872969bf0eSJack F Vogel { 35882969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35892969bf0eSJack F Vogel u8 i; 3590fd75b91dSJack F Vogel s32 ret_val; 35912969bf0eSJack F Vogel 35922969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 35932969bf0eSJack F Vogel 35942969bf0eSJack F Vogel /* 35952969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35962969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 35972969bf0eSJack F Vogel */ 3598fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3599fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 36002969bf0eSJack F Vogel goto san_mac_addr_out; 36012969bf0eSJack F Vogel 36022969bf0eSJack F Vogel /* make sure we know which port we need to program */ 36032969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36042969bf0eSJack F Vogel /* apply the port offset to the address offset */ 36052969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36062969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36072969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3608fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3609fd75b91dSJack F Vogel &san_mac_data); 3610fd75b91dSJack F Vogel if (ret_val) { 3611fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3612fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3613fd75b91dSJack F Vogel san_mac_offset); 3614fd75b91dSJack F Vogel goto san_mac_addr_out; 3615fd75b91dSJack F Vogel } 36162969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 36172969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 36182969bf0eSJack F Vogel san_mac_offset++; 36192969bf0eSJack F Vogel } 3620fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36212969bf0eSJack F Vogel 36222969bf0eSJack F Vogel san_mac_addr_out: 3623fd75b91dSJack F Vogel /* 3624fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3625fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3626fd75b91dSJack F Vogel */ 3627fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3628fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 36292969bf0eSJack F Vogel return IXGBE_SUCCESS; 36302969bf0eSJack F Vogel } 36312969bf0eSJack F Vogel 36322969bf0eSJack F Vogel /** 36332969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 36342969bf0eSJack F Vogel * @hw: pointer to hardware structure 36352969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 36362969bf0eSJack F Vogel * 36372969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 36382969bf0eSJack F Vogel **/ 36392969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 36402969bf0eSJack F Vogel { 3641fd75b91dSJack F Vogel s32 ret_val; 36422969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 36432969bf0eSJack F Vogel u8 i; 36442969bf0eSJack F Vogel 36452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 36462969bf0eSJack F Vogel 36472969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3648fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3649fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3650fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 36512969bf0eSJack F Vogel 36522969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 36532969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36542969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 36552969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36562969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36572969bf0eSJack F Vogel 36582969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 36592969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 36602969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 36612969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 36622969bf0eSJack F Vogel san_mac_offset++; 36632969bf0eSJack F Vogel } 36642969bf0eSJack F Vogel 3665fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36662969bf0eSJack F Vogel } 36672969bf0eSJack F Vogel 36682969bf0eSJack F Vogel /** 36692969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 36702969bf0eSJack F Vogel * @hw: pointer to hardware structure 36712969bf0eSJack F Vogel * 36722969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 36732969bf0eSJack F Vogel * the capabilities table. 36742969bf0eSJack F Vogel **/ 3675a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 36762969bf0eSJack F Vogel { 3677a621e3c8SJack F Vogel u16 msix_count = 1; 3678a621e3c8SJack F Vogel u16 max_msix_count; 3679a621e3c8SJack F Vogel u16 pcie_offset; 3680a621e3c8SJack F Vogel 3681a621e3c8SJack F Vogel switch (hw->mac.type) { 3682a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3683a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3684a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3685a621e3c8SJack F Vogel break; 3686a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3687a621e3c8SJack F Vogel case ixgbe_mac_X540: 3688758cc3dcSJack F Vogel case ixgbe_mac_X550: 3689758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 36908eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3691a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3692a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3693a621e3c8SJack F Vogel break; 3694a621e3c8SJack F Vogel default: 3695a621e3c8SJack F Vogel return msix_count; 3696a621e3c8SJack F Vogel } 36972969bf0eSJack F Vogel 36982969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3699a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3700758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3701758cc3dcSJack F Vogel msix_count = 0; 37022969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 37032969bf0eSJack F Vogel 3704a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 37052969bf0eSJack F Vogel msix_count++; 3706a621e3c8SJack F Vogel 3707a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3708a621e3c8SJack F Vogel msix_count = max_msix_count; 37092969bf0eSJack F Vogel 37102969bf0eSJack F Vogel return msix_count; 37112969bf0eSJack F Vogel } 37122969bf0eSJack F Vogel 37132969bf0eSJack F Vogel /** 37142969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 37152969bf0eSJack F Vogel * @hw: pointer to hardware structure 37162969bf0eSJack F Vogel * @addr: Address to put into receive address register 37172969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 37182969bf0eSJack F Vogel * 37192969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 3720c19c7afeSEric Joyner * finds the rar that it is already in; adds to the pool list 37212969bf0eSJack F Vogel **/ 37222969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 37232969bf0eSJack F Vogel { 37242969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 37252969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 37262969bf0eSJack F Vogel u32 rar; 37272969bf0eSJack F Vogel u32 rar_low, rar_high; 37282969bf0eSJack F Vogel u32 addr_low, addr_high; 37292969bf0eSJack F Vogel 37302969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 37312969bf0eSJack F Vogel 37322969bf0eSJack F Vogel /* swap bytes for HW little endian */ 37332969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 37342969bf0eSJack F Vogel | (addr[2] << 16) 37352969bf0eSJack F Vogel | (addr[3] << 24); 37362969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 37372969bf0eSJack F Vogel 37382969bf0eSJack F Vogel /* 37392969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 37402969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 37412969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 37422969bf0eSJack F Vogel * rar to the top. 37432969bf0eSJack F Vogel */ 37442969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 37452969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 37462969bf0eSJack F Vogel 37472969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 37482969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 37492969bf0eSJack F Vogel first_empty_rar = rar; 37502969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 37512969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 37522969bf0eSJack F Vogel if (rar_low == addr_low) 37532969bf0eSJack F Vogel break; /* found it already in the rars */ 37542969bf0eSJack F Vogel } 37552969bf0eSJack F Vogel } 37562969bf0eSJack F Vogel 37572969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 37582969bf0eSJack F Vogel /* already there so just add to the pool bits */ 37592969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 37602969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 37612969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 37622969bf0eSJack F Vogel rar = first_empty_rar; 37632969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37642969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 37652969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 37662969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37672969bf0eSJack F Vogel hw->mac.rar_highwater++; 37682969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 37692969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 37702969bf0eSJack F Vogel } 37712969bf0eSJack F Vogel 37722969bf0eSJack F Vogel /* 37732969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 37742969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 37752969bf0eSJack F Vogel */ 37762969bf0eSJack F Vogel if (rar == 0) 37772969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 37782969bf0eSJack F Vogel 37792969bf0eSJack F Vogel return rar; 37802969bf0eSJack F Vogel } 37812969bf0eSJack F Vogel 37822969bf0eSJack F Vogel /** 37832969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 37842969bf0eSJack F Vogel * @hw: pointer to hardware struct 37852969bf0eSJack F Vogel * @rar: receive address register index to disassociate 37862969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 37872969bf0eSJack F Vogel **/ 37882969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37892969bf0eSJack F Vogel { 37902969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 37912969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37922969bf0eSJack F Vogel 37932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 37942969bf0eSJack F Vogel 37951a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37961a4e3449SJack F Vogel if (rar >= rar_entries) { 3797fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3798fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 37991a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38001a4e3449SJack F Vogel } 38011a4e3449SJack F Vogel 38022969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38032969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38042969bf0eSJack F Vogel 3805758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3806758cc3dcSJack F Vogel goto done; 3807758cc3dcSJack F Vogel 38082969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 38092969bf0eSJack F Vogel goto done; 38102969bf0eSJack F Vogel 38112969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 38122969bf0eSJack F Vogel if (mpsar_lo) { 38132969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 38148270b717SGuinan Sun mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38152969bf0eSJack F Vogel } 38162969bf0eSJack F Vogel if (mpsar_hi) { 38172969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 38188270b717SGuinan Sun mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38192969bf0eSJack F Vogel } 38202969bf0eSJack F Vogel } else if (vmdq < 32) { 38212969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 38222969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 38232969bf0eSJack F Vogel } else { 38242969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 38252969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 38262969bf0eSJack F Vogel } 38272969bf0eSJack F Vogel 38282969bf0eSJack F Vogel /* was that the last pool using this rar? */ 38298eb6488eSEric Joyner if (mpsar_lo == 0 && mpsar_hi == 0 && 38308eb6488eSEric Joyner rar != 0 && rar != hw->mac.san_mac_rar_index) 38312969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 38322969bf0eSJack F Vogel done: 38332969bf0eSJack F Vogel return IXGBE_SUCCESS; 38342969bf0eSJack F Vogel } 38352969bf0eSJack F Vogel 38362969bf0eSJack F Vogel /** 38372969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 38382969bf0eSJack F Vogel * @hw: pointer to hardware struct 38392969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 38402969bf0eSJack F Vogel * @vmdq: VMDq pool index 38412969bf0eSJack F Vogel **/ 38422969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 38432969bf0eSJack F Vogel { 38442969bf0eSJack F Vogel u32 mpsar; 38452969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 38462969bf0eSJack F Vogel 38472969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 38482969bf0eSJack F Vogel 38491a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 38501a4e3449SJack F Vogel if (rar >= rar_entries) { 3851fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3852fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38531a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38541a4e3449SJack F Vogel } 38551a4e3449SJack F Vogel 38562969bf0eSJack F Vogel if (vmdq < 32) { 38572969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38582969bf0eSJack F Vogel mpsar |= 1 << vmdq; 38592969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 38602969bf0eSJack F Vogel } else { 38612969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38622969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 38632969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 38642969bf0eSJack F Vogel } 38652969bf0eSJack F Vogel return IXGBE_SUCCESS; 38662969bf0eSJack F Vogel } 38672969bf0eSJack F Vogel 38682969bf0eSJack F Vogel /** 3869edef2769SRadoslaw Tyl * ixgbe_set_vmdq_san_mac_generic - Associate default VMDq pool index with 3870edef2769SRadoslaw Tyl * a rx address 3871edef2769SRadoslaw Tyl * @hw: pointer to hardware struct 3872edef2769SRadoslaw Tyl * @vmdq: VMDq pool index 3873edef2769SRadoslaw Tyl * 3874a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3875a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3876a621e3c8SJack F Vogel * VFs advertized and not 0. 3877a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3878a621e3c8SJack F Vogel **/ 3879a621e3c8SJack F Vogel s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) 3880a621e3c8SJack F Vogel { 3881a621e3c8SJack F Vogel u32 rar = hw->mac.san_mac_rar_index; 3882a621e3c8SJack F Vogel 3883a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_san_mac"); 3884a621e3c8SJack F Vogel 3885a621e3c8SJack F Vogel if (vmdq < 32) { 3886a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); 3887a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 3888a621e3c8SJack F Vogel } else { 3889a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 3890a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); 3891a621e3c8SJack F Vogel } 3892a621e3c8SJack F Vogel 3893a621e3c8SJack F Vogel return IXGBE_SUCCESS; 3894a621e3c8SJack F Vogel } 3895a621e3c8SJack F Vogel 3896a621e3c8SJack F Vogel /** 38972969bf0eSJack F Vogel * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 38982969bf0eSJack F Vogel * @hw: pointer to hardware structure 38992969bf0eSJack F Vogel **/ 39002969bf0eSJack F Vogel s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 39012969bf0eSJack F Vogel { 39022969bf0eSJack F Vogel int i; 39032969bf0eSJack F Vogel 39042969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_uta_tables_generic"); 39052969bf0eSJack F Vogel DEBUGOUT(" Clearing UTA\n"); 39062969bf0eSJack F Vogel 39072969bf0eSJack F Vogel for (i = 0; i < 128; i++) 39082969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 39092969bf0eSJack F Vogel 39102969bf0eSJack F Vogel return IXGBE_SUCCESS; 39112969bf0eSJack F Vogel } 39122969bf0eSJack F Vogel 39132969bf0eSJack F Vogel /** 39142969bf0eSJack F Vogel * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 39152969bf0eSJack F Vogel * @hw: pointer to hardware structure 39162969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 391779b36ec9SKevin Bowling * @vlvf_bypass: true to find vlanid only, false returns first empty slot if 39187d48aa4cSEric Joyner * vlanid not found 39197d48aa4cSEric Joyner * 39202969bf0eSJack F Vogel * 39212969bf0eSJack F Vogel * return the VLVF index where this VLAN id should be placed 39222969bf0eSJack F Vogel * 39232969bf0eSJack F Vogel **/ 39248eb6488eSEric Joyner s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass) 39252969bf0eSJack F Vogel { 39268eb6488eSEric Joyner s32 regindex, first_empty_slot; 39278eb6488eSEric Joyner u32 bits; 39282969bf0eSJack F Vogel 3929c0014855SJack F Vogel /* short cut the special case */ 3930c0014855SJack F Vogel if (vlan == 0) 3931c0014855SJack F Vogel return 0; 3932c0014855SJack F Vogel 39338eb6488eSEric Joyner /* if vlvf_bypass is set we don't want to use an empty slot, we 39348eb6488eSEric Joyner * will simply bypass the VLVF if there are no entries present in the 39358eb6488eSEric Joyner * VLVF that contain our VLAN 39362969bf0eSJack F Vogel */ 39378eb6488eSEric Joyner first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0; 39388eb6488eSEric Joyner 39398eb6488eSEric Joyner /* add VLAN enable bit for comparison */ 39408eb6488eSEric Joyner vlan |= IXGBE_VLVF_VIEN; 39418eb6488eSEric Joyner 39428eb6488eSEric Joyner /* Search for the vlan id in the VLVF entries. Save off the first empty 39438eb6488eSEric Joyner * slot found along the way. 39448eb6488eSEric Joyner * 39458eb6488eSEric Joyner * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1 39468eb6488eSEric Joyner */ 39478eb6488eSEric Joyner for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) { 39482969bf0eSJack F Vogel bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 39498eb6488eSEric Joyner if (bits == vlan) 39502969bf0eSJack F Vogel return regindex; 39518eb6488eSEric Joyner if (!first_empty_slot && !bits) 39528eb6488eSEric Joyner first_empty_slot = regindex; 39538eb6488eSEric Joyner } 39548eb6488eSEric Joyner 39558eb6488eSEric Joyner /* If we are here then we didn't find the VLAN. Return first empty 39568eb6488eSEric Joyner * slot we found during our search, else error. 39578eb6488eSEric Joyner */ 39588eb6488eSEric Joyner if (!first_empty_slot) 39598eb6488eSEric Joyner ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); 39608eb6488eSEric Joyner 39618eb6488eSEric Joyner return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE; 39622969bf0eSJack F Vogel } 39632969bf0eSJack F Vogel 39642969bf0eSJack F Vogel /** 39652969bf0eSJack F Vogel * ixgbe_set_vfta_generic - Set VLAN filter table 39662969bf0eSJack F Vogel * @hw: pointer to hardware structure 39672969bf0eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 39688eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 39698eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN 39708eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 39712969bf0eSJack F Vogel * 39722969bf0eSJack F Vogel * Turn on/off specified VLAN in the VLAN filter table. 39732969bf0eSJack F Vogel **/ 39742969bf0eSJack F Vogel s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 39758eb6488eSEric Joyner bool vlan_on, bool vlvf_bypass) 39762969bf0eSJack F Vogel { 39778eb6488eSEric Joyner u32 regidx, vfta_delta, vfta; 39788eb6488eSEric Joyner s32 ret_val; 39792969bf0eSJack F Vogel 39802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vfta_generic"); 39812969bf0eSJack F Vogel 39828eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 39832969bf0eSJack F Vogel return IXGBE_ERR_PARAM; 39842969bf0eSJack F Vogel 39852969bf0eSJack F Vogel /* 39862969bf0eSJack F Vogel * this is a 2 part operation - first the VFTA, then the 39872969bf0eSJack F Vogel * VLVF and VLVFB if VT Mode is set 3988c0014855SJack F Vogel * We don't write the VFTA until we know the VLVF part succeeded. 39892969bf0eSJack F Vogel */ 39902969bf0eSJack F Vogel 39912969bf0eSJack F Vogel /* Part 1 39922969bf0eSJack F Vogel * The VFTA is a bitstring made up of 128 32-bit registers 39932969bf0eSJack F Vogel * that enable the particular VLAN id, much like the MTA: 39942969bf0eSJack F Vogel * bits[11-5]: which register 39952969bf0eSJack F Vogel * bits[4-0]: which bit in the register 39962969bf0eSJack F Vogel */ 39978eb6488eSEric Joyner regidx = vlan / 32; 39988eb6488eSEric Joyner vfta_delta = 1 << (vlan % 32); 39998eb6488eSEric Joyner vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx)); 40002969bf0eSJack F Vogel 40018eb6488eSEric Joyner /* 40028eb6488eSEric Joyner * vfta_delta represents the difference between the current value 40038eb6488eSEric Joyner * of vfta and the value we want in the register. Since the diff 40048eb6488eSEric Joyner * is an XOR mask we can just update the vfta using an XOR 40058eb6488eSEric Joyner */ 40068eb6488eSEric Joyner vfta_delta &= vlan_on ? ~vfta : vfta; 40078eb6488eSEric Joyner vfta ^= vfta_delta; 40082969bf0eSJack F Vogel 40092969bf0eSJack F Vogel /* Part 2 401085d0a26eSJack F Vogel * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF 401185d0a26eSJack F Vogel */ 40128eb6488eSEric Joyner ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta, 40138eb6488eSEric Joyner vfta, vlvf_bypass); 40148eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS) { 40158eb6488eSEric Joyner if (vlvf_bypass) 40168eb6488eSEric Joyner goto vfta_update; 401785d0a26eSJack F Vogel return ret_val; 40188eb6488eSEric Joyner } 401985d0a26eSJack F Vogel 40208eb6488eSEric Joyner vfta_update: 40218eb6488eSEric Joyner /* Update VFTA now that we are ready for traffic */ 40228eb6488eSEric Joyner if (vfta_delta) 40238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta); 402485d0a26eSJack F Vogel 402585d0a26eSJack F Vogel return IXGBE_SUCCESS; 402685d0a26eSJack F Vogel } 402785d0a26eSJack F Vogel 402885d0a26eSJack F Vogel /** 402985d0a26eSJack F Vogel * ixgbe_set_vlvf_generic - Set VLAN Pool Filter 403085d0a26eSJack F Vogel * @hw: pointer to hardware structure 403185d0a26eSJack F Vogel * @vlan: VLAN id to write to VLAN filter 40328eb6488eSEric Joyner * @vind: VMDq output index that maps queue to VLAN id in VLVFB 40338eb6488eSEric Joyner * @vlan_on: boolean flag to turn on/off VLAN in VLVF 40348eb6488eSEric Joyner * @vfta_delta: pointer to the difference between the current value of VFTA 40358eb6488eSEric Joyner * and the desired value 40368eb6488eSEric Joyner * @vfta: the desired value of the VFTA 40378eb6488eSEric Joyner * @vlvf_bypass: boolean flag indicating updating default pool is okay 403885d0a26eSJack F Vogel * 403985d0a26eSJack F Vogel * Turn on/off specified bit in VLVF table. 404085d0a26eSJack F Vogel **/ 404185d0a26eSJack F Vogel s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, 40428eb6488eSEric Joyner bool vlan_on, u32 *vfta_delta, u32 vfta, 40438eb6488eSEric Joyner bool vlvf_bypass) 404485d0a26eSJack F Vogel { 40458eb6488eSEric Joyner u32 bits; 40468eb6488eSEric Joyner s32 vlvf_index; 404785d0a26eSJack F Vogel 404885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_vlvf_generic"); 404985d0a26eSJack F Vogel 40508eb6488eSEric Joyner if (vlan > 4095 || vind > 63) 405185d0a26eSJack F Vogel return IXGBE_ERR_PARAM; 405285d0a26eSJack F Vogel 405385d0a26eSJack F Vogel /* If VT Mode is set 40542969bf0eSJack F Vogel * Either vlan_on 40552969bf0eSJack F Vogel * make sure the vlan is in VLVF 40562969bf0eSJack F Vogel * set the vind bit in the matching VLVFB 40572969bf0eSJack F Vogel * Or !vlan_on 40582969bf0eSJack F Vogel * clear the pool bit and possibly the vind 40592969bf0eSJack F Vogel */ 40608eb6488eSEric Joyner if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE)) 40618eb6488eSEric Joyner return IXGBE_SUCCESS; 4062c0014855SJack F Vogel 40638eb6488eSEric Joyner vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass); 4064c0014855SJack F Vogel if (vlvf_index < 0) 4065c0014855SJack F Vogel return vlvf_index; 40662969bf0eSJack F Vogel 40678eb6488eSEric Joyner bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32)); 40688eb6488eSEric Joyner 40692969bf0eSJack F Vogel /* set the pool bit */ 40708eb6488eSEric Joyner bits |= 1 << (vind % 32); 40718eb6488eSEric Joyner if (vlan_on) 40728eb6488eSEric Joyner goto vlvf_update; 40738eb6488eSEric Joyner 40742969bf0eSJack F Vogel /* clear the pool bit */ 40758eb6488eSEric Joyner bits ^= 1 << (vind % 32); 40768eb6488eSEric Joyner 40778eb6488eSEric Joyner if (!bits && 40788eb6488eSEric Joyner !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) { 40798eb6488eSEric Joyner /* Clear VFTA first, then disable VLVF. Otherwise 40808eb6488eSEric Joyner * we run the risk of stray packets leaking into 40818eb6488eSEric Joyner * the PF via the default pool 40828eb6488eSEric Joyner */ 40838eb6488eSEric Joyner if (*vfta_delta) 40848eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta); 40858eb6488eSEric Joyner 40868eb6488eSEric Joyner /* disable VLVF and clear remaining bit from pool */ 40878eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); 40888eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0); 40898eb6488eSEric Joyner 40908eb6488eSEric Joyner return IXGBE_SUCCESS; 40912969bf0eSJack F Vogel } 40922969bf0eSJack F Vogel 40938eb6488eSEric Joyner /* If there are still bits set in the VLVFB registers 4094c0014855SJack F Vogel * for the VLAN ID indicated we need to see if the 4095c0014855SJack F Vogel * caller is requesting that we clear the VFTA entry bit. 4096c0014855SJack F Vogel * If the caller has requested that we clear the VFTA 4097c0014855SJack F Vogel * entry bit but there are still pools/VFs using this VLAN 4098c0014855SJack F Vogel * ID entry then ignore the request. We're not worried 4099c0014855SJack F Vogel * about the case where we're turning the VFTA VLAN ID 4100c0014855SJack F Vogel * entry bit on, only when requested to turn it off as 4101c0014855SJack F Vogel * there may be multiple pools and/or VFs using the 4102c0014855SJack F Vogel * VLAN ID entry. In that case we cannot clear the 4103c0014855SJack F Vogel * VFTA bit until all pools/VFs using that VLAN ID have also 4104c0014855SJack F Vogel * been cleared. This will be indicated by "bits" being 4105c0014855SJack F Vogel * zero. 4106c0014855SJack F Vogel */ 41078eb6488eSEric Joyner *vfta_delta = 0; 41088eb6488eSEric Joyner 41098eb6488eSEric Joyner vlvf_update: 41108eb6488eSEric Joyner /* record pool change and enable VLAN ID if not already enabled */ 41118eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits); 41128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan); 4113c0014855SJack F Vogel 41142969bf0eSJack F Vogel return IXGBE_SUCCESS; 41152969bf0eSJack F Vogel } 41162969bf0eSJack F Vogel 41172969bf0eSJack F Vogel /** 41182969bf0eSJack F Vogel * ixgbe_clear_vfta_generic - Clear VLAN filter table 41192969bf0eSJack F Vogel * @hw: pointer to hardware structure 41202969bf0eSJack F Vogel * 4121cd7e11f7SGordon Bergling * Clears the VLAN filter table, and the VMDq index associated with the filter 41222969bf0eSJack F Vogel **/ 41232969bf0eSJack F Vogel s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 41242969bf0eSJack F Vogel { 41252969bf0eSJack F Vogel u32 offset; 41262969bf0eSJack F Vogel 41272969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vfta_generic"); 41282969bf0eSJack F Vogel 41292969bf0eSJack F Vogel for (offset = 0; offset < hw->mac.vft_size; offset++) 41302969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 41312969bf0eSJack F Vogel 41322969bf0eSJack F Vogel for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 41332969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 41342969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); 41353f66b96dSKevin Bowling IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2 + 1), 0); 41362969bf0eSJack F Vogel } 41372969bf0eSJack F Vogel 41382969bf0eSJack F Vogel return IXGBE_SUCCESS; 41392969bf0eSJack F Vogel } 41402969bf0eSJack F Vogel 41412969bf0eSJack F Vogel /** 41428eb6488eSEric Joyner * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix 41438eb6488eSEric Joyner * @hw: pointer to hardware structure 41448eb6488eSEric Joyner * 41458eb6488eSEric Joyner * Contains the logic to identify if we need to verify link for the 41468eb6488eSEric Joyner * crosstalk fix 41478eb6488eSEric Joyner **/ 41488eb6488eSEric Joyner static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw) 41498eb6488eSEric Joyner { 41508eb6488eSEric Joyner 41518eb6488eSEric Joyner /* Does FW say we need the fix */ 41528eb6488eSEric Joyner if (!hw->need_crosstalk_fix) 415379b36ec9SKevin Bowling return false; 41548eb6488eSEric Joyner 41558eb6488eSEric Joyner /* Only consider SFP+ PHYs i.e. media type fiber */ 41568eb6488eSEric Joyner switch (hw->mac.ops.get_media_type(hw)) { 41578eb6488eSEric Joyner case ixgbe_media_type_fiber: 41588eb6488eSEric Joyner case ixgbe_media_type_fiber_qsfp: 41598eb6488eSEric Joyner break; 41608eb6488eSEric Joyner default: 416179b36ec9SKevin Bowling return false; 41628eb6488eSEric Joyner } 41638eb6488eSEric Joyner 416479b36ec9SKevin Bowling return true; 41658eb6488eSEric Joyner } 41668eb6488eSEric Joyner 41678eb6488eSEric Joyner /** 41682969bf0eSJack F Vogel * ixgbe_check_mac_link_generic - Determine link and speed status 41692969bf0eSJack F Vogel * @hw: pointer to hardware structure 41702969bf0eSJack F Vogel * @speed: pointer to link speed 417179b36ec9SKevin Bowling * @link_up: true when link is up 41722969bf0eSJack F Vogel * @link_up_wait_to_complete: bool used to wait for link up or not 41732969bf0eSJack F Vogel * 41742969bf0eSJack F Vogel * Reads the links register to determine if link is up and the current speed 41752969bf0eSJack F Vogel **/ 41762969bf0eSJack F Vogel s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 41772969bf0eSJack F Vogel bool *link_up, bool link_up_wait_to_complete) 41782969bf0eSJack F Vogel { 4179c0014855SJack F Vogel u32 links_reg, links_orig; 41802969bf0eSJack F Vogel u32 i; 41812969bf0eSJack F Vogel 41822969bf0eSJack F Vogel DEBUGFUNC("ixgbe_check_mac_link_generic"); 41832969bf0eSJack F Vogel 41848eb6488eSEric Joyner /* If Crosstalk fix enabled do the sanity check of making sure 41858eb6488eSEric Joyner * the SFP+ cage is full. 41868eb6488eSEric Joyner */ 41878eb6488eSEric Joyner if (ixgbe_need_crosstalk_fix(hw)) { 41888eb6488eSEric Joyner u32 sfp_cage_full; 41898eb6488eSEric Joyner 41908eb6488eSEric Joyner switch (hw->mac.type) { 41918eb6488eSEric Joyner case ixgbe_mac_82599EB: 41928eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 41938eb6488eSEric Joyner IXGBE_ESDP_SDP2; 41948eb6488eSEric Joyner break; 41958eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 41968eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 41978eb6488eSEric Joyner sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) & 41988eb6488eSEric Joyner IXGBE_ESDP_SDP0; 41998eb6488eSEric Joyner break; 42008eb6488eSEric Joyner default: 42018eb6488eSEric Joyner /* sanity check - No SFP+ devices here */ 420279b36ec9SKevin Bowling sfp_cage_full = false; 42038eb6488eSEric Joyner break; 42048eb6488eSEric Joyner } 42058eb6488eSEric Joyner 42068eb6488eSEric Joyner if (!sfp_cage_full) { 420779b36ec9SKevin Bowling *link_up = false; 42088eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42098eb6488eSEric Joyner return IXGBE_SUCCESS; 42108eb6488eSEric Joyner } 42118eb6488eSEric Joyner } 42128eb6488eSEric Joyner 4213c0014855SJack F Vogel /* clear the old state */ 4214c0014855SJack F Vogel links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); 4215c0014855SJack F Vogel 42162969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 4217c0014855SJack F Vogel 4218c0014855SJack F Vogel if (links_orig != links_reg) { 4219c0014855SJack F Vogel DEBUGOUT2("LINKS changed from %08X to %08X\n", 4220c0014855SJack F Vogel links_orig, links_reg); 4221c0014855SJack F Vogel } 4222c0014855SJack F Vogel 42232969bf0eSJack F Vogel if (link_up_wait_to_complete) { 4224a9ca1c79SSean Bruno for (i = 0; i < hw->mac.max_link_up_time; i++) { 42252969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) { 422679b36ec9SKevin Bowling *link_up = true; 42272969bf0eSJack F Vogel break; 42282969bf0eSJack F Vogel } else { 422979b36ec9SKevin Bowling *link_up = false; 42302969bf0eSJack F Vogel } 42312969bf0eSJack F Vogel msec_delay(100); 42322969bf0eSJack F Vogel links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 42332969bf0eSJack F Vogel } 42342969bf0eSJack F Vogel } else { 423504a5e6d7SKrzysztof Galazka if (links_reg & IXGBE_LINKS_UP) { 423604a5e6d7SKrzysztof Galazka if (ixgbe_need_crosstalk_fix(hw)) { 423704a5e6d7SKrzysztof Galazka /* Check the link state again after a delay 423804a5e6d7SKrzysztof Galazka * to filter out spurious link up 423904a5e6d7SKrzysztof Galazka * notifications. 424004a5e6d7SKrzysztof Galazka */ 424104a5e6d7SKrzysztof Galazka msec_delay(5); 424204a5e6d7SKrzysztof Galazka links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 424304a5e6d7SKrzysztof Galazka if (!(links_reg & IXGBE_LINKS_UP)) { 424479b36ec9SKevin Bowling *link_up = false; 424504a5e6d7SKrzysztof Galazka *speed = IXGBE_LINK_SPEED_UNKNOWN; 424604a5e6d7SKrzysztof Galazka return IXGBE_SUCCESS; 424704a5e6d7SKrzysztof Galazka } 424804a5e6d7SKrzysztof Galazka 424904a5e6d7SKrzysztof Galazka } 425004a5e6d7SKrzysztof Galazka *link_up = true; 425104a5e6d7SKrzysztof Galazka } else { 425204a5e6d7SKrzysztof Galazka *link_up = false; 425304a5e6d7SKrzysztof Galazka } 42542969bf0eSJack F Vogel } 42552969bf0eSJack F Vogel 4256758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4257758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 42582969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4259758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4260758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4261758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4262758cc3dcSJack F Vogel } 4263758cc3dcSJack F Vogel break; 4264758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 42652969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4266758cc3dcSJack F Vogel break; 4267758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 42682969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 42698eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550) { 4270758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4271758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4272758cc3dcSJack F Vogel } 4273758cc3dcSJack F Vogel break; 42748eb6488eSEric Joyner case IXGBE_LINKS_SPEED_10_X550EM_A: 42758eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42768eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 42777d48aa4cSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) 42788eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_10_FULL; 42798eb6488eSEric Joyner break; 4280758cc3dcSJack F Vogel default: 42811a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4282758cc3dcSJack F Vogel } 42832969bf0eSJack F Vogel 42842969bf0eSJack F Vogel return IXGBE_SUCCESS; 42852969bf0eSJack F Vogel } 42862969bf0eSJack F Vogel 42872969bf0eSJack F Vogel /** 42882969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 42892969bf0eSJack F Vogel * the EEPROM 42902969bf0eSJack F Vogel * @hw: pointer to hardware structure 42912969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 42922969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 42932969bf0eSJack F Vogel * 42942969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 42952969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 42962969bf0eSJack F Vogel **/ 42972969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 42982969bf0eSJack F Vogel u16 *wwpn_prefix) 42992969bf0eSJack F Vogel { 43002969bf0eSJack F Vogel u16 offset, caps; 43012969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 43022969bf0eSJack F Vogel 43032969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 43042969bf0eSJack F Vogel 43052969bf0eSJack F Vogel /* clear output first */ 43062969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 43072969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 43082969bf0eSJack F Vogel 43092969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4310fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4311fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4312fd75b91dSJack F Vogel goto wwn_prefix_err; 43132969bf0eSJack F Vogel 43142969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 43152969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 43162969bf0eSJack F Vogel goto wwn_prefix_out; 43172969bf0eSJack F Vogel 43182969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 43192969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4320fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4321fd75b91dSJack F Vogel goto wwn_prefix_err; 43222969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 43232969bf0eSJack F Vogel goto wwn_prefix_out; 43242969bf0eSJack F Vogel 43252969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 43262969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4327fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4328fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4329fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4330fd75b91dSJack F Vogel } 43312969bf0eSJack F Vogel 43322969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4333fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4334fd75b91dSJack F Vogel goto wwn_prefix_err; 43352969bf0eSJack F Vogel 43362969bf0eSJack F Vogel wwn_prefix_out: 43372969bf0eSJack F Vogel return IXGBE_SUCCESS; 4338fd75b91dSJack F Vogel 4339fd75b91dSJack F Vogel wwn_prefix_err: 4340fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4341fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4342fd75b91dSJack F Vogel return IXGBE_SUCCESS; 43432969bf0eSJack F Vogel } 43441a4e3449SJack F Vogel 43451a4e3449SJack F Vogel /** 43461a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 43471a4e3449SJack F Vogel * @hw: pointer to hardware structure 43481a4e3449SJack F Vogel * @bs: the fcoe boot status 43491a4e3449SJack F Vogel * 43501a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 43511a4e3449SJack F Vogel **/ 43521a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 43531a4e3449SJack F Vogel { 43541a4e3449SJack F Vogel u16 offset, caps, flags; 43551a4e3449SJack F Vogel s32 status; 43561a4e3449SJack F Vogel 43571a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 43581a4e3449SJack F Vogel 43591a4e3449SJack F Vogel /* clear output first */ 43601a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 43611a4e3449SJack F Vogel 43621a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 43631a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 43641a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 43651a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43661a4e3449SJack F Vogel goto out; 43671a4e3449SJack F Vogel 43681a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 43691a4e3449SJack F Vogel goto out; 43701a4e3449SJack F Vogel 43711a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 43721a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 43731a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43741a4e3449SJack F Vogel goto out; 43751a4e3449SJack F Vogel 43761a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 43771a4e3449SJack F Vogel goto out; 43781a4e3449SJack F Vogel 43791a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 43801a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 43811a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 43821a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43831a4e3449SJack F Vogel goto out; 43841a4e3449SJack F Vogel 43851a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 43861a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 43871a4e3449SJack F Vogel else 43881a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 43891a4e3449SJack F Vogel 43901a4e3449SJack F Vogel out: 43911a4e3449SJack F Vogel return status; 43921a4e3449SJack F Vogel } 43931a4e3449SJack F Vogel 43941a4e3449SJack F Vogel /** 43951a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 43961a4e3449SJack F Vogel * @hw: pointer to hardware structure 43978eb6488eSEric Joyner * @enable: enable or disable switch for MAC anti-spoofing 43988eb6488eSEric Joyner * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 43991a4e3449SJack F Vogel * 44001a4e3449SJack F Vogel **/ 44018eb6488eSEric Joyner void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44021a4e3449SJack F Vogel { 44038eb6488eSEric Joyner int vf_target_reg = vf >> 3; 44048eb6488eSEric Joyner int vf_target_shift = vf % 8; 44058eb6488eSEric Joyner u32 pfvfspoof; 44061a4e3449SJack F Vogel 44071a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44081a4e3449SJack F Vogel return; 44091a4e3449SJack F Vogel 44108eb6488eSEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44111a4e3449SJack F Vogel if (enable) 44128eb6488eSEric Joyner pfvfspoof |= (1 << vf_target_shift); 44138eb6488eSEric Joyner else 44148eb6488eSEric Joyner pfvfspoof &= ~(1 << vf_target_shift); 44158eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44161a4e3449SJack F Vogel } 44171a4e3449SJack F Vogel 44181a4e3449SJack F Vogel /** 44191a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 44201a4e3449SJack F Vogel * @hw: pointer to hardware structure 44211a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4422758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 44231a4e3449SJack F Vogel * 44241a4e3449SJack F Vogel **/ 44251a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44261a4e3449SJack F Vogel { 44271a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 44281a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 44291a4e3449SJack F Vogel u32 pfvfspoof; 44301a4e3449SJack F Vogel 44311a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44321a4e3449SJack F Vogel return; 44331a4e3449SJack F Vogel 44341a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44351a4e3449SJack F Vogel if (enable) 44361a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 44371a4e3449SJack F Vogel else 44381a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 44391a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44401a4e3449SJack F Vogel } 4441182b3808SJack F Vogel 4442182b3808SJack F Vogel /** 4443182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4444182b3808SJack F Vogel * @hw: pointer to hardware structure 4445182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4446182b3808SJack F Vogel * 4447182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4448182b3808SJack F Vogel * and return the word through device_caps. 4449182b3808SJack F Vogel **/ 4450182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4451182b3808SJack F Vogel { 4452182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4453182b3808SJack F Vogel 4454182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4455182b3808SJack F Vogel 4456182b3808SJack F Vogel return IXGBE_SUCCESS; 4457182b3808SJack F Vogel } 4458182b3808SJack F Vogel 4459182b3808SJack F Vogel /** 4460182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4461182b3808SJack F Vogel * @hw: pointer to hardware structure 4462182b3808SJack F Vogel * 4463182b3808SJack F Vogel **/ 4464182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4465182b3808SJack F Vogel { 4466182b3808SJack F Vogel u32 regval; 4467182b3808SJack F Vogel u32 i; 4468182b3808SJack F Vogel 4469182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4470182b3808SJack F Vogel 4471182b3808SJack F Vogel /* Enable relaxed ordering */ 4472182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4473182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4474a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4475182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4476182b3808SJack F Vogel } 4477182b3808SJack F Vogel 4478182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4479182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4480a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4481a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4482182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4483182b3808SJack F Vogel } 4484182b3808SJack F Vogel 4485182b3808SJack F Vogel } 448685d0a26eSJack F Vogel 448785d0a26eSJack F Vogel /** 448885d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 448985d0a26eSJack F Vogel * @buffer: pointer to EEPROM 449085d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 449185d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 449285d0a26eSJack F Vogel * checksum calculated is returned. 449385d0a26eSJack F Vogel **/ 44940ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 449585d0a26eSJack F Vogel { 449685d0a26eSJack F Vogel u32 i; 449785d0a26eSJack F Vogel u8 sum = 0; 449885d0a26eSJack F Vogel 449985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 450085d0a26eSJack F Vogel 450185d0a26eSJack F Vogel if (!buffer) 450285d0a26eSJack F Vogel return 0; 450385d0a26eSJack F Vogel 450485d0a26eSJack F Vogel for (i = 0; i < length; i++) 450585d0a26eSJack F Vogel sum += buffer[i]; 450685d0a26eSJack F Vogel 450785d0a26eSJack F Vogel return (u8) (0 - sum); 450885d0a26eSJack F Vogel } 450985d0a26eSJack F Vogel 451085d0a26eSJack F Vogel /** 45118eb6488eSEric Joyner * ixgbe_hic_unlocked - Issue command to manageability block unlocked 451285d0a26eSJack F Vogel * @hw: pointer to the HW structure 45138eb6488eSEric Joyner * @buffer: command to write and where the return status will be placed 4514a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4515758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 451685d0a26eSJack F Vogel * 451785d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 45188eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45198eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45208eb6488eSEric Joyner * 45218eb6488eSEric Joyner * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 45228eb6488eSEric Joyner * by the caller. 452385d0a26eSJack F Vogel **/ 45248eb6488eSEric Joyner s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 45258eb6488eSEric Joyner u32 timeout) 452685d0a26eSJack F Vogel { 45278eb6488eSEric Joyner u32 hicr, i, fwsts; 4528758cc3dcSJack F Vogel u16 dword_len; 452985d0a26eSJack F Vogel 45308eb6488eSEric Joyner DEBUGFUNC("ixgbe_hic_unlocked"); 453185d0a26eSJack F Vogel 45328eb6488eSEric Joyner if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4533758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4534758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 453585d0a26eSJack F Vogel } 45368eb6488eSEric Joyner 4537758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4538758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4539758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 454085d0a26eSJack F Vogel 454185d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 454285d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 45438eb6488eSEric Joyner if (!(hicr & IXGBE_HICR_EN)) { 454485d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4545758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 454685d0a26eSJack F Vogel } 454785d0a26eSJack F Vogel 4548758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 45498eb6488eSEric Joyner if (length % sizeof(u32)) { 4550758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4551758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4552758cc3dcSJack F Vogel } 4553758cc3dcSJack F Vogel 455485d0a26eSJack F Vogel dword_len = length >> 2; 455585d0a26eSJack F Vogel 4556758cc3dcSJack F Vogel /* The device driver writes the relevant command block 455785d0a26eSJack F Vogel * into the ram area. 455885d0a26eSJack F Vogel */ 455985d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 456085d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 456185d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 456285d0a26eSJack F Vogel 456385d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 456485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 456585d0a26eSJack F Vogel 4566758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 456785d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 456885d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 456985d0a26eSJack F Vogel break; 457085d0a26eSJack F Vogel msec_delay(1); 457185d0a26eSJack F Vogel } 457285d0a26eSJack F Vogel 4573c966c431SGuinan Sun /* For each command except "Apply Update" perform 4574c966c431SGuinan Sun * status checks in the HICR registry. 4575c966c431SGuinan Sun */ 4576c966c431SGuinan Sun if ((buffer[0] & IXGBE_HOST_INTERFACE_MASK_CMD) == 4577c966c431SGuinan Sun IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD) 4578c966c431SGuinan Sun return IXGBE_SUCCESS; 4579c966c431SGuinan Sun 4580758cc3dcSJack F Vogel /* Check command completion */ 45818eb6488eSEric Joyner if ((timeout && i == timeout) || 4582758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4583758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4584758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4585758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 458685d0a26eSJack F Vogel } 458785d0a26eSJack F Vogel 45888eb6488eSEric Joyner return IXGBE_SUCCESS; 45898eb6488eSEric Joyner } 45908eb6488eSEric Joyner 45918eb6488eSEric Joyner /** 45928eb6488eSEric Joyner * ixgbe_host_interface_command - Issue command to manageability block 45938eb6488eSEric Joyner * @hw: pointer to the HW structure 45948eb6488eSEric Joyner * @buffer: contains the command to write and where the return status will 45958eb6488eSEric Joyner * be placed 45968eb6488eSEric Joyner * @length: length of buffer, must be multiple of 4 bytes 45978eb6488eSEric Joyner * @timeout: time in ms to wait for command completion 459879b36ec9SKevin Bowling * @return_data: read and return data from the buffer (true) or not (false) 45998eb6488eSEric Joyner * Needed because FW structures are big endian and decoding of 46008eb6488eSEric Joyner * these fields can be 8 bit or 16 bit based on command. Decoding 46018eb6488eSEric Joyner * is not easily understood without making a table of commands. 46028eb6488eSEric Joyner * So we will leave this up to the caller to read back the data 46038eb6488eSEric Joyner * in these cases. 46048eb6488eSEric Joyner * 46058eb6488eSEric Joyner * Communicates with the manageability block. On success return IXGBE_SUCCESS 46068eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 46078eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 46088eb6488eSEric Joyner **/ 46098eb6488eSEric Joyner s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 46108eb6488eSEric Joyner u32 length, u32 timeout, bool return_data) 46118eb6488eSEric Joyner { 46128eb6488eSEric Joyner u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 46137d48aa4cSEric Joyner struct ixgbe_hic_hdr *resp = (struct ixgbe_hic_hdr *)buffer; 46148eb6488eSEric Joyner u16 buf_len; 46158eb6488eSEric Joyner s32 status; 46168eb6488eSEric Joyner u32 bi; 46177d48aa4cSEric Joyner u32 dword_len; 46188eb6488eSEric Joyner 46198eb6488eSEric Joyner DEBUGFUNC("ixgbe_host_interface_command"); 46208eb6488eSEric Joyner 46218eb6488eSEric Joyner if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 46228eb6488eSEric Joyner DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 46238eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND; 46248eb6488eSEric Joyner } 46258eb6488eSEric Joyner 46268eb6488eSEric Joyner /* Take management host interface semaphore */ 46278eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46288eb6488eSEric Joyner if (status) 46298eb6488eSEric Joyner return status; 46308eb6488eSEric Joyner 46318eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 46328eb6488eSEric Joyner if (status) 46338eb6488eSEric Joyner goto rel_out; 46348eb6488eSEric Joyner 4635758cc3dcSJack F Vogel if (!return_data) 46368eb6488eSEric Joyner goto rel_out; 4637758cc3dcSJack F Vogel 463885d0a26eSJack F Vogel /* Calculate length in DWORDs */ 463985d0a26eSJack F Vogel dword_len = hdr_size >> 2; 464085d0a26eSJack F Vogel 464185d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 464285d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 464385d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 4644bef7d491SKevin Bowling IXGBE_LE32_TO_CPUS(&buffer[bi]); 464585d0a26eSJack F Vogel } 464685d0a26eSJack F Vogel 46477d48aa4cSEric Joyner /* 46487d48aa4cSEric Joyner * If there is any thing in data position pull it in 46497d48aa4cSEric Joyner * Read Flash command requires reading buffer length from 46507d48aa4cSEric Joyner * two byes instead of one byte 46517d48aa4cSEric Joyner */ 465231a23e3eSGuinan Sun if (resp->cmd == IXGBE_HOST_INTERFACE_FLASH_READ_CMD || 465331a23e3eSGuinan Sun resp->cmd == IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD) { 46547d48aa4cSEric Joyner for (; bi < dword_len + 2; bi++) { 46557d48aa4cSEric Joyner buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 46567d48aa4cSEric Joyner bi); 46577d48aa4cSEric Joyner IXGBE_LE32_TO_CPUS(&buffer[bi]); 46587d48aa4cSEric Joyner } 46597d48aa4cSEric Joyner buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 46607d48aa4cSEric Joyner & 0xF00) | resp->buf_len; 46617d48aa4cSEric Joyner hdr_size += (2 << 2); 46627d48aa4cSEric Joyner } else { 46637d48aa4cSEric Joyner buf_len = resp->buf_len; 46647d48aa4cSEric Joyner } 46658eb6488eSEric Joyner if (!buf_len) 46668eb6488eSEric Joyner goto rel_out; 466785d0a26eSJack F Vogel 4668758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 466985d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 46708eb6488eSEric Joyner status = IXGBE_ERR_HOST_INTERFACE_COMMAND; 46718eb6488eSEric Joyner goto rel_out; 467285d0a26eSJack F Vogel } 467385d0a26eSJack F Vogel 467485d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 467585d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 467685d0a26eSJack F Vogel 467785d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 467885d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 467985d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 4680bef7d491SKevin Bowling IXGBE_LE32_TO_CPUS(&buffer[bi]); 468185d0a26eSJack F Vogel } 468285d0a26eSJack F Vogel 46838eb6488eSEric Joyner rel_out: 46848eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46858eb6488eSEric Joyner 46868eb6488eSEric Joyner return status; 468785d0a26eSJack F Vogel } 468885d0a26eSJack F Vogel 468985d0a26eSJack F Vogel /** 469085d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 469185d0a26eSJack F Vogel * @hw: pointer to the HW structure 469285d0a26eSJack F Vogel * @maj: driver version major number 469385d0a26eSJack F Vogel * @min: driver version minor number 469485d0a26eSJack F Vogel * @build: driver version build number 469585d0a26eSJack F Vogel * @sub: driver version sub build number 46967d48aa4cSEric Joyner * @len: unused 46977d48aa4cSEric Joyner * @driver_ver: unused 469885d0a26eSJack F Vogel * 469985d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 470085d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 470185d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 470285d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 470385d0a26eSJack F Vogel **/ 470485d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 47058eb6488eSEric Joyner u8 build, u8 sub, u16 len, 47068eb6488eSEric Joyner const char *driver_ver) 470785d0a26eSJack F Vogel { 470885d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 470985d0a26eSJack F Vogel int i; 471085d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 471185d0a26eSJack F Vogel 471285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 47138eb6488eSEric Joyner UNREFERENCED_2PARAMETER(len, driver_ver); 471485d0a26eSJack F Vogel 471585d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 471685d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 471785d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 471885d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 471985d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 472085d0a26eSJack F Vogel fw_cmd.ver_min = min; 472185d0a26eSJack F Vogel fw_cmd.ver_build = build; 472285d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 472385d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 472485d0a26eSJack F Vogel fw_cmd.pad = 0; 472585d0a26eSJack F Vogel fw_cmd.pad2 = 0; 47267d48aa4cSEric Joyner fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 47277d48aa4cSEric Joyner (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 472885d0a26eSJack F Vogel 472985d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 473085d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4731758cc3dcSJack F Vogel sizeof(fw_cmd), 4732758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 473379b36ec9SKevin Bowling true); 473485d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 473585d0a26eSJack F Vogel continue; 473685d0a26eSJack F Vogel 473785d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 473885d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 473985d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 474085d0a26eSJack F Vogel else 474185d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 474285d0a26eSJack F Vogel 474385d0a26eSJack F Vogel break; 474485d0a26eSJack F Vogel } 474585d0a26eSJack F Vogel 474685d0a26eSJack F Vogel return ret_val; 474785d0a26eSJack F Vogel } 474885d0a26eSJack F Vogel 474985d0a26eSJack F Vogel /** 475085d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 475185d0a26eSJack F Vogel * @hw: pointer to hardware structure 475285d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 475385d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 475485d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 475585d0a26eSJack F Vogel **/ 475685d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 475785d0a26eSJack F Vogel int strategy) 475885d0a26eSJack F Vogel { 475985d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 476085d0a26eSJack F Vogel int i = 0; 476185d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 476285d0a26eSJack F Vogel 476385d0a26eSJack F Vogel /* Reserve headroom */ 476485d0a26eSJack F Vogel pbsize -= headroom; 476585d0a26eSJack F Vogel 476685d0a26eSJack F Vogel if (!num_pb) 476785d0a26eSJack F Vogel num_pb = 1; 476885d0a26eSJack F Vogel 476985d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 477085d0a26eSJack F Vogel * buffers requested using supplied strategy. 477185d0a26eSJack F Vogel */ 477285d0a26eSJack F Vogel switch (strategy) { 4773a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 477485d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 477585d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 477685d0a26eSJack F Vogel */ 4777a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 477885d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 477985d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 478085d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 478185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 478250455f73SPiotr Skajewski rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 478350455f73SPiotr Skajewski for (; i < num_pb; i++) 478450455f73SPiotr Skajewski IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 478550455f73SPiotr Skajewski break; 4786a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 478785d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 478885d0a26eSJack F Vogel for (; i < num_pb; i++) 478985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 479085d0a26eSJack F Vogel break; 479185d0a26eSJack F Vogel default: 479285d0a26eSJack F Vogel break; 479385d0a26eSJack F Vogel } 479485d0a26eSJack F Vogel 479585d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 479685d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 479785d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 479885d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 479985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 480085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 480185d0a26eSJack F Vogel } 480285d0a26eSJack F Vogel 480385d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 480485d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 480585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 480685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 480785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 480885d0a26eSJack F Vogel } 480985d0a26eSJack F Vogel } 481085d0a26eSJack F Vogel 481185d0a26eSJack F Vogel /** 481285d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 481385d0a26eSJack F Vogel * @hw: pointer to the hardware structure 481485d0a26eSJack F Vogel * 481585d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 481685d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 481785d0a26eSJack F Vogel * buffers on the system. 481885d0a26eSJack F Vogel **/ 481985d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 482085d0a26eSJack F Vogel { 4821758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4822758cc3dcSJack F Vogel u16 value; 482385d0a26eSJack F Vogel 482485d0a26eSJack F Vogel /* 482585d0a26eSJack F Vogel * If double reset is not requested then all transactions should 482685d0a26eSJack F Vogel * already be clear and as such there is no work to do 482785d0a26eSJack F Vogel */ 482885d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 482985d0a26eSJack F Vogel return; 483085d0a26eSJack F Vogel 483185d0a26eSJack F Vogel /* 483285d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 483385d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 483485d0a26eSJack F Vogel * has already been cleared. 483585d0a26eSJack F Vogel */ 483685d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 483785d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 483885d0a26eSJack F Vogel 4839758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4840758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4841758cc3dcSJack F Vogel msec_delay(3); 4842758cc3dcSJack F Vogel 4843758cc3dcSJack F Vogel /* 4844758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4845758cc3dcSJack F Vogel * transactions pending. 4846758cc3dcSJack F Vogel */ 4847758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4848758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4849758cc3dcSJack F Vogel usec_delay(100); 4850758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4851758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4852758cc3dcSJack F Vogel goto out; 4853758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4854758cc3dcSJack F Vogel goto out; 4855758cc3dcSJack F Vogel } 4856758cc3dcSJack F Vogel 4857758cc3dcSJack F Vogel out: 485885d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 485985d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 486085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 486185d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 486285d0a26eSJack F Vogel 486385d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 486485d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 486585d0a26eSJack F Vogel usec_delay(20); 486685d0a26eSJack F Vogel 486785d0a26eSJack F Vogel /* restore previous register values */ 486885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 486985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 487085d0a26eSJack F Vogel } 487185d0a26eSJack F Vogel 48723f66b96dSKevin Bowling static const u8 ixgbe_emc_temp_data[4] = { 48733f66b96dSKevin Bowling IXGBE_EMC_INTERNAL_DATA, 48743f66b96dSKevin Bowling IXGBE_EMC_DIODE1_DATA, 48753f66b96dSKevin Bowling IXGBE_EMC_DIODE2_DATA, 48763f66b96dSKevin Bowling IXGBE_EMC_DIODE3_DATA 48773f66b96dSKevin Bowling }; 48783f66b96dSKevin Bowling static const u8 ixgbe_emc_therm_limit[4] = { 48793f66b96dSKevin Bowling IXGBE_EMC_INTERNAL_THERM_LIMIT, 48803f66b96dSKevin Bowling IXGBE_EMC_DIODE1_THERM_LIMIT, 48813f66b96dSKevin Bowling IXGBE_EMC_DIODE2_THERM_LIMIT, 48823f66b96dSKevin Bowling IXGBE_EMC_DIODE3_THERM_LIMIT 48833f66b96dSKevin Bowling }; 48843f66b96dSKevin Bowling 48853f66b96dSKevin Bowling /** 4886edef2769SRadoslaw Tyl * ixgbe_get_thermal_sensor_data_generic - Gathers thermal sensor data 48873f66b96dSKevin Bowling * @hw: pointer to hardware structure 48883f66b96dSKevin Bowling * 48893f66b96dSKevin Bowling * Returns the thermal sensor data structure 48903f66b96dSKevin Bowling **/ 48913f66b96dSKevin Bowling s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw) 48923f66b96dSKevin Bowling { 48933f66b96dSKevin Bowling s32 status = IXGBE_SUCCESS; 48943f66b96dSKevin Bowling u16 ets_offset; 48953f66b96dSKevin Bowling u16 ets_cfg; 48963f66b96dSKevin Bowling u16 ets_sensor; 48973f66b96dSKevin Bowling u8 num_sensors; 48983f66b96dSKevin Bowling u8 sensor_index; 48993f66b96dSKevin Bowling u8 sensor_location; 49003f66b96dSKevin Bowling u8 i; 49013f66b96dSKevin Bowling struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 49023f66b96dSKevin Bowling 49033f66b96dSKevin Bowling DEBUGFUNC("ixgbe_get_thermal_sensor_data_generic"); 49043f66b96dSKevin Bowling 49053f66b96dSKevin Bowling /* Only support thermal sensors attached to 82599 physical port 0 */ 49063f66b96dSKevin Bowling if ((hw->mac.type != ixgbe_mac_82599EB) || 49073f66b96dSKevin Bowling (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) { 49083f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 49093f66b96dSKevin Bowling goto out; 49103f66b96dSKevin Bowling } 49113f66b96dSKevin Bowling 49123f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset); 49133f66b96dSKevin Bowling if (status) 49143f66b96dSKevin Bowling goto out; 49153f66b96dSKevin Bowling 49163f66b96dSKevin Bowling if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) { 49173f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 49183f66b96dSKevin Bowling goto out; 49193f66b96dSKevin Bowling } 49203f66b96dSKevin Bowling 49213f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, ets_offset, &ets_cfg); 49223f66b96dSKevin Bowling if (status) 49233f66b96dSKevin Bowling goto out; 49243f66b96dSKevin Bowling 49253f66b96dSKevin Bowling if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) 49263f66b96dSKevin Bowling != IXGBE_ETS_TYPE_EMC) { 49273f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 49283f66b96dSKevin Bowling goto out; 49293f66b96dSKevin Bowling } 49303f66b96dSKevin Bowling 49313f66b96dSKevin Bowling num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 49323f66b96dSKevin Bowling if (num_sensors > IXGBE_MAX_SENSORS) 49333f66b96dSKevin Bowling num_sensors = IXGBE_MAX_SENSORS; 49343f66b96dSKevin Bowling 49353f66b96dSKevin Bowling for (i = 0; i < num_sensors; i++) { 49363f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i), 49373f66b96dSKevin Bowling &ets_sensor); 49383f66b96dSKevin Bowling if (status) 49393f66b96dSKevin Bowling goto out; 49403f66b96dSKevin Bowling 49413f66b96dSKevin Bowling sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 49423f66b96dSKevin Bowling IXGBE_ETS_DATA_INDEX_SHIFT); 49433f66b96dSKevin Bowling sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 49443f66b96dSKevin Bowling IXGBE_ETS_DATA_LOC_SHIFT); 49453f66b96dSKevin Bowling 49463f66b96dSKevin Bowling if (sensor_location != 0) { 49473f66b96dSKevin Bowling status = hw->phy.ops.read_i2c_byte(hw, 49483f66b96dSKevin Bowling ixgbe_emc_temp_data[sensor_index], 49493f66b96dSKevin Bowling IXGBE_I2C_THERMAL_SENSOR_ADDR, 49503f66b96dSKevin Bowling &data->sensor[i].temp); 49513f66b96dSKevin Bowling if (status) 49523f66b96dSKevin Bowling goto out; 49533f66b96dSKevin Bowling } 49543f66b96dSKevin Bowling } 49553f66b96dSKevin Bowling out: 49563f66b96dSKevin Bowling return status; 49573f66b96dSKevin Bowling } 49583f66b96dSKevin Bowling 49593f66b96dSKevin Bowling /** 49603f66b96dSKevin Bowling * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds 49613f66b96dSKevin Bowling * @hw: pointer to hardware structure 49623f66b96dSKevin Bowling * 49633f66b96dSKevin Bowling * Inits the thermal sensor thresholds according to the NVM map 49643f66b96dSKevin Bowling * and save off the threshold and location values into mac.thermal_sensor_data 49653f66b96dSKevin Bowling **/ 49663f66b96dSKevin Bowling s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw) 49673f66b96dSKevin Bowling { 49683f66b96dSKevin Bowling s32 status = IXGBE_SUCCESS; 49693f66b96dSKevin Bowling u16 offset; 49703f66b96dSKevin Bowling u16 ets_offset; 49713f66b96dSKevin Bowling u16 ets_cfg; 49723f66b96dSKevin Bowling u16 ets_sensor; 49733f66b96dSKevin Bowling u8 low_thresh_delta; 49743f66b96dSKevin Bowling u8 num_sensors; 49753f66b96dSKevin Bowling u8 sensor_index; 49763f66b96dSKevin Bowling u8 sensor_location; 49773f66b96dSKevin Bowling u8 therm_limit; 49783f66b96dSKevin Bowling u8 i; 49793f66b96dSKevin Bowling struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 49803f66b96dSKevin Bowling 49813f66b96dSKevin Bowling DEBUGFUNC("ixgbe_init_thermal_sensor_thresh_generic"); 49823f66b96dSKevin Bowling 49833f66b96dSKevin Bowling memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data)); 49843f66b96dSKevin Bowling 49853f66b96dSKevin Bowling /* Only support thermal sensors attached to 82599 physical port 0 */ 49863f66b96dSKevin Bowling if ((hw->mac.type != ixgbe_mac_82599EB) || 49873f66b96dSKevin Bowling (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) 49883f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 49893f66b96dSKevin Bowling 49903f66b96dSKevin Bowling offset = IXGBE_ETS_CFG; 49913f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_offset)) 49923f66b96dSKevin Bowling goto eeprom_err; 49933f66b96dSKevin Bowling if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) 49943f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 49953f66b96dSKevin Bowling 49963f66b96dSKevin Bowling offset = ets_offset; 49973f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_cfg)) 49983f66b96dSKevin Bowling goto eeprom_err; 49993f66b96dSKevin Bowling if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) 50003f66b96dSKevin Bowling != IXGBE_ETS_TYPE_EMC) 50013f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 50023f66b96dSKevin Bowling 50033f66b96dSKevin Bowling low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >> 50043f66b96dSKevin Bowling IXGBE_ETS_LTHRES_DELTA_SHIFT); 50053f66b96dSKevin Bowling num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 50063f66b96dSKevin Bowling 50073f66b96dSKevin Bowling for (i = 0; i < num_sensors; i++) { 50083f66b96dSKevin Bowling offset = ets_offset + 1 + i; 50093f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_sensor)) { 50103f66b96dSKevin Bowling ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 50113f66b96dSKevin Bowling "eeprom read at offset %d failed", 50123f66b96dSKevin Bowling offset); 50133f66b96dSKevin Bowling continue; 50143f66b96dSKevin Bowling } 50153f66b96dSKevin Bowling sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 50163f66b96dSKevin Bowling IXGBE_ETS_DATA_INDEX_SHIFT); 50173f66b96dSKevin Bowling sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 50183f66b96dSKevin Bowling IXGBE_ETS_DATA_LOC_SHIFT); 50193f66b96dSKevin Bowling therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK; 50203f66b96dSKevin Bowling 50213f66b96dSKevin Bowling hw->phy.ops.write_i2c_byte(hw, 50223f66b96dSKevin Bowling ixgbe_emc_therm_limit[sensor_index], 50233f66b96dSKevin Bowling IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit); 50243f66b96dSKevin Bowling 50253f66b96dSKevin Bowling if ((i < IXGBE_MAX_SENSORS) && (sensor_location != 0)) { 50263f66b96dSKevin Bowling data->sensor[i].location = sensor_location; 50273f66b96dSKevin Bowling data->sensor[i].caution_thresh = therm_limit; 50283f66b96dSKevin Bowling data->sensor[i].max_op_thresh = therm_limit - 50293f66b96dSKevin Bowling low_thresh_delta; 50303f66b96dSKevin Bowling } 50313f66b96dSKevin Bowling } 50323f66b96dSKevin Bowling return status; 50333f66b96dSKevin Bowling 50343f66b96dSKevin Bowling eeprom_err: 50353f66b96dSKevin Bowling ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 50363f66b96dSKevin Bowling "eeprom read at offset %d failed", offset); 50373f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 50383f66b96dSKevin Bowling } 50393f66b96dSKevin Bowling 50408eb6488eSEric Joyner /** 50418eb6488eSEric Joyner * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW 50428eb6488eSEric Joyner * 50438eb6488eSEric Joyner * @hw: pointer to hardware structure 50448eb6488eSEric Joyner * @cmd: Command we send to the FW 50458eb6488eSEric Joyner * @status: The reply from the FW 50468eb6488eSEric Joyner * 50478eb6488eSEric Joyner * Bit-bangs the cmd to the by_pass FW status points to what is returned. 50488eb6488eSEric Joyner **/ 50498eb6488eSEric Joyner #define IXGBE_BYPASS_BB_WAIT 1 50508eb6488eSEric Joyner s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) 50518eb6488eSEric Joyner { 50528eb6488eSEric Joyner int i; 50538eb6488eSEric Joyner u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; 50548eb6488eSEric Joyner u32 esdp; 50558eb6488eSEric Joyner 50568eb6488eSEric Joyner if (!status) 50578eb6488eSEric Joyner return IXGBE_ERR_PARAM; 50588eb6488eSEric Joyner 50598eb6488eSEric Joyner *status = 0; 50608eb6488eSEric Joyner 50618eb6488eSEric Joyner /* SDP vary by MAC type */ 50628eb6488eSEric Joyner switch (hw->mac.type) { 50638eb6488eSEric Joyner case ixgbe_mac_82599EB: 50648eb6488eSEric Joyner sck = IXGBE_ESDP_SDP7; 50658eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 50668eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP6; 50678eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP7_DIR; 50688eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 50698eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP6_DIR; 50708eb6488eSEric Joyner break; 50718eb6488eSEric Joyner case ixgbe_mac_X540: 50728eb6488eSEric Joyner sck = IXGBE_ESDP_SDP2; 50738eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 50748eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP1; 50758eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP2_DIR; 50768eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 50778eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP1_DIR; 50788eb6488eSEric Joyner break; 50798eb6488eSEric Joyner default: 50808eb6488eSEric Joyner return IXGBE_ERR_DEVICE_NOT_SUPPORTED; 50818eb6488eSEric Joyner } 50828eb6488eSEric Joyner 50838eb6488eSEric Joyner /* Set SDP pins direction */ 50848eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 50858eb6488eSEric Joyner esdp |= dir_sck; /* SCK as output */ 50868eb6488eSEric Joyner esdp |= dir_sdi; /* SDI as output */ 50878eb6488eSEric Joyner esdp &= ~dir_sdo; /* SDO as input */ 50888eb6488eSEric Joyner esdp |= sck; 50898eb6488eSEric Joyner esdp |= sdi; 50908eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50918eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 50928eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 50938eb6488eSEric Joyner 50948eb6488eSEric Joyner /* Generate start condition */ 50958eb6488eSEric Joyner esdp &= ~sdi; 50968eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50978eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 50988eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 50998eb6488eSEric Joyner 51008eb6488eSEric Joyner esdp &= ~sck; 51018eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51028eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51038eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51048eb6488eSEric Joyner 51058eb6488eSEric Joyner /* Clock out the new control word and clock in the status */ 51068eb6488eSEric Joyner for (i = 0; i < 32; i++) { 51078eb6488eSEric Joyner if ((cmd >> (31 - i)) & 0x01) { 51088eb6488eSEric Joyner esdp |= sdi; 51098eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51108eb6488eSEric Joyner } else { 51118eb6488eSEric Joyner esdp &= ~sdi; 51128eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51138eb6488eSEric Joyner } 51148eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51158eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51168eb6488eSEric Joyner 51178eb6488eSEric Joyner esdp |= sck; 51188eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51198eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51208eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51218eb6488eSEric Joyner 51228eb6488eSEric Joyner esdp &= ~sck; 51238eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51248eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51258eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51268eb6488eSEric Joyner 51278eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 51288eb6488eSEric Joyner if (esdp & sdo) 51298eb6488eSEric Joyner *status = (*status << 1) | 0x01; 51308eb6488eSEric Joyner else 51318eb6488eSEric Joyner *status = (*status << 1) | 0x00; 51328eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51338eb6488eSEric Joyner } 51348eb6488eSEric Joyner 51358eb6488eSEric Joyner /* stop condition */ 51368eb6488eSEric Joyner esdp |= sck; 51378eb6488eSEric Joyner esdp &= ~sdi; 51388eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51398eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51408eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51418eb6488eSEric Joyner 51428eb6488eSEric Joyner esdp |= sdi; 51438eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51448eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51458eb6488eSEric Joyner 51468eb6488eSEric Joyner /* set the page bits to match the cmd that the status it belongs to */ 51478eb6488eSEric Joyner *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); 51488eb6488eSEric Joyner 51498eb6488eSEric Joyner return IXGBE_SUCCESS; 51508eb6488eSEric Joyner } 51518eb6488eSEric Joyner 51528eb6488eSEric Joyner /** 51538eb6488eSEric Joyner * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. 51548eb6488eSEric Joyner * 51558eb6488eSEric Joyner * If we send a write we can't be sure it took until we can read back 515699cb088fSIan Moffett * that same register. It can be a problem as some of the fields may 51578eb6488eSEric Joyner * for valid reasons change inbetween the time wrote the register and 51588eb6488eSEric Joyner * we read it again to verify. So this function check everything we 51598eb6488eSEric Joyner * can check and then assumes it worked. 51608eb6488eSEric Joyner * 51618eb6488eSEric Joyner * @u32 in_reg - The register cmd for the bit-bang read. 51628eb6488eSEric Joyner * @u32 out_reg - The register returned from a bit-bang read. 51638eb6488eSEric Joyner **/ 51648eb6488eSEric Joyner bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) 51658eb6488eSEric Joyner { 51668eb6488eSEric Joyner u32 mask; 51678eb6488eSEric Joyner 51688eb6488eSEric Joyner /* Page must match for all control pages */ 51698eb6488eSEric Joyner if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) 517079b36ec9SKevin Bowling return false; 51718eb6488eSEric Joyner 51728eb6488eSEric Joyner switch (in_reg & BYPASS_PAGE_M) { 51738eb6488eSEric Joyner case BYPASS_PAGE_CTL0: 51748eb6488eSEric Joyner /* All the following can't change since the last write 51758eb6488eSEric Joyner * - All the event actions 51768eb6488eSEric Joyner * - The timeout value 51778eb6488eSEric Joyner */ 51788eb6488eSEric Joyner mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | 51798eb6488eSEric Joyner BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | 51808eb6488eSEric Joyner BYPASS_WDTIMEOUT_M | 51818eb6488eSEric Joyner BYPASS_WDT_VALUE_M; 51828eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 518379b36ec9SKevin Bowling return false; 51848eb6488eSEric Joyner 51858eb6488eSEric Joyner /* 0x0 is never a valid value for bypass status */ 51868eb6488eSEric Joyner if (!(out_reg & BYPASS_STATUS_OFF_M)) 518779b36ec9SKevin Bowling return false; 51888eb6488eSEric Joyner break; 51898eb6488eSEric Joyner case BYPASS_PAGE_CTL1: 51908eb6488eSEric Joyner /* All the following can't change since the last write 51918eb6488eSEric Joyner * - time valid bit 51928eb6488eSEric Joyner * - time we last sent 51938eb6488eSEric Joyner */ 51948eb6488eSEric Joyner mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; 51958eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 519679b36ec9SKevin Bowling return false; 51978eb6488eSEric Joyner break; 51988eb6488eSEric Joyner case BYPASS_PAGE_CTL2: 51998eb6488eSEric Joyner /* All we can check in this page is control number 52008eb6488eSEric Joyner * which is already done above. 52018eb6488eSEric Joyner */ 52028eb6488eSEric Joyner break; 52038eb6488eSEric Joyner } 52048eb6488eSEric Joyner 520579b36ec9SKevin Bowling /* We are as sure as we can be return true */ 520679b36ec9SKevin Bowling return true; 52078eb6488eSEric Joyner } 52088eb6488eSEric Joyner 52098eb6488eSEric Joyner /** 52108eb6488eSEric Joyner * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. 52118eb6488eSEric Joyner * 52128eb6488eSEric Joyner * @hw: pointer to hardware structure 52138eb6488eSEric Joyner * @cmd: The control word we are setting. 52148eb6488eSEric Joyner * @event: The event we are setting in the FW. This also happens to 52158eb6488eSEric Joyner * be the mask for the event we are setting (handy) 52168eb6488eSEric Joyner * @action: The action we set the event to in the FW. This is in a 52178eb6488eSEric Joyner * bit field that happens to be what we want to put in 52188eb6488eSEric Joyner * the event spot (also handy) 52198eb6488eSEric Joyner **/ 52208eb6488eSEric Joyner s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, 52218eb6488eSEric Joyner u32 action) 52228eb6488eSEric Joyner { 52238eb6488eSEric Joyner u32 by_ctl = 0; 52248eb6488eSEric Joyner u32 cmd, verify; 52258eb6488eSEric Joyner u32 count = 0; 52268eb6488eSEric Joyner 52278eb6488eSEric Joyner /* Get current values */ 52288eb6488eSEric Joyner cmd = ctrl; /* just reading only need control number */ 52298eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 52308eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52318eb6488eSEric Joyner 52328eb6488eSEric Joyner /* Set to new action */ 52338eb6488eSEric Joyner cmd = (by_ctl & ~event) | BYPASS_WE | action; 52348eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 52358eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52368eb6488eSEric Joyner 52378eb6488eSEric Joyner /* Page 0 force a FW eeprom write which is slow so verify */ 52388eb6488eSEric Joyner if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { 52398eb6488eSEric Joyner verify = BYPASS_PAGE_CTL0; 52408eb6488eSEric Joyner do { 52418eb6488eSEric Joyner if (count++ > 5) 52428eb6488eSEric Joyner return IXGBE_BYPASS_FW_WRITE_FAILURE; 52438eb6488eSEric Joyner 52448eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) 52458eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52468eb6488eSEric Joyner } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); 52478eb6488eSEric Joyner } else { 52488eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 52498eb6488eSEric Joyner msec_delay(100); 52508eb6488eSEric Joyner } 52518eb6488eSEric Joyner 52528eb6488eSEric Joyner return IXGBE_SUCCESS; 52538eb6488eSEric Joyner } 52548eb6488eSEric Joyner 52558eb6488eSEric Joyner /** 52568eb6488eSEric Joyner * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. 52578eb6488eSEric Joyner * 52588eb6488eSEric Joyner * @hw: pointer to hardware structure 52598eb6488eSEric Joyner * @addr: The bypass eeprom address to read. 52608eb6488eSEric Joyner * @value: The 8b of data at the address above. 52618eb6488eSEric Joyner **/ 52628eb6488eSEric Joyner s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) 52638eb6488eSEric Joyner { 52648eb6488eSEric Joyner u32 cmd; 52658eb6488eSEric Joyner u32 status; 52668eb6488eSEric Joyner 52678eb6488eSEric Joyner 52688eb6488eSEric Joyner /* send the request */ 52698eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 52708eb6488eSEric Joyner cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 52718eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 52728eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52738eb6488eSEric Joyner 52748eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 52758eb6488eSEric Joyner msec_delay(100); 52768eb6488eSEric Joyner 52778eb6488eSEric Joyner /* now read the results */ 52788eb6488eSEric Joyner cmd &= ~BYPASS_WE; 52798eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 52808eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52818eb6488eSEric Joyner 52828eb6488eSEric Joyner *value = status & BYPASS_CTL2_DATA_M; 52838eb6488eSEric Joyner 52848eb6488eSEric Joyner return IXGBE_SUCCESS; 52858eb6488eSEric Joyner } 52868eb6488eSEric Joyner 52877d48aa4cSEric Joyner /** 52887d48aa4cSEric Joyner * ixgbe_get_orom_version - Return option ROM from EEPROM 52897d48aa4cSEric Joyner * 52907d48aa4cSEric Joyner * @hw: pointer to hardware structure 52917d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 52927d48aa4cSEric Joyner * 529379b36ec9SKevin Bowling * if valid option ROM version, nvm_ver->or_valid set to true 529479b36ec9SKevin Bowling * else nvm_ver->or_valid is false. 52957d48aa4cSEric Joyner **/ 52967d48aa4cSEric Joyner void ixgbe_get_orom_version(struct ixgbe_hw *hw, 52977d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 52987d48aa4cSEric Joyner { 52997d48aa4cSEric Joyner u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl; 53007d48aa4cSEric Joyner 530179b36ec9SKevin Bowling nvm_ver->or_valid = false; 53027d48aa4cSEric Joyner /* Option Rom may or may not be present. Start with pointer */ 53037d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset); 53047d48aa4cSEric Joyner 53057d48aa4cSEric Joyner /* make sure offset is valid */ 53067d48aa4cSEric Joyner if ((offset == 0x0) || (offset == NVM_INVALID_PTR)) 53077d48aa4cSEric Joyner return; 53087d48aa4cSEric Joyner 53097d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh); 53107d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl); 53117d48aa4cSEric Joyner 53127d48aa4cSEric Joyner /* option rom exists and is valid */ 53137d48aa4cSEric Joyner if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 || 53147d48aa4cSEric Joyner eeprom_cfg_blkl == NVM_VER_INVALID || 53157d48aa4cSEric Joyner eeprom_cfg_blkh == NVM_VER_INVALID) 53167d48aa4cSEric Joyner return; 53177d48aa4cSEric Joyner 531879b36ec9SKevin Bowling nvm_ver->or_valid = true; 53197d48aa4cSEric Joyner nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT; 53207d48aa4cSEric Joyner nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) | 53217d48aa4cSEric Joyner (eeprom_cfg_blkh >> NVM_OROM_SHIFT); 53227d48aa4cSEric Joyner nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK; 53237d48aa4cSEric Joyner } 53247d48aa4cSEric Joyner 53257d48aa4cSEric Joyner /** 53267d48aa4cSEric Joyner * ixgbe_get_oem_prod_version - Return OEM Product version 53277d48aa4cSEric Joyner * 53287d48aa4cSEric Joyner * @hw: pointer to hardware structure 53297d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 53307d48aa4cSEric Joyner * 533179b36ec9SKevin Bowling * if valid OEM product version, nvm_ver->oem_valid set to true 533279b36ec9SKevin Bowling * else nvm_ver->oem_valid is false. 53337d48aa4cSEric Joyner **/ 53347d48aa4cSEric Joyner void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw, 53357d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 53367d48aa4cSEric Joyner { 53377d48aa4cSEric Joyner u16 rel_num, prod_ver, mod_len, cap, offset; 53387d48aa4cSEric Joyner 533979b36ec9SKevin Bowling nvm_ver->oem_valid = false; 53407d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset); 53417d48aa4cSEric Joyner 5342ab1c54feSEric van Gyzen /* Return if offset to OEM Product Version block is invalid */ 5343ab1c54feSEric van Gyzen if (offset == 0x0 || offset == NVM_INVALID_PTR) 53447d48aa4cSEric Joyner return; 53457d48aa4cSEric Joyner 53467d48aa4cSEric Joyner /* Read product version block */ 53477d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset, &mod_len); 53487d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap); 53497d48aa4cSEric Joyner 53507d48aa4cSEric Joyner /* Return if OEM product version block is invalid */ 53517d48aa4cSEric Joyner if (mod_len != NVM_OEM_PROD_VER_MOD_LEN || 53527d48aa4cSEric Joyner (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0) 53537d48aa4cSEric Joyner return; 53547d48aa4cSEric Joyner 53557d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver); 53567d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num); 53577d48aa4cSEric Joyner 53587d48aa4cSEric Joyner /* Return if version is invalid */ 53597d48aa4cSEric Joyner if ((rel_num | prod_ver) == 0x0 || 53607d48aa4cSEric Joyner rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID) 53617d48aa4cSEric Joyner return; 53627d48aa4cSEric Joyner 53637d48aa4cSEric Joyner nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT; 53647d48aa4cSEric Joyner nvm_ver->oem_minor = prod_ver & NVM_VER_MASK; 53657d48aa4cSEric Joyner nvm_ver->oem_release = rel_num; 536679b36ec9SKevin Bowling nvm_ver->oem_valid = true; 53677d48aa4cSEric Joyner } 53687d48aa4cSEric Joyner 53697d48aa4cSEric Joyner /** 53707d48aa4cSEric Joyner * ixgbe_get_etk_id - Return Etrack ID from EEPROM 53717d48aa4cSEric Joyner * 53727d48aa4cSEric Joyner * @hw: pointer to hardware structure 53737d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 53747d48aa4cSEric Joyner * 53757d48aa4cSEric Joyner * word read errors will return 0xFFFF 53767d48aa4cSEric Joyner **/ 53777d48aa4cSEric Joyner void ixgbe_get_etk_id(struct ixgbe_hw *hw, struct ixgbe_nvm_version *nvm_ver) 53787d48aa4cSEric Joyner { 53797d48aa4cSEric Joyner u16 etk_id_l, etk_id_h; 53807d48aa4cSEric Joyner 53817d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l)) 53827d48aa4cSEric Joyner etk_id_l = NVM_VER_INVALID; 53837d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h)) 53847d48aa4cSEric Joyner etk_id_h = NVM_VER_INVALID; 53857d48aa4cSEric Joyner 53867d48aa4cSEric Joyner /* The word order for the version format is determined by high order 53877d48aa4cSEric Joyner * word bit 15. 53887d48aa4cSEric Joyner */ 53897d48aa4cSEric Joyner if ((etk_id_h & NVM_ETK_VALID) == 0) { 53907d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_h; 53917d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT); 53927d48aa4cSEric Joyner } else { 53937d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_l; 53947d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT); 53957d48aa4cSEric Joyner } 53967d48aa4cSEric Joyner } 53977d48aa4cSEric Joyner 5398fd75b91dSJack F Vogel 5399fd75b91dSJack F Vogel /** 5400fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 5401fd75b91dSJack F Vogel * @hw: pointer to hardware structure 5402fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 5403fd75b91dSJack F Vogel * 5404fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 5405fd75b91dSJack F Vogel **/ 5406fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 5407fd75b91dSJack F Vogel { 5408fd75b91dSJack F Vogel u32 reg, i; 5409fd75b91dSJack F Vogel 5410fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 5411fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 5412fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 5413fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 5414fd75b91dSJack F Vogel return; 5415fd75b91dSJack F Vogel } 5416758cc3dcSJack F Vogel 5417758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 5418758cc3dcSJack F Vogel { 5419758cc3dcSJack F Vogel u32 pfdtxgswc; 5420758cc3dcSJack F Vogel u32 rxctrl; 5421758cc3dcSJack F Vogel 5422758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5423758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 5424758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5425758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5426758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 5427758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 5428758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 542979b36ec9SKevin Bowling hw->mac.set_lben = true; 5430758cc3dcSJack F Vogel } else { 543179b36ec9SKevin Bowling hw->mac.set_lben = false; 5432758cc3dcSJack F Vogel } 5433758cc3dcSJack F Vogel } 5434758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 5435758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 5436758cc3dcSJack F Vogel } 5437758cc3dcSJack F Vogel } 5438758cc3dcSJack F Vogel 5439758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 5440758cc3dcSJack F Vogel { 5441758cc3dcSJack F Vogel u32 pfdtxgswc; 5442758cc3dcSJack F Vogel u32 rxctrl; 5443758cc3dcSJack F Vogel 5444758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5445758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 5446758cc3dcSJack F Vogel 5447758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5448758cc3dcSJack F Vogel if (hw->mac.set_lben) { 5449758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5450758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 5451758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 545279b36ec9SKevin Bowling hw->mac.set_lben = false; 5453758cc3dcSJack F Vogel } 5454758cc3dcSJack F Vogel } 5455758cc3dcSJack F Vogel } 5456758cc3dcSJack F Vogel 5457758cc3dcSJack F Vogel /** 545879b36ec9SKevin Bowling * ixgbe_mng_present - returns true when management capability is present 5459758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5460758cc3dcSJack F Vogel */ 5461758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 5462758cc3dcSJack F Vogel { 5463758cc3dcSJack F Vogel u32 fwsm; 5464758cc3dcSJack F Vogel 5465758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 546679b36ec9SKevin Bowling return false; 5467758cc3dcSJack F Vogel 5468a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 54697d48aa4cSEric Joyner 54707d48aa4cSEric Joyner return !!(fwsm & IXGBE_FWSM_FW_MODE_PT); 5471758cc3dcSJack F Vogel } 5472758cc3dcSJack F Vogel 5473758cc3dcSJack F Vogel /** 5474758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 5475758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5476758cc3dcSJack F Vogel * 547779b36ec9SKevin Bowling * Returns true if the manageability engine is enabled. 5478758cc3dcSJack F Vogel **/ 5479758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 5480758cc3dcSJack F Vogel { 5481758cc3dcSJack F Vogel u32 fwsm, manc, factps; 5482758cc3dcSJack F Vogel 5483a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5484758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 548579b36ec9SKevin Bowling return false; 5486758cc3dcSJack F Vogel 5487758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 5488758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 548979b36ec9SKevin Bowling return false; 5490758cc3dcSJack F Vogel 5491758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 5492a9ca1c79SSean Bruno factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 5493758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 549479b36ec9SKevin Bowling return false; 5495758cc3dcSJack F Vogel } 5496758cc3dcSJack F Vogel 549779b36ec9SKevin Bowling return true; 5498758cc3dcSJack F Vogel } 5499758cc3dcSJack F Vogel 5500758cc3dcSJack F Vogel /** 5501758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 5502758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5503758cc3dcSJack F Vogel * @speed: new link speed 550479b36ec9SKevin Bowling * @autoneg_wait_to_complete: true when waiting for completion is needed 5505758cc3dcSJack F Vogel * 5506758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 5507758cc3dcSJack F Vogel **/ 5508758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 5509758cc3dcSJack F Vogel ixgbe_link_speed speed, 5510758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 5511758cc3dcSJack F Vogel { 5512758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5513758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5514758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 5515758cc3dcSJack F Vogel u32 speedcnt = 0; 5516758cc3dcSJack F Vogel u32 i = 0; 551779b36ec9SKevin Bowling bool autoneg, link_up = false; 5518758cc3dcSJack F Vogel 5519758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 5520758cc3dcSJack F Vogel 5521758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 5522758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 5523758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5524758cc3dcSJack F Vogel return status; 5525758cc3dcSJack F Vogel 5526758cc3dcSJack F Vogel speed &= link_speed; 5527758cc3dcSJack F Vogel 5528758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 5529758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 5530758cc3dcSJack F Vogel */ 5531758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 5532758cc3dcSJack F Vogel speedcnt++; 5533758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 5534758cc3dcSJack F Vogel 5535758cc3dcSJack F Vogel /* Set the module link speed */ 5536758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5537758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5538758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5539758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5540758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 5541758cc3dcSJack F Vogel break; 5542758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5543758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 5544758cc3dcSJack F Vogel break; 5545758cc3dcSJack F Vogel default: 5546758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5547758cc3dcSJack F Vogel break; 5548758cc3dcSJack F Vogel } 5549758cc3dcSJack F Vogel 5550758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 5551758cc3dcSJack F Vogel msec_delay(40); 5552758cc3dcSJack F Vogel 5553758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5554758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 5555758cc3dcSJack F Vogel autoneg_wait_to_complete); 5556758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5557758cc3dcSJack F Vogel return status; 5558758cc3dcSJack F Vogel 5559758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5560758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5561758cc3dcSJack F Vogel 5562758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 556396ef6eb3SXiaolong Ye * Section 73.10.2, we may have to wait up to 1000ms if KR is 5564758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 5565758cc3dcSJack F Vogel */ 5566aaa3af80SMatthew Smith for (i = 0; i < 10; i++) { 5567758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5568758cc3dcSJack F Vogel msec_delay(100); 5569758cc3dcSJack F Vogel 5570758cc3dcSJack F Vogel /* If we have link, just jump out */ 5571758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 557279b36ec9SKevin Bowling &link_up, false); 5573758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5574758cc3dcSJack F Vogel return status; 5575758cc3dcSJack F Vogel 5576758cc3dcSJack F Vogel if (link_up) 5577758cc3dcSJack F Vogel goto out; 5578758cc3dcSJack F Vogel } 5579758cc3dcSJack F Vogel } 5580758cc3dcSJack F Vogel 5581758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 5582758cc3dcSJack F Vogel speedcnt++; 5583758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 5584758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 5585758cc3dcSJack F Vogel 5586758cc3dcSJack F Vogel /* Set the module link speed */ 5587758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5588758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5589758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5590758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5591758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 5592758cc3dcSJack F Vogel break; 5593758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5594758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 5595758cc3dcSJack F Vogel break; 5596758cc3dcSJack F Vogel default: 5597758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5598758cc3dcSJack F Vogel break; 5599758cc3dcSJack F Vogel } 5600758cc3dcSJack F Vogel 5601758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 5602758cc3dcSJack F Vogel msec_delay(40); 5603758cc3dcSJack F Vogel 5604758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5605758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 5606758cc3dcSJack F Vogel autoneg_wait_to_complete); 5607758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5608758cc3dcSJack F Vogel return status; 5609758cc3dcSJack F Vogel 5610758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5611758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5612758cc3dcSJack F Vogel 5613758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5614758cc3dcSJack F Vogel msec_delay(100); 5615758cc3dcSJack F Vogel 5616758cc3dcSJack F Vogel /* If we have link, just jump out */ 561779b36ec9SKevin Bowling status = ixgbe_check_link(hw, &link_speed, &link_up, false); 5618758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5619758cc3dcSJack F Vogel return status; 5620758cc3dcSJack F Vogel 5621758cc3dcSJack F Vogel if (link_up) 5622758cc3dcSJack F Vogel goto out; 5623758cc3dcSJack F Vogel } 5624758cc3dcSJack F Vogel 5625758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 5626758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 5627758cc3dcSJack F Vogel * single highest speed that the user requested. 5628758cc3dcSJack F Vogel */ 5629758cc3dcSJack F Vogel if (speedcnt > 1) 5630758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 5631758cc3dcSJack F Vogel highest_link_speed, 5632758cc3dcSJack F Vogel autoneg_wait_to_complete); 5633758cc3dcSJack F Vogel 5634758cc3dcSJack F Vogel out: 5635758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 5636758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 5637758cc3dcSJack F Vogel 5638758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 5639758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 5640758cc3dcSJack F Vogel 5641758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 5642758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5643758cc3dcSJack F Vogel 5644758cc3dcSJack F Vogel return status; 5645758cc3dcSJack F Vogel } 5646758cc3dcSJack F Vogel 5647758cc3dcSJack F Vogel /** 5648758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 5649758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5650758cc3dcSJack F Vogel * @speed: link speed to set 5651758cc3dcSJack F Vogel * 5652758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 5653758cc3dcSJack F Vogel */ 5654758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 5655758cc3dcSJack F Vogel ixgbe_link_speed speed) 5656758cc3dcSJack F Vogel { 5657758cc3dcSJack F Vogel s32 status; 5658758cc3dcSJack F Vogel u8 rs, eeprom_data; 5659758cc3dcSJack F Vogel 5660758cc3dcSJack F Vogel switch (speed) { 5661758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 5662758cc3dcSJack F Vogel /* one bit mask same as setting on */ 5663758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 5664758cc3dcSJack F Vogel break; 5665758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 5666758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 5667758cc3dcSJack F Vogel break; 5668758cc3dcSJack F Vogel default: 5669758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 5670758cc3dcSJack F Vogel return; 5671758cc3dcSJack F Vogel } 5672758cc3dcSJack F Vogel 5673758cc3dcSJack F Vogel /* Set RS0 */ 5674758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5675758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5676758cc3dcSJack F Vogel &eeprom_data); 5677758cc3dcSJack F Vogel if (status) { 5678758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 5679758cc3dcSJack F Vogel goto out; 5680758cc3dcSJack F Vogel } 5681758cc3dcSJack F Vogel 5682758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5683758cc3dcSJack F Vogel 5684758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5685758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5686758cc3dcSJack F Vogel eeprom_data); 5687758cc3dcSJack F Vogel if (status) { 5688758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 5689758cc3dcSJack F Vogel goto out; 5690758cc3dcSJack F Vogel } 5691758cc3dcSJack F Vogel 5692758cc3dcSJack F Vogel /* Set RS1 */ 5693758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5694758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5695758cc3dcSJack F Vogel &eeprom_data); 5696758cc3dcSJack F Vogel if (status) { 5697758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 5698758cc3dcSJack F Vogel goto out; 5699758cc3dcSJack F Vogel } 5700758cc3dcSJack F Vogel 5701758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5702758cc3dcSJack F Vogel 5703758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5704758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5705758cc3dcSJack F Vogel eeprom_data); 5706758cc3dcSJack F Vogel if (status) { 5707758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 5708758cc3dcSJack F Vogel goto out; 5709758cc3dcSJack F Vogel } 5710758cc3dcSJack F Vogel out: 5711758cc3dcSJack F Vogel return; 5712758cc3dcSJack F Vogel } 5713