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 /*$FreeBSD$*/ 3513705f88SJack F Vogel 3613705f88SJack F Vogel #include "ixgbe_common.h" 371a4e3449SJack F Vogel #include "ixgbe_phy.h" 38fd75b91dSJack F Vogel #include "ixgbe_dcb.h" 39fd75b91dSJack F Vogel #include "ixgbe_dcb_82599.h" 4013705f88SJack F Vogel #include "ixgbe_api.h" 4113705f88SJack F Vogel 4213705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 4313705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 4413705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 4513705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 4613705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 4713705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 4813705f88SJack F Vogel u16 count); 4913705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 5013705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5113705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 5213705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 5313705f88SJack F Vogel 5413705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 552969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 562969bf0eSJack F Vogel u16 *san_mac_offset); 5785d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 5885d0a26eSJack F Vogel u16 words, u16 *data); 5985d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 6085d0a26eSJack F Vogel u16 words, u16 *data); 6185d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 6285d0a26eSJack F Vogel u16 offset); 6313705f88SJack F Vogel 6413705f88SJack F Vogel /** 659ca4041bSJack F Vogel * ixgbe_init_ops_generic - Inits function ptrs 669ca4041bSJack F Vogel * @hw: pointer to the hardware structure 6713705f88SJack F Vogel * 689ca4041bSJack F Vogel * Initialize the function pointers. 6913705f88SJack F Vogel **/ 709ca4041bSJack F Vogel s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 7113705f88SJack F Vogel { 729ca4041bSJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 739ca4041bSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 74a9ca1c79SSean Bruno u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 7513705f88SJack F Vogel 762969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_ops_generic"); 772969bf0eSJack F Vogel 7813705f88SJack F Vogel /* EEPROM */ 79758cc3dcSJack F Vogel eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; 809ca4041bSJack F Vogel /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 8185d0a26eSJack F Vogel if (eec & IXGBE_EEC_PRES) { 82758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eerd_generic; 83758cc3dcSJack F Vogel eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; 8485d0a26eSJack F Vogel } else { 85758cc3dcSJack F Vogel eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; 8685d0a26eSJack F Vogel eeprom->ops.read_buffer = 87758cc3dcSJack F Vogel ixgbe_read_eeprom_buffer_bit_bang_generic; 8885d0a26eSJack F Vogel } 89758cc3dcSJack F Vogel eeprom->ops.write = ixgbe_write_eeprom_generic; 90758cc3dcSJack F Vogel eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; 919ca4041bSJack F Vogel eeprom->ops.validate_checksum = 92758cc3dcSJack F Vogel ixgbe_validate_eeprom_checksum_generic; 93758cc3dcSJack F Vogel eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; 94758cc3dcSJack F Vogel eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; 959ca4041bSJack F Vogel 969ca4041bSJack F Vogel /* MAC */ 97758cc3dcSJack F Vogel mac->ops.init_hw = ixgbe_init_hw_generic; 989ca4041bSJack F Vogel mac->ops.reset_hw = NULL; 99758cc3dcSJack F Vogel mac->ops.start_hw = ixgbe_start_hw_generic; 100758cc3dcSJack F Vogel mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; 1019ca4041bSJack F Vogel mac->ops.get_media_type = NULL; 1021b6e0dbaSJack F Vogel mac->ops.get_supported_physical_layer = NULL; 103758cc3dcSJack F Vogel mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; 104758cc3dcSJack F Vogel mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; 105758cc3dcSJack F Vogel mac->ops.stop_adapter = ixgbe_stop_adapter_generic; 106758cc3dcSJack F Vogel mac->ops.get_bus_info = ixgbe_get_bus_info_generic; 107758cc3dcSJack F Vogel mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; 108758cc3dcSJack F Vogel mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; 109758cc3dcSJack F Vogel mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; 110758cc3dcSJack F Vogel mac->ops.prot_autoc_read = prot_autoc_read_generic; 111758cc3dcSJack F Vogel mac->ops.prot_autoc_write = prot_autoc_write_generic; 1129ca4041bSJack F Vogel 1139ca4041bSJack F Vogel /* LEDs */ 114758cc3dcSJack F Vogel mac->ops.led_on = ixgbe_led_on_generic; 115758cc3dcSJack F Vogel mac->ops.led_off = ixgbe_led_off_generic; 116758cc3dcSJack F Vogel mac->ops.blink_led_start = ixgbe_blink_led_start_generic; 117758cc3dcSJack F Vogel mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; 1188eb6488eSEric Joyner mac->ops.init_led_link_act = ixgbe_init_led_link_act_generic; 1199ca4041bSJack F Vogel 12013705f88SJack F Vogel /* RAR, Multicast, VLAN */ 121758cc3dcSJack F Vogel mac->ops.set_rar = ixgbe_set_rar_generic; 122758cc3dcSJack F Vogel mac->ops.clear_rar = ixgbe_clear_rar_generic; 1230ac6dfecSJack F Vogel mac->ops.insert_mac_addr = NULL; 1249ca4041bSJack F Vogel mac->ops.set_vmdq = NULL; 1255b7f4cedSJack F Vogel mac->ops.clear_vmdq = NULL; 126758cc3dcSJack F Vogel mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; 127758cc3dcSJack F Vogel mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; 128758cc3dcSJack F Vogel mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; 129758cc3dcSJack F Vogel mac->ops.enable_mc = ixgbe_enable_mc_generic; 130758cc3dcSJack F Vogel mac->ops.disable_mc = ixgbe_disable_mc_generic; 1315b7f4cedSJack F Vogel mac->ops.clear_vfta = NULL; 1325b7f4cedSJack F Vogel mac->ops.set_vfta = NULL; 13385d0a26eSJack F Vogel mac->ops.set_vlvf = NULL; 1345b7f4cedSJack F Vogel mac->ops.init_uta_tables = NULL; 135758cc3dcSJack F Vogel mac->ops.enable_rx = ixgbe_enable_rx_generic; 136758cc3dcSJack F Vogel mac->ops.disable_rx = ixgbe_disable_rx_generic; 1379ca4041bSJack F Vogel 1380ac6dfecSJack F Vogel /* Flow Control */ 139758cc3dcSJack F Vogel mac->ops.fc_enable = ixgbe_fc_enable_generic; 140758cc3dcSJack F Vogel mac->ops.setup_fc = ixgbe_setup_fc_generic; 1418eb6488eSEric Joyner mac->ops.fc_autoneg = ixgbe_fc_autoneg; 1429ca4041bSJack F Vogel 1439ca4041bSJack F Vogel /* Link */ 1449ca4041bSJack F Vogel mac->ops.get_link_capabilities = NULL; 1459ca4041bSJack F Vogel mac->ops.setup_link = NULL; 1469ca4041bSJack F Vogel mac->ops.check_link = NULL; 147fd75b91dSJack F Vogel mac->ops.dmac_config = NULL; 148fd75b91dSJack F Vogel mac->ops.dmac_update_tcs = NULL; 149fd75b91dSJack F Vogel mac->ops.dmac_config_tcs = NULL; 15013705f88SJack F Vogel 15113705f88SJack F Vogel return IXGBE_SUCCESS; 15213705f88SJack F Vogel } 15313705f88SJack F Vogel 15413705f88SJack F Vogel /** 155fd75b91dSJack F Vogel * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation 156fd75b91dSJack F Vogel * of flow control 157a621e3c8SJack F Vogel * @hw: pointer to hardware structure 158a621e3c8SJack F Vogel * 15979b36ec9SKevin Bowling * This function returns true if the device supports flow control 16079b36ec9SKevin Bowling * autonegotiation, and false if it does not. 161fd75b91dSJack F Vogel * 162a621e3c8SJack F Vogel **/ 163fd75b91dSJack F Vogel bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) 164a621e3c8SJack F Vogel { 16579b36ec9SKevin Bowling bool supported = false; 166fd75b91dSJack F Vogel ixgbe_link_speed speed; 167fd75b91dSJack F Vogel bool link_up; 168a621e3c8SJack F Vogel 169a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); 170a621e3c8SJack F Vogel 171fd75b91dSJack F Vogel switch (hw->phy.media_type) { 172fd75b91dSJack F Vogel case ixgbe_media_type_fiber_fixed: 173758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 174fd75b91dSJack F Vogel case ixgbe_media_type_fiber: 1758eb6488eSEric Joyner /* flow control autoneg black list */ 1768eb6488eSEric Joyner switch (hw->device_id) { 1778eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP: 1788eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_SFP_N: 1798eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP: 1808eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_QSFP_N: 18179b36ec9SKevin Bowling supported = false; 1828eb6488eSEric Joyner break; 1838eb6488eSEric Joyner default: 18479b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 185fd75b91dSJack F Vogel /* if link is down, assume supported */ 186fd75b91dSJack F Vogel if (link_up) 187fd75b91dSJack F Vogel supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? 18879b36ec9SKevin Bowling true : false; 189fd75b91dSJack F Vogel else 19079b36ec9SKevin Bowling supported = true; 1918eb6488eSEric Joyner } 1928eb6488eSEric Joyner 193fd75b91dSJack F Vogel break; 194fd75b91dSJack F Vogel case ixgbe_media_type_backplane: 1958eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_X_XFI) 19679b36ec9SKevin Bowling supported = false; 1978eb6488eSEric Joyner else 19879b36ec9SKevin Bowling supported = true; 199fd75b91dSJack F Vogel break; 200fd75b91dSJack F Vogel case ixgbe_media_type_copper: 201fd75b91dSJack F Vogel /* only some copper devices support flow control autoneg */ 202a621e3c8SJack F Vogel switch (hw->device_id) { 203a621e3c8SJack F Vogel case IXGBE_DEV_ID_82599_T3_LOM: 2040ecc2ff0SJack F Vogel case IXGBE_DEV_ID_X540T: 205758cc3dcSJack F Vogel case IXGBE_DEV_ID_X540T1: 206fd75b91dSJack F Vogel case IXGBE_DEV_ID_X540_BYPASS: 207758cc3dcSJack F Vogel case IXGBE_DEV_ID_X550T: 208a9ca1c79SSean Bruno case IXGBE_DEV_ID_X550T1: 2096f37f232SEric Joyner case IXGBE_DEV_ID_X550EM_X_10G_T: 2108eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_10G_T: 2118eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T: 2128eb6488eSEric Joyner case IXGBE_DEV_ID_X550EM_A_1G_T_L: 21379b36ec9SKevin Bowling supported = true; 214fd75b91dSJack F Vogel break; 215a621e3c8SJack F Vogel default: 21679b36ec9SKevin Bowling supported = false; 217a621e3c8SJack F Vogel } 218fd75b91dSJack F Vogel default: 219fd75b91dSJack F Vogel break; 220fd75b91dSJack F Vogel } 221fd75b91dSJack F Vogel 2228eb6488eSEric Joyner if (!supported) 223fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, 224fd75b91dSJack F Vogel "Device %x does not support flow control autoneg", 225fd75b91dSJack F Vogel hw->device_id); 226c19c7afeSEric Joyner 227fd75b91dSJack F Vogel return supported; 228a621e3c8SJack F Vogel } 229a621e3c8SJack F Vogel 230a621e3c8SJack F Vogel /** 231758cc3dcSJack F Vogel * ixgbe_setup_fc_generic - Set up flow control 232a621e3c8SJack F Vogel * @hw: pointer to hardware structure 233a621e3c8SJack F Vogel * 234a621e3c8SJack F Vogel * Called at init time to set up flow control. 235a621e3c8SJack F Vogel **/ 236758cc3dcSJack F Vogel s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) 237a621e3c8SJack F Vogel { 238a621e3c8SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 239a621e3c8SJack F Vogel u32 reg = 0, reg_bp = 0; 240a621e3c8SJack F Vogel u16 reg_cu = 0; 24179b36ec9SKevin Bowling bool locked = false; 242a621e3c8SJack F Vogel 243758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_fc_generic"); 244a621e3c8SJack F Vogel 245758cc3dcSJack F Vogel /* Validate the requested mode */ 246a621e3c8SJack F Vogel if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 247fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, 248fd75b91dSJack F Vogel "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 249a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 250a621e3c8SJack F Vogel goto out; 251a621e3c8SJack F Vogel } 252a621e3c8SJack F Vogel 253a621e3c8SJack F Vogel /* 254a621e3c8SJack F Vogel * 10gig parts do not have a word in the EEPROM to determine the 255a621e3c8SJack F Vogel * default flow control setting, so we explicitly set it to full. 256a621e3c8SJack F Vogel */ 257a621e3c8SJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_default) 258a621e3c8SJack F Vogel hw->fc.requested_mode = ixgbe_fc_full; 259a621e3c8SJack F Vogel 260a621e3c8SJack F Vogel /* 261a621e3c8SJack F Vogel * Set up the 1G and 10G flow control advertisement registers so the 262a621e3c8SJack F Vogel * HW will be able to do fc autoneg once the cable is plugged in. If 263a621e3c8SJack F Vogel * we link at 10G, the 1G advertisement is harmless and vice versa. 264a621e3c8SJack F Vogel */ 265a621e3c8SJack F Vogel switch (hw->phy.media_type) { 266a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 267758cc3dcSJack F Vogel /* some MAC's need RMW protection on AUTOC */ 268758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); 269758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 270758cc3dcSJack F Vogel goto out; 271758cc3dcSJack F Vogel 272be9f17dbSToomas Soome /* only backplane uses autoc */ 273be9f17dbSToomas Soome /* FALLTHROUGH */ 274758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 275758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 276758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 277a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 278758cc3dcSJack F Vogel 279a621e3c8SJack F Vogel break; 280a621e3c8SJack F Vogel case ixgbe_media_type_copper: 281a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 282a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); 283a621e3c8SJack F Vogel break; 284a621e3c8SJack F Vogel default: 285a621e3c8SJack F Vogel break; 286a621e3c8SJack F Vogel } 287a621e3c8SJack F Vogel 288a621e3c8SJack F Vogel /* 289a621e3c8SJack F Vogel * The possible values of fc.requested_mode are: 290a621e3c8SJack F Vogel * 0: Flow control is completely disabled 291a621e3c8SJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 292a621e3c8SJack F Vogel * but not send pause frames). 293a621e3c8SJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 294a621e3c8SJack F Vogel * we do not support receiving pause frames). 295a621e3c8SJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 296a621e3c8SJack F Vogel * other: Invalid. 297a621e3c8SJack F Vogel */ 298a621e3c8SJack F Vogel switch (hw->fc.requested_mode) { 299a621e3c8SJack F Vogel case ixgbe_fc_none: 300a621e3c8SJack F Vogel /* Flow control completely disabled by software override. */ 301a621e3c8SJack F Vogel reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 302a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 303a621e3c8SJack F Vogel reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | 304a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE); 305a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 306a621e3c8SJack F Vogel reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); 307a621e3c8SJack F Vogel break; 308a621e3c8SJack F Vogel case ixgbe_fc_tx_pause: 309a621e3c8SJack F Vogel /* 310a621e3c8SJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 311a621e3c8SJack F Vogel * disabled by software override. 312a621e3c8SJack F Vogel */ 313a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_ASM_PAUSE; 314a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; 315a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 316a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_ASM_PAUSE; 317a621e3c8SJack F Vogel reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; 318a621e3c8SJack F Vogel } else if (hw->phy.media_type == ixgbe_media_type_copper) { 319a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_ASM_PAUSE; 320a621e3c8SJack F Vogel reg_cu &= ~IXGBE_TAF_SYM_PAUSE; 321a621e3c8SJack F Vogel } 322a621e3c8SJack F Vogel break; 323a621e3c8SJack F Vogel case ixgbe_fc_rx_pause: 324a621e3c8SJack F Vogel /* 325a621e3c8SJack F Vogel * Rx Flow control is enabled and Tx Flow control is 326a621e3c8SJack F Vogel * disabled by software override. Since there really 327a621e3c8SJack F Vogel * isn't a way to advertise that we are capable of RX 328a621e3c8SJack F Vogel * Pause ONLY, we will advertise that we support both 329a621e3c8SJack F Vogel * symmetric and asymmetric Rx PAUSE, as such we fall 330a621e3c8SJack F Vogel * through to the fc_full statement. Later, we will 331a621e3c8SJack F Vogel * disable the adapter's ability to send PAUSE frames. 332a621e3c8SJack F Vogel */ 333a621e3c8SJack F Vogel case ixgbe_fc_full: 334a621e3c8SJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 335a621e3c8SJack F Vogel reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; 336a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) 337a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_SYM_PAUSE | 338a621e3c8SJack F Vogel IXGBE_AUTOC_ASM_PAUSE; 339a621e3c8SJack F Vogel else if (hw->phy.media_type == ixgbe_media_type_copper) 340a621e3c8SJack F Vogel reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; 341a621e3c8SJack F Vogel break; 342a621e3c8SJack F Vogel default: 343fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 344fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 345a621e3c8SJack F Vogel ret_val = IXGBE_ERR_CONFIG; 346a621e3c8SJack F Vogel goto out; 347a621e3c8SJack F Vogel break; 348a621e3c8SJack F Vogel } 349a621e3c8SJack F Vogel 350758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_X540) { 351a621e3c8SJack F Vogel /* 352a621e3c8SJack F Vogel * Enable auto-negotiation between the MAC & PHY; 353a621e3c8SJack F Vogel * the MAC will advertise clause 37 flow control. 354a621e3c8SJack F Vogel */ 355a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 356a621e3c8SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 357a621e3c8SJack F Vogel 358a621e3c8SJack F Vogel /* Disable AN timeout */ 359a621e3c8SJack F Vogel if (hw->fc.strict_ieee) 360a621e3c8SJack F Vogel reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 361a621e3c8SJack F Vogel 362a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 363a621e3c8SJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 364a621e3c8SJack F Vogel } 365a621e3c8SJack F Vogel 366a621e3c8SJack F Vogel /* 367a621e3c8SJack F Vogel * AUTOC restart handles negotiation of 1G and 10G on backplane 368a621e3c8SJack F Vogel * and copper. There is no need to set the PCS1GCTL register. 369a621e3c8SJack F Vogel * 370a621e3c8SJack F Vogel */ 371a621e3c8SJack F Vogel if (hw->phy.media_type == ixgbe_media_type_backplane) { 372a621e3c8SJack F Vogel reg_bp |= IXGBE_AUTOC_AN_RESTART; 373758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); 374758cc3dcSJack F Vogel if (ret_val) 3750ecc2ff0SJack F Vogel goto out; 376a621e3c8SJack F Vogel } else if ((hw->phy.media_type == ixgbe_media_type_copper) && 377fd75b91dSJack F Vogel (ixgbe_device_supports_autoneg_fc(hw))) { 378a621e3c8SJack F Vogel hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 379a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); 380a621e3c8SJack F Vogel } 381a621e3c8SJack F Vogel 382758cc3dcSJack F Vogel DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 383a621e3c8SJack F Vogel out: 384a621e3c8SJack F Vogel return ret_val; 385a621e3c8SJack F Vogel } 386a621e3c8SJack F Vogel 387a621e3c8SJack F Vogel /** 3889ca4041bSJack F Vogel * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 38913705f88SJack F Vogel * @hw: pointer to hardware structure 39013705f88SJack F Vogel * 39113705f88SJack F Vogel * Starts the hardware by filling the bus info structure and media type, clears 39213705f88SJack F Vogel * all on chip counters, initializes receive address registers, multicast 39313705f88SJack F Vogel * table, VLAN filter table, calls routine to set up link and flow control 39413705f88SJack F Vogel * settings, and leaves transmit and receive units disabled and uninitialized 39513705f88SJack F Vogel **/ 39613705f88SJack F Vogel s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 39713705f88SJack F Vogel { 398a621e3c8SJack F Vogel s32 ret_val; 39913705f88SJack F Vogel u32 ctrl_ext; 4008eb6488eSEric Joyner u16 device_caps; 40113705f88SJack F Vogel 4022969bf0eSJack F Vogel DEBUGFUNC("ixgbe_start_hw_generic"); 4032969bf0eSJack F Vogel 40413705f88SJack F Vogel /* Set the media type */ 4059ca4041bSJack F Vogel hw->phy.media_type = hw->mac.ops.get_media_type(hw); 40613705f88SJack F Vogel 4070ac6dfecSJack F Vogel /* PHY ops initialization must be done in reset_hw() */ 40813705f88SJack F Vogel 40913705f88SJack F Vogel /* Clear the VLAN filter table */ 4109ca4041bSJack F Vogel hw->mac.ops.clear_vfta(hw); 41113705f88SJack F Vogel 41213705f88SJack F Vogel /* Clear statistics registers */ 4139ca4041bSJack F Vogel hw->mac.ops.clear_hw_cntrs(hw); 41413705f88SJack F Vogel 41513705f88SJack F Vogel /* Set No Snoop Disable */ 41613705f88SJack F Vogel ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 41713705f88SJack F Vogel ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 41813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 4199ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 42013705f88SJack F Vogel 4210ac6dfecSJack F Vogel /* Setup flow control */ 422a621e3c8SJack F Vogel ret_val = ixgbe_setup_fc(hw); 4238eb6488eSEric Joyner if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED) { 4248eb6488eSEric Joyner DEBUGOUT1("Flow control setup failed, returning %d\n", ret_val); 4258eb6488eSEric Joyner return ret_val; 4268eb6488eSEric Joyner } 4278eb6488eSEric Joyner 4288eb6488eSEric Joyner /* Cache bit indicating need for crosstalk fix */ 4298eb6488eSEric Joyner switch (hw->mac.type) { 4308eb6488eSEric Joyner case ixgbe_mac_82599EB: 4318eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 4328eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 4338eb6488eSEric Joyner hw->mac.ops.get_device_caps(hw, &device_caps); 4348eb6488eSEric Joyner if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR) 43579b36ec9SKevin Bowling hw->need_crosstalk_fix = false; 4368eb6488eSEric Joyner else 43779b36ec9SKevin Bowling hw->need_crosstalk_fix = true; 4388eb6488eSEric Joyner break; 4398eb6488eSEric Joyner default: 44079b36ec9SKevin Bowling hw->need_crosstalk_fix = false; 4418eb6488eSEric Joyner break; 4428eb6488eSEric Joyner } 4430ac6dfecSJack F Vogel 44413705f88SJack F Vogel /* Clear adapter stopped flag */ 44579b36ec9SKevin Bowling hw->adapter_stopped = false; 44613705f88SJack F Vogel 4478eb6488eSEric Joyner return IXGBE_SUCCESS; 4481a4e3449SJack F Vogel } 4491a4e3449SJack F Vogel 4501a4e3449SJack F Vogel /** 4511a4e3449SJack F Vogel * ixgbe_start_hw_gen2 - Init sequence for common device family 4521a4e3449SJack F Vogel * @hw: pointer to hw structure 4531a4e3449SJack F Vogel * 4541a4e3449SJack F Vogel * Performs the init sequence common to the second generation 4551a4e3449SJack F Vogel * of 10 GbE devices. 4561a4e3449SJack F Vogel * Devices in the second generation: 4571a4e3449SJack F Vogel * 82599 458182b3808SJack F Vogel * X540 4591a4e3449SJack F Vogel **/ 4603a890053SGuinan Sun void ixgbe_start_hw_gen2(struct ixgbe_hw *hw) 4611a4e3449SJack F Vogel { 4621a4e3449SJack F Vogel u32 i; 4631a4e3449SJack F Vogel u32 regval; 4641a4e3449SJack F Vogel 4651a4e3449SJack F Vogel /* Clear the rate limiters */ 4661a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4671a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); 4681a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); 4691a4e3449SJack F Vogel } 4701a4e3449SJack F Vogel IXGBE_WRITE_FLUSH(hw); 4711a4e3449SJack F Vogel 4721a4e3449SJack F Vogel /* Disable relaxed ordering */ 4731a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4741a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 475a621e3c8SJack F Vogel regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4761a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4771a4e3449SJack F Vogel } 4781a4e3449SJack F Vogel 4791a4e3449SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4801a4e3449SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 481a621e3c8SJack F Vogel regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | 482a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN); 4831a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4841a4e3449SJack F Vogel } 48513705f88SJack F Vogel } 48613705f88SJack F Vogel 48713705f88SJack F Vogel /** 48813705f88SJack F Vogel * ixgbe_init_hw_generic - Generic hardware initialization 48913705f88SJack F Vogel * @hw: pointer to hardware structure 49013705f88SJack F Vogel * 4919ca4041bSJack F Vogel * Initialize the hardware by resetting the hardware, filling the bus info 49213705f88SJack F Vogel * structure and media type, clears all on chip counters, initializes receive 49313705f88SJack F Vogel * address registers, multicast table, VLAN filter table, calls routine to set 49413705f88SJack F Vogel * up link and flow control settings, and leaves transmit and receive units 49513705f88SJack F Vogel * disabled and uninitialized 49613705f88SJack F Vogel **/ 49713705f88SJack F Vogel s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 49813705f88SJack F Vogel { 4991a4e3449SJack F Vogel s32 status; 5000ac6dfecSJack F Vogel 5012969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_hw_generic"); 5022969bf0eSJack F Vogel 50313705f88SJack F Vogel /* Reset the hardware */ 5040ac6dfecSJack F Vogel status = hw->mac.ops.reset_hw(hw); 50513705f88SJack F Vogel 5068eb6488eSEric Joyner if (status == IXGBE_SUCCESS || status == IXGBE_ERR_SFP_NOT_PRESENT) { 50713705f88SJack F Vogel /* Start the HW */ 5080ac6dfecSJack F Vogel status = hw->mac.ops.start_hw(hw); 5090ac6dfecSJack F Vogel } 51013705f88SJack F Vogel 5118eb6488eSEric Joyner /* Initialize the LED link active for LED blink support */ 5128eb6488eSEric Joyner if (hw->mac.ops.init_led_link_act) 5138eb6488eSEric Joyner hw->mac.ops.init_led_link_act(hw); 5148eb6488eSEric Joyner 5158eb6488eSEric Joyner if (status != IXGBE_SUCCESS) 5168eb6488eSEric Joyner DEBUGOUT1("Failed to initialize HW, STATUS = %d\n", status); 5178eb6488eSEric Joyner 5180ac6dfecSJack F Vogel return status; 51913705f88SJack F Vogel } 52013705f88SJack F Vogel 52113705f88SJack F Vogel /** 52213705f88SJack F Vogel * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 52313705f88SJack F Vogel * @hw: pointer to hardware structure 52413705f88SJack F Vogel * 52513705f88SJack F Vogel * Clears all hardware statistics counters by reading them from the hardware 52613705f88SJack F Vogel * Statistics counters are clear on read. 52713705f88SJack F Vogel **/ 52813705f88SJack F Vogel s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 52913705f88SJack F Vogel { 53013705f88SJack F Vogel u16 i = 0; 53113705f88SJack F Vogel 5322969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 5332969bf0eSJack F Vogel 53413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_CRCERRS); 53513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ILLERRC); 53613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ERRBC); 53713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MSPDC); 53813705f88SJack F Vogel for (i = 0; i < 8; i++) 53913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPC(i)); 54013705f88SJack F Vogel 54113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MLFC); 54213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MRFC); 54313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RLEC); 54413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONTXC); 54513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 5460ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5470ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 5480ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 5490ac6dfecSJack F Vogel } else { 5501b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXONRXC); 55113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 5520ac6dfecSJack F Vogel } 55313705f88SJack F Vogel 55413705f88SJack F Vogel for (i = 0; i < 8; i++) { 55513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 55613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 5570ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 5580ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 5590ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 5600ac6dfecSJack F Vogel } else { 5611b6e0dbaSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 56213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 56313705f88SJack F Vogel } 5640ac6dfecSJack F Vogel } 5650ac6dfecSJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) 5660ac6dfecSJack F Vogel for (i = 0; i < 8; i++) 5670ac6dfecSJack F Vogel IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 56813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC64); 56913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC127); 57013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC255); 57113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC511); 57213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1023); 57313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PRC1522); 57413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPRC); 57513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPRC); 57613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPRC); 57713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GPTC); 57813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCL); 57913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GORCH); 58013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCL); 58113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_GOTCH); 58285d0a26eSJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 58313705f88SJack F Vogel for (i = 0; i < 8; i++) 58413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 58513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RUC); 58613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RFC); 58713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_ROC); 58813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_RJC); 58913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPRC); 59013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPDC); 59113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MNGPTC); 59213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORL); 59313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TORH); 59413705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPR); 59513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_TPT); 59613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC64); 59713705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC127); 59813705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC255); 59913705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC511); 60013705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1023); 60113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_PTC1522); 60213705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_MPTC); 60313705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_BPTC); 60413705f88SJack F Vogel for (i = 0; i < 16; i++) { 60513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 60613705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 6071a4e3449SJack F Vogel if (hw->mac.type >= ixgbe_mac_82599EB) { 6081a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); 6091a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); 6101a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 6111a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 6121a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); 6131a4e3449SJack F Vogel } else { 6141a4e3449SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 61513705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 61613705f88SJack F Vogel } 6171a4e3449SJack F Vogel } 6181a4e3449SJack F Vogel 619758cc3dcSJack F Vogel if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { 62085d0a26eSJack F Vogel if (hw->phy.id == 0) 62185d0a26eSJack F Vogel ixgbe_identify_phy(hw); 62285d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, 62385d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62485d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, 62585d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62685d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, 62785d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 62885d0a26eSJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, 62985d0a26eSJack F Vogel IXGBE_MDIO_PCS_DEV_TYPE, &i); 63085d0a26eSJack F Vogel } 63185d0a26eSJack F Vogel 6321a4e3449SJack F Vogel return IXGBE_SUCCESS; 6331a4e3449SJack F Vogel } 6341a4e3449SJack F Vogel 6351a4e3449SJack F Vogel /** 6361a4e3449SJack F Vogel * ixgbe_read_pba_string_generic - Reads part number string from EEPROM 6371a4e3449SJack F Vogel * @hw: pointer to hardware structure 6381a4e3449SJack F Vogel * @pba_num: stores the part number string from the EEPROM 6391a4e3449SJack F Vogel * @pba_num_size: part number string buffer length 6401a4e3449SJack F Vogel * 6411a4e3449SJack F Vogel * Reads the part number string from the EEPROM. 6421a4e3449SJack F Vogel **/ 6431a4e3449SJack F Vogel s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, 6441a4e3449SJack F Vogel u32 pba_num_size) 6451a4e3449SJack F Vogel { 6461a4e3449SJack F Vogel s32 ret_val; 6471a4e3449SJack F Vogel u16 data; 6481a4e3449SJack F Vogel u16 pba_ptr; 6491a4e3449SJack F Vogel u16 offset; 6501a4e3449SJack F Vogel u16 length; 6511a4e3449SJack F Vogel 6521a4e3449SJack F Vogel DEBUGFUNC("ixgbe_read_pba_string_generic"); 6531a4e3449SJack F Vogel 6541a4e3449SJack F Vogel if (pba_num == NULL) { 6551a4e3449SJack F Vogel DEBUGOUT("PBA string buffer was null\n"); 6561a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 6571a4e3449SJack F Vogel } 6581a4e3449SJack F Vogel 6591a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 6601a4e3449SJack F Vogel if (ret_val) { 6611a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6621a4e3449SJack F Vogel return ret_val; 6631a4e3449SJack F Vogel } 6641a4e3449SJack F Vogel 6651a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); 6661a4e3449SJack F Vogel if (ret_val) { 6671a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 6681a4e3449SJack F Vogel return ret_val; 6691a4e3449SJack F Vogel } 6701a4e3449SJack F Vogel 6711a4e3449SJack F Vogel /* 6721a4e3449SJack F Vogel * if data is not ptr guard the PBA must be in legacy format which 6731a4e3449SJack F Vogel * means pba_ptr is actually our second data word for the PBA number 6741a4e3449SJack F Vogel * and we can decode it into an ascii string 6751a4e3449SJack F Vogel */ 6761a4e3449SJack F Vogel if (data != IXGBE_PBANUM_PTR_GUARD) { 6771a4e3449SJack F Vogel DEBUGOUT("NVM PBA number is not stored as string\n"); 6781a4e3449SJack F Vogel 6791a4e3449SJack F Vogel /* we will need 11 characters to store the PBA */ 6801a4e3449SJack F Vogel if (pba_num_size < 11) { 6811a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 6821a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 6831a4e3449SJack F Vogel } 6841a4e3449SJack F Vogel 6851a4e3449SJack F Vogel /* extract hex string from data and pba_ptr */ 6861a4e3449SJack F Vogel pba_num[0] = (data >> 12) & 0xF; 6871a4e3449SJack F Vogel pba_num[1] = (data >> 8) & 0xF; 6881a4e3449SJack F Vogel pba_num[2] = (data >> 4) & 0xF; 6891a4e3449SJack F Vogel pba_num[3] = data & 0xF; 6901a4e3449SJack F Vogel pba_num[4] = (pba_ptr >> 12) & 0xF; 6911a4e3449SJack F Vogel pba_num[5] = (pba_ptr >> 8) & 0xF; 6921a4e3449SJack F Vogel pba_num[6] = '-'; 6931a4e3449SJack F Vogel pba_num[7] = 0; 6941a4e3449SJack F Vogel pba_num[8] = (pba_ptr >> 4) & 0xF; 6951a4e3449SJack F Vogel pba_num[9] = pba_ptr & 0xF; 6961a4e3449SJack F Vogel 6971a4e3449SJack F Vogel /* put a null character on the end of our string */ 6981a4e3449SJack F Vogel pba_num[10] = '\0'; 6991a4e3449SJack F Vogel 7001a4e3449SJack F Vogel /* switch all the data but the '-' to hex char */ 7011a4e3449SJack F Vogel for (offset = 0; offset < 10; offset++) { 7021a4e3449SJack F Vogel if (pba_num[offset] < 0xA) 7031a4e3449SJack F Vogel pba_num[offset] += '0'; 7041a4e3449SJack F Vogel else if (pba_num[offset] < 0x10) 7051a4e3449SJack F Vogel pba_num[offset] += 'A' - 0xA; 7061a4e3449SJack F Vogel } 7071a4e3449SJack F Vogel 7081a4e3449SJack F Vogel return IXGBE_SUCCESS; 7091a4e3449SJack F Vogel } 7101a4e3449SJack F Vogel 7111a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); 7121a4e3449SJack F Vogel if (ret_val) { 7131a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7141a4e3449SJack F Vogel return ret_val; 7151a4e3449SJack F Vogel } 7161a4e3449SJack F Vogel 7171a4e3449SJack F Vogel if (length == 0xFFFF || length == 0) { 7181a4e3449SJack F Vogel DEBUGOUT("NVM PBA number section invalid length\n"); 7191a4e3449SJack F Vogel return IXGBE_ERR_PBA_SECTION; 7201a4e3449SJack F Vogel } 7211a4e3449SJack F Vogel 7221a4e3449SJack F Vogel /* check if pba_num buffer is big enough */ 7231a4e3449SJack F Vogel if (pba_num_size < (((u32)length * 2) - 1)) { 7241a4e3449SJack F Vogel DEBUGOUT("PBA string buffer too small\n"); 7251a4e3449SJack F Vogel return IXGBE_ERR_NO_SPACE; 7261a4e3449SJack F Vogel } 7271a4e3449SJack F Vogel 7281a4e3449SJack F Vogel /* trim pba length from start of string */ 7291a4e3449SJack F Vogel pba_ptr++; 7301a4e3449SJack F Vogel length--; 7311a4e3449SJack F Vogel 7321a4e3449SJack F Vogel for (offset = 0; offset < length; offset++) { 7331a4e3449SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); 7341a4e3449SJack F Vogel if (ret_val) { 7351a4e3449SJack F Vogel DEBUGOUT("NVM Read Error\n"); 7361a4e3449SJack F Vogel return ret_val; 7371a4e3449SJack F Vogel } 7381a4e3449SJack F Vogel pba_num[offset * 2] = (u8)(data >> 8); 7391a4e3449SJack F Vogel pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); 7401a4e3449SJack F Vogel } 7411a4e3449SJack F Vogel pba_num[offset * 2] = '\0'; 7421a4e3449SJack F Vogel 7431a4e3449SJack F Vogel return IXGBE_SUCCESS; 7441a4e3449SJack F Vogel } 7451a4e3449SJack F Vogel 7461a4e3449SJack F Vogel /** 7471b6e0dbaSJack F Vogel * ixgbe_read_pba_num_generic - Reads part number from EEPROM 7489ca4041bSJack F Vogel * @hw: pointer to hardware structure 7499ca4041bSJack F Vogel * @pba_num: stores the part number from the EEPROM 7509ca4041bSJack F Vogel * 7519ca4041bSJack F Vogel * Reads the part number from the EEPROM. 7529ca4041bSJack F Vogel **/ 7539ca4041bSJack F Vogel s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 7549ca4041bSJack F Vogel { 7559ca4041bSJack F Vogel s32 ret_val; 7569ca4041bSJack F Vogel u16 data; 7579ca4041bSJack F Vogel 7589ca4041bSJack F Vogel DEBUGFUNC("ixgbe_read_pba_num_generic"); 7599ca4041bSJack F Vogel 7609ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 7619ca4041bSJack F Vogel if (ret_val) { 7629ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7639ca4041bSJack F Vogel return ret_val; 7641a4e3449SJack F Vogel } else if (data == IXGBE_PBANUM_PTR_GUARD) { 7651a4e3449SJack F Vogel DEBUGOUT("NVM Not supported\n"); 7661a4e3449SJack F Vogel return IXGBE_NOT_IMPLEMENTED; 7679ca4041bSJack F Vogel } 7689ca4041bSJack F Vogel *pba_num = (u32)(data << 16); 7699ca4041bSJack F Vogel 7709ca4041bSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 7719ca4041bSJack F Vogel if (ret_val) { 7729ca4041bSJack F Vogel DEBUGOUT("NVM Read Error\n"); 7739ca4041bSJack F Vogel return ret_val; 7749ca4041bSJack F Vogel } 775994dd632SGuinan Sun *pba_num |= (u32)data; 7769ca4041bSJack F Vogel 7779ca4041bSJack F Vogel return IXGBE_SUCCESS; 7789ca4041bSJack F Vogel } 7799ca4041bSJack F Vogel 7809ca4041bSJack F Vogel /** 7810ecc2ff0SJack F Vogel * ixgbe_read_pba_raw 7820ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 7830ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 7840ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 7850ecc2ff0SJack F Vogel * @max_pba_block_size: PBA block size limit 7860ecc2ff0SJack F Vogel * @pba: pointer to output PBA structure 7870ecc2ff0SJack F Vogel * 7880ecc2ff0SJack F Vogel * Reads PBA from EEPROM image when eeprom_buf is not NULL. 7890ecc2ff0SJack F Vogel * Reads PBA from physical EEPROM device when eeprom_buf is NULL. 7900ecc2ff0SJack F Vogel * 7910ecc2ff0SJack F Vogel **/ 7920ecc2ff0SJack F Vogel s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 7930ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 max_pba_block_size, 7940ecc2ff0SJack F Vogel struct ixgbe_pba *pba) 7950ecc2ff0SJack F Vogel { 7960ecc2ff0SJack F Vogel s32 ret_val; 7970ecc2ff0SJack F Vogel u16 pba_block_size; 7980ecc2ff0SJack F Vogel 7990ecc2ff0SJack F Vogel if (pba == NULL) 8000ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8010ecc2ff0SJack F Vogel 8020ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8030ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8040ecc2ff0SJack F Vogel &pba->word[0]); 8050ecc2ff0SJack F Vogel if (ret_val) 8060ecc2ff0SJack F Vogel return ret_val; 8070ecc2ff0SJack F Vogel } else { 8080ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8090ecc2ff0SJack F Vogel pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 8100ecc2ff0SJack F Vogel pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 8110ecc2ff0SJack F Vogel } else { 8120ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8130ecc2ff0SJack F Vogel } 8140ecc2ff0SJack F Vogel } 8150ecc2ff0SJack F Vogel 8160ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8170ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8180ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8190ecc2ff0SJack F Vogel 8200ecc2ff0SJack F Vogel ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, 8210ecc2ff0SJack F Vogel eeprom_buf_size, 8220ecc2ff0SJack F Vogel &pba_block_size); 8230ecc2ff0SJack F Vogel if (ret_val) 8240ecc2ff0SJack F Vogel return ret_val; 8250ecc2ff0SJack F Vogel 8260ecc2ff0SJack F Vogel if (pba_block_size > max_pba_block_size) 8270ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8280ecc2ff0SJack F Vogel 8290ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8300ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], 8310ecc2ff0SJack F Vogel pba_block_size, 8320ecc2ff0SJack F Vogel pba->pba_block); 8330ecc2ff0SJack F Vogel if (ret_val) 8340ecc2ff0SJack F Vogel return ret_val; 8350ecc2ff0SJack F Vogel } else { 8360ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 837758cc3dcSJack F Vogel pba_block_size)) { 8380ecc2ff0SJack F Vogel memcpy(pba->pba_block, 8390ecc2ff0SJack F Vogel &eeprom_buf[pba->word[1]], 8400ecc2ff0SJack F Vogel pba_block_size * sizeof(u16)); 8410ecc2ff0SJack F Vogel } else { 8420ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8430ecc2ff0SJack F Vogel } 8440ecc2ff0SJack F Vogel } 8450ecc2ff0SJack F Vogel } 8460ecc2ff0SJack F Vogel 8470ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 8480ecc2ff0SJack F Vogel } 8490ecc2ff0SJack F Vogel 8500ecc2ff0SJack F Vogel /** 8510ecc2ff0SJack F Vogel * ixgbe_write_pba_raw 8520ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 8530ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 8540ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 8550ecc2ff0SJack F Vogel * @pba: pointer to PBA structure 8560ecc2ff0SJack F Vogel * 8570ecc2ff0SJack F Vogel * Writes PBA to EEPROM image when eeprom_buf is not NULL. 8580ecc2ff0SJack F Vogel * Writes PBA to physical EEPROM device when eeprom_buf is NULL. 8590ecc2ff0SJack F Vogel * 8600ecc2ff0SJack F Vogel **/ 8610ecc2ff0SJack F Vogel s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, 8620ecc2ff0SJack F Vogel u32 eeprom_buf_size, struct ixgbe_pba *pba) 8630ecc2ff0SJack F Vogel { 8640ecc2ff0SJack F Vogel s32 ret_val; 8650ecc2ff0SJack F Vogel 8660ecc2ff0SJack F Vogel if (pba == NULL) 8670ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8680ecc2ff0SJack F Vogel 8690ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8700ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, 8710ecc2ff0SJack F Vogel &pba->word[0]); 8720ecc2ff0SJack F Vogel if (ret_val) 8730ecc2ff0SJack F Vogel return ret_val; 8740ecc2ff0SJack F Vogel } else { 8750ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 8760ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; 8770ecc2ff0SJack F Vogel eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; 8780ecc2ff0SJack F Vogel } else { 8790ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8800ecc2ff0SJack F Vogel } 8810ecc2ff0SJack F Vogel } 8820ecc2ff0SJack F Vogel 8830ecc2ff0SJack F Vogel if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { 8840ecc2ff0SJack F Vogel if (pba->pba_block == NULL) 8850ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 8860ecc2ff0SJack F Vogel 8870ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 8880ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], 8890ecc2ff0SJack F Vogel pba->pba_block[0], 8900ecc2ff0SJack F Vogel pba->pba_block); 8910ecc2ff0SJack F Vogel if (ret_val) 8920ecc2ff0SJack F Vogel return ret_val; 8930ecc2ff0SJack F Vogel } else { 8940ecc2ff0SJack F Vogel if (eeprom_buf_size > (u32)(pba->word[1] + 8950ecc2ff0SJack F Vogel pba->pba_block[0])) { 8960ecc2ff0SJack F Vogel memcpy(&eeprom_buf[pba->word[1]], 8970ecc2ff0SJack F Vogel pba->pba_block, 8980ecc2ff0SJack F Vogel pba->pba_block[0] * sizeof(u16)); 8990ecc2ff0SJack F Vogel } else { 9000ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9010ecc2ff0SJack F Vogel } 9020ecc2ff0SJack F Vogel } 9030ecc2ff0SJack F Vogel } 9040ecc2ff0SJack F Vogel 9050ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9060ecc2ff0SJack F Vogel } 9070ecc2ff0SJack F Vogel 9080ecc2ff0SJack F Vogel /** 9090ecc2ff0SJack F Vogel * ixgbe_get_pba_block_size 9100ecc2ff0SJack F Vogel * @hw: pointer to the HW structure 9110ecc2ff0SJack F Vogel * @eeprom_buf: optional pointer to EEPROM image 9120ecc2ff0SJack F Vogel * @eeprom_buf_size: size of EEPROM image in words 9130ecc2ff0SJack F Vogel * @pba_data_size: pointer to output variable 9140ecc2ff0SJack F Vogel * 9150ecc2ff0SJack F Vogel * Returns the size of the PBA block in words. Function operates on EEPROM 9160ecc2ff0SJack F Vogel * image if the eeprom_buf pointer is not NULL otherwise it accesses physical 9170ecc2ff0SJack F Vogel * EEPROM device. 9180ecc2ff0SJack F Vogel * 9190ecc2ff0SJack F Vogel **/ 9200ecc2ff0SJack F Vogel s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, 9210ecc2ff0SJack F Vogel u32 eeprom_buf_size, u16 *pba_block_size) 9220ecc2ff0SJack F Vogel { 9230ecc2ff0SJack F Vogel s32 ret_val; 9240ecc2ff0SJack F Vogel u16 pba_word[2]; 9250ecc2ff0SJack F Vogel u16 length; 9260ecc2ff0SJack F Vogel 9270ecc2ff0SJack F Vogel DEBUGFUNC("ixgbe_get_pba_block_size"); 9280ecc2ff0SJack F Vogel 9290ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9300ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, 9310ecc2ff0SJack F Vogel &pba_word[0]); 9320ecc2ff0SJack F Vogel if (ret_val) 9330ecc2ff0SJack F Vogel return ret_val; 9340ecc2ff0SJack F Vogel } else { 9350ecc2ff0SJack F Vogel if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { 9360ecc2ff0SJack F Vogel pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; 9370ecc2ff0SJack F Vogel pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; 9380ecc2ff0SJack F Vogel } else { 9390ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9400ecc2ff0SJack F Vogel } 9410ecc2ff0SJack F Vogel } 9420ecc2ff0SJack F Vogel 9430ecc2ff0SJack F Vogel if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { 9440ecc2ff0SJack F Vogel if (eeprom_buf == NULL) { 9450ecc2ff0SJack F Vogel ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, 9460ecc2ff0SJack F Vogel &length); 9470ecc2ff0SJack F Vogel if (ret_val) 9480ecc2ff0SJack F Vogel return ret_val; 9490ecc2ff0SJack F Vogel } else { 9500ecc2ff0SJack F Vogel if (eeprom_buf_size > pba_word[1]) 9510ecc2ff0SJack F Vogel length = eeprom_buf[pba_word[1] + 0]; 9520ecc2ff0SJack F Vogel else 9530ecc2ff0SJack F Vogel return IXGBE_ERR_PARAM; 9540ecc2ff0SJack F Vogel } 9550ecc2ff0SJack F Vogel 9560ecc2ff0SJack F Vogel if (length == 0xFFFF || length == 0) 9570ecc2ff0SJack F Vogel return IXGBE_ERR_PBA_SECTION; 9580ecc2ff0SJack F Vogel } else { 9590ecc2ff0SJack F Vogel /* PBA number in legacy format, there is no PBA Block. */ 9600ecc2ff0SJack F Vogel length = 0; 9610ecc2ff0SJack F Vogel } 9620ecc2ff0SJack F Vogel 9630ecc2ff0SJack F Vogel if (pba_block_size != NULL) 9640ecc2ff0SJack F Vogel *pba_block_size = length; 9650ecc2ff0SJack F Vogel 9660ecc2ff0SJack F Vogel return IXGBE_SUCCESS; 9670ecc2ff0SJack F Vogel } 9680ecc2ff0SJack F Vogel 9690ecc2ff0SJack F Vogel /** 97013705f88SJack F Vogel * ixgbe_get_mac_addr_generic - Generic get MAC address 97113705f88SJack F Vogel * @hw: pointer to hardware structure 97213705f88SJack F Vogel * @mac_addr: Adapter MAC address 97313705f88SJack F Vogel * 97413705f88SJack F Vogel * Reads the adapter's MAC address from first Receive Address Register (RAR0) 97513705f88SJack F Vogel * A reset of the adapter must be performed prior to calling this function 97613705f88SJack F Vogel * in order for the MAC address to have been loaded from the EEPROM into RAR0 97713705f88SJack F Vogel **/ 97813705f88SJack F Vogel s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 97913705f88SJack F Vogel { 98013705f88SJack F Vogel u32 rar_high; 98113705f88SJack F Vogel u32 rar_low; 98213705f88SJack F Vogel u16 i; 98313705f88SJack F Vogel 9842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_mac_addr_generic"); 9852969bf0eSJack F Vogel 98613705f88SJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 98713705f88SJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 98813705f88SJack F Vogel 98913705f88SJack F Vogel for (i = 0; i < 4; i++) 99013705f88SJack F Vogel mac_addr[i] = (u8)(rar_low >> (i*8)); 99113705f88SJack F Vogel 99213705f88SJack F Vogel for (i = 0; i < 2; i++) 99313705f88SJack F Vogel mac_addr[i+4] = (u8)(rar_high >> (i*8)); 99413705f88SJack F Vogel 99513705f88SJack F Vogel return IXGBE_SUCCESS; 99613705f88SJack F Vogel } 99713705f88SJack F Vogel 99813705f88SJack F Vogel /** 999fd75b91dSJack F Vogel * ixgbe_set_pci_config_data_generic - Generic store PCI bus info 100013705f88SJack F Vogel * @hw: pointer to hardware structure 1001fd75b91dSJack F Vogel * @link_status: the link status returned by the PCI config space 100213705f88SJack F Vogel * 1003fd75b91dSJack F Vogel * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure 100413705f88SJack F Vogel **/ 1005fd75b91dSJack F Vogel void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) 100613705f88SJack F Vogel { 10071b6e0dbaSJack F Vogel struct ixgbe_mac_info *mac = &hw->mac; 10082969bf0eSJack F Vogel 1009758cc3dcSJack F Vogel if (hw->bus.type == ixgbe_bus_type_unknown) 101013705f88SJack F Vogel hw->bus.type = ixgbe_bus_type_pci_express; 101113705f88SJack F Vogel 101213705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_WIDTH) { 101313705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_1: 101413705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x1; 101513705f88SJack F Vogel break; 101613705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_2: 101713705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x2; 101813705f88SJack F Vogel break; 101913705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_4: 102013705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x4; 102113705f88SJack F Vogel break; 102213705f88SJack F Vogel case IXGBE_PCI_LINK_WIDTH_8: 102313705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_pcie_x8; 102413705f88SJack F Vogel break; 102513705f88SJack F Vogel default: 102613705f88SJack F Vogel hw->bus.width = ixgbe_bus_width_unknown; 102713705f88SJack F Vogel break; 102813705f88SJack F Vogel } 102913705f88SJack F Vogel 103013705f88SJack F Vogel switch (link_status & IXGBE_PCI_LINK_SPEED) { 103113705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_2500: 103213705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_2500; 103313705f88SJack F Vogel break; 103413705f88SJack F Vogel case IXGBE_PCI_LINK_SPEED_5000: 103513705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_5000; 103613705f88SJack F Vogel break; 1037a621e3c8SJack F Vogel case IXGBE_PCI_LINK_SPEED_8000: 1038a621e3c8SJack F Vogel hw->bus.speed = ixgbe_bus_speed_8000; 1039a621e3c8SJack F Vogel break; 104013705f88SJack F Vogel default: 104113705f88SJack F Vogel hw->bus.speed = ixgbe_bus_speed_unknown; 104213705f88SJack F Vogel break; 104313705f88SJack F Vogel } 104413705f88SJack F Vogel 10451b6e0dbaSJack F Vogel mac->ops.set_lan_id(hw); 1046fd75b91dSJack F Vogel } 1047fd75b91dSJack F Vogel 1048fd75b91dSJack F Vogel /** 1049fd75b91dSJack F Vogel * ixgbe_get_bus_info_generic - Generic set PCI bus info 1050fd75b91dSJack F Vogel * @hw: pointer to hardware structure 1051fd75b91dSJack F Vogel * 1052fd75b91dSJack F Vogel * Gets the PCI bus info (speed, width, type) then calls helper function to 1053fd75b91dSJack F Vogel * store this data within the ixgbe_hw structure. 1054fd75b91dSJack F Vogel **/ 1055fd75b91dSJack F Vogel s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 1056fd75b91dSJack F Vogel { 1057fd75b91dSJack F Vogel u16 link_status; 1058fd75b91dSJack F Vogel 1059fd75b91dSJack F Vogel DEBUGFUNC("ixgbe_get_bus_info_generic"); 1060fd75b91dSJack F Vogel 1061fd75b91dSJack F Vogel /* Get the negotiated link width and speed from PCI config space */ 1062fd75b91dSJack F Vogel link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 1063fd75b91dSJack F Vogel 1064fd75b91dSJack F Vogel ixgbe_set_pci_config_data_generic(hw, link_status); 10651b6e0dbaSJack F Vogel 106613705f88SJack F Vogel return IXGBE_SUCCESS; 106713705f88SJack F Vogel } 106813705f88SJack F Vogel 106913705f88SJack F Vogel /** 10701b6e0dbaSJack F Vogel * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 10711b6e0dbaSJack F Vogel * @hw: pointer to the HW structure 10721b6e0dbaSJack F Vogel * 10738eb6488eSEric Joyner * Determines the LAN function id by reading memory-mapped registers and swaps 10748eb6488eSEric Joyner * the port value if requested, and set MAC instance for devices that share 10758eb6488eSEric Joyner * CS4227. 10761b6e0dbaSJack F Vogel **/ 10771b6e0dbaSJack F Vogel void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 10781b6e0dbaSJack F Vogel { 10791b6e0dbaSJack F Vogel struct ixgbe_bus_info *bus = &hw->bus; 10801b6e0dbaSJack F Vogel u32 reg; 10818eb6488eSEric Joyner u16 ee_ctrl_4; 10821b6e0dbaSJack F Vogel 10832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 10842969bf0eSJack F Vogel 10851b6e0dbaSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 10861b6e0dbaSJack F Vogel bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 10878eb6488eSEric Joyner bus->lan_id = (u8)bus->func; 10881b6e0dbaSJack F Vogel 10891b6e0dbaSJack F Vogel /* check for a port swap */ 1090a9ca1c79SSean Bruno reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 10911b6e0dbaSJack F Vogel if (reg & IXGBE_FACTPS_LFS) 10921b6e0dbaSJack F Vogel bus->func ^= 0x1; 10938eb6488eSEric Joyner 10948eb6488eSEric Joyner /* Get MAC instance from EEPROM for configuring CS4227 */ 10958eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) { 10968eb6488eSEric Joyner hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4); 10978eb6488eSEric Joyner bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >> 10988eb6488eSEric Joyner IXGBE_EE_CTRL_4_INST_ID_SHIFT; 10998eb6488eSEric Joyner } 11001b6e0dbaSJack F Vogel } 11011b6e0dbaSJack F Vogel 11021b6e0dbaSJack F Vogel /** 11039ca4041bSJack F Vogel * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 110413705f88SJack F Vogel * @hw: pointer to hardware structure 110513705f88SJack F Vogel * 110613705f88SJack F Vogel * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 110713705f88SJack F Vogel * disables transmit and receive units. The adapter_stopped flag is used by 110813705f88SJack F Vogel * the shared code and drivers to determine if the adapter is in a stopped 110913705f88SJack F Vogel * state and should not touch the hardware. 111013705f88SJack F Vogel **/ 111113705f88SJack F Vogel s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 111213705f88SJack F Vogel { 111313705f88SJack F Vogel u32 reg_val; 111413705f88SJack F Vogel u16 i; 111513705f88SJack F Vogel 11162969bf0eSJack F Vogel DEBUGFUNC("ixgbe_stop_adapter_generic"); 11172969bf0eSJack F Vogel 111813705f88SJack F Vogel /* 111913705f88SJack F Vogel * Set the adapter_stopped flag so other driver functions stop touching 112013705f88SJack F Vogel * the hardware 112113705f88SJack F Vogel */ 112279b36ec9SKevin Bowling hw->adapter_stopped = true; 112313705f88SJack F Vogel 112413705f88SJack F Vogel /* Disable the receive unit */ 1125758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 112613705f88SJack F Vogel 112785d0a26eSJack F Vogel /* Clear interrupt mask to stop interrupts from being generated */ 112813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 112913705f88SJack F Vogel 113085d0a26eSJack F Vogel /* Clear any pending interrupts, flush previous writes */ 113113705f88SJack F Vogel IXGBE_READ_REG(hw, IXGBE_EICR); 113213705f88SJack F Vogel 113313705f88SJack F Vogel /* Disable the transmit unit. Each queue must be disabled. */ 113485d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) 113585d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); 113685d0a26eSJack F Vogel 113785d0a26eSJack F Vogel /* Disable the receive unit by stopping each queue */ 113885d0a26eSJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 113985d0a26eSJack F Vogel reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 114085d0a26eSJack F Vogel reg_val &= ~IXGBE_RXDCTL_ENABLE; 114185d0a26eSJack F Vogel reg_val |= IXGBE_RXDCTL_SWFLSH; 114285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 114313705f88SJack F Vogel } 114485d0a26eSJack F Vogel 114585d0a26eSJack F Vogel /* flush all queues disables */ 114685d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 114785d0a26eSJack F Vogel msec_delay(2); 114813705f88SJack F Vogel 11499ca4041bSJack F Vogel /* 11506f37f232SEric Joyner * Prevent the PCI-E bus from hanging by disabling PCI-E master 11519ca4041bSJack F Vogel * access and verify no pending requests 11529ca4041bSJack F Vogel */ 115385d0a26eSJack F Vogel return ixgbe_disable_pcie_master(hw); 115413705f88SJack F Vogel } 115513705f88SJack F Vogel 115613705f88SJack F Vogel /** 11578eb6488eSEric Joyner * ixgbe_init_led_link_act_generic - Store the LED index link/activity. 11588eb6488eSEric Joyner * @hw: pointer to hardware structure 11598eb6488eSEric Joyner * 11608eb6488eSEric Joyner * Store the index for the link active LED. This will be used to support 11618eb6488eSEric Joyner * blinking the LED. 11628eb6488eSEric Joyner **/ 11638eb6488eSEric Joyner s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw) 11648eb6488eSEric Joyner { 11658eb6488eSEric Joyner struct ixgbe_mac_info *mac = &hw->mac; 11668eb6488eSEric Joyner u32 led_reg, led_mode; 11678eb6488eSEric Joyner u8 i; 11688eb6488eSEric Joyner 11698eb6488eSEric Joyner led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 11708eb6488eSEric Joyner 11718eb6488eSEric Joyner /* Get LED link active from the LEDCTL register */ 11728eb6488eSEric Joyner for (i = 0; i < 4; i++) { 11738eb6488eSEric Joyner led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i); 11748eb6488eSEric Joyner 11758eb6488eSEric Joyner if ((led_mode & IXGBE_LED_MODE_MASK_BASE) == 11768eb6488eSEric Joyner IXGBE_LED_LINK_ACTIVE) { 11778eb6488eSEric Joyner mac->led_link_act = i; 11788eb6488eSEric Joyner return IXGBE_SUCCESS; 11798eb6488eSEric Joyner } 11808eb6488eSEric Joyner } 11818eb6488eSEric Joyner 11828eb6488eSEric Joyner /* 11838eb6488eSEric Joyner * If LEDCTL register does not have the LED link active set, then use 11848eb6488eSEric Joyner * known MAC defaults. 11858eb6488eSEric Joyner */ 11868eb6488eSEric Joyner switch (hw->mac.type) { 11878eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 11888eb6488eSEric Joyner case ixgbe_mac_X550EM_x: 11898eb6488eSEric Joyner mac->led_link_act = 1; 11908eb6488eSEric Joyner break; 11918eb6488eSEric Joyner default: 11928eb6488eSEric Joyner mac->led_link_act = 2; 11938eb6488eSEric Joyner } 11948eb6488eSEric Joyner return IXGBE_SUCCESS; 11958eb6488eSEric Joyner } 11968eb6488eSEric Joyner 11978eb6488eSEric Joyner /** 119813705f88SJack F Vogel * ixgbe_led_on_generic - Turns on the software controllable LEDs. 119913705f88SJack F Vogel * @hw: pointer to hardware structure 120013705f88SJack F Vogel * @index: led number to turn on 120113705f88SJack F Vogel **/ 120213705f88SJack F Vogel s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 120313705f88SJack F Vogel { 120413705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 120513705f88SJack F Vogel 12062969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_on_generic"); 12072969bf0eSJack F Vogel 12088eb6488eSEric Joyner if (index > 3) 12098eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12108eb6488eSEric Joyner 121113705f88SJack F Vogel /* To turn on the LED, set mode to ON. */ 121213705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 121313705f88SJack F Vogel led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 121413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12159ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 121613705f88SJack F Vogel 121713705f88SJack F Vogel return IXGBE_SUCCESS; 121813705f88SJack F Vogel } 121913705f88SJack F Vogel 122013705f88SJack F Vogel /** 122113705f88SJack F Vogel * ixgbe_led_off_generic - Turns off the software controllable LEDs. 122213705f88SJack F Vogel * @hw: pointer to hardware structure 122313705f88SJack F Vogel * @index: led number to turn off 122413705f88SJack F Vogel **/ 122513705f88SJack F Vogel s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 122613705f88SJack F Vogel { 122713705f88SJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 122813705f88SJack F Vogel 12292969bf0eSJack F Vogel DEBUGFUNC("ixgbe_led_off_generic"); 12302969bf0eSJack F Vogel 12318eb6488eSEric Joyner if (index > 3) 12328eb6488eSEric Joyner return IXGBE_ERR_PARAM; 12338eb6488eSEric Joyner 123413705f88SJack F Vogel /* To turn off the LED, set mode to OFF. */ 123513705f88SJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 123613705f88SJack F Vogel led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 123713705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 12389ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 123913705f88SJack F Vogel 124013705f88SJack F Vogel return IXGBE_SUCCESS; 124113705f88SJack F Vogel } 124213705f88SJack F Vogel 124313705f88SJack F Vogel /** 124413705f88SJack F Vogel * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 124513705f88SJack F Vogel * @hw: pointer to hardware structure 124613705f88SJack F Vogel * 124713705f88SJack F Vogel * Initializes the EEPROM parameters ixgbe_eeprom_info within the 124813705f88SJack F Vogel * ixgbe_hw struct in order to set up EEPROM access. 124913705f88SJack F Vogel **/ 125013705f88SJack F Vogel s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 125113705f88SJack F Vogel { 125213705f88SJack F Vogel struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 125313705f88SJack F Vogel u32 eec; 125413705f88SJack F Vogel u16 eeprom_size; 125513705f88SJack F Vogel 12562969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 12572969bf0eSJack F Vogel 125813705f88SJack F Vogel if (eeprom->type == ixgbe_eeprom_uninitialized) { 125913705f88SJack F Vogel eeprom->type = ixgbe_eeprom_none; 12605b7f4cedSJack F Vogel /* Set default semaphore delay to 10ms which is a well 12615b7f4cedSJack F Vogel * tested value */ 12625b7f4cedSJack F Vogel eeprom->semaphore_delay = 10; 126385d0a26eSJack F Vogel /* Clear EEPROM page size, it will be initialized as needed */ 126485d0a26eSJack F Vogel eeprom->word_page_size = 0; 126513705f88SJack F Vogel 126613705f88SJack F Vogel /* 126713705f88SJack F Vogel * Check for EEPROM present first. 126813705f88SJack F Vogel * If not present leave as none 126913705f88SJack F Vogel */ 1270a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 127113705f88SJack F Vogel if (eec & IXGBE_EEC_PRES) { 127213705f88SJack F Vogel eeprom->type = ixgbe_eeprom_spi; 127313705f88SJack F Vogel 127413705f88SJack F Vogel /* 127513705f88SJack F Vogel * SPI EEPROM is assumed here. This code would need to 127613705f88SJack F Vogel * change if a future EEPROM is not SPI. 127713705f88SJack F Vogel */ 127813705f88SJack F Vogel eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 127913705f88SJack F Vogel IXGBE_EEC_SIZE_SHIFT); 128013705f88SJack F Vogel eeprom->word_size = 1 << (eeprom_size + 128185d0a26eSJack F Vogel IXGBE_EEPROM_WORD_SIZE_SHIFT); 128213705f88SJack F Vogel } 128313705f88SJack F Vogel 128413705f88SJack F Vogel if (eec & IXGBE_EEC_ADDR_SIZE) 128513705f88SJack F Vogel eeprom->address_bits = 16; 128613705f88SJack F Vogel else 128713705f88SJack F Vogel eeprom->address_bits = 8; 128813705f88SJack F Vogel DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 128913705f88SJack F Vogel "%d\n", eeprom->type, eeprom->word_size, 129013705f88SJack F Vogel eeprom->address_bits); 129113705f88SJack F Vogel } 129213705f88SJack F Vogel 129313705f88SJack F Vogel return IXGBE_SUCCESS; 129413705f88SJack F Vogel } 129513705f88SJack F Vogel 129613705f88SJack F Vogel /** 129785d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang 129885d0a26eSJack F Vogel * @hw: pointer to hardware structure 129985d0a26eSJack F Vogel * @offset: offset within the EEPROM to write 130085d0a26eSJack F Vogel * @words: number of word(s) 130185d0a26eSJack F Vogel * @data: 16 bit word(s) to write to EEPROM 130285d0a26eSJack F Vogel * 130385d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 130485d0a26eSJack F Vogel **/ 130585d0a26eSJack F Vogel s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 130685d0a26eSJack F Vogel u16 words, u16 *data) 130785d0a26eSJack F Vogel { 130885d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 130985d0a26eSJack F Vogel u16 i, count; 131085d0a26eSJack F Vogel 131185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); 131285d0a26eSJack F Vogel 131385d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 131485d0a26eSJack F Vogel 131585d0a26eSJack F Vogel if (words == 0) { 131685d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 131785d0a26eSJack F Vogel goto out; 131885d0a26eSJack F Vogel } 131985d0a26eSJack F Vogel 132085d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 132185d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 132285d0a26eSJack F Vogel goto out; 132385d0a26eSJack F Vogel } 132485d0a26eSJack F Vogel 132585d0a26eSJack F Vogel /* 132685d0a26eSJack F Vogel * The EEPROM page size cannot be queried from the chip. We do lazy 132785d0a26eSJack F Vogel * initialization. It is worth to do that when we write large buffer. 132885d0a26eSJack F Vogel */ 132985d0a26eSJack F Vogel if ((hw->eeprom.word_page_size == 0) && 133085d0a26eSJack F Vogel (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) 133185d0a26eSJack F Vogel ixgbe_detect_eeprom_page_size_generic(hw, offset); 133285d0a26eSJack F Vogel 133385d0a26eSJack F Vogel /* 133485d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 133585d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 133685d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 133785d0a26eSJack F Vogel */ 133885d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 133985d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 134085d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 134185d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, 134285d0a26eSJack F Vogel count, &data[i]); 134385d0a26eSJack F Vogel 134485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 134585d0a26eSJack F Vogel break; 134685d0a26eSJack F Vogel } 134785d0a26eSJack F Vogel 134885d0a26eSJack F Vogel out: 134985d0a26eSJack F Vogel return status; 135085d0a26eSJack F Vogel } 135185d0a26eSJack F Vogel 135285d0a26eSJack F Vogel /** 135385d0a26eSJack F Vogel * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM 135413705f88SJack F Vogel * @hw: pointer to hardware structure 135513705f88SJack F Vogel * @offset: offset within the EEPROM to be written to 135685d0a26eSJack F Vogel * @words: number of word(s) 135785d0a26eSJack F Vogel * @data: 16 bit word(s) to be written to the EEPROM 135813705f88SJack F Vogel * 135913705f88SJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 136013705f88SJack F Vogel * EEPROM will most likely contain an invalid checksum. 136113705f88SJack F Vogel **/ 136285d0a26eSJack F Vogel static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 136385d0a26eSJack F Vogel u16 words, u16 *data) 136413705f88SJack F Vogel { 136513705f88SJack F Vogel s32 status; 136685d0a26eSJack F Vogel u16 word; 136785d0a26eSJack F Vogel u16 page_size; 136885d0a26eSJack F Vogel u16 i; 136913705f88SJack F Vogel u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 137013705f88SJack F Vogel 137185d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); 13729ca4041bSJack F Vogel 137313705f88SJack F Vogel /* Prepare the EEPROM for writing */ 137413705f88SJack F Vogel status = ixgbe_acquire_eeprom(hw); 137513705f88SJack F Vogel 137613705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 137713705f88SJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 137813705f88SJack F Vogel ixgbe_release_eeprom(hw); 137913705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 138013705f88SJack F Vogel } 138113705f88SJack F Vogel } 138213705f88SJack F Vogel 138313705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 138485d0a26eSJack F Vogel for (i = 0; i < words; i++) { 138513705f88SJack F Vogel ixgbe_standby_eeprom(hw); 138613705f88SJack F Vogel 138713705f88SJack F Vogel /* Send the WRITE ENABLE command (8 bit opcode ) */ 138885d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, 138985d0a26eSJack F Vogel IXGBE_EEPROM_WREN_OPCODE_SPI, 139013705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 139113705f88SJack F Vogel 139213705f88SJack F Vogel ixgbe_standby_eeprom(hw); 139313705f88SJack F Vogel 139413705f88SJack F Vogel /* 139585d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 139685d0a26eSJack F Vogel * in the opcode 139713705f88SJack F Vogel */ 139885d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 139985d0a26eSJack F Vogel ((offset + i) >= 128)) 140013705f88SJack F Vogel write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 140113705f88SJack F Vogel 140213705f88SJack F Vogel /* Send the Write command (8-bit opcode + addr) */ 140313705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, write_opcode, 140413705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 140585d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 140613705f88SJack F Vogel hw->eeprom.address_bits); 140713705f88SJack F Vogel 140885d0a26eSJack F Vogel page_size = hw->eeprom.word_page_size; 140913705f88SJack F Vogel 141085d0a26eSJack F Vogel /* Send the data in burst via SPI*/ 141185d0a26eSJack F Vogel do { 141285d0a26eSJack F Vogel word = data[i]; 141385d0a26eSJack F Vogel word = (word >> 8) | (word << 8); 141485d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, word, 16); 141585d0a26eSJack F Vogel 141685d0a26eSJack F Vogel if (page_size == 0) 141785d0a26eSJack F Vogel break; 141885d0a26eSJack F Vogel 141985d0a26eSJack F Vogel /* do not wrap around page */ 142085d0a26eSJack F Vogel if (((offset + i) & (page_size - 1)) == 142185d0a26eSJack F Vogel (page_size - 1)) 142285d0a26eSJack F Vogel break; 142385d0a26eSJack F Vogel } while (++i < words); 142485d0a26eSJack F Vogel 142585d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 142685d0a26eSJack F Vogel msec_delay(10); 142785d0a26eSJack F Vogel } 142813705f88SJack F Vogel /* Done with writing - release the EEPROM */ 142913705f88SJack F Vogel ixgbe_release_eeprom(hw); 143013705f88SJack F Vogel } 143113705f88SJack F Vogel 143285d0a26eSJack F Vogel return status; 143385d0a26eSJack F Vogel } 143485d0a26eSJack F Vogel 143585d0a26eSJack F Vogel /** 143685d0a26eSJack F Vogel * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 143785d0a26eSJack F Vogel * @hw: pointer to hardware structure 143885d0a26eSJack F Vogel * @offset: offset within the EEPROM to be written to 143985d0a26eSJack F Vogel * @data: 16 bit word to be written to the EEPROM 144085d0a26eSJack F Vogel * 144185d0a26eSJack F Vogel * If ixgbe_eeprom_update_checksum is not called after this function, the 144285d0a26eSJack F Vogel * EEPROM will most likely contain an invalid checksum. 144385d0a26eSJack F Vogel **/ 144485d0a26eSJack F Vogel s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 144585d0a26eSJack F Vogel { 144685d0a26eSJack F Vogel s32 status; 144785d0a26eSJack F Vogel 144885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eeprom_generic"); 144985d0a26eSJack F Vogel 145085d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 145185d0a26eSJack F Vogel 145285d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 145385d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 145485d0a26eSJack F Vogel goto out; 145585d0a26eSJack F Vogel } 145685d0a26eSJack F Vogel 145785d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); 145885d0a26eSJack F Vogel 14599ca4041bSJack F Vogel out: 146013705f88SJack F Vogel return status; 146113705f88SJack F Vogel } 146213705f88SJack F Vogel 146313705f88SJack F Vogel /** 146485d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang 146585d0a26eSJack F Vogel * @hw: pointer to hardware structure 146685d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 146785d0a26eSJack F Vogel * @data: read 16 bit words(s) from EEPROM 146885d0a26eSJack F Vogel * @words: number of word(s) 146985d0a26eSJack F Vogel * 147085d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 147185d0a26eSJack F Vogel **/ 147285d0a26eSJack F Vogel s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 147385d0a26eSJack F Vogel u16 words, u16 *data) 147485d0a26eSJack F Vogel { 147585d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 147685d0a26eSJack F Vogel u16 i, count; 147785d0a26eSJack F Vogel 147885d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); 147985d0a26eSJack F Vogel 148085d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 148185d0a26eSJack F Vogel 148285d0a26eSJack F Vogel if (words == 0) { 148385d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 148485d0a26eSJack F Vogel goto out; 148585d0a26eSJack F Vogel } 148685d0a26eSJack F Vogel 148785d0a26eSJack F Vogel if (offset + words > hw->eeprom.word_size) { 148885d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 148985d0a26eSJack F Vogel goto out; 149085d0a26eSJack F Vogel } 149185d0a26eSJack F Vogel 149285d0a26eSJack F Vogel /* 149385d0a26eSJack F Vogel * We cannot hold synchronization semaphores for too long 149485d0a26eSJack F Vogel * to avoid other entity starvation. However it is more efficient 149585d0a26eSJack F Vogel * to read in bursts than synchronizing access for each word. 149685d0a26eSJack F Vogel */ 149785d0a26eSJack F Vogel for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { 149885d0a26eSJack F Vogel count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? 149985d0a26eSJack F Vogel IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); 150085d0a26eSJack F Vogel 150185d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, 150285d0a26eSJack F Vogel count, &data[i]); 150385d0a26eSJack F Vogel 150485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 150585d0a26eSJack F Vogel break; 150685d0a26eSJack F Vogel } 150785d0a26eSJack F Vogel 150885d0a26eSJack F Vogel out: 150985d0a26eSJack F Vogel return status; 151085d0a26eSJack F Vogel } 151185d0a26eSJack F Vogel 151285d0a26eSJack F Vogel /** 151385d0a26eSJack F Vogel * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang 151485d0a26eSJack F Vogel * @hw: pointer to hardware structure 151585d0a26eSJack F Vogel * @offset: offset within the EEPROM to be read 151685d0a26eSJack F Vogel * @words: number of word(s) 151785d0a26eSJack F Vogel * @data: read 16 bit word(s) from EEPROM 151885d0a26eSJack F Vogel * 151985d0a26eSJack F Vogel * Reads 16 bit word(s) from EEPROM through bit-bang method 152085d0a26eSJack F Vogel **/ 152185d0a26eSJack F Vogel static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, 152285d0a26eSJack F Vogel u16 words, u16 *data) 152385d0a26eSJack F Vogel { 152485d0a26eSJack F Vogel s32 status; 152585d0a26eSJack F Vogel u16 word_in; 152685d0a26eSJack F Vogel u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 152785d0a26eSJack F Vogel u16 i; 152885d0a26eSJack F Vogel 152985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); 153085d0a26eSJack F Vogel 153185d0a26eSJack F Vogel /* Prepare the EEPROM for reading */ 153285d0a26eSJack F Vogel status = ixgbe_acquire_eeprom(hw); 153385d0a26eSJack F Vogel 153485d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 153585d0a26eSJack F Vogel if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 153685d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 153785d0a26eSJack F Vogel status = IXGBE_ERR_EEPROM; 153885d0a26eSJack F Vogel } 153985d0a26eSJack F Vogel } 154085d0a26eSJack F Vogel 154185d0a26eSJack F Vogel if (status == IXGBE_SUCCESS) { 154285d0a26eSJack F Vogel for (i = 0; i < words; i++) { 154385d0a26eSJack F Vogel ixgbe_standby_eeprom(hw); 154485d0a26eSJack F Vogel /* 154585d0a26eSJack F Vogel * Some SPI eeproms use the 8th address bit embedded 154685d0a26eSJack F Vogel * in the opcode 154785d0a26eSJack F Vogel */ 154885d0a26eSJack F Vogel if ((hw->eeprom.address_bits == 8) && 154985d0a26eSJack F Vogel ((offset + i) >= 128)) 155085d0a26eSJack F Vogel read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 155185d0a26eSJack F Vogel 155285d0a26eSJack F Vogel /* Send the READ command (opcode + addr) */ 155385d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, read_opcode, 155485d0a26eSJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 155585d0a26eSJack F Vogel ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), 155685d0a26eSJack F Vogel hw->eeprom.address_bits); 155785d0a26eSJack F Vogel 155885d0a26eSJack F Vogel /* Read the data. */ 155985d0a26eSJack F Vogel word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 156085d0a26eSJack F Vogel data[i] = (word_in >> 8) | (word_in << 8); 156185d0a26eSJack F Vogel } 156285d0a26eSJack F Vogel 156385d0a26eSJack F Vogel /* End this read operation */ 156485d0a26eSJack F Vogel ixgbe_release_eeprom(hw); 156585d0a26eSJack F Vogel } 156685d0a26eSJack F Vogel 156785d0a26eSJack F Vogel return status; 156885d0a26eSJack F Vogel } 156985d0a26eSJack F Vogel 157085d0a26eSJack F Vogel /** 157113705f88SJack F Vogel * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 157213705f88SJack F Vogel * @hw: pointer to hardware structure 157313705f88SJack F Vogel * @offset: offset within the EEPROM to be read 157413705f88SJack F Vogel * @data: read 16 bit value from EEPROM 157513705f88SJack F Vogel * 157613705f88SJack F Vogel * Reads 16 bit value from EEPROM through bit-bang method 157713705f88SJack F Vogel **/ 157813705f88SJack F Vogel s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 157913705f88SJack F Vogel u16 *data) 158013705f88SJack F Vogel { 158113705f88SJack F Vogel s32 status; 158213705f88SJack F Vogel 15832969bf0eSJack F Vogel DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 15842969bf0eSJack F Vogel 15859ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 15869ca4041bSJack F Vogel 15879ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 15889ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 15899ca4041bSJack F Vogel goto out; 15909ca4041bSJack F Vogel } 15919ca4041bSJack F Vogel 159285d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 159313705f88SJack F Vogel 159485d0a26eSJack F Vogel out: 159585d0a26eSJack F Vogel return status; 159685d0a26eSJack F Vogel } 159785d0a26eSJack F Vogel 159885d0a26eSJack F Vogel /** 159985d0a26eSJack F Vogel * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD 160085d0a26eSJack F Vogel * @hw: pointer to hardware structure 160185d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to read 160285d0a26eSJack F Vogel * @words: number of word(s) 160385d0a26eSJack F Vogel * @data: 16 bit word(s) from the EEPROM 160485d0a26eSJack F Vogel * 160585d0a26eSJack F Vogel * Reads a 16 bit word(s) from the EEPROM using the EERD register. 160685d0a26eSJack F Vogel **/ 160785d0a26eSJack F Vogel s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, 160885d0a26eSJack F Vogel u16 words, u16 *data) 160985d0a26eSJack F Vogel { 161085d0a26eSJack F Vogel u32 eerd; 161185d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 161285d0a26eSJack F Vogel u32 i; 161385d0a26eSJack F Vogel 161485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); 161585d0a26eSJack F Vogel 161685d0a26eSJack F Vogel hw->eeprom.ops.init_params(hw); 161785d0a26eSJack F Vogel 161885d0a26eSJack F Vogel if (words == 0) { 161985d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1620fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 162185d0a26eSJack F Vogel goto out; 162285d0a26eSJack F Vogel } 162385d0a26eSJack F Vogel 162485d0a26eSJack F Vogel if (offset >= hw->eeprom.word_size) { 162513705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 1626fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 162785d0a26eSJack F Vogel goto out; 162813705f88SJack F Vogel } 162913705f88SJack F Vogel 163085d0a26eSJack F Vogel for (i = 0; i < words; i++) { 16310ecc2ff0SJack F Vogel eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 163285d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 163385d0a26eSJack F Vogel 163485d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 163585d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 163685d0a26eSJack F Vogel 163713705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 163885d0a26eSJack F Vogel data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 163985d0a26eSJack F Vogel IXGBE_EEPROM_RW_REG_DATA); 164085d0a26eSJack F Vogel } else { 164185d0a26eSJack F Vogel DEBUGOUT("Eeprom read timed out\n"); 164285d0a26eSJack F Vogel goto out; 164385d0a26eSJack F Vogel } 164485d0a26eSJack F Vogel } 164585d0a26eSJack F Vogel out: 164685d0a26eSJack F Vogel return status; 164785d0a26eSJack F Vogel } 164885d0a26eSJack F Vogel 164985d0a26eSJack F Vogel /** 165085d0a26eSJack F Vogel * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size 165185d0a26eSJack F Vogel * @hw: pointer to hardware structure 165285d0a26eSJack F Vogel * @offset: offset within the EEPROM to be used as a scratch pad 165385d0a26eSJack F Vogel * 165485d0a26eSJack F Vogel * Discover EEPROM page size by writing marching data at given offset. 165585d0a26eSJack F Vogel * This function is called only when we are writing a new large buffer 165685d0a26eSJack F Vogel * at given offset so the data would be overwritten anyway. 165785d0a26eSJack F Vogel **/ 165885d0a26eSJack F Vogel static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, 165985d0a26eSJack F Vogel u16 offset) 166085d0a26eSJack F Vogel { 166185d0a26eSJack F Vogel u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; 166285d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 166385d0a26eSJack F Vogel u16 i; 166485d0a26eSJack F Vogel 166585d0a26eSJack F Vogel DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); 166685d0a26eSJack F Vogel 166785d0a26eSJack F Vogel for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) 166885d0a26eSJack F Vogel data[i] = i; 166985d0a26eSJack F Vogel 167085d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; 167185d0a26eSJack F Vogel status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 167285d0a26eSJack F Vogel IXGBE_EEPROM_PAGE_SIZE_MAX, data); 167385d0a26eSJack F Vogel hw->eeprom.word_page_size = 0; 167485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167585d0a26eSJack F Vogel goto out; 167685d0a26eSJack F Vogel 167785d0a26eSJack F Vogel status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); 167885d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) 167985d0a26eSJack F Vogel goto out; 168013705f88SJack F Vogel 168113705f88SJack F Vogel /* 168285d0a26eSJack F Vogel * When writing in burst more than the actual page size 168385d0a26eSJack F Vogel * EEPROM address wraps around current page. 168413705f88SJack F Vogel */ 168585d0a26eSJack F Vogel hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; 168613705f88SJack F Vogel 168785d0a26eSJack F Vogel DEBUGOUT1("Detected EEPROM page size = %d words.", 168885d0a26eSJack F Vogel hw->eeprom.word_page_size); 16899ca4041bSJack F Vogel out: 169013705f88SJack F Vogel return status; 169113705f88SJack F Vogel } 169213705f88SJack F Vogel 169313705f88SJack F Vogel /** 16942969bf0eSJack F Vogel * ixgbe_read_eerd_generic - Read EEPROM word using EERD 169513705f88SJack F Vogel * @hw: pointer to hardware structure 169613705f88SJack F Vogel * @offset: offset of word in the EEPROM to read 169713705f88SJack F Vogel * @data: word read from the EEPROM 169813705f88SJack F Vogel * 169913705f88SJack F Vogel * Reads a 16 bit word from the EEPROM using the EERD register. 170013705f88SJack F Vogel **/ 17012969bf0eSJack F Vogel s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 170213705f88SJack F Vogel { 170385d0a26eSJack F Vogel return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); 170485d0a26eSJack F Vogel } 170513705f88SJack F Vogel 170685d0a26eSJack F Vogel /** 170785d0a26eSJack F Vogel * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR 170885d0a26eSJack F Vogel * @hw: pointer to hardware structure 170985d0a26eSJack F Vogel * @offset: offset of word in the EEPROM to write 171085d0a26eSJack F Vogel * @words: number of word(s) 171185d0a26eSJack F Vogel * @data: word(s) write to the EEPROM 171285d0a26eSJack F Vogel * 171385d0a26eSJack F Vogel * Write a 16 bit word(s) to the EEPROM using the EEWR register. 171485d0a26eSJack F Vogel **/ 171585d0a26eSJack F Vogel s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, 171685d0a26eSJack F Vogel u16 words, u16 *data) 171785d0a26eSJack F Vogel { 171885d0a26eSJack F Vogel u32 eewr; 171985d0a26eSJack F Vogel s32 status = IXGBE_SUCCESS; 172085d0a26eSJack F Vogel u16 i; 172185d0a26eSJack F Vogel 172285d0a26eSJack F Vogel DEBUGFUNC("ixgbe_write_eewr_generic"); 17232969bf0eSJack F Vogel 17249ca4041bSJack F Vogel hw->eeprom.ops.init_params(hw); 17259ca4041bSJack F Vogel 172685d0a26eSJack F Vogel if (words == 0) { 172785d0a26eSJack F Vogel status = IXGBE_ERR_INVALID_ARGUMENT; 1728fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); 172985d0a26eSJack F Vogel goto out; 173085d0a26eSJack F Vogel } 173185d0a26eSJack F Vogel 17329ca4041bSJack F Vogel if (offset >= hw->eeprom.word_size) { 17339ca4041bSJack F Vogel status = IXGBE_ERR_EEPROM; 1734fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); 17359ca4041bSJack F Vogel goto out; 17369ca4041bSJack F Vogel } 17379ca4041bSJack F Vogel 173885d0a26eSJack F Vogel for (i = 0; i < words; i++) { 173985d0a26eSJack F Vogel eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | 174085d0a26eSJack F Vogel (data[i] << IXGBE_EEPROM_RW_REG_DATA) | 17412969bf0eSJack F Vogel IXGBE_EEPROM_RW_REG_START; 174213705f88SJack F Vogel 174385d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 174485d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 174585d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 174685d0a26eSJack F Vogel goto out; 174785d0a26eSJack F Vogel } 174813705f88SJack F Vogel 174985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); 175085d0a26eSJack F Vogel 175185d0a26eSJack F Vogel status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); 175285d0a26eSJack F Vogel if (status != IXGBE_SUCCESS) { 175385d0a26eSJack F Vogel DEBUGOUT("Eeprom write EEWR timed out\n"); 175485d0a26eSJack F Vogel goto out; 175585d0a26eSJack F Vogel } 175685d0a26eSJack F Vogel } 175713705f88SJack F Vogel 17589ca4041bSJack F Vogel out: 175913705f88SJack F Vogel return status; 176013705f88SJack F Vogel } 176113705f88SJack F Vogel 176213705f88SJack F Vogel /** 17631a4e3449SJack F Vogel * ixgbe_write_eewr_generic - Write EEPROM word using EEWR 17641a4e3449SJack F Vogel * @hw: pointer to hardware structure 17651a4e3449SJack F Vogel * @offset: offset of word in the EEPROM to write 17661a4e3449SJack F Vogel * @data: word write to the EEPROM 17671a4e3449SJack F Vogel * 17681a4e3449SJack F Vogel * Write a 16 bit word to the EEPROM using the EEWR register. 17691a4e3449SJack F Vogel **/ 17701a4e3449SJack F Vogel s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 17711a4e3449SJack F Vogel { 177285d0a26eSJack F Vogel return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); 17731a4e3449SJack F Vogel } 17741a4e3449SJack F Vogel 17751a4e3449SJack F Vogel /** 17762969bf0eSJack F Vogel * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 177713705f88SJack F Vogel * @hw: pointer to hardware structure 17782969bf0eSJack F Vogel * @ee_reg: EEPROM flag for polling 177913705f88SJack F Vogel * 17802969bf0eSJack F Vogel * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 17812969bf0eSJack F Vogel * read or write is done respectively. 178213705f88SJack F Vogel **/ 17832969bf0eSJack F Vogel s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 178413705f88SJack F Vogel { 178513705f88SJack F Vogel u32 i; 178613705f88SJack F Vogel u32 reg; 178713705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 178813705f88SJack F Vogel 17892969bf0eSJack F Vogel DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 17902969bf0eSJack F Vogel 17912969bf0eSJack F Vogel for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 17922969bf0eSJack F Vogel if (ee_reg == IXGBE_NVM_POLL_READ) 179313705f88SJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EERD); 17942969bf0eSJack F Vogel else 17952969bf0eSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 17962969bf0eSJack F Vogel 17972969bf0eSJack F Vogel if (reg & IXGBE_EEPROM_RW_REG_DONE) { 179813705f88SJack F Vogel status = IXGBE_SUCCESS; 179913705f88SJack F Vogel break; 180013705f88SJack F Vogel } 180113705f88SJack F Vogel usec_delay(5); 180213705f88SJack F Vogel } 1803fd75b91dSJack F Vogel 1804fd75b91dSJack F Vogel if (i == IXGBE_EERD_EEWR_ATTEMPTS) 1805fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1806fd75b91dSJack F Vogel "EEPROM read/write done polling timed out"); 1807fd75b91dSJack F Vogel 180813705f88SJack F Vogel return status; 180913705f88SJack F Vogel } 181013705f88SJack F Vogel 181113705f88SJack F Vogel /** 181213705f88SJack F Vogel * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 181313705f88SJack F Vogel * @hw: pointer to hardware structure 181413705f88SJack F Vogel * 181513705f88SJack F Vogel * Prepares EEPROM for access using bit-bang method. This function should 181613705f88SJack F Vogel * be called before issuing a command to the EEPROM. 181713705f88SJack F Vogel **/ 181813705f88SJack F Vogel static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 181913705f88SJack F Vogel { 182013705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 182113705f88SJack F Vogel u32 eec; 182213705f88SJack F Vogel u32 i; 182313705f88SJack F Vogel 18242969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_eeprom"); 18252969bf0eSJack F Vogel 182685d0a26eSJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) 182785d0a26eSJack F Vogel != IXGBE_SUCCESS) 182813705f88SJack F Vogel status = IXGBE_ERR_SWFW_SYNC; 182913705f88SJack F Vogel 183013705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 1831a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183213705f88SJack F Vogel 183313705f88SJack F Vogel /* Request EEPROM Access */ 183413705f88SJack F Vogel eec |= IXGBE_EEC_REQ; 1835a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 183613705f88SJack F Vogel 183713705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 1838a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 183913705f88SJack F Vogel if (eec & IXGBE_EEC_GNT) 184013705f88SJack F Vogel break; 184113705f88SJack F Vogel usec_delay(5); 184213705f88SJack F Vogel } 184313705f88SJack F Vogel 18449ca4041bSJack F Vogel /* Release if grant not acquired */ 184513705f88SJack F Vogel if (!(eec & IXGBE_EEC_GNT)) { 184613705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 1847a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 184813705f88SJack F Vogel DEBUGOUT("Could not acquire EEPROM grant\n"); 184913705f88SJack F Vogel 185085d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 185113705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 185213705f88SJack F Vogel } 185313705f88SJack F Vogel 185413705f88SJack F Vogel /* Setup EEPROM for Read/Write */ 185513705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 185613705f88SJack F Vogel /* Clear CS and SK */ 185713705f88SJack F Vogel eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 1858a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 185913705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 186013705f88SJack F Vogel usec_delay(1); 186113705f88SJack F Vogel } 18621a4e3449SJack F Vogel } 186313705f88SJack F Vogel return status; 186413705f88SJack F Vogel } 186513705f88SJack F Vogel 186613705f88SJack F Vogel /** 186713705f88SJack F Vogel * ixgbe_get_eeprom_semaphore - Get hardware semaphore 186813705f88SJack F Vogel * @hw: pointer to hardware structure 186913705f88SJack F Vogel * 187013705f88SJack F Vogel * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 187113705f88SJack F Vogel **/ 187213705f88SJack F Vogel static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 187313705f88SJack F Vogel { 187413705f88SJack F Vogel s32 status = IXGBE_ERR_EEPROM; 1875d8602bb9SJack F Vogel u32 timeout = 2000; 187613705f88SJack F Vogel u32 i; 187713705f88SJack F Vogel u32 swsm; 187813705f88SJack F Vogel 18792969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 18802969bf0eSJack F Vogel 18811a4e3449SJack F Vogel 188213705f88SJack F Vogel /* Get SMBI software semaphore between device drivers first */ 188313705f88SJack F Vogel for (i = 0; i < timeout; i++) { 188413705f88SJack F Vogel /* 188513705f88SJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 188613705f88SJack F Vogel * set and we have the semaphore 188713705f88SJack F Vogel */ 1888a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 188913705f88SJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) { 189013705f88SJack F Vogel status = IXGBE_SUCCESS; 189113705f88SJack F Vogel break; 189213705f88SJack F Vogel } 18930ac6dfecSJack F Vogel usec_delay(50); 189413705f88SJack F Vogel } 189513705f88SJack F Vogel 189685d0a26eSJack F Vogel if (i == timeout) { 189785d0a26eSJack F Vogel DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " 189885d0a26eSJack F Vogel "not granted.\n"); 189985d0a26eSJack F Vogel /* 190085d0a26eSJack F Vogel * this release is particularly important because our attempts 190185d0a26eSJack F Vogel * above to get the semaphore may have succeeded, and if there 190285d0a26eSJack F Vogel * was a timeout, we should unconditionally clear the semaphore 190385d0a26eSJack F Vogel * bits to free the driver to make progress 190485d0a26eSJack F Vogel */ 190585d0a26eSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 190685d0a26eSJack F Vogel 190785d0a26eSJack F Vogel usec_delay(50); 190885d0a26eSJack F Vogel /* 190985d0a26eSJack F Vogel * one last try 191085d0a26eSJack F Vogel * If the SMBI bit is 0 when we read it, then the bit will be 191185d0a26eSJack F Vogel * set and we have the semaphore 191285d0a26eSJack F Vogel */ 1913a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 191485d0a26eSJack F Vogel if (!(swsm & IXGBE_SWSM_SMBI)) 191585d0a26eSJack F Vogel status = IXGBE_SUCCESS; 191685d0a26eSJack F Vogel } 191785d0a26eSJack F Vogel 191813705f88SJack F Vogel /* Now get the semaphore between SW/FW through the SWESMBI bit */ 191913705f88SJack F Vogel if (status == IXGBE_SUCCESS) { 192013705f88SJack F Vogel for (i = 0; i < timeout; i++) { 1921a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 192213705f88SJack F Vogel 192313705f88SJack F Vogel /* Set the SW EEPROM semaphore bit to request access */ 192413705f88SJack F Vogel swsm |= IXGBE_SWSM_SWESMBI; 1925a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm); 192613705f88SJack F Vogel 192713705f88SJack F Vogel /* 192813705f88SJack F Vogel * If we set the bit successfully then we got the 192913705f88SJack F Vogel * semaphore. 193013705f88SJack F Vogel */ 1931a9ca1c79SSean Bruno swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw)); 193213705f88SJack F Vogel if (swsm & IXGBE_SWSM_SWESMBI) 193313705f88SJack F Vogel break; 193413705f88SJack F Vogel 193513705f88SJack F Vogel usec_delay(50); 193613705f88SJack F Vogel } 193713705f88SJack F Vogel 193813705f88SJack F Vogel /* 193913705f88SJack F Vogel * Release semaphores and return error if SW EEPROM semaphore 194013705f88SJack F Vogel * was not granted because we don't have access to the EEPROM 194113705f88SJack F Vogel */ 194213705f88SJack F Vogel if (i >= timeout) { 1943fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1944fd75b91dSJack F Vogel "SWESMBI Software EEPROM semaphore not granted.\n"); 194513705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 194613705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 194713705f88SJack F Vogel } 19480ac6dfecSJack F Vogel } else { 1949fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 1950fd75b91dSJack F Vogel "Software semaphore SMBI between device drivers " 19510ac6dfecSJack F Vogel "not granted.\n"); 195213705f88SJack F Vogel } 195313705f88SJack F Vogel 195413705f88SJack F Vogel return status; 195513705f88SJack F Vogel } 195613705f88SJack F Vogel 195713705f88SJack F Vogel /** 195813705f88SJack F Vogel * ixgbe_release_eeprom_semaphore - Release hardware semaphore 195913705f88SJack F Vogel * @hw: pointer to hardware structure 196013705f88SJack F Vogel * 196113705f88SJack F Vogel * This function clears hardware semaphore bits. 196213705f88SJack F Vogel **/ 196313705f88SJack F Vogel static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 196413705f88SJack F Vogel { 196513705f88SJack F Vogel u32 swsm; 196613705f88SJack F Vogel 19672969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 19682969bf0eSJack F Vogel 196913705f88SJack F Vogel swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 197013705f88SJack F Vogel 197113705f88SJack F Vogel /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 197213705f88SJack F Vogel swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 197313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 19749ca4041bSJack F Vogel IXGBE_WRITE_FLUSH(hw); 197513705f88SJack F Vogel } 197613705f88SJack F Vogel 197713705f88SJack F Vogel /** 197813705f88SJack F Vogel * ixgbe_ready_eeprom - Polls for EEPROM ready 197913705f88SJack F Vogel * @hw: pointer to hardware structure 198013705f88SJack F Vogel **/ 198113705f88SJack F Vogel static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 198213705f88SJack F Vogel { 198313705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 198413705f88SJack F Vogel u16 i; 198513705f88SJack F Vogel u8 spi_stat_reg; 198613705f88SJack F Vogel 19872969bf0eSJack F Vogel DEBUGFUNC("ixgbe_ready_eeprom"); 19882969bf0eSJack F Vogel 198913705f88SJack F Vogel /* 199013705f88SJack F Vogel * Read "Status Register" repeatedly until the LSB is cleared. The 199113705f88SJack F Vogel * EEPROM will signal that the command has been completed by clearing 199213705f88SJack F Vogel * bit 0 of the internal status register. If it's not cleared within 199313705f88SJack F Vogel * 5 milliseconds, then error out. 199413705f88SJack F Vogel */ 199513705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 199613705f88SJack F Vogel ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 199713705f88SJack F Vogel IXGBE_EEPROM_OPCODE_BITS); 199813705f88SJack F Vogel spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 199913705f88SJack F Vogel if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 200013705f88SJack F Vogel break; 200113705f88SJack F Vogel 200213705f88SJack F Vogel usec_delay(5); 200313705f88SJack F Vogel ixgbe_standby_eeprom(hw); 2004c19c7afeSEric Joyner } 200513705f88SJack F Vogel 200613705f88SJack F Vogel /* 200713705f88SJack F Vogel * On some parts, SPI write time could vary from 0-20mSec on 3.3V 200813705f88SJack F Vogel * devices (and only 0-5mSec on 5V devices) 200913705f88SJack F Vogel */ 201013705f88SJack F Vogel if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 201113705f88SJack F Vogel DEBUGOUT("SPI EEPROM Status error\n"); 201213705f88SJack F Vogel status = IXGBE_ERR_EEPROM; 201313705f88SJack F Vogel } 201413705f88SJack F Vogel 201513705f88SJack F Vogel return status; 201613705f88SJack F Vogel } 201713705f88SJack F Vogel 201813705f88SJack F Vogel /** 201913705f88SJack F Vogel * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 202013705f88SJack F Vogel * @hw: pointer to hardware structure 202113705f88SJack F Vogel **/ 202213705f88SJack F Vogel static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) 202313705f88SJack F Vogel { 202413705f88SJack F Vogel u32 eec; 202513705f88SJack F Vogel 20262969bf0eSJack F Vogel DEBUGFUNC("ixgbe_standby_eeprom"); 20272969bf0eSJack F Vogel 2028a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 202913705f88SJack F Vogel 203013705f88SJack F Vogel /* Toggle CS to flush commands */ 203113705f88SJack F Vogel eec |= IXGBE_EEC_CS; 2032a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203313705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203413705f88SJack F Vogel usec_delay(1); 203513705f88SJack F Vogel eec &= ~IXGBE_EEC_CS; 2036a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 203713705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 203813705f88SJack F Vogel usec_delay(1); 203913705f88SJack F Vogel } 204013705f88SJack F Vogel 204113705f88SJack F Vogel /** 204213705f88SJack F Vogel * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 204313705f88SJack F Vogel * @hw: pointer to hardware structure 204413705f88SJack F Vogel * @data: data to send to the EEPROM 204513705f88SJack F Vogel * @count: number of bits to shift out 204613705f88SJack F Vogel **/ 204713705f88SJack F Vogel static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 204813705f88SJack F Vogel u16 count) 204913705f88SJack F Vogel { 205013705f88SJack F Vogel u32 eec; 205113705f88SJack F Vogel u32 mask; 205213705f88SJack F Vogel u32 i; 205313705f88SJack F Vogel 20542969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 20552969bf0eSJack F Vogel 2056a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 205713705f88SJack F Vogel 205813705f88SJack F Vogel /* 205913705f88SJack F Vogel * Mask is used to shift "count" bits of "data" out to the EEPROM 206013705f88SJack F Vogel * one bit at a time. Determine the starting bit based on count 206113705f88SJack F Vogel */ 206213705f88SJack F Vogel mask = 0x01 << (count - 1); 206313705f88SJack F Vogel 206413705f88SJack F Vogel for (i = 0; i < count; i++) { 206513705f88SJack F Vogel /* 206613705f88SJack F Vogel * A "1" is shifted out to the EEPROM by setting bit "DI" to a 206713705f88SJack F Vogel * "1", and then raising and then lowering the clock (the SK 206813705f88SJack F Vogel * bit controls the clock input to the EEPROM). A "0" is 206913705f88SJack F Vogel * shifted out to the EEPROM by setting "DI" to "0" and then 207013705f88SJack F Vogel * raising and then lowering the clock. 207113705f88SJack F Vogel */ 207213705f88SJack F Vogel if (data & mask) 207313705f88SJack F Vogel eec |= IXGBE_EEC_DI; 207413705f88SJack F Vogel else 207513705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 207613705f88SJack F Vogel 2077a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 207813705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 207913705f88SJack F Vogel 208013705f88SJack F Vogel usec_delay(1); 208113705f88SJack F Vogel 208213705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 208313705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 208413705f88SJack F Vogel 208513705f88SJack F Vogel /* 208613705f88SJack F Vogel * Shift mask to signify next bit of data to shift in to the 208713705f88SJack F Vogel * EEPROM 208813705f88SJack F Vogel */ 208913705f88SJack F Vogel mask = mask >> 1; 2090c19c7afeSEric Joyner } 209113705f88SJack F Vogel 209213705f88SJack F Vogel /* We leave the "DI" bit set to "0" when we leave this routine. */ 209313705f88SJack F Vogel eec &= ~IXGBE_EEC_DI; 2094a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 209513705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 209613705f88SJack F Vogel } 209713705f88SJack F Vogel 209813705f88SJack F Vogel /** 209913705f88SJack F Vogel * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 210013705f88SJack F Vogel * @hw: pointer to hardware structure 21017d48aa4cSEric Joyner * @count: number of bits to shift 210213705f88SJack F Vogel **/ 210313705f88SJack F Vogel static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 210413705f88SJack F Vogel { 210513705f88SJack F Vogel u32 eec; 210613705f88SJack F Vogel u32 i; 210713705f88SJack F Vogel u16 data = 0; 210813705f88SJack F Vogel 21092969bf0eSJack F Vogel DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 21102969bf0eSJack F Vogel 211113705f88SJack F Vogel /* 211213705f88SJack F Vogel * In order to read a register from the EEPROM, we need to shift 211313705f88SJack F Vogel * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 211413705f88SJack F Vogel * the clock input to the EEPROM (setting the SK bit), and then reading 211513705f88SJack F Vogel * the value of the "DO" bit. During this "shifting in" process the 211613705f88SJack F Vogel * "DI" bit should always be clear. 211713705f88SJack F Vogel */ 2118a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 211913705f88SJack F Vogel 212013705f88SJack F Vogel eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 212113705f88SJack F Vogel 212213705f88SJack F Vogel for (i = 0; i < count; i++) { 212313705f88SJack F Vogel data = data << 1; 212413705f88SJack F Vogel ixgbe_raise_eeprom_clk(hw, &eec); 212513705f88SJack F Vogel 2126a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 212713705f88SJack F Vogel 212813705f88SJack F Vogel eec &= ~(IXGBE_EEC_DI); 212913705f88SJack F Vogel if (eec & IXGBE_EEC_DO) 213013705f88SJack F Vogel data |= 1; 213113705f88SJack F Vogel 213213705f88SJack F Vogel ixgbe_lower_eeprom_clk(hw, &eec); 213313705f88SJack F Vogel } 213413705f88SJack F Vogel 213513705f88SJack F Vogel return data; 213613705f88SJack F Vogel } 213713705f88SJack F Vogel 213813705f88SJack F Vogel /** 213913705f88SJack F Vogel * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 214013705f88SJack F Vogel * @hw: pointer to hardware structure 214113705f88SJack F Vogel * @eec: EEC register's current value 214213705f88SJack F Vogel **/ 214313705f88SJack F Vogel static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 214413705f88SJack F Vogel { 21452969bf0eSJack F Vogel DEBUGFUNC("ixgbe_raise_eeprom_clk"); 21462969bf0eSJack F Vogel 214713705f88SJack F Vogel /* 214813705f88SJack F Vogel * Raise the clock input to the EEPROM 214913705f88SJack F Vogel * (setting the SK bit), then delay 215013705f88SJack F Vogel */ 215113705f88SJack F Vogel *eec = *eec | IXGBE_EEC_SK; 2152a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 215313705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 215413705f88SJack F Vogel usec_delay(1); 215513705f88SJack F Vogel } 215613705f88SJack F Vogel 215713705f88SJack F Vogel /** 215813705f88SJack F Vogel * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 215913705f88SJack F Vogel * @hw: pointer to hardware structure 21607d48aa4cSEric Joyner * @eec: EEC's current value 216113705f88SJack F Vogel **/ 216213705f88SJack F Vogel static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 216313705f88SJack F Vogel { 21642969bf0eSJack F Vogel DEBUGFUNC("ixgbe_lower_eeprom_clk"); 21652969bf0eSJack F Vogel 216613705f88SJack F Vogel /* 216713705f88SJack F Vogel * Lower the clock input to the EEPROM (clearing the SK bit), then 216813705f88SJack F Vogel * delay 216913705f88SJack F Vogel */ 217013705f88SJack F Vogel *eec = *eec & ~IXGBE_EEC_SK; 2171a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec); 217213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 217313705f88SJack F Vogel usec_delay(1); 217413705f88SJack F Vogel } 217513705f88SJack F Vogel 217613705f88SJack F Vogel /** 217713705f88SJack F Vogel * ixgbe_release_eeprom - Release EEPROM, release semaphores 217813705f88SJack F Vogel * @hw: pointer to hardware structure 217913705f88SJack F Vogel **/ 218013705f88SJack F Vogel static void ixgbe_release_eeprom(struct ixgbe_hw *hw) 218113705f88SJack F Vogel { 218213705f88SJack F Vogel u32 eec; 218313705f88SJack F Vogel 21842969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_eeprom"); 21852969bf0eSJack F Vogel 2186a9ca1c79SSean Bruno eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)); 218713705f88SJack F Vogel 218813705f88SJack F Vogel eec |= IXGBE_EEC_CS; /* Pull CS high */ 218913705f88SJack F Vogel eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 219013705f88SJack F Vogel 2191a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219213705f88SJack F Vogel IXGBE_WRITE_FLUSH(hw); 219313705f88SJack F Vogel 219413705f88SJack F Vogel usec_delay(1); 219513705f88SJack F Vogel 219613705f88SJack F Vogel /* Stop requesting EEPROM access */ 219713705f88SJack F Vogel eec &= ~IXGBE_EEC_REQ; 2198a9ca1c79SSean Bruno IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec); 219913705f88SJack F Vogel 220085d0a26eSJack F Vogel hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 2201d8602bb9SJack F Vogel 2202d8602bb9SJack F Vogel /* Delay before attempt to obtain semaphore again to allow FW access */ 2203d8602bb9SJack F Vogel msec_delay(hw->eeprom.semaphore_delay); 220413705f88SJack F Vogel } 220513705f88SJack F Vogel 220613705f88SJack F Vogel /** 22072969bf0eSJack F Vogel * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum 220813705f88SJack F Vogel * @hw: pointer to hardware structure 2209758cc3dcSJack F Vogel * 2210758cc3dcSJack F Vogel * Returns a negative error code on error, or the 16-bit checksum 221113705f88SJack F Vogel **/ 2212758cc3dcSJack F Vogel s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) 221313705f88SJack F Vogel { 221413705f88SJack F Vogel u16 i; 221513705f88SJack F Vogel u16 j; 221613705f88SJack F Vogel u16 checksum = 0; 221713705f88SJack F Vogel u16 length = 0; 221813705f88SJack F Vogel u16 pointer = 0; 221913705f88SJack F Vogel u16 word = 0; 222013705f88SJack F Vogel 22212969bf0eSJack F Vogel DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); 22222969bf0eSJack F Vogel 222313705f88SJack F Vogel /* Include 0x0-0x3F in the checksum */ 222413705f88SJack F Vogel for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 2225758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &word)) { 222613705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2227758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 222813705f88SJack F Vogel } 222913705f88SJack F Vogel checksum += word; 223013705f88SJack F Vogel } 223113705f88SJack F Vogel 223213705f88SJack F Vogel /* Include all data from pointers except for the fw pointer */ 223313705f88SJack F Vogel for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 2234758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, i, &pointer)) { 2235758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2236758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2237758cc3dcSJack F Vogel } 223813705f88SJack F Vogel 2239758cc3dcSJack F Vogel /* If the pointer seems invalid */ 2240758cc3dcSJack F Vogel if (pointer == 0xFFFF || pointer == 0) 2241758cc3dcSJack F Vogel continue; 224213705f88SJack F Vogel 2243758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, pointer, &length)) { 2244758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2245758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2246758cc3dcSJack F Vogel } 2247758cc3dcSJack F Vogel 2248758cc3dcSJack F Vogel if (length == 0xFFFF || length == 0) 2249758cc3dcSJack F Vogel continue; 2250758cc3dcSJack F Vogel 225113705f88SJack F Vogel for (j = pointer + 1; j <= pointer + length; j++) { 2252758cc3dcSJack F Vogel if (hw->eeprom.ops.read(hw, j, &word)) { 2253758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2254758cc3dcSJack F Vogel return IXGBE_ERR_EEPROM; 2255758cc3dcSJack F Vogel } 225613705f88SJack F Vogel checksum += word; 225713705f88SJack F Vogel } 225813705f88SJack F Vogel } 225913705f88SJack F Vogel 226013705f88SJack F Vogel checksum = (u16)IXGBE_EEPROM_SUM - checksum; 226113705f88SJack F Vogel 2262758cc3dcSJack F Vogel return (s32)checksum; 226313705f88SJack F Vogel } 226413705f88SJack F Vogel 226513705f88SJack F Vogel /** 226613705f88SJack F Vogel * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 226713705f88SJack F Vogel * @hw: pointer to hardware structure 226813705f88SJack F Vogel * @checksum_val: calculated checksum 226913705f88SJack F Vogel * 227013705f88SJack F Vogel * Performs checksum calculation and validates the EEPROM checksum. If the 227113705f88SJack F Vogel * caller does not need checksum_val, the value can be NULL. 227213705f88SJack F Vogel **/ 227313705f88SJack F Vogel s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 227413705f88SJack F Vogel u16 *checksum_val) 227513705f88SJack F Vogel { 227613705f88SJack F Vogel s32 status; 227713705f88SJack F Vogel u16 checksum; 227813705f88SJack F Vogel u16 read_checksum = 0; 227913705f88SJack F Vogel 22802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 22812969bf0eSJack F Vogel 2282758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 228313705f88SJack F Vogel * not continue or we could be in for a very long wait while every 228413705f88SJack F Vogel * EEPROM read fails 228513705f88SJack F Vogel */ 22869ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2287758cc3dcSJack F Vogel if (status) { 2288758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2289758cc3dcSJack F Vogel return status; 2290758cc3dcSJack F Vogel } 229113705f88SJack F Vogel 2292758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2293758cc3dcSJack F Vogel if (status < 0) 2294758cc3dcSJack F Vogel return status; 229513705f88SJack F Vogel 2296758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 229713705f88SJack F Vogel 2298758cc3dcSJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 2299758cc3dcSJack F Vogel if (status) { 2300758cc3dcSJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2301758cc3dcSJack F Vogel return status; 2302758cc3dcSJack F Vogel } 2303758cc3dcSJack F Vogel 2304758cc3dcSJack F Vogel /* Verify read checksum from EEPROM is the same as 230513705f88SJack F Vogel * calculated checksum 230613705f88SJack F Vogel */ 23079ca4041bSJack F Vogel if (read_checksum != checksum) 230813705f88SJack F Vogel status = IXGBE_ERR_EEPROM_CHECKSUM; 230913705f88SJack F Vogel 231013705f88SJack F Vogel /* If the user cares, return the calculated checksum */ 23119ca4041bSJack F Vogel if (checksum_val) 231213705f88SJack F Vogel *checksum_val = checksum; 231313705f88SJack F Vogel 231413705f88SJack F Vogel return status; 231513705f88SJack F Vogel } 231613705f88SJack F Vogel 231713705f88SJack F Vogel /** 23189ca4041bSJack F Vogel * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 231913705f88SJack F Vogel * @hw: pointer to hardware structure 232013705f88SJack F Vogel **/ 232113705f88SJack F Vogel s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 232213705f88SJack F Vogel { 232313705f88SJack F Vogel s32 status; 232413705f88SJack F Vogel u16 checksum; 232513705f88SJack F Vogel 23262969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 23272969bf0eSJack F Vogel 2328758cc3dcSJack F Vogel /* Read the first word from the EEPROM. If this times out or fails, do 232913705f88SJack F Vogel * not continue or we could be in for a very long wait while every 233013705f88SJack F Vogel * EEPROM read fails 233113705f88SJack F Vogel */ 23329ca4041bSJack F Vogel status = hw->eeprom.ops.read(hw, 0, &checksum); 2333758cc3dcSJack F Vogel if (status) { 233413705f88SJack F Vogel DEBUGOUT("EEPROM read failed\n"); 2335758cc3dcSJack F Vogel return status; 233613705f88SJack F Vogel } 233713705f88SJack F Vogel 2338758cc3dcSJack F Vogel status = hw->eeprom.ops.calc_checksum(hw); 2339758cc3dcSJack F Vogel if (status < 0) 2340758cc3dcSJack F Vogel return status; 2341758cc3dcSJack F Vogel 2342758cc3dcSJack F Vogel checksum = (u16)(status & 0xffff); 2343758cc3dcSJack F Vogel 2344758cc3dcSJack F Vogel status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); 2345758cc3dcSJack F Vogel 234613705f88SJack F Vogel return status; 234713705f88SJack F Vogel } 234813705f88SJack F Vogel 234913705f88SJack F Vogel /** 235013705f88SJack F Vogel * ixgbe_validate_mac_addr - Validate MAC address 235113705f88SJack F Vogel * @mac_addr: pointer to MAC address. 235213705f88SJack F Vogel * 23538eb6488eSEric Joyner * Tests a MAC address to ensure it is a valid Individual Address. 235413705f88SJack F Vogel **/ 235513705f88SJack F Vogel s32 ixgbe_validate_mac_addr(u8 *mac_addr) 235613705f88SJack F Vogel { 235713705f88SJack F Vogel s32 status = IXGBE_SUCCESS; 235813705f88SJack F Vogel 23592969bf0eSJack F Vogel DEBUGFUNC("ixgbe_validate_mac_addr"); 23602969bf0eSJack F Vogel 236113705f88SJack F Vogel /* Make sure it is not a multicast address */ 236213705f88SJack F Vogel if (IXGBE_IS_MULTICAST(mac_addr)) { 236313705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236413705f88SJack F Vogel /* Not a broadcast address */ 236513705f88SJack F Vogel } else if (IXGBE_IS_BROADCAST(mac_addr)) { 236613705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 236713705f88SJack F Vogel /* Reject the zero address */ 236813705f88SJack F Vogel } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 236913705f88SJack F Vogel mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 237013705f88SJack F Vogel status = IXGBE_ERR_INVALID_MAC_ADDR; 237113705f88SJack F Vogel } 237213705f88SJack F Vogel return status; 237313705f88SJack F Vogel } 237413705f88SJack F Vogel 237513705f88SJack F Vogel /** 23769ca4041bSJack F Vogel * ixgbe_set_rar_generic - Set Rx address register 237713705f88SJack F Vogel * @hw: pointer to hardware structure 237813705f88SJack F Vogel * @index: Receive address register to write 23799ca4041bSJack F Vogel * @addr: Address to put into receive address register 23809ca4041bSJack F Vogel * @vmdq: VMDq "set" or "pool" index 238113705f88SJack F Vogel * @enable_addr: set flag that address is active 238213705f88SJack F Vogel * 238313705f88SJack F Vogel * Puts an ethernet address into a receive address register. 238413705f88SJack F Vogel **/ 23859ca4041bSJack F Vogel s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 238613705f88SJack F Vogel u32 enable_addr) 238713705f88SJack F Vogel { 238813705f88SJack F Vogel u32 rar_low, rar_high; 23899ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 239013705f88SJack F Vogel 23912969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_rar_generic"); 23922969bf0eSJack F Vogel 23931a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 23941a4e3449SJack F Vogel if (index >= rar_entries) { 2395fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2396fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 23971a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 23981a4e3449SJack F Vogel } 23991a4e3449SJack F Vogel 24009ca4041bSJack F Vogel /* setup VMDq pool selection before this RAR gets enabled */ 24019ca4041bSJack F Vogel hw->mac.ops.set_vmdq(hw, index, vmdq); 24029ca4041bSJack F Vogel 240313705f88SJack F Vogel /* 24049ca4041bSJack F Vogel * HW expects these in little endian so we reverse the byte 24059ca4041bSJack F Vogel * order from network order (big endian) to little endian 240613705f88SJack F Vogel */ 240713705f88SJack F Vogel rar_low = ((u32)addr[0] | 240813705f88SJack F Vogel ((u32)addr[1] << 8) | 240913705f88SJack F Vogel ((u32)addr[2] << 16) | 241013705f88SJack F Vogel ((u32)addr[3] << 24)); 24119ca4041bSJack F Vogel /* 24129ca4041bSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24139ca4041bSJack F Vogel * so save everything except the lower 16 bits that hold part 24149ca4041bSJack F Vogel * of the address and the address valid bit. 24159ca4041bSJack F Vogel */ 24169ca4041bSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24179ca4041bSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24189ca4041bSJack F Vogel rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 241913705f88SJack F Vogel 242013705f88SJack F Vogel if (enable_addr != 0) 242113705f88SJack F Vogel rar_high |= IXGBE_RAH_AV; 242213705f88SJack F Vogel 242313705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 242413705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 242513705f88SJack F Vogel 242613705f88SJack F Vogel return IXGBE_SUCCESS; 242713705f88SJack F Vogel } 242813705f88SJack F Vogel 242913705f88SJack F Vogel /** 24305b7f4cedSJack F Vogel * ixgbe_clear_rar_generic - Remove Rx address register 24315b7f4cedSJack F Vogel * @hw: pointer to hardware structure 24325b7f4cedSJack F Vogel * @index: Receive address register to write 24335b7f4cedSJack F Vogel * 24345b7f4cedSJack F Vogel * Clears an ethernet address from a receive address register. 24355b7f4cedSJack F Vogel **/ 24365b7f4cedSJack F Vogel s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 24375b7f4cedSJack F Vogel { 24385b7f4cedSJack F Vogel u32 rar_high; 24395b7f4cedSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 24405b7f4cedSJack F Vogel 24412969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_rar_generic"); 24422969bf0eSJack F Vogel 24435b7f4cedSJack F Vogel /* Make sure we are using a valid rar index range */ 24441a4e3449SJack F Vogel if (index >= rar_entries) { 2445fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 2446fd75b91dSJack F Vogel "RAR index %d is out of range.\n", index); 24471a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 24481a4e3449SJack F Vogel } 24491a4e3449SJack F Vogel 24505b7f4cedSJack F Vogel /* 24515b7f4cedSJack F Vogel * Some parts put the VMDq setting in the extra RAH bits, 24525b7f4cedSJack F Vogel * so save everything except the lower 16 bits that hold part 24535b7f4cedSJack F Vogel * of the address and the address valid bit. 24545b7f4cedSJack F Vogel */ 24555b7f4cedSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 24565b7f4cedSJack F Vogel rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 24575b7f4cedSJack F Vogel 24585b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 24595b7f4cedSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 24605b7f4cedSJack F Vogel 24615b7f4cedSJack F Vogel /* clear VMDq pool/queue selection for this RAR */ 24625b7f4cedSJack F Vogel hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 24635b7f4cedSJack F Vogel 24645b7f4cedSJack F Vogel return IXGBE_SUCCESS; 24655b7f4cedSJack F Vogel } 24665b7f4cedSJack F Vogel 24675b7f4cedSJack F Vogel /** 246813705f88SJack F Vogel * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 246913705f88SJack F Vogel * @hw: pointer to hardware structure 247013705f88SJack F Vogel * 247113705f88SJack F Vogel * Places the MAC address in receive address register 0 and clears the rest 24729ca4041bSJack F Vogel * of the receive address registers. Clears the multicast table. Assumes 247313705f88SJack F Vogel * the receiver is in reset when the routine is called. 247413705f88SJack F Vogel **/ 247513705f88SJack F Vogel s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 247613705f88SJack F Vogel { 247713705f88SJack F Vogel u32 i; 24789ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 247913705f88SJack F Vogel 24802969bf0eSJack F Vogel DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 24812969bf0eSJack F Vogel 248213705f88SJack F Vogel /* 248313705f88SJack F Vogel * If the current mac address is valid, assume it is a software override 248413705f88SJack F Vogel * to the permanent address. 248513705f88SJack F Vogel * Otherwise, use the permanent address from the eeprom. 248613705f88SJack F Vogel */ 248713705f88SJack F Vogel if (ixgbe_validate_mac_addr(hw->mac.addr) == 248813705f88SJack F Vogel IXGBE_ERR_INVALID_MAC_ADDR) { 248913705f88SJack F Vogel /* Get the MAC address from the RAR0 for later reference */ 24909ca4041bSJack F Vogel hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 249113705f88SJack F Vogel 249213705f88SJack F Vogel DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 249313705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 249413705f88SJack F Vogel hw->mac.addr[2]); 249513705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 249613705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 249713705f88SJack F Vogel } else { 249813705f88SJack F Vogel /* Setup the receive address. */ 249913705f88SJack F Vogel DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 250013705f88SJack F Vogel DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 250113705f88SJack F Vogel hw->mac.addr[0], hw->mac.addr[1], 250213705f88SJack F Vogel hw->mac.addr[2]); 250313705f88SJack F Vogel DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 250413705f88SJack F Vogel hw->mac.addr[4], hw->mac.addr[5]); 250513705f88SJack F Vogel 25069ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 25078eb6488eSEric Joyner } 2508182b3808SJack F Vogel 2509182b3808SJack F Vogel /* clear VMDq pool/queue selection for RAR 0 */ 2510182b3808SJack F Vogel hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); 25118eb6488eSEric Joyner 25129ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 251313705f88SJack F Vogel 251413705f88SJack F Vogel hw->addr_ctrl.rar_used_count = 1; 251513705f88SJack F Vogel 251613705f88SJack F Vogel /* Zero out the other receive addresses. */ 25179ca4041bSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 251813705f88SJack F Vogel for (i = 1; i < rar_entries; i++) { 251913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 252013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 252113705f88SJack F Vogel } 252213705f88SJack F Vogel 252313705f88SJack F Vogel /* Clear the MTA */ 252413705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 252513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 252613705f88SJack F Vogel 252713705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 25289ca4041bSJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 252913705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 253013705f88SJack F Vogel 25315b7f4cedSJack F Vogel ixgbe_init_uta_tables(hw); 25325b7f4cedSJack F Vogel 253313705f88SJack F Vogel return IXGBE_SUCCESS; 253413705f88SJack F Vogel } 253513705f88SJack F Vogel 253613705f88SJack F Vogel /** 25379ca4041bSJack F Vogel * ixgbe_add_uc_addr - Adds a secondary unicast address. 25389ca4041bSJack F Vogel * @hw: pointer to hardware structure 25399ca4041bSJack F Vogel * @addr: new address 25407d48aa4cSEric Joyner * @vmdq: VMDq "set" or "pool" index 25419ca4041bSJack F Vogel * 25429ca4041bSJack F Vogel * Adds it to unused receive address register or goes into promiscuous mode. 25439ca4041bSJack F Vogel **/ 25449ca4041bSJack F Vogel void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 25459ca4041bSJack F Vogel { 25469ca4041bSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 25479ca4041bSJack F Vogel u32 rar; 25489ca4041bSJack F Vogel 25492969bf0eSJack F Vogel DEBUGFUNC("ixgbe_add_uc_addr"); 25502969bf0eSJack F Vogel 25519ca4041bSJack F Vogel DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 25529ca4041bSJack F Vogel addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 25539ca4041bSJack F Vogel 25549ca4041bSJack F Vogel /* 25559ca4041bSJack F Vogel * Place this address in the RAR if there is room, 25569ca4041bSJack F Vogel * else put the controller into promiscuous mode 25579ca4041bSJack F Vogel */ 25589ca4041bSJack F Vogel if (hw->addr_ctrl.rar_used_count < rar_entries) { 25590ac6dfecSJack F Vogel rar = hw->addr_ctrl.rar_used_count; 25609ca4041bSJack F Vogel hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 25619ca4041bSJack F Vogel DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 25629ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count++; 25639ca4041bSJack F Vogel } else { 25649ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc++; 25659ca4041bSJack F Vogel } 25669ca4041bSJack F Vogel 25679ca4041bSJack F Vogel DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 25689ca4041bSJack F Vogel } 25699ca4041bSJack F Vogel 25709ca4041bSJack F Vogel /** 25719ca4041bSJack F Vogel * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 25729ca4041bSJack F Vogel * @hw: pointer to hardware structure 25739ca4041bSJack F Vogel * @addr_list: the list of new addresses 25749ca4041bSJack F Vogel * @addr_count: number of addresses 25759ca4041bSJack F Vogel * @next: iterator function to walk the address list 25769ca4041bSJack F Vogel * 25779ca4041bSJack F Vogel * The given list replaces any existing list. Clears the secondary addrs from 25789ca4041bSJack F Vogel * receive address registers. Uses unused receive address registers for the 25799ca4041bSJack F Vogel * first secondary addresses, and falls back to promiscuous mode as needed. 25809ca4041bSJack F Vogel * 25819ca4041bSJack F Vogel * Drivers using secondary unicast addresses must set user_set_promisc when 25829ca4041bSJack F Vogel * manually putting the device into promiscuous mode. 25839ca4041bSJack F Vogel **/ 25849ca4041bSJack F Vogel s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 25859ca4041bSJack F Vogel u32 addr_count, ixgbe_mc_addr_itr next) 25869ca4041bSJack F Vogel { 25879ca4041bSJack F Vogel u8 *addr; 25889ca4041bSJack F Vogel u32 i; 25899ca4041bSJack F Vogel u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 25909ca4041bSJack F Vogel u32 uc_addr_in_use; 25919ca4041bSJack F Vogel u32 fctrl; 25929ca4041bSJack F Vogel u32 vmdq; 25939ca4041bSJack F Vogel 25942969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 25952969bf0eSJack F Vogel 25969ca4041bSJack F Vogel /* 25979ca4041bSJack F Vogel * Clear accounting of old secondary address list, 25989ca4041bSJack F Vogel * don't count RAR[0] 25999ca4041bSJack F Vogel */ 26000ac6dfecSJack F Vogel uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 26019ca4041bSJack F Vogel hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 26029ca4041bSJack F Vogel hw->addr_ctrl.overflow_promisc = 0; 26039ca4041bSJack F Vogel 26049ca4041bSJack F Vogel /* Zero out the other receive addresses */ 26052969bf0eSJack F Vogel DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); 26062969bf0eSJack F Vogel for (i = 0; i < uc_addr_in_use; i++) { 26072969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); 26082969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); 26099ca4041bSJack F Vogel } 26109ca4041bSJack F Vogel 26119ca4041bSJack F Vogel /* Add the new addresses */ 26129ca4041bSJack F Vogel for (i = 0; i < addr_count; i++) { 26139ca4041bSJack F Vogel DEBUGOUT(" Adding the secondary addresses:\n"); 26149ca4041bSJack F Vogel addr = next(hw, &addr_list, &vmdq); 26159ca4041bSJack F Vogel ixgbe_add_uc_addr(hw, addr, vmdq); 26169ca4041bSJack F Vogel } 26179ca4041bSJack F Vogel 26189ca4041bSJack F Vogel if (hw->addr_ctrl.overflow_promisc) { 26199ca4041bSJack F Vogel /* enable promisc if not already in overflow or set by user */ 26209ca4041bSJack F Vogel if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26219ca4041bSJack F Vogel DEBUGOUT(" Entering address overflow promisc mode\n"); 26229ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26239ca4041bSJack F Vogel fctrl |= IXGBE_FCTRL_UPE; 26249ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26259ca4041bSJack F Vogel } 26269ca4041bSJack F Vogel } else { 26279ca4041bSJack F Vogel /* only disable if set by overflow, not by user */ 26289ca4041bSJack F Vogel if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 26299ca4041bSJack F Vogel DEBUGOUT(" Leaving address overflow promisc mode\n"); 26309ca4041bSJack F Vogel fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 26319ca4041bSJack F Vogel fctrl &= ~IXGBE_FCTRL_UPE; 26329ca4041bSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 26339ca4041bSJack F Vogel } 26349ca4041bSJack F Vogel } 26359ca4041bSJack F Vogel 26369ca4041bSJack F Vogel DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 26379ca4041bSJack F Vogel return IXGBE_SUCCESS; 26389ca4041bSJack F Vogel } 26399ca4041bSJack F Vogel 26409ca4041bSJack F Vogel /** 264113705f88SJack F Vogel * ixgbe_mta_vector - Determines bit-vector in multicast table to set 264213705f88SJack F Vogel * @hw: pointer to hardware structure 264313705f88SJack F Vogel * @mc_addr: the multicast address 264413705f88SJack F Vogel * 264513705f88SJack F Vogel * Extracts the 12 bits, from a multicast address, to determine which 264613705f88SJack F Vogel * bit-vector to set in the multicast table. The hardware uses 12 bits, from 264713705f88SJack F Vogel * incoming rx multicast addresses, to determine the bit-vector to check in 264813705f88SJack F Vogel * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 26499ca4041bSJack F Vogel * by the MO field of the MCSTCTRL. The MO field is set during initialization 265013705f88SJack F Vogel * to mc_filter_type. 265113705f88SJack F Vogel **/ 265213705f88SJack F Vogel static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 265313705f88SJack F Vogel { 265413705f88SJack F Vogel u32 vector = 0; 265513705f88SJack F Vogel 26562969bf0eSJack F Vogel DEBUGFUNC("ixgbe_mta_vector"); 26572969bf0eSJack F Vogel 265813705f88SJack F Vogel switch (hw->mac.mc_filter_type) { 265913705f88SJack F Vogel case 0: /* use bits [47:36] of the address */ 266013705f88SJack F Vogel vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 266113705f88SJack F Vogel break; 266213705f88SJack F Vogel case 1: /* use bits [46:35] of the address */ 266313705f88SJack F Vogel vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 266413705f88SJack F Vogel break; 266513705f88SJack F Vogel case 2: /* use bits [45:34] of the address */ 266613705f88SJack F Vogel vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 266713705f88SJack F Vogel break; 266813705f88SJack F Vogel case 3: /* use bits [43:32] of the address */ 266913705f88SJack F Vogel vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 267013705f88SJack F Vogel break; 267113705f88SJack F Vogel default: /* Invalid mc_filter_type */ 267213705f88SJack F Vogel DEBUGOUT("MC filter type param set incorrectly\n"); 267313705f88SJack F Vogel ASSERT(0); 267413705f88SJack F Vogel break; 267513705f88SJack F Vogel } 267613705f88SJack F Vogel 267713705f88SJack F Vogel /* vector can only be 12-bits or boundary will be exceeded */ 267813705f88SJack F Vogel vector &= 0xFFF; 267913705f88SJack F Vogel return vector; 268013705f88SJack F Vogel } 268113705f88SJack F Vogel 268213705f88SJack F Vogel /** 268313705f88SJack F Vogel * ixgbe_set_mta - Set bit-vector in multicast table 268413705f88SJack F Vogel * @hw: pointer to hardware structure 26857d48aa4cSEric Joyner * @mc_addr: Multicast address 268613705f88SJack F Vogel * 268713705f88SJack F Vogel * Sets the bit-vector in the multicast table. 268813705f88SJack F Vogel **/ 268913705f88SJack F Vogel void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 269013705f88SJack F Vogel { 269113705f88SJack F Vogel u32 vector; 269213705f88SJack F Vogel u32 vector_bit; 269313705f88SJack F Vogel u32 vector_reg; 269413705f88SJack F Vogel 26952969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_mta"); 26962969bf0eSJack F Vogel 269713705f88SJack F Vogel hw->addr_ctrl.mta_in_use++; 269813705f88SJack F Vogel 269913705f88SJack F Vogel vector = ixgbe_mta_vector(hw, mc_addr); 270013705f88SJack F Vogel DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 270113705f88SJack F Vogel 270213705f88SJack F Vogel /* 270313705f88SJack F Vogel * The MTA is a register array of 128 32-bit registers. It is treated 270413705f88SJack F Vogel * like an array of 4096 bits. We want to set bit 270513705f88SJack F Vogel * BitArray[vector_value]. So we figure out what register the bit is 270613705f88SJack F Vogel * in, read it, OR in the new bit, then write back the new value. The 270713705f88SJack F Vogel * register is determined by the upper 7 bits of the vector value and 270813705f88SJack F Vogel * the bit within that register are determined by the lower 5 bits of 270913705f88SJack F Vogel * the value. 271013705f88SJack F Vogel */ 271113705f88SJack F Vogel vector_reg = (vector >> 5) & 0x7F; 271213705f88SJack F Vogel vector_bit = vector & 0x1F; 27131a4e3449SJack F Vogel hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); 271413705f88SJack F Vogel } 271513705f88SJack F Vogel 271613705f88SJack F Vogel /** 271713705f88SJack F Vogel * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 271813705f88SJack F Vogel * @hw: pointer to hardware structure 271913705f88SJack F Vogel * @mc_addr_list: the list of new multicast addresses 272013705f88SJack F Vogel * @mc_addr_count: number of addresses 27219ca4041bSJack F Vogel * @next: iterator function to walk the multicast address list 272285d0a26eSJack F Vogel * @clear: flag, when set clears the table beforehand 272313705f88SJack F Vogel * 272485d0a26eSJack F Vogel * When the clear flag is set, the given list replaces any existing list. 272585d0a26eSJack F Vogel * Hashes the given addresses into the multicast table. 272613705f88SJack F Vogel **/ 272713705f88SJack F Vogel s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 272885d0a26eSJack F Vogel u32 mc_addr_count, ixgbe_mc_addr_itr next, 272985d0a26eSJack F Vogel bool clear) 273013705f88SJack F Vogel { 273113705f88SJack F Vogel u32 i; 27329ca4041bSJack F Vogel u32 vmdq; 273313705f88SJack F Vogel 27342969bf0eSJack F Vogel DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 27352969bf0eSJack F Vogel 273613705f88SJack F Vogel /* 273713705f88SJack F Vogel * Set the new number of MC addresses that we are being requested to 273813705f88SJack F Vogel * use. 273913705f88SJack F Vogel */ 274013705f88SJack F Vogel hw->addr_ctrl.num_mc_addrs = mc_addr_count; 274113705f88SJack F Vogel hw->addr_ctrl.mta_in_use = 0; 274213705f88SJack F Vogel 27431a4e3449SJack F Vogel /* Clear mta_shadow */ 274485d0a26eSJack F Vogel if (clear) { 274513705f88SJack F Vogel DEBUGOUT(" Clearing MTA\n"); 27461a4e3449SJack F Vogel memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); 274785d0a26eSJack F Vogel } 274813705f88SJack F Vogel 27491a4e3449SJack F Vogel /* Update mta_shadow */ 275013705f88SJack F Vogel for (i = 0; i < mc_addr_count; i++) { 275113705f88SJack F Vogel DEBUGOUT(" Adding the multicast addresses:\n"); 27520ac6dfecSJack F Vogel ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 275313705f88SJack F Vogel } 275413705f88SJack F Vogel 275513705f88SJack F Vogel /* Enable mta */ 27561a4e3449SJack F Vogel for (i = 0; i < hw->mac.mcft_size; i++) 27571a4e3449SJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, 27581a4e3449SJack F Vogel hw->mac.mta_shadow[i]); 27591a4e3449SJack F Vogel 276013705f88SJack F Vogel if (hw->addr_ctrl.mta_in_use > 0) 276113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 276213705f88SJack F Vogel IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 276313705f88SJack F Vogel 276413705f88SJack F Vogel DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 276513705f88SJack F Vogel return IXGBE_SUCCESS; 276613705f88SJack F Vogel } 276713705f88SJack F Vogel 276813705f88SJack F Vogel /** 276913705f88SJack F Vogel * ixgbe_enable_mc_generic - Enable multicast address in RAR 277013705f88SJack F Vogel * @hw: pointer to hardware structure 277113705f88SJack F Vogel * 277213705f88SJack F Vogel * Enables multicast address in RAR and the use of the multicast hash table. 277313705f88SJack F Vogel **/ 277413705f88SJack F Vogel s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 277513705f88SJack F Vogel { 277613705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 277713705f88SJack F Vogel 27782969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_mc_generic"); 27792969bf0eSJack F Vogel 278013705f88SJack F Vogel if (a->mta_in_use > 0) 278113705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 278213705f88SJack F Vogel hw->mac.mc_filter_type); 278313705f88SJack F Vogel 278413705f88SJack F Vogel return IXGBE_SUCCESS; 278513705f88SJack F Vogel } 278613705f88SJack F Vogel 278713705f88SJack F Vogel /** 27889ca4041bSJack F Vogel * ixgbe_disable_mc_generic - Disable multicast address in RAR 278913705f88SJack F Vogel * @hw: pointer to hardware structure 279013705f88SJack F Vogel * 279113705f88SJack F Vogel * Disables multicast address in RAR and the use of the multicast hash table. 279213705f88SJack F Vogel **/ 279313705f88SJack F Vogel s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 279413705f88SJack F Vogel { 279513705f88SJack F Vogel struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 279613705f88SJack F Vogel 27972969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_mc_generic"); 27982969bf0eSJack F Vogel 279913705f88SJack F Vogel if (a->mta_in_use > 0) 280013705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 280113705f88SJack F Vogel 280213705f88SJack F Vogel return IXGBE_SUCCESS; 280313705f88SJack F Vogel } 280413705f88SJack F Vogel 28051b6e0dbaSJack F Vogel /** 28060ac6dfecSJack F Vogel * ixgbe_fc_enable_generic - Enable flow control 28071b6e0dbaSJack F Vogel * @hw: pointer to hardware structure 28081b6e0dbaSJack F Vogel * 28090ac6dfecSJack F Vogel * Enable flow control according to the current settings. 28101b6e0dbaSJack F Vogel **/ 2811a621e3c8SJack F Vogel s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) 28121b6e0dbaSJack F Vogel { 28131b6e0dbaSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 28140ac6dfecSJack F Vogel u32 mflcn_reg, fccfg_reg; 28150ac6dfecSJack F Vogel u32 reg; 28161a4e3449SJack F Vogel u32 fcrtl, fcrth; 2817a621e3c8SJack F Vogel int i; 28181b6e0dbaSJack F Vogel 28190ac6dfecSJack F Vogel DEBUGFUNC("ixgbe_fc_enable_generic"); 28201b6e0dbaSJack F Vogel 2821a621e3c8SJack F Vogel /* Validate the water mark configuration */ 2822a621e3c8SJack F Vogel if (!hw->fc.pause_time) { 2823a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 28240ac6dfecSJack F Vogel goto out; 2825a621e3c8SJack F Vogel } 2826a621e3c8SJack F Vogel 2827a621e3c8SJack F Vogel /* Low water mark of zero causes XOFF floods */ 2828a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2829a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2830a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2831a621e3c8SJack F Vogel if (!hw->fc.low_water[i] || 2832a621e3c8SJack F Vogel hw->fc.low_water[i] >= hw->fc.high_water[i]) { 2833a621e3c8SJack F Vogel DEBUGOUT("Invalid water mark configuration\n"); 2834a621e3c8SJack F Vogel ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 2835a621e3c8SJack F Vogel goto out; 2836a621e3c8SJack F Vogel } 2837a621e3c8SJack F Vogel } 2838a621e3c8SJack F Vogel } 2839a621e3c8SJack F Vogel 2840a621e3c8SJack F Vogel /* Negotiate the fc mode to use */ 28418eb6488eSEric Joyner hw->mac.ops.fc_autoneg(hw); 28420ac6dfecSJack F Vogel 28430ac6dfecSJack F Vogel /* Disable any previous flow control settings */ 28440ac6dfecSJack F Vogel mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 2845a621e3c8SJack F Vogel mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); 28460ac6dfecSJack F Vogel 28470ac6dfecSJack F Vogel fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 28480ac6dfecSJack F Vogel fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 28491b6e0dbaSJack F Vogel 28501b6e0dbaSJack F Vogel /* 28511b6e0dbaSJack F Vogel * The possible values of fc.current_mode are: 28521b6e0dbaSJack F Vogel * 0: Flow control is completely disabled 28531b6e0dbaSJack F Vogel * 1: Rx flow control is enabled (we can receive pause frames, 28541b6e0dbaSJack F Vogel * but not send pause frames). 28551b6e0dbaSJack F Vogel * 2: Tx flow control is enabled (we can send pause frames but 28561b6e0dbaSJack F Vogel * we do not support receiving pause frames). 28571b6e0dbaSJack F Vogel * 3: Both Rx and Tx flow control (symmetric) are enabled. 28581b6e0dbaSJack F Vogel * other: Invalid. 28591b6e0dbaSJack F Vogel */ 28601b6e0dbaSJack F Vogel switch (hw->fc.current_mode) { 28611b6e0dbaSJack F Vogel case ixgbe_fc_none: 28621a4e3449SJack F Vogel /* 28631a4e3449SJack F Vogel * Flow control is disabled by software override or autoneg. 28640ac6dfecSJack F Vogel * The code below will actually disable it in the HW. 28650ac6dfecSJack F Vogel */ 28661b6e0dbaSJack F Vogel break; 28671b6e0dbaSJack F Vogel case ixgbe_fc_rx_pause: 28681b6e0dbaSJack F Vogel /* 28691b6e0dbaSJack F Vogel * Rx Flow control is enabled and Tx Flow control is 28701b6e0dbaSJack F Vogel * disabled by software override. Since there really 28711b6e0dbaSJack F Vogel * isn't a way to advertise that we are capable of RX 28721b6e0dbaSJack F Vogel * Pause ONLY, we will advertise that we support both 28731b6e0dbaSJack F Vogel * symmetric and asymmetric Rx PAUSE. Later, we will 28741b6e0dbaSJack F Vogel * disable the adapter's ability to send PAUSE frames. 28751b6e0dbaSJack F Vogel */ 28760ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28771b6e0dbaSJack F Vogel break; 28781b6e0dbaSJack F Vogel case ixgbe_fc_tx_pause: 28791b6e0dbaSJack F Vogel /* 28801b6e0dbaSJack F Vogel * Tx Flow control is enabled, and Rx Flow control is 28811b6e0dbaSJack F Vogel * disabled by software override. 28821b6e0dbaSJack F Vogel */ 28830ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28841b6e0dbaSJack F Vogel break; 28851b6e0dbaSJack F Vogel case ixgbe_fc_full: 28861b6e0dbaSJack F Vogel /* Flow control (both Rx and Tx) is enabled by SW override. */ 28870ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_RFCE; 28880ac6dfecSJack F Vogel fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 28891b6e0dbaSJack F Vogel break; 28901b6e0dbaSJack F Vogel default: 2891fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, 2892fd75b91dSJack F Vogel "Flow control param set incorrectly\n"); 28932969bf0eSJack F Vogel ret_val = IXGBE_ERR_CONFIG; 28941b6e0dbaSJack F Vogel goto out; 28951b6e0dbaSJack F Vogel break; 28961b6e0dbaSJack F Vogel } 28971b6e0dbaSJack F Vogel 28980ac6dfecSJack F Vogel /* Set 802.3x based flow control settings. */ 28990ac6dfecSJack F Vogel mflcn_reg |= IXGBE_MFLCN_DPF; 29000ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 29010ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 29021b6e0dbaSJack F Vogel 2903d8602bb9SJack F Vogel 2904a621e3c8SJack F Vogel /* Set up and enable Rx high/low water mark thresholds, enable XON. */ 2905a621e3c8SJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { 2906a621e3c8SJack F Vogel if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && 2907a621e3c8SJack F Vogel hw->fc.high_water[i]) { 2908a621e3c8SJack F Vogel fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; 2909a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); 2910a621e3c8SJack F Vogel fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; 2911a621e3c8SJack F Vogel } else { 2912a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); 2913a621e3c8SJack F Vogel /* 2914a621e3c8SJack F Vogel * In order to prevent Tx hangs when the internal Tx 2915a621e3c8SJack F Vogel * switch is enabled we must set the high water mark 2916758cc3dcSJack F Vogel * to the Rx packet buffer size - 24KB. This allows 2917758cc3dcSJack F Vogel * the Tx switch to function even under heavy Rx 2918758cc3dcSJack F Vogel * workloads. 2919a621e3c8SJack F Vogel */ 2920758cc3dcSJack F Vogel fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; 29211b6e0dbaSJack F Vogel } 29221b6e0dbaSJack F Vogel 2923a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); 2924a621e3c8SJack F Vogel } 29250ac6dfecSJack F Vogel 29260ac6dfecSJack F Vogel /* Configure pause time (2 TCs per register) */ 2927a621e3c8SJack F Vogel reg = hw->fc.pause_time * 0x00010001; 2928a621e3c8SJack F Vogel for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) 2929a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); 29300ac6dfecSJack F Vogel 2931a621e3c8SJack F Vogel /* Configure flow control refresh threshold value */ 2932a621e3c8SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); 29330ac6dfecSJack F Vogel 29340ac6dfecSJack F Vogel out: 29350ac6dfecSJack F Vogel return ret_val; 29360ac6dfecSJack F Vogel } 29370ac6dfecSJack F Vogel 29380ac6dfecSJack F Vogel /** 29391a4e3449SJack F Vogel * ixgbe_negotiate_fc - Negotiate flow control 29401a4e3449SJack F Vogel * @hw: pointer to hardware structure 29411a4e3449SJack F Vogel * @adv_reg: flow control advertised settings 29421a4e3449SJack F Vogel * @lp_reg: link partner's flow control settings 29431a4e3449SJack F Vogel * @adv_sym: symmetric pause bit in advertisement 29441a4e3449SJack F Vogel * @adv_asm: asymmetric pause bit in advertisement 29451a4e3449SJack F Vogel * @lp_sym: symmetric pause bit in link partner advertisement 29461a4e3449SJack F Vogel * @lp_asm: asymmetric pause bit in link partner advertisement 29471a4e3449SJack F Vogel * 29481a4e3449SJack F Vogel * Find the intersection between advertised settings and link partner's 29491a4e3449SJack F Vogel * advertised settings 29501a4e3449SJack F Vogel **/ 29518eb6488eSEric Joyner s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, 29521a4e3449SJack F Vogel u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) 29531a4e3449SJack F Vogel { 2954fd75b91dSJack F Vogel if ((!(adv_reg)) || (!(lp_reg))) { 2955fd75b91dSJack F Vogel ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, 2956fd75b91dSJack F Vogel "Local or link partner's advertised flow control " 2957fd75b91dSJack F Vogel "settings are NULL. Local: %x, link partner: %x\n", 2958fd75b91dSJack F Vogel adv_reg, lp_reg); 29591a4e3449SJack F Vogel return IXGBE_ERR_FC_NOT_NEGOTIATED; 2960fd75b91dSJack F Vogel } 29611a4e3449SJack F Vogel 29621a4e3449SJack F Vogel if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { 29632969bf0eSJack F Vogel /* 29642969bf0eSJack F Vogel * Now we need to check if the user selected Rx ONLY 29652969bf0eSJack F Vogel * of pause frames. In this case, we had to advertise 29662969bf0eSJack F Vogel * FULL flow control because we could not advertise RX 29672969bf0eSJack F Vogel * ONLY. Hence, we must now check to see if we need to 29682969bf0eSJack F Vogel * turn OFF the TRANSMISSION of PAUSE frames. 29692969bf0eSJack F Vogel */ 29702969bf0eSJack F Vogel if (hw->fc.requested_mode == ixgbe_fc_full) { 29712969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_full; 29722969bf0eSJack F Vogel DEBUGOUT("Flow Control = FULL.\n"); 29732969bf0eSJack F Vogel } else { 29742969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29752969bf0eSJack F Vogel DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 29762969bf0eSJack F Vogel } 29771a4e3449SJack F Vogel } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && 29781a4e3449SJack F Vogel (lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29792969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_tx_pause; 29802969bf0eSJack F Vogel DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 29811a4e3449SJack F Vogel } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && 29821a4e3449SJack F Vogel !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { 29832969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_rx_pause; 29842969bf0eSJack F Vogel DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 29852969bf0eSJack F Vogel } else { 29862969bf0eSJack F Vogel hw->fc.current_mode = ixgbe_fc_none; 29872969bf0eSJack F Vogel DEBUGOUT("Flow Control = NONE.\n"); 29882969bf0eSJack F Vogel } 29891a4e3449SJack F Vogel return IXGBE_SUCCESS; 29901b6e0dbaSJack F Vogel } 29911b6e0dbaSJack F Vogel 29920ac6dfecSJack F Vogel /** 2993a621e3c8SJack F Vogel * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber 29940ac6dfecSJack F Vogel * @hw: pointer to hardware structure 29950ac6dfecSJack F Vogel * 2996a621e3c8SJack F Vogel * Enable flow control according on 1 gig fiber. 29970ac6dfecSJack F Vogel **/ 2998a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) 29990ac6dfecSJack F Vogel { 3000a621e3c8SJack F Vogel u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 3001a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 30020ac6dfecSJack F Vogel 3003a621e3c8SJack F Vogel /* 3004a621e3c8SJack F Vogel * On multispeed fiber at 1g, bail out if 3005a621e3c8SJack F Vogel * - link is up but AN did not complete, or if 3006a621e3c8SJack F Vogel * - link is up and AN completed but timed out 3007a621e3c8SJack F Vogel */ 30082969bf0eSJack F Vogel 3009a621e3c8SJack F Vogel linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 3010a621e3c8SJack F Vogel if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 3011fd75b91dSJack F Vogel (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 3012758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); 30130ac6dfecSJack F Vogel goto out; 3014fd75b91dSJack F Vogel } 30150ac6dfecSJack F Vogel 3016a621e3c8SJack F Vogel pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 3017a621e3c8SJack F Vogel pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 30180ac6dfecSJack F Vogel 3019a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, 3020a621e3c8SJack F Vogel pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, 3021a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE, 3022a621e3c8SJack F Vogel IXGBE_PCS1GANA_SYM_PAUSE, 3023a621e3c8SJack F Vogel IXGBE_PCS1GANA_ASM_PAUSE); 30240ac6dfecSJack F Vogel 30250ac6dfecSJack F Vogel out: 30260ac6dfecSJack F Vogel return ret_val; 30270ac6dfecSJack F Vogel } 30281b6e0dbaSJack F Vogel 302913705f88SJack F Vogel /** 3030a621e3c8SJack F Vogel * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 3031a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3032a621e3c8SJack F Vogel * 3033a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3034a621e3c8SJack F Vogel **/ 3035a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) 3036a621e3c8SJack F Vogel { 3037a621e3c8SJack F Vogel u32 links2, anlp1_reg, autoc_reg, links; 3038a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3039a621e3c8SJack F Vogel 3040a621e3c8SJack F Vogel /* 3041a621e3c8SJack F Vogel * On backplane, bail out if 3042a621e3c8SJack F Vogel * - backplane autoneg was not completed, or if 3043a621e3c8SJack F Vogel * - we are 82599 and link partner is not AN enabled 3044a621e3c8SJack F Vogel */ 3045a621e3c8SJack F Vogel links = IXGBE_READ_REG(hw, IXGBE_LINKS); 3046fd75b91dSJack F Vogel if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { 3047758cc3dcSJack F Vogel DEBUGOUT("Auto-Negotiation did not complete\n"); 3048a621e3c8SJack F Vogel goto out; 3049fd75b91dSJack F Vogel } 3050a621e3c8SJack F Vogel 3051a621e3c8SJack F Vogel if (hw->mac.type == ixgbe_mac_82599EB) { 3052a621e3c8SJack F Vogel links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 3053fd75b91dSJack F Vogel if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { 3054758cc3dcSJack F Vogel DEBUGOUT("Link partner is not AN enabled\n"); 3055a621e3c8SJack F Vogel goto out; 3056a621e3c8SJack F Vogel } 3057fd75b91dSJack F Vogel } 3058a621e3c8SJack F Vogel /* 3059a621e3c8SJack F Vogel * Read the 10g AN autoc and LP ability registers and resolve 3060a621e3c8SJack F Vogel * local flow control settings accordingly 3061a621e3c8SJack F Vogel */ 3062a621e3c8SJack F Vogel autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3063a621e3c8SJack F Vogel anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 3064a621e3c8SJack F Vogel 3065a621e3c8SJack F Vogel ret_val = ixgbe_negotiate_fc(hw, autoc_reg, 3066a621e3c8SJack F Vogel anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, 3067a621e3c8SJack F Vogel IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); 3068a621e3c8SJack F Vogel 3069a621e3c8SJack F Vogel out: 3070a621e3c8SJack F Vogel return ret_val; 3071a621e3c8SJack F Vogel } 3072a621e3c8SJack F Vogel 3073a621e3c8SJack F Vogel /** 3074a621e3c8SJack F Vogel * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 3075a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3076a621e3c8SJack F Vogel * 3077a621e3c8SJack F Vogel * Enable flow control according to IEEE clause 37. 3078a621e3c8SJack F Vogel **/ 3079a621e3c8SJack F Vogel static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) 3080a621e3c8SJack F Vogel { 3081a621e3c8SJack F Vogel u16 technology_ability_reg = 0; 3082a621e3c8SJack F Vogel u16 lp_technology_ability_reg = 0; 3083a621e3c8SJack F Vogel 3084a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, 3085a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3086a621e3c8SJack F Vogel &technology_ability_reg); 3087a621e3c8SJack F Vogel hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, 3088a621e3c8SJack F Vogel IXGBE_MDIO_AUTO_NEG_DEV_TYPE, 3089a621e3c8SJack F Vogel &lp_technology_ability_reg); 3090a621e3c8SJack F Vogel 3091a621e3c8SJack F Vogel return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, 3092a621e3c8SJack F Vogel (u32)lp_technology_ability_reg, 3093a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, 3094a621e3c8SJack F Vogel IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); 3095a621e3c8SJack F Vogel } 3096a621e3c8SJack F Vogel 3097a621e3c8SJack F Vogel /** 3098a621e3c8SJack F Vogel * ixgbe_fc_autoneg - Configure flow control 3099a621e3c8SJack F Vogel * @hw: pointer to hardware structure 3100a621e3c8SJack F Vogel * 3101a621e3c8SJack F Vogel * Compares our advertised flow control capabilities to those advertised by 3102a621e3c8SJack F Vogel * our link partner, and determines the proper flow control mode to use. 3103a621e3c8SJack F Vogel **/ 3104a621e3c8SJack F Vogel void ixgbe_fc_autoneg(struct ixgbe_hw *hw) 3105a621e3c8SJack F Vogel { 3106a621e3c8SJack F Vogel s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; 3107a621e3c8SJack F Vogel ixgbe_link_speed speed; 3108a621e3c8SJack F Vogel bool link_up; 3109a621e3c8SJack F Vogel 3110a621e3c8SJack F Vogel DEBUGFUNC("ixgbe_fc_autoneg"); 3111a621e3c8SJack F Vogel 3112a621e3c8SJack F Vogel /* 3113a621e3c8SJack F Vogel * AN should have completed when the cable was plugged in. 3114a621e3c8SJack F Vogel * Look for reasons to bail out. Bail out if: 3115a621e3c8SJack F Vogel * - FC autoneg is disabled, or if 3116a621e3c8SJack F Vogel * - link is not up. 3117a621e3c8SJack F Vogel */ 3118fd75b91dSJack F Vogel if (hw->fc.disable_fc_autoneg) { 3119f511cd22SGuinan Sun /* TODO: This should be just an informative log */ 3120f511cd22SGuinan Sun ERROR_REPORT1(IXGBE_ERROR_CAUTION, 3121fd75b91dSJack F Vogel "Flow control autoneg is disabled"); 3122a621e3c8SJack F Vogel goto out; 3123fd75b91dSJack F Vogel } 3124a621e3c8SJack F Vogel 312579b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 3126fd75b91dSJack F Vogel if (!link_up) { 3127fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); 3128a621e3c8SJack F Vogel goto out; 3129fd75b91dSJack F Vogel } 3130a621e3c8SJack F Vogel 3131a621e3c8SJack F Vogel switch (hw->phy.media_type) { 3132a621e3c8SJack F Vogel /* Autoneg flow control on fiber adapters */ 31330ecc2ff0SJack F Vogel case ixgbe_media_type_fiber_fixed: 3134758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 3135a621e3c8SJack F Vogel case ixgbe_media_type_fiber: 3136a621e3c8SJack F Vogel if (speed == IXGBE_LINK_SPEED_1GB_FULL) 3137a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_fiber(hw); 3138a621e3c8SJack F Vogel break; 3139a621e3c8SJack F Vogel 3140a621e3c8SJack F Vogel /* Autoneg flow control on backplane adapters */ 3141a621e3c8SJack F Vogel case ixgbe_media_type_backplane: 3142a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_backplane(hw); 3143a621e3c8SJack F Vogel break; 3144a621e3c8SJack F Vogel 3145a621e3c8SJack F Vogel /* Autoneg flow control on copper adapters */ 3146a621e3c8SJack F Vogel case ixgbe_media_type_copper: 3147fd75b91dSJack F Vogel if (ixgbe_device_supports_autoneg_fc(hw)) 3148a621e3c8SJack F Vogel ret_val = ixgbe_fc_autoneg_copper(hw); 3149a621e3c8SJack F Vogel break; 3150a621e3c8SJack F Vogel 3151a621e3c8SJack F Vogel default: 3152a621e3c8SJack F Vogel break; 3153a621e3c8SJack F Vogel } 3154a621e3c8SJack F Vogel 3155a621e3c8SJack F Vogel out: 3156a621e3c8SJack F Vogel if (ret_val == IXGBE_SUCCESS) { 315779b36ec9SKevin Bowling hw->fc.fc_was_autonegged = true; 3158a621e3c8SJack F Vogel } else { 315979b36ec9SKevin Bowling hw->fc.fc_was_autonegged = false; 3160a621e3c8SJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 3161a621e3c8SJack F Vogel } 3162a621e3c8SJack F Vogel } 3163a621e3c8SJack F Vogel 3164fd75b91dSJack F Vogel /* 3165fd75b91dSJack F Vogel * ixgbe_pcie_timeout_poll - Return number of times to poll for completion 3166fd75b91dSJack F Vogel * @hw: pointer to hardware structure 3167fd75b91dSJack F Vogel * 3168fd75b91dSJack F Vogel * System-wide timeout range is encoded in PCIe Device Control2 register. 3169fd75b91dSJack F Vogel * 3170fd75b91dSJack F Vogel * Add 10% to specified maximum and return the number of times to poll for 3171fd75b91dSJack F Vogel * completion timeout, in units of 100 microsec. Never return less than 3172fd75b91dSJack F Vogel * 800 = 80 millisec. 3173fd75b91dSJack F Vogel */ 3174fd75b91dSJack F Vogel static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) 3175fd75b91dSJack F Vogel { 3176fd75b91dSJack F Vogel s16 devctl2; 3177fd75b91dSJack F Vogel u32 pollcnt; 3178fd75b91dSJack F Vogel 3179fd75b91dSJack F Vogel devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); 3180fd75b91dSJack F Vogel devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; 3181fd75b91dSJack F Vogel 3182fd75b91dSJack F Vogel switch (devctl2) { 3183fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_65_130ms: 3184fd75b91dSJack F Vogel pollcnt = 1300; /* 130 millisec */ 3185fd75b91dSJack F Vogel break; 3186fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_260_520ms: 3187fd75b91dSJack F Vogel pollcnt = 5200; /* 520 millisec */ 3188fd75b91dSJack F Vogel break; 3189fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2s: 3190fd75b91dSJack F Vogel pollcnt = 20000; /* 2 sec */ 3191fd75b91dSJack F Vogel break; 3192fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_4_8s: 3193fd75b91dSJack F Vogel pollcnt = 80000; /* 8 sec */ 3194fd75b91dSJack F Vogel break; 3195fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_17_34s: 3196fd75b91dSJack F Vogel pollcnt = 34000; /* 34 sec */ 3197fd75b91dSJack F Vogel break; 3198fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ 3199fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ 3200fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ 3201fd75b91dSJack F Vogel case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ 3202fd75b91dSJack F Vogel default: 3203fd75b91dSJack F Vogel pollcnt = 800; /* 80 millisec minimum */ 3204fd75b91dSJack F Vogel break; 3205fd75b91dSJack F Vogel } 3206fd75b91dSJack F Vogel 3207fd75b91dSJack F Vogel /* add 10% to spec maximum */ 3208fd75b91dSJack F Vogel return (pollcnt * 11) / 10; 3209fd75b91dSJack F Vogel } 3210fd75b91dSJack F Vogel 3211a621e3c8SJack F Vogel /** 321213705f88SJack F Vogel * ixgbe_disable_pcie_master - Disable PCI-express master access 321313705f88SJack F Vogel * @hw: pointer to hardware structure 321413705f88SJack F Vogel * 321513705f88SJack F Vogel * Disables PCI-Express master access and verifies there are no pending 321613705f88SJack F Vogel * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 321713705f88SJack F Vogel * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 321813705f88SJack F Vogel * is returned signifying master requests disabled. 321913705f88SJack F Vogel **/ 322013705f88SJack F Vogel s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 322113705f88SJack F Vogel { 3222c0014855SJack F Vogel s32 status = IXGBE_SUCCESS; 3223fd75b91dSJack F Vogel u32 i, poll; 3224758cc3dcSJack F Vogel u16 value; 322513705f88SJack F Vogel 32262969bf0eSJack F Vogel DEBUGFUNC("ixgbe_disable_pcie_master"); 32272969bf0eSJack F Vogel 322885d0a26eSJack F Vogel /* Always set this bit to ensure any future transactions are blocked */ 322985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); 323085d0a26eSJack F Vogel 3231fd75b91dSJack F Vogel /* Exit if master requests are blocked */ 3232758cc3dcSJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || 3233758cc3dcSJack F Vogel IXGBE_REMOVED(hw->hw_addr)) 3234c0014855SJack F Vogel goto out; 3235c0014855SJack F Vogel 323685d0a26eSJack F Vogel /* Poll for master request bit to clear */ 323713705f88SJack F Vogel for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 323885d0a26eSJack F Vogel usec_delay(100); 3239c0014855SJack F Vogel if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) 3240182b3808SJack F Vogel goto out; 324185d0a26eSJack F Vogel } 3242c0014855SJack F Vogel 3243c0014855SJack F Vogel /* 3244c0014855SJack F Vogel * Two consecutive resets are required via CTRL.RST per datasheet 3245c0014855SJack F Vogel * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine 3246c0014855SJack F Vogel * of this need. The first reset prevents new master requests from 324785d0a26eSJack F Vogel * being issued by our device. We then must wait 1usec or more for any 3248c0014855SJack F Vogel * remaining completions from the PCIe bus to trickle in, and then reset 3249c0014855SJack F Vogel * again to clear out any effects they may have had on our device. 3250c0014855SJack F Vogel */ 325185d0a26eSJack F Vogel DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); 3252c0014855SJack F Vogel hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; 3253c0014855SJack F Vogel 3254a9ca1c79SSean Bruno if (hw->mac.type >= ixgbe_mac_X550) 3255a9ca1c79SSean Bruno goto out; 3256a9ca1c79SSean Bruno 325785d0a26eSJack F Vogel /* 325885d0a26eSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 325985d0a26eSJack F Vogel * transactions pending. 326085d0a26eSJack F Vogel */ 3261fd75b91dSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 3262fd75b91dSJack F Vogel for (i = 0; i < poll; i++) { 326385d0a26eSJack F Vogel usec_delay(100); 3264758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 3265758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3266758cc3dcSJack F Vogel goto out; 3267758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 326885d0a26eSJack F Vogel goto out; 326985d0a26eSJack F Vogel } 327085d0a26eSJack F Vogel 3271fd75b91dSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_POLLING, 3272fd75b91dSJack F Vogel "PCIe transaction pending bit also did not clear.\n"); 327385d0a26eSJack F Vogel status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 327485d0a26eSJack F Vogel 3275c0014855SJack F Vogel out: 327613705f88SJack F Vogel return status; 327713705f88SJack F Vogel } 327813705f88SJack F Vogel 327913705f88SJack F Vogel /** 32809ca4041bSJack F Vogel * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 328113705f88SJack F Vogel * @hw: pointer to hardware structure 32829ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to acquire 328313705f88SJack F Vogel * 328485d0a26eSJack F Vogel * Acquires the SWFW semaphore through the GSSR register for the specified 328513705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 328613705f88SJack F Vogel **/ 3287758cc3dcSJack F Vogel s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) 328813705f88SJack F Vogel { 3289fd75b91dSJack F Vogel u32 gssr = 0; 329013705f88SJack F Vogel u32 swmask = mask; 329113705f88SJack F Vogel u32 fwmask = mask << 5; 3292fd75b91dSJack F Vogel u32 timeout = 200; 3293fd75b91dSJack F Vogel u32 i; 329413705f88SJack F Vogel 32952969bf0eSJack F Vogel DEBUGFUNC("ixgbe_acquire_swfw_sync"); 32962969bf0eSJack F Vogel 3297fd75b91dSJack F Vogel for (i = 0; i < timeout; i++) { 32980ac6dfecSJack F Vogel /* 3299fd75b91dSJack F Vogel * SW NVM semaphore bit is used for access to all 3300fd75b91dSJack F Vogel * SW_FW_SYNC bits (not just NVM) 33010ac6dfecSJack F Vogel */ 330213705f88SJack F Vogel if (ixgbe_get_eeprom_semaphore(hw)) 33032969bf0eSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 330413705f88SJack F Vogel 330513705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 3306fd75b91dSJack F Vogel if (!(gssr & (fwmask | swmask))) { 330713705f88SJack F Vogel gssr |= swmask; 330813705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 330913705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 331013705f88SJack F Vogel return IXGBE_SUCCESS; 3311fd75b91dSJack F Vogel } else { 3312fd75b91dSJack F Vogel /* Resource is currently in use by FW or SW */ 3313fd75b91dSJack F Vogel ixgbe_release_eeprom_semaphore(hw); 3314fd75b91dSJack F Vogel msec_delay(5); 3315fd75b91dSJack F Vogel } 3316fd75b91dSJack F Vogel } 3317fd75b91dSJack F Vogel 3318fd75b91dSJack F Vogel /* If time expired clear the bits holding the lock and retry */ 3319fd75b91dSJack F Vogel if (gssr & (fwmask | swmask)) 3320fd75b91dSJack F Vogel ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); 3321fd75b91dSJack F Vogel 3322fd75b91dSJack F Vogel msec_delay(5); 3323fd75b91dSJack F Vogel return IXGBE_ERR_SWFW_SYNC; 332413705f88SJack F Vogel } 332513705f88SJack F Vogel 332613705f88SJack F Vogel /** 332713705f88SJack F Vogel * ixgbe_release_swfw_sync - Release SWFW semaphore 332813705f88SJack F Vogel * @hw: pointer to hardware structure 33299ca4041bSJack F Vogel * @mask: Mask to specify which semaphore to release 333013705f88SJack F Vogel * 333185d0a26eSJack F Vogel * Releases the SWFW semaphore through the GSSR register for the specified 333213705f88SJack F Vogel * function (CSR, PHY0, PHY1, EEPROM, Flash) 333313705f88SJack F Vogel **/ 3334758cc3dcSJack F Vogel void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) 333513705f88SJack F Vogel { 333613705f88SJack F Vogel u32 gssr; 333713705f88SJack F Vogel u32 swmask = mask; 333813705f88SJack F Vogel 33392969bf0eSJack F Vogel DEBUGFUNC("ixgbe_release_swfw_sync"); 33402969bf0eSJack F Vogel 334113705f88SJack F Vogel ixgbe_get_eeprom_semaphore(hw); 334213705f88SJack F Vogel 334313705f88SJack F Vogel gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 334413705f88SJack F Vogel gssr &= ~swmask; 334513705f88SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 334613705f88SJack F Vogel 334713705f88SJack F Vogel ixgbe_release_eeprom_semaphore(hw); 33480ac6dfecSJack F Vogel } 33490ac6dfecSJack F Vogel 33500ac6dfecSJack F Vogel /** 335185d0a26eSJack F Vogel * ixgbe_disable_sec_rx_path_generic - Stops the receive data path 335285d0a26eSJack F Vogel * @hw: pointer to hardware structure 335385d0a26eSJack F Vogel * 335485d0a26eSJack F Vogel * Stops the receive data path and waits for the HW to internally empty 335585d0a26eSJack F Vogel * the Rx security block 335685d0a26eSJack F Vogel **/ 335785d0a26eSJack F Vogel s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) 335885d0a26eSJack F Vogel { 33595fd1f4beSQiming Yang #define IXGBE_MAX_SECRX_POLL 4000 336085d0a26eSJack F Vogel 336185d0a26eSJack F Vogel int i; 336285d0a26eSJack F Vogel int secrxreg; 336385d0a26eSJack F Vogel 336485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); 336585d0a26eSJack F Vogel 336685d0a26eSJack F Vogel 336785d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 336885d0a26eSJack F Vogel secrxreg |= IXGBE_SECRXCTRL_RX_DIS; 336985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 337085d0a26eSJack F Vogel for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { 337185d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); 337285d0a26eSJack F Vogel if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) 337385d0a26eSJack F Vogel break; 337485d0a26eSJack F Vogel else 337585d0a26eSJack F Vogel /* Use interrupt-safe sleep just in case */ 33765fd1f4beSQiming Yang usec_delay(10); 337785d0a26eSJack F Vogel } 337885d0a26eSJack F Vogel 337985d0a26eSJack F Vogel /* For informational purposes only */ 338085d0a26eSJack F Vogel if (i >= IXGBE_MAX_SECRX_POLL) 338185d0a26eSJack F Vogel DEBUGOUT("Rx unit being enabled before security " 338285d0a26eSJack F Vogel "path fully disabled. Continuing with init.\n"); 338385d0a26eSJack F Vogel 338485d0a26eSJack F Vogel return IXGBE_SUCCESS; 338585d0a26eSJack F Vogel } 338685d0a26eSJack F Vogel 338785d0a26eSJack F Vogel /** 3388758cc3dcSJack F Vogel * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read 3389758cc3dcSJack F Vogel * @hw: pointer to hardware structure 33907d48aa4cSEric Joyner * @locked: bool to indicate whether the SW/FW lock was taken 3391758cc3dcSJack F Vogel * @reg_val: Value we read from AUTOC 3392758cc3dcSJack F Vogel * 3393758cc3dcSJack F Vogel * The default case requires no protection so just to the register read. 3394758cc3dcSJack F Vogel */ 3395758cc3dcSJack F Vogel s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) 3396758cc3dcSJack F Vogel { 339779b36ec9SKevin Bowling *locked = false; 3398758cc3dcSJack F Vogel *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); 3399758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3400758cc3dcSJack F Vogel } 3401758cc3dcSJack F Vogel 3402758cc3dcSJack F Vogel /** 3403758cc3dcSJack F Vogel * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write 3404758cc3dcSJack F Vogel * @hw: pointer to hardware structure 3405758cc3dcSJack F Vogel * @reg_val: value to write to AUTOC 3406758cc3dcSJack F Vogel * @locked: bool to indicate whether the SW/FW lock was already taken by 3407758cc3dcSJack F Vogel * previous read. 3408758cc3dcSJack F Vogel * 3409758cc3dcSJack F Vogel * The default case requires no protection so just to the register write. 3410758cc3dcSJack F Vogel */ 3411758cc3dcSJack F Vogel s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) 3412758cc3dcSJack F Vogel { 3413758cc3dcSJack F Vogel UNREFERENCED_1PARAMETER(locked); 3414758cc3dcSJack F Vogel 3415758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); 3416758cc3dcSJack F Vogel return IXGBE_SUCCESS; 3417758cc3dcSJack F Vogel } 3418758cc3dcSJack F Vogel 3419758cc3dcSJack F Vogel /** 342085d0a26eSJack F Vogel * ixgbe_enable_sec_rx_path_generic - Enables the receive data path 342185d0a26eSJack F Vogel * @hw: pointer to hardware structure 342285d0a26eSJack F Vogel * 342385d0a26eSJack F Vogel * Enables the receive data path. 342485d0a26eSJack F Vogel **/ 342585d0a26eSJack F Vogel s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) 342685d0a26eSJack F Vogel { 34278eb6488eSEric Joyner u32 secrxreg; 342885d0a26eSJack F Vogel 342985d0a26eSJack F Vogel DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); 343085d0a26eSJack F Vogel 343185d0a26eSJack F Vogel secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); 343285d0a26eSJack F Vogel secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; 343385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); 343485d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 343585d0a26eSJack F Vogel 343685d0a26eSJack F Vogel return IXGBE_SUCCESS; 343785d0a26eSJack F Vogel } 343885d0a26eSJack F Vogel 343985d0a26eSJack F Vogel /** 34400ac6dfecSJack F Vogel * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 34410ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34420ac6dfecSJack F Vogel * @regval: register value to write to RXCTRL 34430ac6dfecSJack F Vogel * 34440ac6dfecSJack F Vogel * Enables the Rx DMA unit 34450ac6dfecSJack F Vogel **/ 34460ac6dfecSJack F Vogel s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 34470ac6dfecSJack F Vogel { 34482969bf0eSJack F Vogel DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 34492969bf0eSJack F Vogel 3450758cc3dcSJack F Vogel if (regval & IXGBE_RXCTRL_RXEN) 3451758cc3dcSJack F Vogel ixgbe_enable_rx(hw); 3452758cc3dcSJack F Vogel else 3453758cc3dcSJack F Vogel ixgbe_disable_rx(hw); 34540ac6dfecSJack F Vogel 34550ac6dfecSJack F Vogel return IXGBE_SUCCESS; 34560ac6dfecSJack F Vogel } 34570ac6dfecSJack F Vogel 34580ac6dfecSJack F Vogel /** 34590ac6dfecSJack F Vogel * ixgbe_blink_led_start_generic - Blink LED based on index. 34600ac6dfecSJack F Vogel * @hw: pointer to hardware structure 34610ac6dfecSJack F Vogel * @index: led number to blink 34620ac6dfecSJack F Vogel **/ 34630ac6dfecSJack F Vogel s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 34640ac6dfecSJack F Vogel { 34650ac6dfecSJack F Vogel ixgbe_link_speed speed = 0; 34660ac6dfecSJack F Vogel bool link_up = 0; 3467758cc3dcSJack F Vogel u32 autoc_reg = 0; 34680ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 34690ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 347079b36ec9SKevin Bowling bool locked = false; 34710ac6dfecSJack F Vogel 34722969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_start_generic"); 34732969bf0eSJack F Vogel 34748eb6488eSEric Joyner if (index > 3) 34758eb6488eSEric Joyner return IXGBE_ERR_PARAM; 34768eb6488eSEric Joyner 34770ac6dfecSJack F Vogel /* 34780ac6dfecSJack F Vogel * Link must be up to auto-blink the LEDs; 34790ac6dfecSJack F Vogel * Force it if link is down. 34800ac6dfecSJack F Vogel */ 348179b36ec9SKevin Bowling hw->mac.ops.check_link(hw, &speed, &link_up, false); 34820ac6dfecSJack F Vogel 34830ac6dfecSJack F Vogel if (!link_up) { 3484758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3485758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 34860ecc2ff0SJack F Vogel goto out; 34870ecc2ff0SJack F Vogel 3488d8602bb9SJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 34890ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_FLU; 34900ecc2ff0SJack F Vogel 3491758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3492758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3493758cc3dcSJack F Vogel goto out; 3494758cc3dcSJack F Vogel 3495758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 34960ac6dfecSJack F Vogel msec_delay(10); 34970ac6dfecSJack F Vogel } 34980ac6dfecSJack F Vogel 34990ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35000ac6dfecSJack F Vogel led_reg |= IXGBE_LED_BLINK(index); 35010ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35020ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35030ac6dfecSJack F Vogel 35040ecc2ff0SJack F Vogel out: 35050ecc2ff0SJack F Vogel return ret_val; 35060ac6dfecSJack F Vogel } 35070ac6dfecSJack F Vogel 35080ac6dfecSJack F Vogel /** 35090ac6dfecSJack F Vogel * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 35100ac6dfecSJack F Vogel * @hw: pointer to hardware structure 35110ac6dfecSJack F Vogel * @index: led number to stop blinking 35120ac6dfecSJack F Vogel **/ 35130ac6dfecSJack F Vogel s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 35140ac6dfecSJack F Vogel { 3515758cc3dcSJack F Vogel u32 autoc_reg = 0; 35160ac6dfecSJack F Vogel u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 35170ecc2ff0SJack F Vogel s32 ret_val = IXGBE_SUCCESS; 351879b36ec9SKevin Bowling bool locked = false; 35190ac6dfecSJack F Vogel 35202969bf0eSJack F Vogel DEBUGFUNC("ixgbe_blink_led_stop_generic"); 35212969bf0eSJack F Vogel 35228eb6488eSEric Joyner if (index > 3) 35238eb6488eSEric Joyner return IXGBE_ERR_PARAM; 35248eb6488eSEric Joyner 3525758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); 3526758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3527758cc3dcSJack F Vogel goto out; 3528d8602bb9SJack F Vogel 35290ac6dfecSJack F Vogel autoc_reg &= ~IXGBE_AUTOC_FLU; 35300ac6dfecSJack F Vogel autoc_reg |= IXGBE_AUTOC_AN_RESTART; 35310ac6dfecSJack F Vogel 3532758cc3dcSJack F Vogel ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); 3533758cc3dcSJack F Vogel if (ret_val != IXGBE_SUCCESS) 3534758cc3dcSJack F Vogel goto out; 35350ecc2ff0SJack F Vogel 35360ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_MODE_MASK(index); 35370ac6dfecSJack F Vogel led_reg &= ~IXGBE_LED_BLINK(index); 35380ac6dfecSJack F Vogel led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 35390ac6dfecSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 35400ac6dfecSJack F Vogel IXGBE_WRITE_FLUSH(hw); 35410ac6dfecSJack F Vogel 35420ecc2ff0SJack F Vogel out: 35430ecc2ff0SJack F Vogel return ret_val; 354413705f88SJack F Vogel } 354513705f88SJack F Vogel 35462969bf0eSJack F Vogel /** 35472969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 35482969bf0eSJack F Vogel * @hw: pointer to hardware structure 35492969bf0eSJack F Vogel * @san_mac_offset: SAN MAC address offset 35502969bf0eSJack F Vogel * 35512969bf0eSJack F Vogel * This function will read the EEPROM location for the SAN MAC address 35522969bf0eSJack F Vogel * pointer, and returns the value at that location. This is used in both 35532969bf0eSJack F Vogel * get and set mac_addr routines. 35542969bf0eSJack F Vogel **/ 35552969bf0eSJack F Vogel static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 35562969bf0eSJack F Vogel u16 *san_mac_offset) 35572969bf0eSJack F Vogel { 3558fd75b91dSJack F Vogel s32 ret_val; 3559fd75b91dSJack F Vogel 35602969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 35612969bf0eSJack F Vogel 35622969bf0eSJack F Vogel /* 35632969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35642969bf0eSJack F Vogel * available. 35652969bf0eSJack F Vogel */ 3566fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, 3567fd75b91dSJack F Vogel san_mac_offset); 3568fd75b91dSJack F Vogel if (ret_val) { 3569fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3570fd75b91dSJack F Vogel "eeprom at offset %d failed", 3571fd75b91dSJack F Vogel IXGBE_SAN_MAC_ADDR_PTR); 3572fd75b91dSJack F Vogel } 35732969bf0eSJack F Vogel 3574fd75b91dSJack F Vogel return ret_val; 35752969bf0eSJack F Vogel } 35762969bf0eSJack F Vogel 35772969bf0eSJack F Vogel /** 35782969bf0eSJack F Vogel * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 35792969bf0eSJack F Vogel * @hw: pointer to hardware structure 35802969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 35812969bf0eSJack F Vogel * 35822969bf0eSJack F Vogel * Reads the SAN MAC address from the EEPROM, if it's available. This is 35832969bf0eSJack F Vogel * per-port, so set_lan_id() must be called before reading the addresses. 35842969bf0eSJack F Vogel * set_lan_id() is called by identify_sfp(), but this cannot be relied 35852969bf0eSJack F Vogel * upon for non-SFP connections, so we must call it here. 35862969bf0eSJack F Vogel **/ 35872969bf0eSJack F Vogel s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 35882969bf0eSJack F Vogel { 35892969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 35902969bf0eSJack F Vogel u8 i; 3591fd75b91dSJack F Vogel s32 ret_val; 35922969bf0eSJack F Vogel 35932969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 35942969bf0eSJack F Vogel 35952969bf0eSJack F Vogel /* 35962969bf0eSJack F Vogel * First read the EEPROM pointer to see if the MAC addresses are 35972969bf0eSJack F Vogel * available. If they're not, no point in calling set_lan_id() here. 35982969bf0eSJack F Vogel */ 3599fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3600fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 36012969bf0eSJack F Vogel goto san_mac_addr_out; 36022969bf0eSJack F Vogel 36032969bf0eSJack F Vogel /* make sure we know which port we need to program */ 36042969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36052969bf0eSJack F Vogel /* apply the port offset to the address offset */ 36062969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36072969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36082969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 3609fd75b91dSJack F Vogel ret_val = hw->eeprom.ops.read(hw, san_mac_offset, 3610fd75b91dSJack F Vogel &san_mac_data); 3611fd75b91dSJack F Vogel if (ret_val) { 3612fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 3613fd75b91dSJack F Vogel "eeprom read at offset %d failed", 3614fd75b91dSJack F Vogel san_mac_offset); 3615fd75b91dSJack F Vogel goto san_mac_addr_out; 3616fd75b91dSJack F Vogel } 36172969bf0eSJack F Vogel san_mac_addr[i * 2] = (u8)(san_mac_data); 36182969bf0eSJack F Vogel san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 36192969bf0eSJack F Vogel san_mac_offset++; 36202969bf0eSJack F Vogel } 3621fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36222969bf0eSJack F Vogel 36232969bf0eSJack F Vogel san_mac_addr_out: 3624fd75b91dSJack F Vogel /* 3625fd75b91dSJack F Vogel * No addresses available in this EEPROM. It's not an 3626fd75b91dSJack F Vogel * error though, so just wipe the local address and return. 3627fd75b91dSJack F Vogel */ 3628fd75b91dSJack F Vogel for (i = 0; i < 6; i++) 3629fd75b91dSJack F Vogel san_mac_addr[i] = 0xFF; 36302969bf0eSJack F Vogel return IXGBE_SUCCESS; 36312969bf0eSJack F Vogel } 36322969bf0eSJack F Vogel 36332969bf0eSJack F Vogel /** 36342969bf0eSJack F Vogel * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 36352969bf0eSJack F Vogel * @hw: pointer to hardware structure 36362969bf0eSJack F Vogel * @san_mac_addr: SAN MAC address 36372969bf0eSJack F Vogel * 36382969bf0eSJack F Vogel * Write a SAN MAC address to the EEPROM. 36392969bf0eSJack F Vogel **/ 36402969bf0eSJack F Vogel s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 36412969bf0eSJack F Vogel { 3642fd75b91dSJack F Vogel s32 ret_val; 36432969bf0eSJack F Vogel u16 san_mac_data, san_mac_offset; 36442969bf0eSJack F Vogel u8 i; 36452969bf0eSJack F Vogel 36462969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 36472969bf0eSJack F Vogel 36482969bf0eSJack F Vogel /* Look for SAN mac address pointer. If not defined, return */ 3649fd75b91dSJack F Vogel ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 3650fd75b91dSJack F Vogel if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) 3651fd75b91dSJack F Vogel return IXGBE_ERR_NO_SAN_ADDR_PTR; 36522969bf0eSJack F Vogel 36532969bf0eSJack F Vogel /* Make sure we know which port we need to write */ 36542969bf0eSJack F Vogel hw->mac.ops.set_lan_id(hw); 36552969bf0eSJack F Vogel /* Apply the port offset to the address offset */ 36562969bf0eSJack F Vogel (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 36572969bf0eSJack F Vogel (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 36582969bf0eSJack F Vogel 36592969bf0eSJack F Vogel for (i = 0; i < 3; i++) { 36602969bf0eSJack F Vogel san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 36612969bf0eSJack F Vogel san_mac_data |= (u16)(san_mac_addr[i * 2]); 36622969bf0eSJack F Vogel hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 36632969bf0eSJack F Vogel san_mac_offset++; 36642969bf0eSJack F Vogel } 36652969bf0eSJack F Vogel 3666fd75b91dSJack F Vogel return IXGBE_SUCCESS; 36672969bf0eSJack F Vogel } 36682969bf0eSJack F Vogel 36692969bf0eSJack F Vogel /** 36702969bf0eSJack F Vogel * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 36712969bf0eSJack F Vogel * @hw: pointer to hardware structure 36722969bf0eSJack F Vogel * 36732969bf0eSJack F Vogel * Read PCIe configuration space, and get the MSI-X vector count from 36742969bf0eSJack F Vogel * the capabilities table. 36752969bf0eSJack F Vogel **/ 3676a621e3c8SJack F Vogel u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 36772969bf0eSJack F Vogel { 3678a621e3c8SJack F Vogel u16 msix_count = 1; 3679a621e3c8SJack F Vogel u16 max_msix_count; 3680a621e3c8SJack F Vogel u16 pcie_offset; 3681a621e3c8SJack F Vogel 3682a621e3c8SJack F Vogel switch (hw->mac.type) { 3683a621e3c8SJack F Vogel case ixgbe_mac_82598EB: 3684a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; 3685a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; 3686a621e3c8SJack F Vogel break; 3687a621e3c8SJack F Vogel case ixgbe_mac_82599EB: 3688a621e3c8SJack F Vogel case ixgbe_mac_X540: 3689758cc3dcSJack F Vogel case ixgbe_mac_X550: 3690758cc3dcSJack F Vogel case ixgbe_mac_X550EM_x: 36918eb6488eSEric Joyner case ixgbe_mac_X550EM_a: 3692a621e3c8SJack F Vogel pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; 3693a621e3c8SJack F Vogel max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; 3694a621e3c8SJack F Vogel break; 3695a621e3c8SJack F Vogel default: 3696a621e3c8SJack F Vogel return msix_count; 3697a621e3c8SJack F Vogel } 36982969bf0eSJack F Vogel 36992969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 3700a621e3c8SJack F Vogel msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); 3701758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3702758cc3dcSJack F Vogel msix_count = 0; 37032969bf0eSJack F Vogel msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 37042969bf0eSJack F Vogel 3705a621e3c8SJack F Vogel /* MSI-X count is zero-based in HW */ 37062969bf0eSJack F Vogel msix_count++; 3707a621e3c8SJack F Vogel 3708a621e3c8SJack F Vogel if (msix_count > max_msix_count) 3709a621e3c8SJack F Vogel msix_count = max_msix_count; 37102969bf0eSJack F Vogel 37112969bf0eSJack F Vogel return msix_count; 37122969bf0eSJack F Vogel } 37132969bf0eSJack F Vogel 37142969bf0eSJack F Vogel /** 37152969bf0eSJack F Vogel * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 37162969bf0eSJack F Vogel * @hw: pointer to hardware structure 37172969bf0eSJack F Vogel * @addr: Address to put into receive address register 37182969bf0eSJack F Vogel * @vmdq: VMDq pool to assign 37192969bf0eSJack F Vogel * 37202969bf0eSJack F Vogel * Puts an ethernet address into a receive address register, or 3721c19c7afeSEric Joyner * finds the rar that it is already in; adds to the pool list 37222969bf0eSJack F Vogel **/ 37232969bf0eSJack F Vogel s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 37242969bf0eSJack F Vogel { 37252969bf0eSJack F Vogel static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 37262969bf0eSJack F Vogel u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 37272969bf0eSJack F Vogel u32 rar; 37282969bf0eSJack F Vogel u32 rar_low, rar_high; 37292969bf0eSJack F Vogel u32 addr_low, addr_high; 37302969bf0eSJack F Vogel 37312969bf0eSJack F Vogel DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 37322969bf0eSJack F Vogel 37332969bf0eSJack F Vogel /* swap bytes for HW little endian */ 37342969bf0eSJack F Vogel addr_low = addr[0] | (addr[1] << 8) 37352969bf0eSJack F Vogel | (addr[2] << 16) 37362969bf0eSJack F Vogel | (addr[3] << 24); 37372969bf0eSJack F Vogel addr_high = addr[4] | (addr[5] << 8); 37382969bf0eSJack F Vogel 37392969bf0eSJack F Vogel /* 37402969bf0eSJack F Vogel * Either find the mac_id in rar or find the first empty space. 37412969bf0eSJack F Vogel * rar_highwater points to just after the highest currently used 37422969bf0eSJack F Vogel * rar in order to shorten the search. It grows when we add a new 37432969bf0eSJack F Vogel * rar to the top. 37442969bf0eSJack F Vogel */ 37452969bf0eSJack F Vogel for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 37462969bf0eSJack F Vogel rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 37472969bf0eSJack F Vogel 37482969bf0eSJack F Vogel if (((IXGBE_RAH_AV & rar_high) == 0) 37492969bf0eSJack F Vogel && first_empty_rar == NO_EMPTY_RAR_FOUND) { 37502969bf0eSJack F Vogel first_empty_rar = rar; 37512969bf0eSJack F Vogel } else if ((rar_high & 0xFFFF) == addr_high) { 37522969bf0eSJack F Vogel rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 37532969bf0eSJack F Vogel if (rar_low == addr_low) 37542969bf0eSJack F Vogel break; /* found it already in the rars */ 37552969bf0eSJack F Vogel } 37562969bf0eSJack F Vogel } 37572969bf0eSJack F Vogel 37582969bf0eSJack F Vogel if (rar < hw->mac.rar_highwater) { 37592969bf0eSJack F Vogel /* already there so just add to the pool bits */ 37602969bf0eSJack F Vogel ixgbe_set_vmdq(hw, rar, vmdq); 37612969bf0eSJack F Vogel } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 37622969bf0eSJack F Vogel /* stick it into first empty RAR slot we found */ 37632969bf0eSJack F Vogel rar = first_empty_rar; 37642969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37652969bf0eSJack F Vogel } else if (rar == hw->mac.rar_highwater) { 37662969bf0eSJack F Vogel /* add it to the top of the list and inc the highwater mark */ 37672969bf0eSJack F Vogel ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 37682969bf0eSJack F Vogel hw->mac.rar_highwater++; 37692969bf0eSJack F Vogel } else if (rar >= hw->mac.num_rar_entries) { 37702969bf0eSJack F Vogel return IXGBE_ERR_INVALID_MAC_ADDR; 37712969bf0eSJack F Vogel } 37722969bf0eSJack F Vogel 37732969bf0eSJack F Vogel /* 37742969bf0eSJack F Vogel * If we found rar[0], make sure the default pool bit (we use pool 0) 37752969bf0eSJack F Vogel * remains cleared to be sure default pool packets will get delivered 37762969bf0eSJack F Vogel */ 37772969bf0eSJack F Vogel if (rar == 0) 37782969bf0eSJack F Vogel ixgbe_clear_vmdq(hw, rar, 0); 37792969bf0eSJack F Vogel 37802969bf0eSJack F Vogel return rar; 37812969bf0eSJack F Vogel } 37822969bf0eSJack F Vogel 37832969bf0eSJack F Vogel /** 37842969bf0eSJack F Vogel * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 37852969bf0eSJack F Vogel * @hw: pointer to hardware struct 37862969bf0eSJack F Vogel * @rar: receive address register index to disassociate 37872969bf0eSJack F Vogel * @vmdq: VMDq pool index to remove from the rar 37882969bf0eSJack F Vogel **/ 37892969bf0eSJack F Vogel s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 37902969bf0eSJack F Vogel { 37912969bf0eSJack F Vogel u32 mpsar_lo, mpsar_hi; 37922969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 37932969bf0eSJack F Vogel 37942969bf0eSJack F Vogel DEBUGFUNC("ixgbe_clear_vmdq_generic"); 37952969bf0eSJack F Vogel 37961a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 37971a4e3449SJack F Vogel if (rar >= rar_entries) { 3798fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3799fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38001a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38011a4e3449SJack F Vogel } 38021a4e3449SJack F Vogel 38032969bf0eSJack F Vogel mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38042969bf0eSJack F Vogel mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38052969bf0eSJack F Vogel 3806758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 3807758cc3dcSJack F Vogel goto done; 3808758cc3dcSJack F Vogel 38092969bf0eSJack F Vogel if (!mpsar_lo && !mpsar_hi) 38102969bf0eSJack F Vogel goto done; 38112969bf0eSJack F Vogel 38122969bf0eSJack F Vogel if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 38132969bf0eSJack F Vogel if (mpsar_lo) { 38142969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 38158270b717SGuinan Sun mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38162969bf0eSJack F Vogel } 38172969bf0eSJack F Vogel if (mpsar_hi) { 38182969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 38198270b717SGuinan Sun mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38202969bf0eSJack F Vogel } 38212969bf0eSJack F Vogel } else if (vmdq < 32) { 38222969bf0eSJack F Vogel mpsar_lo &= ~(1 << vmdq); 38232969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 38242969bf0eSJack F Vogel } else { 38252969bf0eSJack F Vogel mpsar_hi &= ~(1 << (vmdq - 32)); 38262969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 38272969bf0eSJack F Vogel } 38282969bf0eSJack F Vogel 38292969bf0eSJack F Vogel /* was that the last pool using this rar? */ 38308eb6488eSEric Joyner if (mpsar_lo == 0 && mpsar_hi == 0 && 38318eb6488eSEric Joyner rar != 0 && rar != hw->mac.san_mac_rar_index) 38322969bf0eSJack F Vogel hw->mac.ops.clear_rar(hw, rar); 38332969bf0eSJack F Vogel done: 38342969bf0eSJack F Vogel return IXGBE_SUCCESS; 38352969bf0eSJack F Vogel } 38362969bf0eSJack F Vogel 38372969bf0eSJack F Vogel /** 38382969bf0eSJack F Vogel * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 38392969bf0eSJack F Vogel * @hw: pointer to hardware struct 38402969bf0eSJack F Vogel * @rar: receive address register index to associate with a VMDq index 38412969bf0eSJack F Vogel * @vmdq: VMDq pool index 38422969bf0eSJack F Vogel **/ 38432969bf0eSJack F Vogel s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 38442969bf0eSJack F Vogel { 38452969bf0eSJack F Vogel u32 mpsar; 38462969bf0eSJack F Vogel u32 rar_entries = hw->mac.num_rar_entries; 38472969bf0eSJack F Vogel 38482969bf0eSJack F Vogel DEBUGFUNC("ixgbe_set_vmdq_generic"); 38492969bf0eSJack F Vogel 38501a4e3449SJack F Vogel /* Make sure we are using a valid rar index range */ 38511a4e3449SJack F Vogel if (rar >= rar_entries) { 3852fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 3853fd75b91dSJack F Vogel "RAR index %d is out of range.\n", rar); 38541a4e3449SJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 38551a4e3449SJack F Vogel } 38561a4e3449SJack F Vogel 38572969bf0eSJack F Vogel if (vmdq < 32) { 38582969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 38592969bf0eSJack F Vogel mpsar |= 1 << vmdq; 38602969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 38612969bf0eSJack F Vogel } else { 38622969bf0eSJack F Vogel mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 38632969bf0eSJack F Vogel mpsar |= 1 << (vmdq - 32); 38642969bf0eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 38652969bf0eSJack F Vogel } 38662969bf0eSJack F Vogel return IXGBE_SUCCESS; 38672969bf0eSJack F Vogel } 38682969bf0eSJack F Vogel 38692969bf0eSJack F Vogel /** 3870a621e3c8SJack F Vogel * This function should only be involved in the IOV mode. 3871a621e3c8SJack F Vogel * In IOV mode, Default pool is next pool after the number of 3872a621e3c8SJack F Vogel * VFs advertized and not 0. 3873a621e3c8SJack F Vogel * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] 3874a621e3c8SJack F Vogel * 3875a621e3c8SJack F Vogel * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address 3876a621e3c8SJack F Vogel * @hw: pointer to hardware struct 3877a621e3c8SJack F Vogel * @vmdq: VMDq pool 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 * 4121*cd7e11f7SGordon 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 { 42352969bf0eSJack F Vogel if (links_reg & IXGBE_LINKS_UP) 423679b36ec9SKevin Bowling *link_up = true; 42372969bf0eSJack F Vogel else 423879b36ec9SKevin Bowling *link_up = false; 42392969bf0eSJack F Vogel } 42402969bf0eSJack F Vogel 4241758cc3dcSJack F Vogel switch (links_reg & IXGBE_LINKS_SPEED_82599) { 4242758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_10G_82599: 42432969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_10GB_FULL; 4244758cc3dcSJack F Vogel if (hw->mac.type >= ixgbe_mac_X550) { 4245758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4246758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 4247758cc3dcSJack F Vogel } 4248758cc3dcSJack F Vogel break; 4249758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_1G_82599: 42502969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_1GB_FULL; 4251758cc3dcSJack F Vogel break; 4252758cc3dcSJack F Vogel case IXGBE_LINKS_SPEED_100_82599: 42532969bf0eSJack F Vogel *speed = IXGBE_LINK_SPEED_100_FULL; 42548eb6488eSEric Joyner if (hw->mac.type == ixgbe_mac_X550) { 4255758cc3dcSJack F Vogel if (links_reg & IXGBE_LINKS_SPEED_NON_STD) 4256758cc3dcSJack F Vogel *speed = IXGBE_LINK_SPEED_5GB_FULL; 4257758cc3dcSJack F Vogel } 4258758cc3dcSJack F Vogel break; 42598eb6488eSEric Joyner case IXGBE_LINKS_SPEED_10_X550EM_A: 42608eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_UNKNOWN; 42618eb6488eSEric Joyner if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || 42627d48aa4cSEric Joyner hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) 42638eb6488eSEric Joyner *speed = IXGBE_LINK_SPEED_10_FULL; 42648eb6488eSEric Joyner break; 4265758cc3dcSJack F Vogel default: 42661a4e3449SJack F Vogel *speed = IXGBE_LINK_SPEED_UNKNOWN; 4267758cc3dcSJack F Vogel } 42682969bf0eSJack F Vogel 42692969bf0eSJack F Vogel return IXGBE_SUCCESS; 42702969bf0eSJack F Vogel } 42712969bf0eSJack F Vogel 42722969bf0eSJack F Vogel /** 42732969bf0eSJack F Vogel * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 42742969bf0eSJack F Vogel * the EEPROM 42752969bf0eSJack F Vogel * @hw: pointer to hardware structure 42762969bf0eSJack F Vogel * @wwnn_prefix: the alternative WWNN prefix 42772969bf0eSJack F Vogel * @wwpn_prefix: the alternative WWPN prefix 42782969bf0eSJack F Vogel * 42792969bf0eSJack F Vogel * This function will read the EEPROM from the alternative SAN MAC address 42802969bf0eSJack F Vogel * block to check the support for the alternative WWNN/WWPN prefix support. 42812969bf0eSJack F Vogel **/ 42822969bf0eSJack F Vogel s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 42832969bf0eSJack F Vogel u16 *wwpn_prefix) 42842969bf0eSJack F Vogel { 42852969bf0eSJack F Vogel u16 offset, caps; 42862969bf0eSJack F Vogel u16 alt_san_mac_blk_offset; 42872969bf0eSJack F Vogel 42882969bf0eSJack F Vogel DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 42892969bf0eSJack F Vogel 42902969bf0eSJack F Vogel /* clear output first */ 42912969bf0eSJack F Vogel *wwnn_prefix = 0xFFFF; 42922969bf0eSJack F Vogel *wwpn_prefix = 0xFFFF; 42932969bf0eSJack F Vogel 42942969bf0eSJack F Vogel /* check if alternative SAN MAC is supported */ 4295fd75b91dSJack F Vogel offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; 4296fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) 4297fd75b91dSJack F Vogel goto wwn_prefix_err; 42982969bf0eSJack F Vogel 42992969bf0eSJack F Vogel if ((alt_san_mac_blk_offset == 0) || 43002969bf0eSJack F Vogel (alt_san_mac_blk_offset == 0xFFFF)) 43012969bf0eSJack F Vogel goto wwn_prefix_out; 43022969bf0eSJack F Vogel 43032969bf0eSJack F Vogel /* check capability in alternative san mac address block */ 43042969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 4305fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, &caps)) 4306fd75b91dSJack F Vogel goto wwn_prefix_err; 43072969bf0eSJack F Vogel if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 43082969bf0eSJack F Vogel goto wwn_prefix_out; 43092969bf0eSJack F Vogel 43102969bf0eSJack F Vogel /* get the corresponding prefix for WWNN/WWPN */ 43112969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 4312fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { 4313fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4314fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4315fd75b91dSJack F Vogel } 43162969bf0eSJack F Vogel 43172969bf0eSJack F Vogel offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 4318fd75b91dSJack F Vogel if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) 4319fd75b91dSJack F Vogel goto wwn_prefix_err; 43202969bf0eSJack F Vogel 43212969bf0eSJack F Vogel wwn_prefix_out: 43222969bf0eSJack F Vogel return IXGBE_SUCCESS; 4323fd75b91dSJack F Vogel 4324fd75b91dSJack F Vogel wwn_prefix_err: 4325fd75b91dSJack F Vogel ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 4326fd75b91dSJack F Vogel "eeprom read at offset %d failed", offset); 4327fd75b91dSJack F Vogel return IXGBE_SUCCESS; 43282969bf0eSJack F Vogel } 43291a4e3449SJack F Vogel 43301a4e3449SJack F Vogel /** 43311a4e3449SJack F Vogel * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM 43321a4e3449SJack F Vogel * @hw: pointer to hardware structure 43331a4e3449SJack F Vogel * @bs: the fcoe boot status 43341a4e3449SJack F Vogel * 43351a4e3449SJack F Vogel * This function will read the FCOE boot status from the iSCSI FCOE block 43361a4e3449SJack F Vogel **/ 43371a4e3449SJack F Vogel s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) 43381a4e3449SJack F Vogel { 43391a4e3449SJack F Vogel u16 offset, caps, flags; 43401a4e3449SJack F Vogel s32 status; 43411a4e3449SJack F Vogel 43421a4e3449SJack F Vogel DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); 43431a4e3449SJack F Vogel 43441a4e3449SJack F Vogel /* clear output first */ 43451a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_unavailable; 43461a4e3449SJack F Vogel 43471a4e3449SJack F Vogel /* check if FCOE IBA block is present */ 43481a4e3449SJack F Vogel offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; 43491a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &caps); 43501a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43511a4e3449SJack F Vogel goto out; 43521a4e3449SJack F Vogel 43531a4e3449SJack F Vogel if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) 43541a4e3449SJack F Vogel goto out; 43551a4e3449SJack F Vogel 43561a4e3449SJack F Vogel /* check if iSCSI FCOE block is populated */ 43571a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); 43581a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43591a4e3449SJack F Vogel goto out; 43601a4e3449SJack F Vogel 43611a4e3449SJack F Vogel if ((offset == 0) || (offset == 0xFFFF)) 43621a4e3449SJack F Vogel goto out; 43631a4e3449SJack F Vogel 43641a4e3449SJack F Vogel /* read fcoe flags in iSCSI FCOE block */ 43651a4e3449SJack F Vogel offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; 43661a4e3449SJack F Vogel status = hw->eeprom.ops.read(hw, offset, &flags); 43671a4e3449SJack F Vogel if (status != IXGBE_SUCCESS) 43681a4e3449SJack F Vogel goto out; 43691a4e3449SJack F Vogel 43701a4e3449SJack F Vogel if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) 43711a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_enabled; 43721a4e3449SJack F Vogel else 43731a4e3449SJack F Vogel *bs = ixgbe_fcoe_bootstatus_disabled; 43741a4e3449SJack F Vogel 43751a4e3449SJack F Vogel out: 43761a4e3449SJack F Vogel return status; 43771a4e3449SJack F Vogel } 43781a4e3449SJack F Vogel 43791a4e3449SJack F Vogel /** 43801a4e3449SJack F Vogel * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing 43811a4e3449SJack F Vogel * @hw: pointer to hardware structure 43828eb6488eSEric Joyner * @enable: enable or disable switch for MAC anti-spoofing 43838eb6488eSEric Joyner * @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing 43841a4e3449SJack F Vogel * 43851a4e3449SJack F Vogel **/ 43868eb6488eSEric Joyner void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 43871a4e3449SJack F Vogel { 43888eb6488eSEric Joyner int vf_target_reg = vf >> 3; 43898eb6488eSEric Joyner int vf_target_shift = vf % 8; 43908eb6488eSEric Joyner u32 pfvfspoof; 43911a4e3449SJack F Vogel 43921a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 43931a4e3449SJack F Vogel return; 43941a4e3449SJack F Vogel 43958eb6488eSEric Joyner pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 43961a4e3449SJack F Vogel if (enable) 43978eb6488eSEric Joyner pfvfspoof |= (1 << vf_target_shift); 43988eb6488eSEric Joyner else 43998eb6488eSEric Joyner pfvfspoof &= ~(1 << vf_target_shift); 44008eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44011a4e3449SJack F Vogel } 44021a4e3449SJack F Vogel 44031a4e3449SJack F Vogel /** 44041a4e3449SJack F Vogel * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing 44051a4e3449SJack F Vogel * @hw: pointer to hardware structure 44061a4e3449SJack F Vogel * @enable: enable or disable switch for VLAN anti-spoofing 4407758cc3dcSJack F Vogel * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing 44081a4e3449SJack F Vogel * 44091a4e3449SJack F Vogel **/ 44101a4e3449SJack F Vogel void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) 44111a4e3449SJack F Vogel { 44121a4e3449SJack F Vogel int vf_target_reg = vf >> 3; 44131a4e3449SJack F Vogel int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; 44141a4e3449SJack F Vogel u32 pfvfspoof; 44151a4e3449SJack F Vogel 44161a4e3449SJack F Vogel if (hw->mac.type == ixgbe_mac_82598EB) 44171a4e3449SJack F Vogel return; 44181a4e3449SJack F Vogel 44191a4e3449SJack F Vogel pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); 44201a4e3449SJack F Vogel if (enable) 44211a4e3449SJack F Vogel pfvfspoof |= (1 << vf_target_shift); 44221a4e3449SJack F Vogel else 44231a4e3449SJack F Vogel pfvfspoof &= ~(1 << vf_target_shift); 44241a4e3449SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); 44251a4e3449SJack F Vogel } 4426182b3808SJack F Vogel 4427182b3808SJack F Vogel /** 4428182b3808SJack F Vogel * ixgbe_get_device_caps_generic - Get additional device capabilities 4429182b3808SJack F Vogel * @hw: pointer to hardware structure 4430182b3808SJack F Vogel * @device_caps: the EEPROM word with the extra device capabilities 4431182b3808SJack F Vogel * 4432182b3808SJack F Vogel * This function will read the EEPROM location for the device capabilities, 4433182b3808SJack F Vogel * and return the word through device_caps. 4434182b3808SJack F Vogel **/ 4435182b3808SJack F Vogel s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) 4436182b3808SJack F Vogel { 4437182b3808SJack F Vogel DEBUGFUNC("ixgbe_get_device_caps_generic"); 4438182b3808SJack F Vogel 4439182b3808SJack F Vogel hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); 4440182b3808SJack F Vogel 4441182b3808SJack F Vogel return IXGBE_SUCCESS; 4442182b3808SJack F Vogel } 4443182b3808SJack F Vogel 4444182b3808SJack F Vogel /** 4445182b3808SJack F Vogel * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering 4446182b3808SJack F Vogel * @hw: pointer to hardware structure 4447182b3808SJack F Vogel * 4448182b3808SJack F Vogel **/ 4449182b3808SJack F Vogel void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) 4450182b3808SJack F Vogel { 4451182b3808SJack F Vogel u32 regval; 4452182b3808SJack F Vogel u32 i; 4453182b3808SJack F Vogel 4454182b3808SJack F Vogel DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); 4455182b3808SJack F Vogel 4456182b3808SJack F Vogel /* Enable relaxed ordering */ 4457182b3808SJack F Vogel for (i = 0; i < hw->mac.max_tx_queues; i++) { 4458182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); 4459a621e3c8SJack F Vogel regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; 4460182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); 4461182b3808SJack F Vogel } 4462182b3808SJack F Vogel 4463182b3808SJack F Vogel for (i = 0; i < hw->mac.max_rx_queues; i++) { 4464182b3808SJack F Vogel regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); 4465a621e3c8SJack F Vogel regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | 4466a621e3c8SJack F Vogel IXGBE_DCA_RXCTRL_HEAD_WRO_EN; 4467182b3808SJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); 4468182b3808SJack F Vogel } 4469182b3808SJack F Vogel 4470182b3808SJack F Vogel } 447185d0a26eSJack F Vogel 447285d0a26eSJack F Vogel /** 447385d0a26eSJack F Vogel * ixgbe_calculate_checksum - Calculate checksum for buffer 447485d0a26eSJack F Vogel * @buffer: pointer to EEPROM 447585d0a26eSJack F Vogel * @length: size of EEPROM to calculate a checksum for 447685d0a26eSJack F Vogel * Calculates the checksum for some buffer on a specified length. The 447785d0a26eSJack F Vogel * checksum calculated is returned. 447885d0a26eSJack F Vogel **/ 44790ecc2ff0SJack F Vogel u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) 448085d0a26eSJack F Vogel { 448185d0a26eSJack F Vogel u32 i; 448285d0a26eSJack F Vogel u8 sum = 0; 448385d0a26eSJack F Vogel 448485d0a26eSJack F Vogel DEBUGFUNC("ixgbe_calculate_checksum"); 448585d0a26eSJack F Vogel 448685d0a26eSJack F Vogel if (!buffer) 448785d0a26eSJack F Vogel return 0; 448885d0a26eSJack F Vogel 448985d0a26eSJack F Vogel for (i = 0; i < length; i++) 449085d0a26eSJack F Vogel sum += buffer[i]; 449185d0a26eSJack F Vogel 449285d0a26eSJack F Vogel return (u8) (0 - sum); 449385d0a26eSJack F Vogel } 449485d0a26eSJack F Vogel 449585d0a26eSJack F Vogel /** 44968eb6488eSEric Joyner * ixgbe_hic_unlocked - Issue command to manageability block unlocked 449785d0a26eSJack F Vogel * @hw: pointer to the HW structure 44988eb6488eSEric Joyner * @buffer: command to write and where the return status will be placed 4499a621e3c8SJack F Vogel * @length: length of buffer, must be multiple of 4 bytes 4500758cc3dcSJack F Vogel * @timeout: time in ms to wait for command completion 450185d0a26eSJack F Vogel * 450285d0a26eSJack F Vogel * Communicates with the manageability block. On success return IXGBE_SUCCESS 45038eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45048eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45058eb6488eSEric Joyner * 45068eb6488eSEric Joyner * This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held 45078eb6488eSEric Joyner * by the caller. 450885d0a26eSJack F Vogel **/ 45098eb6488eSEric Joyner s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, 45108eb6488eSEric Joyner u32 timeout) 451185d0a26eSJack F Vogel { 45128eb6488eSEric Joyner u32 hicr, i, fwsts; 4513758cc3dcSJack F Vogel u16 dword_len; 451485d0a26eSJack F Vogel 45158eb6488eSEric Joyner DEBUGFUNC("ixgbe_hic_unlocked"); 451685d0a26eSJack F Vogel 45178eb6488eSEric Joyner if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 4518758cc3dcSJack F Vogel DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 4519758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 452085d0a26eSJack F Vogel } 45218eb6488eSEric Joyner 4522758cc3dcSJack F Vogel /* Set bit 9 of FWSTS clearing FW reset indication */ 4523758cc3dcSJack F Vogel fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); 4524758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); 452585d0a26eSJack F Vogel 452685d0a26eSJack F Vogel /* Check that the host interface is enabled. */ 452785d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 45288eb6488eSEric Joyner if (!(hicr & IXGBE_HICR_EN)) { 452985d0a26eSJack F Vogel DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); 4530758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 453185d0a26eSJack F Vogel } 453285d0a26eSJack F Vogel 4533758cc3dcSJack F Vogel /* Calculate length in DWORDs. We must be DWORD aligned */ 45348eb6488eSEric Joyner if (length % sizeof(u32)) { 4535758cc3dcSJack F Vogel DEBUGOUT("Buffer length failure, not aligned to dword"); 4536758cc3dcSJack F Vogel return IXGBE_ERR_INVALID_ARGUMENT; 4537758cc3dcSJack F Vogel } 4538758cc3dcSJack F Vogel 453985d0a26eSJack F Vogel dword_len = length >> 2; 454085d0a26eSJack F Vogel 4541758cc3dcSJack F Vogel /* The device driver writes the relevant command block 454285d0a26eSJack F Vogel * into the ram area. 454385d0a26eSJack F Vogel */ 454485d0a26eSJack F Vogel for (i = 0; i < dword_len; i++) 454585d0a26eSJack F Vogel IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, 454685d0a26eSJack F Vogel i, IXGBE_CPU_TO_LE32(buffer[i])); 454785d0a26eSJack F Vogel 454885d0a26eSJack F Vogel /* Setting this bit tells the ARC that a new command is pending. */ 454985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); 455085d0a26eSJack F Vogel 4551758cc3dcSJack F Vogel for (i = 0; i < timeout; i++) { 455285d0a26eSJack F Vogel hicr = IXGBE_READ_REG(hw, IXGBE_HICR); 455385d0a26eSJack F Vogel if (!(hicr & IXGBE_HICR_C)) 455485d0a26eSJack F Vogel break; 455585d0a26eSJack F Vogel msec_delay(1); 455685d0a26eSJack F Vogel } 455785d0a26eSJack F Vogel 4558c966c431SGuinan Sun /* For each command except "Apply Update" perform 4559c966c431SGuinan Sun * status checks in the HICR registry. 4560c966c431SGuinan Sun */ 4561c966c431SGuinan Sun if ((buffer[0] & IXGBE_HOST_INTERFACE_MASK_CMD) == 4562c966c431SGuinan Sun IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD) 4563c966c431SGuinan Sun return IXGBE_SUCCESS; 4564c966c431SGuinan Sun 4565758cc3dcSJack F Vogel /* Check command completion */ 45668eb6488eSEric Joyner if ((timeout && i == timeout) || 4567758cc3dcSJack F Vogel !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { 4568758cc3dcSJack F Vogel ERROR_REPORT1(IXGBE_ERROR_CAUTION, 4569758cc3dcSJack F Vogel "Command has failed with no status valid.\n"); 4570758cc3dcSJack F Vogel return IXGBE_ERR_HOST_INTERFACE_COMMAND; 457185d0a26eSJack F Vogel } 457285d0a26eSJack F Vogel 45738eb6488eSEric Joyner return IXGBE_SUCCESS; 45748eb6488eSEric Joyner } 45758eb6488eSEric Joyner 45768eb6488eSEric Joyner /** 45778eb6488eSEric Joyner * ixgbe_host_interface_command - Issue command to manageability block 45788eb6488eSEric Joyner * @hw: pointer to the HW structure 45798eb6488eSEric Joyner * @buffer: contains the command to write and where the return status will 45808eb6488eSEric Joyner * be placed 45818eb6488eSEric Joyner * @length: length of buffer, must be multiple of 4 bytes 45828eb6488eSEric Joyner * @timeout: time in ms to wait for command completion 458379b36ec9SKevin Bowling * @return_data: read and return data from the buffer (true) or not (false) 45848eb6488eSEric Joyner * Needed because FW structures are big endian and decoding of 45858eb6488eSEric Joyner * these fields can be 8 bit or 16 bit based on command. Decoding 45868eb6488eSEric Joyner * is not easily understood without making a table of commands. 45878eb6488eSEric Joyner * So we will leave this up to the caller to read back the data 45888eb6488eSEric Joyner * in these cases. 45898eb6488eSEric Joyner * 45908eb6488eSEric Joyner * Communicates with the manageability block. On success return IXGBE_SUCCESS 45918eb6488eSEric Joyner * else returns semaphore error when encountering an error acquiring 45928eb6488eSEric Joyner * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 45938eb6488eSEric Joyner **/ 45948eb6488eSEric Joyner s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, 45958eb6488eSEric Joyner u32 length, u32 timeout, bool return_data) 45968eb6488eSEric Joyner { 45978eb6488eSEric Joyner u32 hdr_size = sizeof(struct ixgbe_hic_hdr); 45987d48aa4cSEric Joyner struct ixgbe_hic_hdr *resp = (struct ixgbe_hic_hdr *)buffer; 45998eb6488eSEric Joyner u16 buf_len; 46008eb6488eSEric Joyner s32 status; 46018eb6488eSEric Joyner u32 bi; 46027d48aa4cSEric Joyner u32 dword_len; 46038eb6488eSEric Joyner 46048eb6488eSEric Joyner DEBUGFUNC("ixgbe_host_interface_command"); 46058eb6488eSEric Joyner 46068eb6488eSEric Joyner if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { 46078eb6488eSEric Joyner DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); 46088eb6488eSEric Joyner return IXGBE_ERR_HOST_INTERFACE_COMMAND; 46098eb6488eSEric Joyner } 46108eb6488eSEric Joyner 46118eb6488eSEric Joyner /* Take management host interface semaphore */ 46128eb6488eSEric Joyner status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46138eb6488eSEric Joyner if (status) 46148eb6488eSEric Joyner return status; 46158eb6488eSEric Joyner 46168eb6488eSEric Joyner status = ixgbe_hic_unlocked(hw, buffer, length, timeout); 46178eb6488eSEric Joyner if (status) 46188eb6488eSEric Joyner goto rel_out; 46198eb6488eSEric Joyner 4620758cc3dcSJack F Vogel if (!return_data) 46218eb6488eSEric Joyner goto rel_out; 4622758cc3dcSJack F Vogel 462385d0a26eSJack F Vogel /* Calculate length in DWORDs */ 462485d0a26eSJack F Vogel dword_len = hdr_size >> 2; 462585d0a26eSJack F Vogel 462685d0a26eSJack F Vogel /* first pull in the header so we know the buffer length */ 462785d0a26eSJack F Vogel for (bi = 0; bi < dword_len; bi++) { 462885d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 46293f66b96dSKevin Bowling IXGBE_LE32_TO_CPUS((uintptr_t)&buffer[bi]); 463085d0a26eSJack F Vogel } 463185d0a26eSJack F Vogel 46327d48aa4cSEric Joyner /* 46337d48aa4cSEric Joyner * If there is any thing in data position pull it in 46347d48aa4cSEric Joyner * Read Flash command requires reading buffer length from 46357d48aa4cSEric Joyner * two byes instead of one byte 46367d48aa4cSEric Joyner */ 463731a23e3eSGuinan Sun if (resp->cmd == IXGBE_HOST_INTERFACE_FLASH_READ_CMD || 463831a23e3eSGuinan Sun resp->cmd == IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD) { 46397d48aa4cSEric Joyner for (; bi < dword_len + 2; bi++) { 46407d48aa4cSEric Joyner buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, 46417d48aa4cSEric Joyner bi); 46427d48aa4cSEric Joyner IXGBE_LE32_TO_CPUS(&buffer[bi]); 46437d48aa4cSEric Joyner } 46447d48aa4cSEric Joyner buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 46457d48aa4cSEric Joyner & 0xF00) | resp->buf_len; 46467d48aa4cSEric Joyner hdr_size += (2 << 2); 46477d48aa4cSEric Joyner } else { 46487d48aa4cSEric Joyner buf_len = resp->buf_len; 46497d48aa4cSEric Joyner } 46508eb6488eSEric Joyner if (!buf_len) 46518eb6488eSEric Joyner goto rel_out; 465285d0a26eSJack F Vogel 4653758cc3dcSJack F Vogel if (length < buf_len + hdr_size) { 465485d0a26eSJack F Vogel DEBUGOUT("Buffer not large enough for reply message.\n"); 46558eb6488eSEric Joyner status = IXGBE_ERR_HOST_INTERFACE_COMMAND; 46568eb6488eSEric Joyner goto rel_out; 465785d0a26eSJack F Vogel } 465885d0a26eSJack F Vogel 465985d0a26eSJack F Vogel /* Calculate length in DWORDs, add 3 for odd lengths */ 466085d0a26eSJack F Vogel dword_len = (buf_len + 3) >> 2; 466185d0a26eSJack F Vogel 466285d0a26eSJack F Vogel /* Pull in the rest of the buffer (bi is where we left off) */ 466385d0a26eSJack F Vogel for (; bi <= dword_len; bi++) { 466485d0a26eSJack F Vogel buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); 46653f66b96dSKevin Bowling IXGBE_LE32_TO_CPUS((uintptr_t)&buffer[bi]); 466685d0a26eSJack F Vogel } 466785d0a26eSJack F Vogel 46688eb6488eSEric Joyner rel_out: 46698eb6488eSEric Joyner hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); 46708eb6488eSEric Joyner 46718eb6488eSEric Joyner return status; 467285d0a26eSJack F Vogel } 467385d0a26eSJack F Vogel 467485d0a26eSJack F Vogel /** 467585d0a26eSJack F Vogel * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware 467685d0a26eSJack F Vogel * @hw: pointer to the HW structure 467785d0a26eSJack F Vogel * @maj: driver version major number 467885d0a26eSJack F Vogel * @min: driver version minor number 467985d0a26eSJack F Vogel * @build: driver version build number 468085d0a26eSJack F Vogel * @sub: driver version sub build number 46817d48aa4cSEric Joyner * @len: unused 46827d48aa4cSEric Joyner * @driver_ver: unused 468385d0a26eSJack F Vogel * 468485d0a26eSJack F Vogel * Sends driver version number to firmware through the manageability 468585d0a26eSJack F Vogel * block. On success return IXGBE_SUCCESS 468685d0a26eSJack F Vogel * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring 468785d0a26eSJack F Vogel * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 468885d0a26eSJack F Vogel **/ 468985d0a26eSJack F Vogel s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, 46908eb6488eSEric Joyner u8 build, u8 sub, u16 len, 46918eb6488eSEric Joyner const char *driver_ver) 469285d0a26eSJack F Vogel { 469385d0a26eSJack F Vogel struct ixgbe_hic_drv_info fw_cmd; 469485d0a26eSJack F Vogel int i; 469585d0a26eSJack F Vogel s32 ret_val = IXGBE_SUCCESS; 469685d0a26eSJack F Vogel 469785d0a26eSJack F Vogel DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); 46988eb6488eSEric Joyner UNREFERENCED_2PARAMETER(len, driver_ver); 469985d0a26eSJack F Vogel 470085d0a26eSJack F Vogel fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 470185d0a26eSJack F Vogel fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 470285d0a26eSJack F Vogel fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 470385d0a26eSJack F Vogel fw_cmd.port_num = (u8)hw->bus.func; 470485d0a26eSJack F Vogel fw_cmd.ver_maj = maj; 470585d0a26eSJack F Vogel fw_cmd.ver_min = min; 470685d0a26eSJack F Vogel fw_cmd.ver_build = build; 470785d0a26eSJack F Vogel fw_cmd.ver_sub = sub; 470885d0a26eSJack F Vogel fw_cmd.hdr.checksum = 0; 470985d0a26eSJack F Vogel fw_cmd.pad = 0; 471085d0a26eSJack F Vogel fw_cmd.pad2 = 0; 47117d48aa4cSEric Joyner fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, 47127d48aa4cSEric Joyner (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 471385d0a26eSJack F Vogel 471485d0a26eSJack F Vogel for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 471585d0a26eSJack F Vogel ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, 4716758cc3dcSJack F Vogel sizeof(fw_cmd), 4717758cc3dcSJack F Vogel IXGBE_HI_COMMAND_TIMEOUT, 471879b36ec9SKevin Bowling true); 471985d0a26eSJack F Vogel if (ret_val != IXGBE_SUCCESS) 472085d0a26eSJack F Vogel continue; 472185d0a26eSJack F Vogel 472285d0a26eSJack F Vogel if (fw_cmd.hdr.cmd_or_resp.ret_status == 472385d0a26eSJack F Vogel FW_CEM_RESP_STATUS_SUCCESS) 472485d0a26eSJack F Vogel ret_val = IXGBE_SUCCESS; 472585d0a26eSJack F Vogel else 472685d0a26eSJack F Vogel ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; 472785d0a26eSJack F Vogel 472885d0a26eSJack F Vogel break; 472985d0a26eSJack F Vogel } 473085d0a26eSJack F Vogel 473185d0a26eSJack F Vogel return ret_val; 473285d0a26eSJack F Vogel } 473385d0a26eSJack F Vogel 473485d0a26eSJack F Vogel /** 473585d0a26eSJack F Vogel * ixgbe_set_rxpba_generic - Initialize Rx packet buffer 473685d0a26eSJack F Vogel * @hw: pointer to hardware structure 473785d0a26eSJack F Vogel * @num_pb: number of packet buffers to allocate 473885d0a26eSJack F Vogel * @headroom: reserve n KB of headroom 473985d0a26eSJack F Vogel * @strategy: packet buffer allocation strategy 474085d0a26eSJack F Vogel **/ 474185d0a26eSJack F Vogel void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, 474285d0a26eSJack F Vogel int strategy) 474385d0a26eSJack F Vogel { 474485d0a26eSJack F Vogel u32 pbsize = hw->mac.rx_pb_size; 474585d0a26eSJack F Vogel int i = 0; 474685d0a26eSJack F Vogel u32 rxpktsize, txpktsize, txpbthresh; 474785d0a26eSJack F Vogel 474885d0a26eSJack F Vogel /* Reserve headroom */ 474985d0a26eSJack F Vogel pbsize -= headroom; 475085d0a26eSJack F Vogel 475185d0a26eSJack F Vogel if (!num_pb) 475285d0a26eSJack F Vogel num_pb = 1; 475385d0a26eSJack F Vogel 475485d0a26eSJack F Vogel /* Divide remaining packet buffer space amongst the number of packet 475585d0a26eSJack F Vogel * buffers requested using supplied strategy. 475685d0a26eSJack F Vogel */ 475785d0a26eSJack F Vogel switch (strategy) { 4758a621e3c8SJack F Vogel case PBA_STRATEGY_WEIGHTED: 475985d0a26eSJack F Vogel /* ixgbe_dcb_pba_80_48 strategy weight first half of packet 476085d0a26eSJack F Vogel * buffer with 5/8 of the packet buffer space. 476185d0a26eSJack F Vogel */ 4762a621e3c8SJack F Vogel rxpktsize = (pbsize * 5) / (num_pb * 4); 476385d0a26eSJack F Vogel pbsize -= rxpktsize * (num_pb / 2); 476485d0a26eSJack F Vogel rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; 476585d0a26eSJack F Vogel for (; i < (num_pb / 2); i++) 476685d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 4767be9f17dbSToomas Soome /* configure remaining packet buffers */ 4768be9f17dbSToomas Soome /* FALLTHROUGH */ 4769a621e3c8SJack F Vogel case PBA_STRATEGY_EQUAL: 477085d0a26eSJack F Vogel rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; 477185d0a26eSJack F Vogel for (; i < num_pb; i++) 477285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); 477385d0a26eSJack F Vogel break; 477485d0a26eSJack F Vogel default: 477585d0a26eSJack F Vogel break; 477685d0a26eSJack F Vogel } 477785d0a26eSJack F Vogel 477885d0a26eSJack F Vogel /* Only support an equally distributed Tx packet buffer strategy. */ 477985d0a26eSJack F Vogel txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; 478085d0a26eSJack F Vogel txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; 478185d0a26eSJack F Vogel for (i = 0; i < num_pb; i++) { 478285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); 478385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); 478485d0a26eSJack F Vogel } 478585d0a26eSJack F Vogel 478685d0a26eSJack F Vogel /* Clear unused TCs, if any, to zero buffer size*/ 478785d0a26eSJack F Vogel for (; i < IXGBE_MAX_PB; i++) { 478885d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 478985d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); 479085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); 479185d0a26eSJack F Vogel } 479285d0a26eSJack F Vogel } 479385d0a26eSJack F Vogel 479485d0a26eSJack F Vogel /** 479585d0a26eSJack F Vogel * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo 479685d0a26eSJack F Vogel * @hw: pointer to the hardware structure 479785d0a26eSJack F Vogel * 479885d0a26eSJack F Vogel * The 82599 and x540 MACs can experience issues if TX work is still pending 479985d0a26eSJack F Vogel * when a reset occurs. This function prevents this by flushing the PCIe 480085d0a26eSJack F Vogel * buffers on the system. 480185d0a26eSJack F Vogel **/ 480285d0a26eSJack F Vogel void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) 480385d0a26eSJack F Vogel { 4804758cc3dcSJack F Vogel u32 gcr_ext, hlreg0, i, poll; 4805758cc3dcSJack F Vogel u16 value; 480685d0a26eSJack F Vogel 480785d0a26eSJack F Vogel /* 480885d0a26eSJack F Vogel * If double reset is not requested then all transactions should 480985d0a26eSJack F Vogel * already be clear and as such there is no work to do 481085d0a26eSJack F Vogel */ 481185d0a26eSJack F Vogel if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) 481285d0a26eSJack F Vogel return; 481385d0a26eSJack F Vogel 481485d0a26eSJack F Vogel /* 481585d0a26eSJack F Vogel * Set loopback enable to prevent any transmits from being sent 481685d0a26eSJack F Vogel * should the link come up. This assumes that the RXCTRL.RXEN bit 481785d0a26eSJack F Vogel * has already been cleared. 481885d0a26eSJack F Vogel */ 481985d0a26eSJack F Vogel hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); 482085d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); 482185d0a26eSJack F Vogel 4822758cc3dcSJack F Vogel /* Wait for a last completion before clearing buffers */ 4823758cc3dcSJack F Vogel IXGBE_WRITE_FLUSH(hw); 4824758cc3dcSJack F Vogel msec_delay(3); 4825758cc3dcSJack F Vogel 4826758cc3dcSJack F Vogel /* 4827758cc3dcSJack F Vogel * Before proceeding, make sure that the PCIe block does not have 4828758cc3dcSJack F Vogel * transactions pending. 4829758cc3dcSJack F Vogel */ 4830758cc3dcSJack F Vogel poll = ixgbe_pcie_timeout_poll(hw); 4831758cc3dcSJack F Vogel for (i = 0; i < poll; i++) { 4832758cc3dcSJack F Vogel usec_delay(100); 4833758cc3dcSJack F Vogel value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); 4834758cc3dcSJack F Vogel if (IXGBE_REMOVED(hw->hw_addr)) 4835758cc3dcSJack F Vogel goto out; 4836758cc3dcSJack F Vogel if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) 4837758cc3dcSJack F Vogel goto out; 4838758cc3dcSJack F Vogel } 4839758cc3dcSJack F Vogel 4840758cc3dcSJack F Vogel out: 484185d0a26eSJack F Vogel /* initiate cleaning flow for buffers in the PCIe transaction layer */ 484285d0a26eSJack F Vogel gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); 484385d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, 484485d0a26eSJack F Vogel gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); 484585d0a26eSJack F Vogel 484685d0a26eSJack F Vogel /* Flush all writes and allow 20usec for all transactions to clear */ 484785d0a26eSJack F Vogel IXGBE_WRITE_FLUSH(hw); 484885d0a26eSJack F Vogel usec_delay(20); 484985d0a26eSJack F Vogel 485085d0a26eSJack F Vogel /* restore previous register values */ 485185d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); 485285d0a26eSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); 485385d0a26eSJack F Vogel } 485485d0a26eSJack F Vogel 48553f66b96dSKevin Bowling static const u8 ixgbe_emc_temp_data[4] = { 48563f66b96dSKevin Bowling IXGBE_EMC_INTERNAL_DATA, 48573f66b96dSKevin Bowling IXGBE_EMC_DIODE1_DATA, 48583f66b96dSKevin Bowling IXGBE_EMC_DIODE2_DATA, 48593f66b96dSKevin Bowling IXGBE_EMC_DIODE3_DATA 48603f66b96dSKevin Bowling }; 48613f66b96dSKevin Bowling static const u8 ixgbe_emc_therm_limit[4] = { 48623f66b96dSKevin Bowling IXGBE_EMC_INTERNAL_THERM_LIMIT, 48633f66b96dSKevin Bowling IXGBE_EMC_DIODE1_THERM_LIMIT, 48643f66b96dSKevin Bowling IXGBE_EMC_DIODE2_THERM_LIMIT, 48653f66b96dSKevin Bowling IXGBE_EMC_DIODE3_THERM_LIMIT 48663f66b96dSKevin Bowling }; 48673f66b96dSKevin Bowling 48683f66b96dSKevin Bowling /** 48693f66b96dSKevin Bowling * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data 48703f66b96dSKevin Bowling * @hw: pointer to hardware structure 48713f66b96dSKevin Bowling * 48723f66b96dSKevin Bowling * Returns the thermal sensor data structure 48733f66b96dSKevin Bowling **/ 48743f66b96dSKevin Bowling s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw) 48753f66b96dSKevin Bowling { 48763f66b96dSKevin Bowling s32 status = IXGBE_SUCCESS; 48773f66b96dSKevin Bowling u16 ets_offset; 48783f66b96dSKevin Bowling u16 ets_cfg; 48793f66b96dSKevin Bowling u16 ets_sensor; 48803f66b96dSKevin Bowling u8 num_sensors; 48813f66b96dSKevin Bowling u8 sensor_index; 48823f66b96dSKevin Bowling u8 sensor_location; 48833f66b96dSKevin Bowling u8 i; 48843f66b96dSKevin Bowling struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 48853f66b96dSKevin Bowling 48863f66b96dSKevin Bowling DEBUGFUNC("ixgbe_get_thermal_sensor_data_generic"); 48873f66b96dSKevin Bowling 48883f66b96dSKevin Bowling /* Only support thermal sensors attached to 82599 physical port 0 */ 48893f66b96dSKevin Bowling if ((hw->mac.type != ixgbe_mac_82599EB) || 48903f66b96dSKevin Bowling (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) { 48913f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 48923f66b96dSKevin Bowling goto out; 48933f66b96dSKevin Bowling } 48943f66b96dSKevin Bowling 48953f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset); 48963f66b96dSKevin Bowling if (status) 48973f66b96dSKevin Bowling goto out; 48983f66b96dSKevin Bowling 48993f66b96dSKevin Bowling if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) { 49003f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 49013f66b96dSKevin Bowling goto out; 49023f66b96dSKevin Bowling } 49033f66b96dSKevin Bowling 49043f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, ets_offset, &ets_cfg); 49053f66b96dSKevin Bowling if (status) 49063f66b96dSKevin Bowling goto out; 49073f66b96dSKevin Bowling 49083f66b96dSKevin Bowling if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) 49093f66b96dSKevin Bowling != IXGBE_ETS_TYPE_EMC) { 49103f66b96dSKevin Bowling status = IXGBE_NOT_IMPLEMENTED; 49113f66b96dSKevin Bowling goto out; 49123f66b96dSKevin Bowling } 49133f66b96dSKevin Bowling 49143f66b96dSKevin Bowling num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 49153f66b96dSKevin Bowling if (num_sensors > IXGBE_MAX_SENSORS) 49163f66b96dSKevin Bowling num_sensors = IXGBE_MAX_SENSORS; 49173f66b96dSKevin Bowling 49183f66b96dSKevin Bowling for (i = 0; i < num_sensors; i++) { 49193f66b96dSKevin Bowling status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i), 49203f66b96dSKevin Bowling &ets_sensor); 49213f66b96dSKevin Bowling if (status) 49223f66b96dSKevin Bowling goto out; 49233f66b96dSKevin Bowling 49243f66b96dSKevin Bowling sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 49253f66b96dSKevin Bowling IXGBE_ETS_DATA_INDEX_SHIFT); 49263f66b96dSKevin Bowling sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 49273f66b96dSKevin Bowling IXGBE_ETS_DATA_LOC_SHIFT); 49283f66b96dSKevin Bowling 49293f66b96dSKevin Bowling if (sensor_location != 0) { 49303f66b96dSKevin Bowling status = hw->phy.ops.read_i2c_byte(hw, 49313f66b96dSKevin Bowling ixgbe_emc_temp_data[sensor_index], 49323f66b96dSKevin Bowling IXGBE_I2C_THERMAL_SENSOR_ADDR, 49333f66b96dSKevin Bowling &data->sensor[i].temp); 49343f66b96dSKevin Bowling if (status) 49353f66b96dSKevin Bowling goto out; 49363f66b96dSKevin Bowling } 49373f66b96dSKevin Bowling } 49383f66b96dSKevin Bowling out: 49393f66b96dSKevin Bowling return status; 49403f66b96dSKevin Bowling } 49413f66b96dSKevin Bowling 49423f66b96dSKevin Bowling /** 49433f66b96dSKevin Bowling * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds 49443f66b96dSKevin Bowling * @hw: pointer to hardware structure 49453f66b96dSKevin Bowling * 49463f66b96dSKevin Bowling * Inits the thermal sensor thresholds according to the NVM map 49473f66b96dSKevin Bowling * and save off the threshold and location values into mac.thermal_sensor_data 49483f66b96dSKevin Bowling **/ 49493f66b96dSKevin Bowling s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw) 49503f66b96dSKevin Bowling { 49513f66b96dSKevin Bowling s32 status = IXGBE_SUCCESS; 49523f66b96dSKevin Bowling u16 offset; 49533f66b96dSKevin Bowling u16 ets_offset; 49543f66b96dSKevin Bowling u16 ets_cfg; 49553f66b96dSKevin Bowling u16 ets_sensor; 49563f66b96dSKevin Bowling u8 low_thresh_delta; 49573f66b96dSKevin Bowling u8 num_sensors; 49583f66b96dSKevin Bowling u8 sensor_index; 49593f66b96dSKevin Bowling u8 sensor_location; 49603f66b96dSKevin Bowling u8 therm_limit; 49613f66b96dSKevin Bowling u8 i; 49623f66b96dSKevin Bowling struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; 49633f66b96dSKevin Bowling 49643f66b96dSKevin Bowling DEBUGFUNC("ixgbe_init_thermal_sensor_thresh_generic"); 49653f66b96dSKevin Bowling 49663f66b96dSKevin Bowling memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data)); 49673f66b96dSKevin Bowling 49683f66b96dSKevin Bowling /* Only support thermal sensors attached to 82599 physical port 0 */ 49693f66b96dSKevin Bowling if ((hw->mac.type != ixgbe_mac_82599EB) || 49703f66b96dSKevin Bowling (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) 49713f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 49723f66b96dSKevin Bowling 49733f66b96dSKevin Bowling offset = IXGBE_ETS_CFG; 49743f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_offset)) 49753f66b96dSKevin Bowling goto eeprom_err; 49763f66b96dSKevin Bowling if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) 49773f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 49783f66b96dSKevin Bowling 49793f66b96dSKevin Bowling offset = ets_offset; 49803f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_cfg)) 49813f66b96dSKevin Bowling goto eeprom_err; 49823f66b96dSKevin Bowling if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) 49833f66b96dSKevin Bowling != IXGBE_ETS_TYPE_EMC) 49843f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 49853f66b96dSKevin Bowling 49863f66b96dSKevin Bowling low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >> 49873f66b96dSKevin Bowling IXGBE_ETS_LTHRES_DELTA_SHIFT); 49883f66b96dSKevin Bowling num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); 49893f66b96dSKevin Bowling 49903f66b96dSKevin Bowling for (i = 0; i < num_sensors; i++) { 49913f66b96dSKevin Bowling offset = ets_offset + 1 + i; 49923f66b96dSKevin Bowling if (hw->eeprom.ops.read(hw, offset, &ets_sensor)) { 49933f66b96dSKevin Bowling ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 49943f66b96dSKevin Bowling "eeprom read at offset %d failed", 49953f66b96dSKevin Bowling offset); 49963f66b96dSKevin Bowling continue; 49973f66b96dSKevin Bowling } 49983f66b96dSKevin Bowling sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> 49993f66b96dSKevin Bowling IXGBE_ETS_DATA_INDEX_SHIFT); 50003f66b96dSKevin Bowling sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> 50013f66b96dSKevin Bowling IXGBE_ETS_DATA_LOC_SHIFT); 50023f66b96dSKevin Bowling therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK; 50033f66b96dSKevin Bowling 50043f66b96dSKevin Bowling hw->phy.ops.write_i2c_byte(hw, 50053f66b96dSKevin Bowling ixgbe_emc_therm_limit[sensor_index], 50063f66b96dSKevin Bowling IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit); 50073f66b96dSKevin Bowling 50083f66b96dSKevin Bowling if ((i < IXGBE_MAX_SENSORS) && (sensor_location != 0)) { 50093f66b96dSKevin Bowling data->sensor[i].location = sensor_location; 50103f66b96dSKevin Bowling data->sensor[i].caution_thresh = therm_limit; 50113f66b96dSKevin Bowling data->sensor[i].max_op_thresh = therm_limit - 50123f66b96dSKevin Bowling low_thresh_delta; 50133f66b96dSKevin Bowling } 50143f66b96dSKevin Bowling } 50153f66b96dSKevin Bowling return status; 50163f66b96dSKevin Bowling 50173f66b96dSKevin Bowling eeprom_err: 50183f66b96dSKevin Bowling ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, 50193f66b96dSKevin Bowling "eeprom read at offset %d failed", offset); 50203f66b96dSKevin Bowling return IXGBE_NOT_IMPLEMENTED; 50213f66b96dSKevin Bowling } 50223f66b96dSKevin Bowling 50238eb6488eSEric Joyner /** 50248eb6488eSEric Joyner * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW 50258eb6488eSEric Joyner * 50268eb6488eSEric Joyner * @hw: pointer to hardware structure 50278eb6488eSEric Joyner * @cmd: Command we send to the FW 50288eb6488eSEric Joyner * @status: The reply from the FW 50298eb6488eSEric Joyner * 50308eb6488eSEric Joyner * Bit-bangs the cmd to the by_pass FW status points to what is returned. 50318eb6488eSEric Joyner **/ 50328eb6488eSEric Joyner #define IXGBE_BYPASS_BB_WAIT 1 50338eb6488eSEric Joyner s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) 50348eb6488eSEric Joyner { 50358eb6488eSEric Joyner int i; 50368eb6488eSEric Joyner u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; 50378eb6488eSEric Joyner u32 esdp; 50388eb6488eSEric Joyner 50398eb6488eSEric Joyner if (!status) 50408eb6488eSEric Joyner return IXGBE_ERR_PARAM; 50418eb6488eSEric Joyner 50428eb6488eSEric Joyner *status = 0; 50438eb6488eSEric Joyner 50448eb6488eSEric Joyner /* SDP vary by MAC type */ 50458eb6488eSEric Joyner switch (hw->mac.type) { 50468eb6488eSEric Joyner case ixgbe_mac_82599EB: 50478eb6488eSEric Joyner sck = IXGBE_ESDP_SDP7; 50488eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 50498eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP6; 50508eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP7_DIR; 50518eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 50528eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP6_DIR; 50538eb6488eSEric Joyner break; 50548eb6488eSEric Joyner case ixgbe_mac_X540: 50558eb6488eSEric Joyner sck = IXGBE_ESDP_SDP2; 50568eb6488eSEric Joyner sdi = IXGBE_ESDP_SDP0; 50578eb6488eSEric Joyner sdo = IXGBE_ESDP_SDP1; 50588eb6488eSEric Joyner dir_sck = IXGBE_ESDP_SDP2_DIR; 50598eb6488eSEric Joyner dir_sdi = IXGBE_ESDP_SDP0_DIR; 50608eb6488eSEric Joyner dir_sdo = IXGBE_ESDP_SDP1_DIR; 50618eb6488eSEric Joyner break; 50628eb6488eSEric Joyner default: 50638eb6488eSEric Joyner return IXGBE_ERR_DEVICE_NOT_SUPPORTED; 50648eb6488eSEric Joyner } 50658eb6488eSEric Joyner 50668eb6488eSEric Joyner /* Set SDP pins direction */ 50678eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 50688eb6488eSEric Joyner esdp |= dir_sck; /* SCK as output */ 50698eb6488eSEric Joyner esdp |= dir_sdi; /* SDI as output */ 50708eb6488eSEric Joyner esdp &= ~dir_sdo; /* SDO as input */ 50718eb6488eSEric Joyner esdp |= sck; 50728eb6488eSEric Joyner esdp |= sdi; 50738eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50748eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 50758eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 50768eb6488eSEric Joyner 50778eb6488eSEric Joyner /* Generate start condition */ 50788eb6488eSEric Joyner esdp &= ~sdi; 50798eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50808eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 50818eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 50828eb6488eSEric Joyner 50838eb6488eSEric Joyner esdp &= ~sck; 50848eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50858eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 50868eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 50878eb6488eSEric Joyner 50888eb6488eSEric Joyner /* Clock out the new control word and clock in the status */ 50898eb6488eSEric Joyner for (i = 0; i < 32; i++) { 50908eb6488eSEric Joyner if ((cmd >> (31 - i)) & 0x01) { 50918eb6488eSEric Joyner esdp |= sdi; 50928eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50938eb6488eSEric Joyner } else { 50948eb6488eSEric Joyner esdp &= ~sdi; 50958eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 50968eb6488eSEric Joyner } 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 esdp &= ~sck; 51068eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51078eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51088eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51098eb6488eSEric Joyner 51108eb6488eSEric Joyner esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); 51118eb6488eSEric Joyner if (esdp & sdo) 51128eb6488eSEric Joyner *status = (*status << 1) | 0x01; 51138eb6488eSEric Joyner else 51148eb6488eSEric Joyner *status = (*status << 1) | 0x00; 51158eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51168eb6488eSEric Joyner } 51178eb6488eSEric Joyner 51188eb6488eSEric Joyner /* stop condition */ 51198eb6488eSEric Joyner esdp |= sck; 51208eb6488eSEric Joyner esdp &= ~sdi; 51218eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51228eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51238eb6488eSEric Joyner msec_delay(IXGBE_BYPASS_BB_WAIT); 51248eb6488eSEric Joyner 51258eb6488eSEric Joyner esdp |= sdi; 51268eb6488eSEric Joyner IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); 51278eb6488eSEric Joyner IXGBE_WRITE_FLUSH(hw); 51288eb6488eSEric Joyner 51298eb6488eSEric Joyner /* set the page bits to match the cmd that the status it belongs to */ 51308eb6488eSEric Joyner *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); 51318eb6488eSEric Joyner 51328eb6488eSEric Joyner return IXGBE_SUCCESS; 51338eb6488eSEric Joyner } 51348eb6488eSEric Joyner 51358eb6488eSEric Joyner /** 51368eb6488eSEric Joyner * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. 51378eb6488eSEric Joyner * 51388eb6488eSEric Joyner * If we send a write we can't be sure it took until we can read back 51398eb6488eSEric Joyner * that same register. It can be a problem as some of the feilds may 51408eb6488eSEric Joyner * for valid reasons change inbetween the time wrote the register and 51418eb6488eSEric Joyner * we read it again to verify. So this function check everything we 51428eb6488eSEric Joyner * can check and then assumes it worked. 51438eb6488eSEric Joyner * 51448eb6488eSEric Joyner * @u32 in_reg - The register cmd for the bit-bang read. 51458eb6488eSEric Joyner * @u32 out_reg - The register returned from a bit-bang read. 51468eb6488eSEric Joyner **/ 51478eb6488eSEric Joyner bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) 51488eb6488eSEric Joyner { 51498eb6488eSEric Joyner u32 mask; 51508eb6488eSEric Joyner 51518eb6488eSEric Joyner /* Page must match for all control pages */ 51528eb6488eSEric Joyner if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) 515379b36ec9SKevin Bowling return false; 51548eb6488eSEric Joyner 51558eb6488eSEric Joyner switch (in_reg & BYPASS_PAGE_M) { 51568eb6488eSEric Joyner case BYPASS_PAGE_CTL0: 51578eb6488eSEric Joyner /* All the following can't change since the last write 51588eb6488eSEric Joyner * - All the event actions 51598eb6488eSEric Joyner * - The timeout value 51608eb6488eSEric Joyner */ 51618eb6488eSEric Joyner mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | 51628eb6488eSEric Joyner BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | 51638eb6488eSEric Joyner BYPASS_WDTIMEOUT_M | 51648eb6488eSEric Joyner BYPASS_WDT_VALUE_M; 51658eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 516679b36ec9SKevin Bowling return false; 51678eb6488eSEric Joyner 51688eb6488eSEric Joyner /* 0x0 is never a valid value for bypass status */ 51698eb6488eSEric Joyner if (!(out_reg & BYPASS_STATUS_OFF_M)) 517079b36ec9SKevin Bowling return false; 51718eb6488eSEric Joyner break; 51728eb6488eSEric Joyner case BYPASS_PAGE_CTL1: 51738eb6488eSEric Joyner /* All the following can't change since the last write 51748eb6488eSEric Joyner * - time valid bit 51758eb6488eSEric Joyner * - time we last sent 51768eb6488eSEric Joyner */ 51778eb6488eSEric Joyner mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; 51788eb6488eSEric Joyner if ((out_reg & mask) != (in_reg & mask)) 517979b36ec9SKevin Bowling return false; 51808eb6488eSEric Joyner break; 51818eb6488eSEric Joyner case BYPASS_PAGE_CTL2: 51828eb6488eSEric Joyner /* All we can check in this page is control number 51838eb6488eSEric Joyner * which is already done above. 51848eb6488eSEric Joyner */ 51858eb6488eSEric Joyner break; 51868eb6488eSEric Joyner } 51878eb6488eSEric Joyner 518879b36ec9SKevin Bowling /* We are as sure as we can be return true */ 518979b36ec9SKevin Bowling return true; 51908eb6488eSEric Joyner } 51918eb6488eSEric Joyner 51928eb6488eSEric Joyner /** 51938eb6488eSEric Joyner * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. 51948eb6488eSEric Joyner * 51958eb6488eSEric Joyner * @hw: pointer to hardware structure 51968eb6488eSEric Joyner * @cmd: The control word we are setting. 51978eb6488eSEric Joyner * @event: The event we are setting in the FW. This also happens to 51988eb6488eSEric Joyner * be the mask for the event we are setting (handy) 51998eb6488eSEric Joyner * @action: The action we set the event to in the FW. This is in a 52008eb6488eSEric Joyner * bit field that happens to be what we want to put in 52018eb6488eSEric Joyner * the event spot (also handy) 52028eb6488eSEric Joyner **/ 52038eb6488eSEric Joyner s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, 52048eb6488eSEric Joyner u32 action) 52058eb6488eSEric Joyner { 52068eb6488eSEric Joyner u32 by_ctl = 0; 52078eb6488eSEric Joyner u32 cmd, verify; 52088eb6488eSEric Joyner u32 count = 0; 52098eb6488eSEric Joyner 52108eb6488eSEric Joyner /* Get current values */ 52118eb6488eSEric Joyner cmd = ctrl; /* just reading only need control number */ 52128eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 52138eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52148eb6488eSEric Joyner 52158eb6488eSEric Joyner /* Set to new action */ 52168eb6488eSEric Joyner cmd = (by_ctl & ~event) | BYPASS_WE | action; 52178eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) 52188eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52198eb6488eSEric Joyner 52208eb6488eSEric Joyner /* Page 0 force a FW eeprom write which is slow so verify */ 52218eb6488eSEric Joyner if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { 52228eb6488eSEric Joyner verify = BYPASS_PAGE_CTL0; 52238eb6488eSEric Joyner do { 52248eb6488eSEric Joyner if (count++ > 5) 52258eb6488eSEric Joyner return IXGBE_BYPASS_FW_WRITE_FAILURE; 52268eb6488eSEric Joyner 52278eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) 52288eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52298eb6488eSEric Joyner } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); 52308eb6488eSEric Joyner } else { 52318eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 52328eb6488eSEric Joyner msec_delay(100); 52338eb6488eSEric Joyner } 52348eb6488eSEric Joyner 52358eb6488eSEric Joyner return IXGBE_SUCCESS; 52368eb6488eSEric Joyner } 52378eb6488eSEric Joyner 52388eb6488eSEric Joyner /** 52398eb6488eSEric Joyner * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom addres. 52408eb6488eSEric Joyner * 52418eb6488eSEric Joyner * @hw: pointer to hardware structure 52428eb6488eSEric Joyner * @addr: The bypass eeprom address to read. 52438eb6488eSEric Joyner * @value: The 8b of data at the address above. 52448eb6488eSEric Joyner **/ 52458eb6488eSEric Joyner s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) 52468eb6488eSEric Joyner { 52478eb6488eSEric Joyner u32 cmd; 52488eb6488eSEric Joyner u32 status; 52498eb6488eSEric Joyner 52508eb6488eSEric Joyner 52518eb6488eSEric Joyner /* send the request */ 52528eb6488eSEric Joyner cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; 52538eb6488eSEric Joyner cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; 52548eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 52558eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52568eb6488eSEric Joyner 52578eb6488eSEric Joyner /* We have give the FW time for the write to stick */ 52588eb6488eSEric Joyner msec_delay(100); 52598eb6488eSEric Joyner 52608eb6488eSEric Joyner /* now read the results */ 52618eb6488eSEric Joyner cmd &= ~BYPASS_WE; 52628eb6488eSEric Joyner if (ixgbe_bypass_rw_generic(hw, cmd, &status)) 52638eb6488eSEric Joyner return IXGBE_ERR_INVALID_ARGUMENT; 52648eb6488eSEric Joyner 52658eb6488eSEric Joyner *value = status & BYPASS_CTL2_DATA_M; 52668eb6488eSEric Joyner 52678eb6488eSEric Joyner return IXGBE_SUCCESS; 52688eb6488eSEric Joyner } 52698eb6488eSEric Joyner 52707d48aa4cSEric Joyner /** 52717d48aa4cSEric Joyner * ixgbe_get_orom_version - Return option ROM from EEPROM 52727d48aa4cSEric Joyner * 52737d48aa4cSEric Joyner * @hw: pointer to hardware structure 52747d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 52757d48aa4cSEric Joyner * 527679b36ec9SKevin Bowling * if valid option ROM version, nvm_ver->or_valid set to true 527779b36ec9SKevin Bowling * else nvm_ver->or_valid is false. 52787d48aa4cSEric Joyner **/ 52797d48aa4cSEric Joyner void ixgbe_get_orom_version(struct ixgbe_hw *hw, 52807d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 52817d48aa4cSEric Joyner { 52827d48aa4cSEric Joyner u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl; 52837d48aa4cSEric Joyner 528479b36ec9SKevin Bowling nvm_ver->or_valid = false; 52857d48aa4cSEric Joyner /* Option Rom may or may not be present. Start with pointer */ 52867d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset); 52877d48aa4cSEric Joyner 52887d48aa4cSEric Joyner /* make sure offset is valid */ 52897d48aa4cSEric Joyner if ((offset == 0x0) || (offset == NVM_INVALID_PTR)) 52907d48aa4cSEric Joyner return; 52917d48aa4cSEric Joyner 52927d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh); 52937d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl); 52947d48aa4cSEric Joyner 52957d48aa4cSEric Joyner /* option rom exists and is valid */ 52967d48aa4cSEric Joyner if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 || 52977d48aa4cSEric Joyner eeprom_cfg_blkl == NVM_VER_INVALID || 52987d48aa4cSEric Joyner eeprom_cfg_blkh == NVM_VER_INVALID) 52997d48aa4cSEric Joyner return; 53007d48aa4cSEric Joyner 530179b36ec9SKevin Bowling nvm_ver->or_valid = true; 53027d48aa4cSEric Joyner nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT; 53037d48aa4cSEric Joyner nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) | 53047d48aa4cSEric Joyner (eeprom_cfg_blkh >> NVM_OROM_SHIFT); 53057d48aa4cSEric Joyner nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK; 53067d48aa4cSEric Joyner } 53077d48aa4cSEric Joyner 53087d48aa4cSEric Joyner /** 53097d48aa4cSEric Joyner * ixgbe_get_oem_prod_version - Return OEM Product version 53107d48aa4cSEric Joyner * 53117d48aa4cSEric Joyner * @hw: pointer to hardware structure 53127d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 53137d48aa4cSEric Joyner * 531479b36ec9SKevin Bowling * if valid OEM product version, nvm_ver->oem_valid set to true 531579b36ec9SKevin Bowling * else nvm_ver->oem_valid is false. 53167d48aa4cSEric Joyner **/ 53177d48aa4cSEric Joyner void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw, 53187d48aa4cSEric Joyner struct ixgbe_nvm_version *nvm_ver) 53197d48aa4cSEric Joyner { 53207d48aa4cSEric Joyner u16 rel_num, prod_ver, mod_len, cap, offset; 53217d48aa4cSEric Joyner 532279b36ec9SKevin Bowling nvm_ver->oem_valid = false; 53237d48aa4cSEric Joyner hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset); 53247d48aa4cSEric Joyner 5325ab1c54feSEric van Gyzen /* Return if offset to OEM Product Version block is invalid */ 5326ab1c54feSEric van Gyzen if (offset == 0x0 || offset == NVM_INVALID_PTR) 53277d48aa4cSEric Joyner return; 53287d48aa4cSEric Joyner 53297d48aa4cSEric Joyner /* Read product version block */ 53307d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset, &mod_len); 53317d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap); 53327d48aa4cSEric Joyner 53337d48aa4cSEric Joyner /* Return if OEM product version block is invalid */ 53347d48aa4cSEric Joyner if (mod_len != NVM_OEM_PROD_VER_MOD_LEN || 53357d48aa4cSEric Joyner (cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0) 53367d48aa4cSEric Joyner return; 53377d48aa4cSEric Joyner 53387d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver); 53397d48aa4cSEric Joyner hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num); 53407d48aa4cSEric Joyner 53417d48aa4cSEric Joyner /* Return if version is invalid */ 53427d48aa4cSEric Joyner if ((rel_num | prod_ver) == 0x0 || 53437d48aa4cSEric Joyner rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID) 53447d48aa4cSEric Joyner return; 53457d48aa4cSEric Joyner 53467d48aa4cSEric Joyner nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT; 53477d48aa4cSEric Joyner nvm_ver->oem_minor = prod_ver & NVM_VER_MASK; 53487d48aa4cSEric Joyner nvm_ver->oem_release = rel_num; 534979b36ec9SKevin Bowling nvm_ver->oem_valid = true; 53507d48aa4cSEric Joyner } 53517d48aa4cSEric Joyner 53527d48aa4cSEric Joyner /** 53537d48aa4cSEric Joyner * ixgbe_get_etk_id - Return Etrack ID from EEPROM 53547d48aa4cSEric Joyner * 53557d48aa4cSEric Joyner * @hw: pointer to hardware structure 53567d48aa4cSEric Joyner * @nvm_ver: pointer to output structure 53577d48aa4cSEric Joyner * 53587d48aa4cSEric Joyner * word read errors will return 0xFFFF 53597d48aa4cSEric Joyner **/ 53607d48aa4cSEric Joyner void ixgbe_get_etk_id(struct ixgbe_hw *hw, struct ixgbe_nvm_version *nvm_ver) 53617d48aa4cSEric Joyner { 53627d48aa4cSEric Joyner u16 etk_id_l, etk_id_h; 53637d48aa4cSEric Joyner 53647d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l)) 53657d48aa4cSEric Joyner etk_id_l = NVM_VER_INVALID; 53667d48aa4cSEric Joyner if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h)) 53677d48aa4cSEric Joyner etk_id_h = NVM_VER_INVALID; 53687d48aa4cSEric Joyner 53697d48aa4cSEric Joyner /* The word order for the version format is determined by high order 53707d48aa4cSEric Joyner * word bit 15. 53717d48aa4cSEric Joyner */ 53727d48aa4cSEric Joyner if ((etk_id_h & NVM_ETK_VALID) == 0) { 53737d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_h; 53747d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT); 53757d48aa4cSEric Joyner } else { 53767d48aa4cSEric Joyner nvm_ver->etk_id = etk_id_l; 53777d48aa4cSEric Joyner nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT); 53787d48aa4cSEric Joyner } 53797d48aa4cSEric Joyner } 53807d48aa4cSEric Joyner 5381fd75b91dSJack F Vogel 5382fd75b91dSJack F Vogel /** 5383fd75b91dSJack F Vogel * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg 5384fd75b91dSJack F Vogel * @hw: pointer to hardware structure 5385fd75b91dSJack F Vogel * @map: pointer to u8 arr for returning map 5386fd75b91dSJack F Vogel * 5387fd75b91dSJack F Vogel * Read the rtrup2tc HW register and resolve its content into map 5388fd75b91dSJack F Vogel **/ 5389fd75b91dSJack F Vogel void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) 5390fd75b91dSJack F Vogel { 5391fd75b91dSJack F Vogel u32 reg, i; 5392fd75b91dSJack F Vogel 5393fd75b91dSJack F Vogel reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); 5394fd75b91dSJack F Vogel for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) 5395fd75b91dSJack F Vogel map[i] = IXGBE_RTRUP2TC_UP_MASK & 5396fd75b91dSJack F Vogel (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); 5397fd75b91dSJack F Vogel return; 5398fd75b91dSJack F Vogel } 5399758cc3dcSJack F Vogel 5400758cc3dcSJack F Vogel void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) 5401758cc3dcSJack F Vogel { 5402758cc3dcSJack F Vogel u32 pfdtxgswc; 5403758cc3dcSJack F Vogel u32 rxctrl; 5404758cc3dcSJack F Vogel 5405758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5406758cc3dcSJack F Vogel if (rxctrl & IXGBE_RXCTRL_RXEN) { 5407758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5408758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5409758cc3dcSJack F Vogel if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { 5410758cc3dcSJack F Vogel pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; 5411758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 541279b36ec9SKevin Bowling hw->mac.set_lben = true; 5413758cc3dcSJack F Vogel } else { 541479b36ec9SKevin Bowling hw->mac.set_lben = false; 5415758cc3dcSJack F Vogel } 5416758cc3dcSJack F Vogel } 5417758cc3dcSJack F Vogel rxctrl &= ~IXGBE_RXCTRL_RXEN; 5418758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); 5419758cc3dcSJack F Vogel } 5420758cc3dcSJack F Vogel } 5421758cc3dcSJack F Vogel 5422758cc3dcSJack F Vogel void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) 5423758cc3dcSJack F Vogel { 5424758cc3dcSJack F Vogel u32 pfdtxgswc; 5425758cc3dcSJack F Vogel u32 rxctrl; 5426758cc3dcSJack F Vogel 5427758cc3dcSJack F Vogel rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 5428758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); 5429758cc3dcSJack F Vogel 5430758cc3dcSJack F Vogel if (hw->mac.type != ixgbe_mac_82598EB) { 5431758cc3dcSJack F Vogel if (hw->mac.set_lben) { 5432758cc3dcSJack F Vogel pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); 5433758cc3dcSJack F Vogel pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; 5434758cc3dcSJack F Vogel IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); 543579b36ec9SKevin Bowling hw->mac.set_lben = false; 5436758cc3dcSJack F Vogel } 5437758cc3dcSJack F Vogel } 5438758cc3dcSJack F Vogel } 5439758cc3dcSJack F Vogel 5440758cc3dcSJack F Vogel /** 544179b36ec9SKevin Bowling * ixgbe_mng_present - returns true when management capability is present 5442758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5443758cc3dcSJack F Vogel */ 5444758cc3dcSJack F Vogel bool ixgbe_mng_present(struct ixgbe_hw *hw) 5445758cc3dcSJack F Vogel { 5446758cc3dcSJack F Vogel u32 fwsm; 5447758cc3dcSJack F Vogel 5448758cc3dcSJack F Vogel if (hw->mac.type < ixgbe_mac_82599EB) 544979b36ec9SKevin Bowling return false; 5450758cc3dcSJack F Vogel 5451a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 54527d48aa4cSEric Joyner 54537d48aa4cSEric Joyner return !!(fwsm & IXGBE_FWSM_FW_MODE_PT); 5454758cc3dcSJack F Vogel } 5455758cc3dcSJack F Vogel 5456758cc3dcSJack F Vogel /** 5457758cc3dcSJack F Vogel * ixgbe_mng_enabled - Is the manageability engine enabled? 5458758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5459758cc3dcSJack F Vogel * 546079b36ec9SKevin Bowling * Returns true if the manageability engine is enabled. 5461758cc3dcSJack F Vogel **/ 5462758cc3dcSJack F Vogel bool ixgbe_mng_enabled(struct ixgbe_hw *hw) 5463758cc3dcSJack F Vogel { 5464758cc3dcSJack F Vogel u32 fwsm, manc, factps; 5465758cc3dcSJack F Vogel 5466a9ca1c79SSean Bruno fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); 5467758cc3dcSJack F Vogel if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) 546879b36ec9SKevin Bowling return false; 5469758cc3dcSJack F Vogel 5470758cc3dcSJack F Vogel manc = IXGBE_READ_REG(hw, IXGBE_MANC); 5471758cc3dcSJack F Vogel if (!(manc & IXGBE_MANC_RCV_TCO_EN)) 547279b36ec9SKevin Bowling return false; 5473758cc3dcSJack F Vogel 5474758cc3dcSJack F Vogel if (hw->mac.type <= ixgbe_mac_X540) { 5475a9ca1c79SSean Bruno factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw)); 5476758cc3dcSJack F Vogel if (factps & IXGBE_FACTPS_MNGCG) 547779b36ec9SKevin Bowling return false; 5478758cc3dcSJack F Vogel } 5479758cc3dcSJack F Vogel 548079b36ec9SKevin Bowling return true; 5481758cc3dcSJack F Vogel } 5482758cc3dcSJack F Vogel 5483758cc3dcSJack F Vogel /** 5484758cc3dcSJack F Vogel * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed 5485758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5486758cc3dcSJack F Vogel * @speed: new link speed 548779b36ec9SKevin Bowling * @autoneg_wait_to_complete: true when waiting for completion is needed 5488758cc3dcSJack F Vogel * 5489758cc3dcSJack F Vogel * Set the link speed in the MAC and/or PHY register and restarts link. 5490758cc3dcSJack F Vogel **/ 5491758cc3dcSJack F Vogel s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, 5492758cc3dcSJack F Vogel ixgbe_link_speed speed, 5493758cc3dcSJack F Vogel bool autoneg_wait_to_complete) 5494758cc3dcSJack F Vogel { 5495758cc3dcSJack F Vogel ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5496758cc3dcSJack F Vogel ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; 5497758cc3dcSJack F Vogel s32 status = IXGBE_SUCCESS; 5498758cc3dcSJack F Vogel u32 speedcnt = 0; 5499758cc3dcSJack F Vogel u32 i = 0; 550079b36ec9SKevin Bowling bool autoneg, link_up = false; 5501758cc3dcSJack F Vogel 5502758cc3dcSJack F Vogel DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); 5503758cc3dcSJack F Vogel 5504758cc3dcSJack F Vogel /* Mask off requested but non-supported speeds */ 5505758cc3dcSJack F Vogel status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); 5506758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5507758cc3dcSJack F Vogel return status; 5508758cc3dcSJack F Vogel 5509758cc3dcSJack F Vogel speed &= link_speed; 5510758cc3dcSJack F Vogel 5511758cc3dcSJack F Vogel /* Try each speed one by one, highest priority first. We do this in 5512758cc3dcSJack F Vogel * software because 10Gb fiber doesn't support speed autonegotiation. 5513758cc3dcSJack F Vogel */ 5514758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) { 5515758cc3dcSJack F Vogel speedcnt++; 5516758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; 5517758cc3dcSJack F Vogel 5518758cc3dcSJack F Vogel /* Set the module link speed */ 5519758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5520758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5521758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5522758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5523758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL); 5524758cc3dcSJack F Vogel break; 5525758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5526758cc3dcSJack F Vogel /* QSFP module automatically detects MAC link speed */ 5527758cc3dcSJack F Vogel break; 5528758cc3dcSJack F Vogel default: 5529758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5530758cc3dcSJack F Vogel break; 5531758cc3dcSJack F Vogel } 5532758cc3dcSJack F Vogel 5533758cc3dcSJack F Vogel /* Allow module to change analog characteristics (1G->10G) */ 5534758cc3dcSJack F Vogel msec_delay(40); 5535758cc3dcSJack F Vogel 5536758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5537758cc3dcSJack F Vogel IXGBE_LINK_SPEED_10GB_FULL, 5538758cc3dcSJack F Vogel autoneg_wait_to_complete); 5539758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5540758cc3dcSJack F Vogel return status; 5541758cc3dcSJack F Vogel 5542758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5543758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5544758cc3dcSJack F Vogel 5545758cc3dcSJack F Vogel /* Wait for the controller to acquire link. Per IEEE 802.3ap, 554696ef6eb3SXiaolong Ye * Section 73.10.2, we may have to wait up to 1000ms if KR is 5547758cc3dcSJack F Vogel * attempted. 82599 uses the same timing for 10g SFI. 5548758cc3dcSJack F Vogel */ 5549aaa3af80SMatthew Smith for (i = 0; i < 10; i++) { 5550758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5551758cc3dcSJack F Vogel msec_delay(100); 5552758cc3dcSJack F Vogel 5553758cc3dcSJack F Vogel /* If we have link, just jump out */ 5554758cc3dcSJack F Vogel status = ixgbe_check_link(hw, &link_speed, 555579b36ec9SKevin Bowling &link_up, false); 5556758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5557758cc3dcSJack F Vogel return status; 5558758cc3dcSJack F Vogel 5559758cc3dcSJack F Vogel if (link_up) 5560758cc3dcSJack F Vogel goto out; 5561758cc3dcSJack F Vogel } 5562758cc3dcSJack F Vogel } 5563758cc3dcSJack F Vogel 5564758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) { 5565758cc3dcSJack F Vogel speedcnt++; 5566758cc3dcSJack F Vogel if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) 5567758cc3dcSJack F Vogel highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; 5568758cc3dcSJack F Vogel 5569758cc3dcSJack F Vogel /* Set the module link speed */ 5570758cc3dcSJack F Vogel switch (hw->phy.media_type) { 5571758cc3dcSJack F Vogel case ixgbe_media_type_fiber_fixed: 5572758cc3dcSJack F Vogel case ixgbe_media_type_fiber: 5573758cc3dcSJack F Vogel ixgbe_set_rate_select_speed(hw, 5574758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL); 5575758cc3dcSJack F Vogel break; 5576758cc3dcSJack F Vogel case ixgbe_media_type_fiber_qsfp: 5577758cc3dcSJack F Vogel /* QSFP module automatically detects link speed */ 5578758cc3dcSJack F Vogel break; 5579758cc3dcSJack F Vogel default: 5580758cc3dcSJack F Vogel DEBUGOUT("Unexpected media type.\n"); 5581758cc3dcSJack F Vogel break; 5582758cc3dcSJack F Vogel } 5583758cc3dcSJack F Vogel 5584758cc3dcSJack F Vogel /* Allow module to change analog characteristics (10G->1G) */ 5585758cc3dcSJack F Vogel msec_delay(40); 5586758cc3dcSJack F Vogel 5587758cc3dcSJack F Vogel status = ixgbe_setup_mac_link(hw, 5588758cc3dcSJack F Vogel IXGBE_LINK_SPEED_1GB_FULL, 5589758cc3dcSJack F Vogel autoneg_wait_to_complete); 5590758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5591758cc3dcSJack F Vogel return status; 5592758cc3dcSJack F Vogel 5593758cc3dcSJack F Vogel /* Flap the Tx laser if it has not already been done */ 5594758cc3dcSJack F Vogel ixgbe_flap_tx_laser(hw); 5595758cc3dcSJack F Vogel 5596758cc3dcSJack F Vogel /* Wait for the link partner to also set speed */ 5597758cc3dcSJack F Vogel msec_delay(100); 5598758cc3dcSJack F Vogel 5599758cc3dcSJack F Vogel /* If we have link, just jump out */ 560079b36ec9SKevin Bowling status = ixgbe_check_link(hw, &link_speed, &link_up, false); 5601758cc3dcSJack F Vogel if (status != IXGBE_SUCCESS) 5602758cc3dcSJack F Vogel return status; 5603758cc3dcSJack F Vogel 5604758cc3dcSJack F Vogel if (link_up) 5605758cc3dcSJack F Vogel goto out; 5606758cc3dcSJack F Vogel } 5607758cc3dcSJack F Vogel 5608758cc3dcSJack F Vogel /* We didn't get link. Configure back to the highest speed we tried, 5609758cc3dcSJack F Vogel * (if there was more than one). We call ourselves back with just the 5610758cc3dcSJack F Vogel * single highest speed that the user requested. 5611758cc3dcSJack F Vogel */ 5612758cc3dcSJack F Vogel if (speedcnt > 1) 5613758cc3dcSJack F Vogel status = ixgbe_setup_mac_link_multispeed_fiber(hw, 5614758cc3dcSJack F Vogel highest_link_speed, 5615758cc3dcSJack F Vogel autoneg_wait_to_complete); 5616758cc3dcSJack F Vogel 5617758cc3dcSJack F Vogel out: 5618758cc3dcSJack F Vogel /* Set autoneg_advertised value based on input link speed */ 5619758cc3dcSJack F Vogel hw->phy.autoneg_advertised = 0; 5620758cc3dcSJack F Vogel 5621758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_10GB_FULL) 5622758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; 5623758cc3dcSJack F Vogel 5624758cc3dcSJack F Vogel if (speed & IXGBE_LINK_SPEED_1GB_FULL) 5625758cc3dcSJack F Vogel hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; 5626758cc3dcSJack F Vogel 5627758cc3dcSJack F Vogel return status; 5628758cc3dcSJack F Vogel } 5629758cc3dcSJack F Vogel 5630758cc3dcSJack F Vogel /** 5631758cc3dcSJack F Vogel * ixgbe_set_soft_rate_select_speed - Set module link speed 5632758cc3dcSJack F Vogel * @hw: pointer to hardware structure 5633758cc3dcSJack F Vogel * @speed: link speed to set 5634758cc3dcSJack F Vogel * 5635758cc3dcSJack F Vogel * Set module link speed via the soft rate select. 5636758cc3dcSJack F Vogel */ 5637758cc3dcSJack F Vogel void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, 5638758cc3dcSJack F Vogel ixgbe_link_speed speed) 5639758cc3dcSJack F Vogel { 5640758cc3dcSJack F Vogel s32 status; 5641758cc3dcSJack F Vogel u8 rs, eeprom_data; 5642758cc3dcSJack F Vogel 5643758cc3dcSJack F Vogel switch (speed) { 5644758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_10GB_FULL: 5645758cc3dcSJack F Vogel /* one bit mask same as setting on */ 5646758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_10G; 5647758cc3dcSJack F Vogel break; 5648758cc3dcSJack F Vogel case IXGBE_LINK_SPEED_1GB_FULL: 5649758cc3dcSJack F Vogel rs = IXGBE_SFF_SOFT_RS_SELECT_1G; 5650758cc3dcSJack F Vogel break; 5651758cc3dcSJack F Vogel default: 5652758cc3dcSJack F Vogel DEBUGOUT("Invalid fixed module speed\n"); 5653758cc3dcSJack F Vogel return; 5654758cc3dcSJack F Vogel } 5655758cc3dcSJack F Vogel 5656758cc3dcSJack F Vogel /* Set RS0 */ 5657758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5658758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5659758cc3dcSJack F Vogel &eeprom_data); 5660758cc3dcSJack F Vogel if (status) { 5661758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS0\n"); 5662758cc3dcSJack F Vogel goto out; 5663758cc3dcSJack F Vogel } 5664758cc3dcSJack F Vogel 5665758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5666758cc3dcSJack F Vogel 5667758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, 5668758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5669758cc3dcSJack F Vogel eeprom_data); 5670758cc3dcSJack F Vogel if (status) { 5671758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS0\n"); 5672758cc3dcSJack F Vogel goto out; 5673758cc3dcSJack F Vogel } 5674758cc3dcSJack F Vogel 5675758cc3dcSJack F Vogel /* Set RS1 */ 5676758cc3dcSJack F Vogel status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5677758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5678758cc3dcSJack F Vogel &eeprom_data); 5679758cc3dcSJack F Vogel if (status) { 5680758cc3dcSJack F Vogel DEBUGOUT("Failed to read Rx Rate Select RS1\n"); 5681758cc3dcSJack F Vogel goto out; 5682758cc3dcSJack F Vogel } 5683758cc3dcSJack F Vogel 5684758cc3dcSJack F Vogel eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; 5685758cc3dcSJack F Vogel 5686758cc3dcSJack F Vogel status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, 5687758cc3dcSJack F Vogel IXGBE_I2C_EEPROM_DEV_ADDR2, 5688758cc3dcSJack F Vogel eeprom_data); 5689758cc3dcSJack F Vogel if (status) { 5690758cc3dcSJack F Vogel DEBUGOUT("Failed to write Rx Rate Select RS1\n"); 5691758cc3dcSJack F Vogel goto out; 5692758cc3dcSJack F Vogel } 5693758cc3dcSJack F Vogel out: 5694758cc3dcSJack F Vogel return; 5695758cc3dcSJack F Vogel } 5696