16621Sbt150084 /* 26621Sbt150084 * CDDL HEADER START 36621Sbt150084 * 49353SSamuel.Tu@Sun.COM * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 56621Sbt150084 * The contents of this file are subject to the terms of the 66621Sbt150084 * Common Development and Distribution License (the "License"). 76621Sbt150084 * You may not use this file except in compliance with the License. 86621Sbt150084 * 98275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 108275SEric Cheng * or http://www.opensolaris.org/os/licensing. 116621Sbt150084 * See the License for the specific language governing permissions 126621Sbt150084 * and limitations under the License. 136621Sbt150084 * 148275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 158275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 166621Sbt150084 * If applicable, add the following below this CDDL HEADER, with the 176621Sbt150084 * fields enclosed by brackets "[]" replaced with your own identifying 186621Sbt150084 * information: Portions Copyright [yyyy] [name of copyright owner] 196621Sbt150084 * 206621Sbt150084 * CDDL HEADER END 216621Sbt150084 */ 226621Sbt150084 236621Sbt150084 /* 248490SPaul.Guo@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 258275SEric Cheng * Use is subject to license terms. 266621Sbt150084 */ 276621Sbt150084 28*10998SChenlu.Chen@Sun.COM /* IntelVersion: 1.218 scm_100309_002210 */ 296621Sbt150084 306621Sbt150084 #include "ixgbe_common.h" 316621Sbt150084 #include "ixgbe_api.h" 326621Sbt150084 336621Sbt150084 static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); 346621Sbt150084 static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); 356621Sbt150084 static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); 366621Sbt150084 static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); 376621Sbt150084 static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); 386621Sbt150084 static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 396621Sbt150084 u16 count); 406621Sbt150084 static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); 416621Sbt150084 static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 426621Sbt150084 static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); 436621Sbt150084 static void ixgbe_release_eeprom(struct ixgbe_hw *hw); 446621Sbt150084 static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); 456621Sbt150084 466621Sbt150084 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); 47*10998SChenlu.Chen@Sun.COM static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, 48*10998SChenlu.Chen@Sun.COM u16 *san_mac_offset); 49*10998SChenlu.Chen@Sun.COM s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan); 506621Sbt150084 516621Sbt150084 /* 526621Sbt150084 * ixgbe_init_ops_generic - Inits function ptrs 536621Sbt150084 * @hw: pointer to the hardware structure 546621Sbt150084 * 556621Sbt150084 * Initialize the function pointers. 566621Sbt150084 */ 576621Sbt150084 s32 586621Sbt150084 ixgbe_init_ops_generic(struct ixgbe_hw *hw) 596621Sbt150084 { 606621Sbt150084 struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 616621Sbt150084 struct ixgbe_mac_info *mac = &hw->mac; 628490SPaul.Guo@Sun.COM u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 636621Sbt150084 64*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_init_ops_generic"); 65*10998SChenlu.Chen@Sun.COM 666621Sbt150084 /* EEPROM */ 676621Sbt150084 eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; 688490SPaul.Guo@Sun.COM /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ 698490SPaul.Guo@Sun.COM if (eec & (1 << 8)) 70*10998SChenlu.Chen@Sun.COM eeprom->ops.read = &ixgbe_read_eerd_generic; 718490SPaul.Guo@Sun.COM else 728490SPaul.Guo@Sun.COM eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; 736621Sbt150084 eeprom->ops.write = &ixgbe_write_eeprom_generic; 746621Sbt150084 eeprom->ops.validate_checksum = 756621Sbt150084 &ixgbe_validate_eeprom_checksum_generic; 766621Sbt150084 eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; 776621Sbt150084 786621Sbt150084 /* MAC */ 796621Sbt150084 mac->ops.init_hw = &ixgbe_init_hw_generic; 806621Sbt150084 mac->ops.reset_hw = NULL; 816621Sbt150084 mac->ops.start_hw = &ixgbe_start_hw_generic; 826621Sbt150084 mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; 836621Sbt150084 mac->ops.get_media_type = NULL; 848490SPaul.Guo@Sun.COM mac->ops.get_supported_physical_layer = NULL; 859353SSamuel.Tu@Sun.COM mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic; 866621Sbt150084 mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; 876621Sbt150084 mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; 886621Sbt150084 mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; 899353SSamuel.Tu@Sun.COM mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie; 9010305SPaul.Guo@Sun.COM mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync; 9110305SPaul.Guo@Sun.COM mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync; 926621Sbt150084 936621Sbt150084 /* LEDs */ 946621Sbt150084 mac->ops.led_on = &ixgbe_led_on_generic; 956621Sbt150084 mac->ops.led_off = &ixgbe_led_off_generic; 969353SSamuel.Tu@Sun.COM mac->ops.blink_led_start = &ixgbe_blink_led_start_generic; 979353SSamuel.Tu@Sun.COM mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic; 986621Sbt150084 996621Sbt150084 /* RAR, Multicast, VLAN */ 1006621Sbt150084 mac->ops.set_rar = &ixgbe_set_rar_generic; 1018490SPaul.Guo@Sun.COM mac->ops.clear_rar = &ixgbe_clear_rar_generic; 1029353SSamuel.Tu@Sun.COM mac->ops.insert_mac_addr = NULL; 1036621Sbt150084 mac->ops.set_vmdq = NULL; 1048490SPaul.Guo@Sun.COM mac->ops.clear_vmdq = NULL; 1056621Sbt150084 mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic; 1066621Sbt150084 mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic; 1076621Sbt150084 mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; 1086621Sbt150084 mac->ops.enable_mc = &ixgbe_enable_mc_generic; 1096621Sbt150084 mac->ops.disable_mc = &ixgbe_disable_mc_generic; 1108490SPaul.Guo@Sun.COM mac->ops.clear_vfta = NULL; 1118490SPaul.Guo@Sun.COM mac->ops.set_vfta = NULL; 1128490SPaul.Guo@Sun.COM mac->ops.init_uta_tables = NULL; 1136621Sbt150084 1146621Sbt150084 /* Flow Control */ 1159353SSamuel.Tu@Sun.COM mac->ops.fc_enable = &ixgbe_fc_enable_generic; 1166621Sbt150084 1176621Sbt150084 /* Link */ 1186621Sbt150084 mac->ops.get_link_capabilities = NULL; 1196621Sbt150084 mac->ops.setup_link = NULL; 1206621Sbt150084 mac->ops.check_link = NULL; 1216621Sbt150084 1226621Sbt150084 return (IXGBE_SUCCESS); 1236621Sbt150084 } 1246621Sbt150084 1256621Sbt150084 /* 1266621Sbt150084 * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx 1276621Sbt150084 * @hw: pointer to hardware structure 1286621Sbt150084 * 1296621Sbt150084 * Starts the hardware by filling the bus info structure and media type, clears 1306621Sbt150084 * all on chip counters, initializes receive address registers, multicast 1316621Sbt150084 * table, VLAN filter table, calls routine to set up link and flow control 1326621Sbt150084 * settings, and leaves transmit and receive units disabled and uninitialized 1336621Sbt150084 */ 1346621Sbt150084 s32 1356621Sbt150084 ixgbe_start_hw_generic(struct ixgbe_hw *hw) 1366621Sbt150084 { 1376621Sbt150084 u32 ctrl_ext; 1386621Sbt150084 139*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_start_hw_generic"); 140*10998SChenlu.Chen@Sun.COM 1416621Sbt150084 /* Set the media type */ 1426621Sbt150084 hw->phy.media_type = hw->mac.ops.get_media_type(hw); 1436621Sbt150084 1449353SSamuel.Tu@Sun.COM /* PHY ops initialization must be done in reset_hw() */ 1456621Sbt150084 1466621Sbt150084 /* Clear the VLAN filter table */ 1476621Sbt150084 hw->mac.ops.clear_vfta(hw); 1486621Sbt150084 1496621Sbt150084 /* Clear statistics registers */ 1506621Sbt150084 hw->mac.ops.clear_hw_cntrs(hw); 1516621Sbt150084 1526621Sbt150084 /* Set No Snoop Disable */ 1536621Sbt150084 ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); 1546621Sbt150084 ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; 1556621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); 1566621Sbt150084 IXGBE_WRITE_FLUSH(hw); 1576621Sbt150084 1589353SSamuel.Tu@Sun.COM /* Setup flow control */ 1599353SSamuel.Tu@Sun.COM (void) ixgbe_setup_fc(hw, 0); 1609353SSamuel.Tu@Sun.COM 1616621Sbt150084 /* Clear adapter stopped flag */ 1628490SPaul.Guo@Sun.COM hw->adapter_stopped = false; 1636621Sbt150084 1646621Sbt150084 return (IXGBE_SUCCESS); 1656621Sbt150084 } 1666621Sbt150084 1676621Sbt150084 /* 1686621Sbt150084 * ixgbe_init_hw_generic - Generic hardware initialization 1696621Sbt150084 * @hw: pointer to hardware structure 1706621Sbt150084 * 1716621Sbt150084 * Initialize the hardware by resetting the hardware, filling the bus info 1726621Sbt150084 * structure and media type, clears all on chip counters, initializes receive 1736621Sbt150084 * address registers, multicast table, VLAN filter table, calls routine to set 1746621Sbt150084 * up link and flow control settings, and leaves transmit and receive units 1756621Sbt150084 * disabled and uninitialized 1766621Sbt150084 */ 1776621Sbt150084 s32 1786621Sbt150084 ixgbe_init_hw_generic(struct ixgbe_hw *hw) 1796621Sbt150084 { 1809353SSamuel.Tu@Sun.COM s32 status = IXGBE_SUCCESS; 1819353SSamuel.Tu@Sun.COM 182*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_init_hw_generic"); 183*10998SChenlu.Chen@Sun.COM 1846621Sbt150084 /* Reset the hardware */ 1859353SSamuel.Tu@Sun.COM status = hw->mac.ops.reset_hw(hw); 1866621Sbt150084 1879353SSamuel.Tu@Sun.COM if (status == IXGBE_SUCCESS) { 1889353SSamuel.Tu@Sun.COM /* Start the HW */ 1899353SSamuel.Tu@Sun.COM status = hw->mac.ops.start_hw(hw); 1909353SSamuel.Tu@Sun.COM } 1916621Sbt150084 1929353SSamuel.Tu@Sun.COM return (status); 1936621Sbt150084 } 1946621Sbt150084 1956621Sbt150084 /* 1966621Sbt150084 * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters 1976621Sbt150084 * @hw: pointer to hardware structure 1986621Sbt150084 * 1996621Sbt150084 * Clears all hardware statistics counters by reading them from the hardware 2006621Sbt150084 * Statistics counters are clear on read. 2016621Sbt150084 */ 2026621Sbt150084 s32 2036621Sbt150084 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) 2046621Sbt150084 { 2056621Sbt150084 u16 i = 0; 2066621Sbt150084 207*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); 208*10998SChenlu.Chen@Sun.COM 2096621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_CRCERRS); 2106621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_ILLERRC); 2116621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_ERRBC); 2126621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MSPDC); 2136621Sbt150084 for (i = 0; i < 8; i++) 2146621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MPC(i)); 2156621Sbt150084 2166621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MLFC); 2176621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MRFC); 2186621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_RLEC); 2196621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_LXONTXC); 2206621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); 2219353SSamuel.Tu@Sun.COM if (hw->mac.type >= ixgbe_mac_82599EB) { 2229353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); 2239353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); 2249353SSamuel.Tu@Sun.COM } else { 2259353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_LXONRXC); 2269353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); 2279353SSamuel.Tu@Sun.COM } 2286621Sbt150084 2296621Sbt150084 for (i = 0; i < 8; i++) { 2306621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); 2316621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); 2329353SSamuel.Tu@Sun.COM if (hw->mac.type >= ixgbe_mac_82599EB) { 2339353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); 2349353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); 2359353SSamuel.Tu@Sun.COM } else { 2369353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); 2379353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); 2389353SSamuel.Tu@Sun.COM } 2396621Sbt150084 } 2409353SSamuel.Tu@Sun.COM if (hw->mac.type >= ixgbe_mac_82599EB) 2419353SSamuel.Tu@Sun.COM for (i = 0; i < 8; i++) 2429353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); 2436621Sbt150084 2446621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC64); 2456621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC127); 2466621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC255); 2476621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC511); 2486621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC1023); 2496621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PRC1522); 2506621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GPRC); 2516621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_BPRC); 2526621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MPRC); 2536621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GPTC); 2546621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GORCL); 2556621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GORCH); 2566621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GOTCL); 2576621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_GOTCH); 2586621Sbt150084 for (i = 0; i < 8; i++) 2596621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 2606621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_RUC); 2616621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_RFC); 2626621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_ROC); 2636621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_RJC); 2646621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MNGPRC); 2656621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MNGPDC); 2666621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MNGPTC); 2676621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_TORL); 2686621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_TORH); 2696621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_TPR); 2706621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_TPT); 2716621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC64); 2726621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC127); 2736621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC255); 2746621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC511); 2756621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC1023); 2766621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_PTC1522); 2776621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_MPTC); 2786621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_BPTC); 2796621Sbt150084 for (i = 0; i < 16; i++) { 2806621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_QPRC(i)); 2816621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 2826621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_QPTC(i)); 2839353SSamuel.Tu@Sun.COM if (hw->mac.type >= ixgbe_mac_82599EB) { 2849353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); 2859353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); 2869353SSamuel.Tu@Sun.COM } else { 2879353SSamuel.Tu@Sun.COM (void) IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 2889353SSamuel.Tu@Sun.COM } 2896621Sbt150084 } 2906621Sbt150084 2916621Sbt150084 return (IXGBE_SUCCESS); 2926621Sbt150084 } 2936621Sbt150084 2946621Sbt150084 /* 2958490SPaul.Guo@Sun.COM * ixgbe_read_pba_num_generic - Reads part number from EEPROM 2966621Sbt150084 * @hw: pointer to hardware structure 2976621Sbt150084 * @pba_num: stores the part number from the EEPROM 2986621Sbt150084 * 2996621Sbt150084 * Reads the part number from the EEPROM. 3006621Sbt150084 */ 3016621Sbt150084 s32 3026621Sbt150084 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) 3036621Sbt150084 { 3046621Sbt150084 s32 ret_val; 3056621Sbt150084 u16 data; 3066621Sbt150084 3076621Sbt150084 DEBUGFUNC("ixgbe_read_pba_num_generic"); 3086621Sbt150084 3096621Sbt150084 ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); 3106621Sbt150084 if (ret_val) { 3116621Sbt150084 DEBUGOUT("NVM Read Error\n"); 3126621Sbt150084 return (ret_val); 3136621Sbt150084 } 3146621Sbt150084 *pba_num = (u32)(data << 16); 3156621Sbt150084 3166621Sbt150084 ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); 3176621Sbt150084 if (ret_val) { 3186621Sbt150084 DEBUGOUT("NVM Read Error\n"); 3196621Sbt150084 return (ret_val); 3206621Sbt150084 } 3216621Sbt150084 *pba_num |= data; 3226621Sbt150084 3236621Sbt150084 return (IXGBE_SUCCESS); 3246621Sbt150084 } 3256621Sbt150084 3266621Sbt150084 /* 3276621Sbt150084 * ixgbe_get_mac_addr_generic - Generic get MAC address 3286621Sbt150084 * @hw: pointer to hardware structure 3296621Sbt150084 * @mac_addr: Adapter MAC address 3306621Sbt150084 * 3316621Sbt150084 * Reads the adapter's MAC address from first Receive Address Register (RAR0) 3326621Sbt150084 * A reset of the adapter must be performed prior to calling this function 3336621Sbt150084 * in order for the MAC address to have been loaded from the EEPROM into RAR0 3346621Sbt150084 */ 3356621Sbt150084 s32 3366621Sbt150084 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) 3376621Sbt150084 { 3386621Sbt150084 u32 rar_high; 3396621Sbt150084 u32 rar_low; 3406621Sbt150084 u16 i; 3416621Sbt150084 342*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_mac_addr_generic"); 343*10998SChenlu.Chen@Sun.COM 3446621Sbt150084 rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); 3456621Sbt150084 rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); 3466621Sbt150084 3476621Sbt150084 for (i = 0; i < 4; i++) 3486621Sbt150084 mac_addr[i] = (u8)(rar_low >> (i*8)); 3496621Sbt150084 3506621Sbt150084 for (i = 0; i < 2; i++) 3516621Sbt150084 mac_addr[i+4] = (u8)(rar_high >> (i*8)); 3526621Sbt150084 3536621Sbt150084 return (IXGBE_SUCCESS); 3546621Sbt150084 } 3556621Sbt150084 3566621Sbt150084 /* 3576621Sbt150084 * ixgbe_get_bus_info_generic - Generic set PCI bus info 3586621Sbt150084 * @hw: pointer to hardware structure 3596621Sbt150084 * 3606621Sbt150084 * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure 3616621Sbt150084 */ 3626621Sbt150084 s32 3636621Sbt150084 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) 3646621Sbt150084 { 3659353SSamuel.Tu@Sun.COM struct ixgbe_mac_info *mac = &hw->mac; 3666621Sbt150084 u16 link_status; 3676621Sbt150084 368*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_bus_info_generic"); 369*10998SChenlu.Chen@Sun.COM 3706621Sbt150084 hw->bus.type = ixgbe_bus_type_pci_express; 3716621Sbt150084 3726621Sbt150084 /* Get the negotiated link width and speed from PCI config space */ 3736621Sbt150084 link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); 3746621Sbt150084 3756621Sbt150084 switch (link_status & IXGBE_PCI_LINK_WIDTH) { 3766621Sbt150084 case IXGBE_PCI_LINK_WIDTH_1: 3776621Sbt150084 hw->bus.width = ixgbe_bus_width_pcie_x1; 3786621Sbt150084 break; 3796621Sbt150084 case IXGBE_PCI_LINK_WIDTH_2: 3806621Sbt150084 hw->bus.width = ixgbe_bus_width_pcie_x2; 3816621Sbt150084 break; 3826621Sbt150084 case IXGBE_PCI_LINK_WIDTH_4: 3836621Sbt150084 hw->bus.width = ixgbe_bus_width_pcie_x4; 3846621Sbt150084 break; 3856621Sbt150084 case IXGBE_PCI_LINK_WIDTH_8: 3866621Sbt150084 hw->bus.width = ixgbe_bus_width_pcie_x8; 3876621Sbt150084 break; 3886621Sbt150084 default: 3896621Sbt150084 hw->bus.width = ixgbe_bus_width_unknown; 3906621Sbt150084 break; 3916621Sbt150084 } 3926621Sbt150084 3936621Sbt150084 switch (link_status & IXGBE_PCI_LINK_SPEED) { 3946621Sbt150084 case IXGBE_PCI_LINK_SPEED_2500: 3956621Sbt150084 hw->bus.speed = ixgbe_bus_speed_2500; 3966621Sbt150084 break; 3976621Sbt150084 case IXGBE_PCI_LINK_SPEED_5000: 3986621Sbt150084 hw->bus.speed = ixgbe_bus_speed_5000; 3996621Sbt150084 break; 4006621Sbt150084 default: 4016621Sbt150084 hw->bus.speed = ixgbe_bus_speed_unknown; 4026621Sbt150084 break; 4036621Sbt150084 } 4046621Sbt150084 4059353SSamuel.Tu@Sun.COM mac->ops.set_lan_id(hw); 4069353SSamuel.Tu@Sun.COM 4076621Sbt150084 return (IXGBE_SUCCESS); 4086621Sbt150084 } 4096621Sbt150084 4109353SSamuel.Tu@Sun.COM 4119353SSamuel.Tu@Sun.COM /* 4129353SSamuel.Tu@Sun.COM * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices 4139353SSamuel.Tu@Sun.COM * @hw: pointer to the HW structure 4149353SSamuel.Tu@Sun.COM * 4159353SSamuel.Tu@Sun.COM * Determines the LAN function id by reading memory-mapped registers 4169353SSamuel.Tu@Sun.COM * and swaps the port value if requested. 4179353SSamuel.Tu@Sun.COM */ 4189353SSamuel.Tu@Sun.COM void 4199353SSamuel.Tu@Sun.COM ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) 4209353SSamuel.Tu@Sun.COM { 4219353SSamuel.Tu@Sun.COM struct ixgbe_bus_info *bus = &hw->bus; 4229353SSamuel.Tu@Sun.COM u32 reg; 4239353SSamuel.Tu@Sun.COM 424*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); 425*10998SChenlu.Chen@Sun.COM 4269353SSamuel.Tu@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_STATUS); 4279353SSamuel.Tu@Sun.COM bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; 4289353SSamuel.Tu@Sun.COM bus->lan_id = bus->func; 4299353SSamuel.Tu@Sun.COM 4309353SSamuel.Tu@Sun.COM /* check for a port swap */ 4319353SSamuel.Tu@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); 4329353SSamuel.Tu@Sun.COM if (reg & IXGBE_FACTPS_LFS) 4339353SSamuel.Tu@Sun.COM bus->func ^= 0x1; 4349353SSamuel.Tu@Sun.COM } 4359353SSamuel.Tu@Sun.COM 4366621Sbt150084 /* 4376621Sbt150084 * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units 4386621Sbt150084 * @hw: pointer to hardware structure 4396621Sbt150084 * 4406621Sbt150084 * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, 4416621Sbt150084 * disables transmit and receive units. The adapter_stopped flag is used by 4426621Sbt150084 * the shared code and drivers to determine if the adapter is in a stopped 4436621Sbt150084 * state and should not touch the hardware. 4446621Sbt150084 */ 4456621Sbt150084 s32 4466621Sbt150084 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) 4476621Sbt150084 { 4486621Sbt150084 u32 number_of_queues; 4496621Sbt150084 u32 reg_val; 4506621Sbt150084 u16 i; 4516621Sbt150084 452*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_stop_adapter_generic"); 453*10998SChenlu.Chen@Sun.COM 4546621Sbt150084 /* 4556621Sbt150084 * Set the adapter_stopped flag so other driver functions stop touching 4566621Sbt150084 * the hardware 4576621Sbt150084 */ 4588490SPaul.Guo@Sun.COM hw->adapter_stopped = true; 4596621Sbt150084 4606621Sbt150084 /* Disable the receive unit */ 4616621Sbt150084 reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL); 4626621Sbt150084 reg_val &= ~(IXGBE_RXCTRL_RXEN); 4636621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val); 4646621Sbt150084 IXGBE_WRITE_FLUSH(hw); 4656621Sbt150084 msec_delay(2); 4666621Sbt150084 4676621Sbt150084 /* Clear interrupt mask to stop from interrupts being generated */ 4686621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); 4696621Sbt150084 4706621Sbt150084 /* Clear any pending interrupts */ 4716621Sbt150084 (void) IXGBE_READ_REG(hw, IXGBE_EICR); 4726621Sbt150084 4736621Sbt150084 /* Disable the transmit unit. Each queue must be disabled. */ 4746621Sbt150084 number_of_queues = hw->mac.max_tx_queues; 4756621Sbt150084 for (i = 0; i < number_of_queues; i++) { 4766621Sbt150084 reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); 4776621Sbt150084 if (reg_val & IXGBE_TXDCTL_ENABLE) { 4786621Sbt150084 reg_val &= ~IXGBE_TXDCTL_ENABLE; 4796621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val); 4806621Sbt150084 } 4816621Sbt150084 } 4826621Sbt150084 4836621Sbt150084 /* 4846621Sbt150084 * Prevent the PCI-E bus from from hanging by disabling PCI-E master 4856621Sbt150084 * access and verify no pending requests 4866621Sbt150084 */ 4876621Sbt150084 if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) { 4886621Sbt150084 DEBUGOUT("PCI-E Master disable polling has failed.\n"); 4896621Sbt150084 } 4906621Sbt150084 4916621Sbt150084 return (IXGBE_SUCCESS); 4926621Sbt150084 } 4936621Sbt150084 4946621Sbt150084 /* 4956621Sbt150084 * ixgbe_led_on_generic - Turns on the software controllable LEDs. 4966621Sbt150084 * @hw: pointer to hardware structure 4976621Sbt150084 * @index: led number to turn on 4986621Sbt150084 */ 4996621Sbt150084 s32 5006621Sbt150084 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) 5016621Sbt150084 { 5026621Sbt150084 u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 5036621Sbt150084 504*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_led_on_generic"); 505*10998SChenlu.Chen@Sun.COM 5066621Sbt150084 /* To turn on the LED, set mode to ON. */ 5076621Sbt150084 led_reg &= ~IXGBE_LED_MODE_MASK(index); 5086621Sbt150084 led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); 5096621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 5106621Sbt150084 IXGBE_WRITE_FLUSH(hw); 5116621Sbt150084 5126621Sbt150084 return (IXGBE_SUCCESS); 5136621Sbt150084 } 5146621Sbt150084 5156621Sbt150084 /* 5166621Sbt150084 * ixgbe_led_off_generic - Turns off the software controllable LEDs. 5176621Sbt150084 * @hw: pointer to hardware structure 5186621Sbt150084 * @index: led number to turn off 5196621Sbt150084 */ 5206621Sbt150084 s32 5216621Sbt150084 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) 5226621Sbt150084 { 5236621Sbt150084 u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 5246621Sbt150084 525*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_led_off_generic"); 526*10998SChenlu.Chen@Sun.COM 5276621Sbt150084 /* To turn off the LED, set mode to OFF. */ 5286621Sbt150084 led_reg &= ~IXGBE_LED_MODE_MASK(index); 5296621Sbt150084 led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); 5306621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 5316621Sbt150084 IXGBE_WRITE_FLUSH(hw); 5326621Sbt150084 5336621Sbt150084 return (IXGBE_SUCCESS); 5346621Sbt150084 } 5356621Sbt150084 5366621Sbt150084 /* 5376621Sbt150084 * ixgbe_init_eeprom_params_generic - Initialize EEPROM params 5386621Sbt150084 * @hw: pointer to hardware structure 5396621Sbt150084 * 5406621Sbt150084 * Initializes the EEPROM parameters ixgbe_eeprom_info within the 5416621Sbt150084 * ixgbe_hw struct in order to set up EEPROM access. 5426621Sbt150084 */ 5436621Sbt150084 s32 5446621Sbt150084 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) 5456621Sbt150084 { 5466621Sbt150084 struct ixgbe_eeprom_info *eeprom = &hw->eeprom; 5476621Sbt150084 u32 eec; 5486621Sbt150084 u16 eeprom_size; 5496621Sbt150084 550*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_init_eeprom_params_generic"); 551*10998SChenlu.Chen@Sun.COM 5526621Sbt150084 if (eeprom->type == ixgbe_eeprom_uninitialized) { 5536621Sbt150084 eeprom->type = ixgbe_eeprom_none; 5548490SPaul.Guo@Sun.COM /* 5558490SPaul.Guo@Sun.COM * Set default semaphore delay to 10ms which is a well 5568490SPaul.Guo@Sun.COM * tested value 5578490SPaul.Guo@Sun.COM */ 5588490SPaul.Guo@Sun.COM eeprom->semaphore_delay = 10; 5596621Sbt150084 5606621Sbt150084 /* 5616621Sbt150084 * Check for EEPROM present first. 5626621Sbt150084 * If not present leave as none 5636621Sbt150084 */ 5646621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 5656621Sbt150084 if (eec & IXGBE_EEC_PRES) { 5666621Sbt150084 eeprom->type = ixgbe_eeprom_spi; 5676621Sbt150084 5686621Sbt150084 /* 5696621Sbt150084 * SPI EEPROM is assumed here. This code would need to 5706621Sbt150084 * change if a future EEPROM is not SPI. 5716621Sbt150084 */ 5726621Sbt150084 eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> 5736621Sbt150084 IXGBE_EEC_SIZE_SHIFT); 5746621Sbt150084 eeprom->word_size = 1 << (eeprom_size + 575*10998SChenlu.Chen@Sun.COM IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT); 5766621Sbt150084 } 5776621Sbt150084 5786621Sbt150084 if (eec & IXGBE_EEC_ADDR_SIZE) 5796621Sbt150084 eeprom->address_bits = 16; 5806621Sbt150084 else 5816621Sbt150084 eeprom->address_bits = 8; 5826621Sbt150084 DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " 5836621Sbt150084 "%d\n", eeprom->type, eeprom->word_size, 5846621Sbt150084 eeprom->address_bits); 5856621Sbt150084 } 5866621Sbt150084 5876621Sbt150084 return (IXGBE_SUCCESS); 5886621Sbt150084 } 5896621Sbt150084 5906621Sbt150084 /* 5916621Sbt150084 * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM 5926621Sbt150084 * @hw: pointer to hardware structure 5936621Sbt150084 * @offset: offset within the EEPROM to be written to 5946621Sbt150084 * @data: 16 bit word to be written to the EEPROM 5956621Sbt150084 * 5966621Sbt150084 * If ixgbe_eeprom_update_checksum is not called after this function, the 5976621Sbt150084 * EEPROM will most likely contain an invalid checksum. 5986621Sbt150084 */ 5996621Sbt150084 s32 6006621Sbt150084 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) 6016621Sbt150084 { 6026621Sbt150084 s32 status; 6036621Sbt150084 u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; 6046621Sbt150084 605*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_write_eeprom_generic"); 606*10998SChenlu.Chen@Sun.COM 6076621Sbt150084 hw->eeprom.ops.init_params(hw); 6086621Sbt150084 6096621Sbt150084 if (offset >= hw->eeprom.word_size) { 6106621Sbt150084 status = IXGBE_ERR_EEPROM; 6116621Sbt150084 goto out; 6126621Sbt150084 } 6136621Sbt150084 6146621Sbt150084 /* Prepare the EEPROM for writing */ 6156621Sbt150084 status = ixgbe_acquire_eeprom(hw); 6166621Sbt150084 6176621Sbt150084 if (status == IXGBE_SUCCESS) { 6186621Sbt150084 if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 6196621Sbt150084 ixgbe_release_eeprom(hw); 6206621Sbt150084 status = IXGBE_ERR_EEPROM; 6216621Sbt150084 } 6226621Sbt150084 } 6236621Sbt150084 6246621Sbt150084 if (status == IXGBE_SUCCESS) { 6256621Sbt150084 ixgbe_standby_eeprom(hw); 6266621Sbt150084 6276621Sbt150084 /* Send the WRITE ENABLE command (8 bit opcode ) */ 6286621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, 6296621Sbt150084 IXGBE_EEPROM_OPCODE_BITS); 6306621Sbt150084 6316621Sbt150084 ixgbe_standby_eeprom(hw); 6326621Sbt150084 6336621Sbt150084 /* 6346621Sbt150084 * Some SPI eeproms use the 8th address bit embedded in the 6356621Sbt150084 * opcode 6366621Sbt150084 */ 6376621Sbt150084 if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 6386621Sbt150084 write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 6396621Sbt150084 6406621Sbt150084 /* Send the Write command (8-bit opcode + addr) */ 6416621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, write_opcode, 6426621Sbt150084 IXGBE_EEPROM_OPCODE_BITS); 6436621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 6446621Sbt150084 hw->eeprom.address_bits); 6456621Sbt150084 6466621Sbt150084 /* Send the data */ 6476621Sbt150084 data = (data >> 8) | (data << 8); 6486621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, data, 16); 6496621Sbt150084 ixgbe_standby_eeprom(hw); 6506621Sbt150084 6516621Sbt150084 /* Done with writing - release the EEPROM */ 6526621Sbt150084 ixgbe_release_eeprom(hw); 6536621Sbt150084 } 6546621Sbt150084 6556621Sbt150084 out: 6566621Sbt150084 return (status); 6576621Sbt150084 } 6586621Sbt150084 6596621Sbt150084 /* 6606621Sbt150084 * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang 6616621Sbt150084 * @hw: pointer to hardware structure 6626621Sbt150084 * @offset: offset within the EEPROM to be read 6636621Sbt150084 * @data: read 16 bit value from EEPROM 6646621Sbt150084 * 6656621Sbt150084 * Reads 16 bit value from EEPROM through bit-bang method 6666621Sbt150084 */ 6676621Sbt150084 s32 6686621Sbt150084 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, 6696621Sbt150084 u16 *data) 6706621Sbt150084 { 6716621Sbt150084 s32 status; 6726621Sbt150084 u16 word_in; 6736621Sbt150084 u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; 6746621Sbt150084 675*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); 676*10998SChenlu.Chen@Sun.COM 6776621Sbt150084 hw->eeprom.ops.init_params(hw); 6786621Sbt150084 6796621Sbt150084 if (offset >= hw->eeprom.word_size) { 6806621Sbt150084 status = IXGBE_ERR_EEPROM; 6816621Sbt150084 goto out; 6826621Sbt150084 } 6836621Sbt150084 6846621Sbt150084 /* Prepare the EEPROM for reading */ 6856621Sbt150084 status = ixgbe_acquire_eeprom(hw); 6866621Sbt150084 6876621Sbt150084 if (status == IXGBE_SUCCESS) { 6886621Sbt150084 if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { 6896621Sbt150084 ixgbe_release_eeprom(hw); 6906621Sbt150084 status = IXGBE_ERR_EEPROM; 6916621Sbt150084 } 6926621Sbt150084 } 6936621Sbt150084 6946621Sbt150084 if (status == IXGBE_SUCCESS) { 6956621Sbt150084 ixgbe_standby_eeprom(hw); 6966621Sbt150084 6976621Sbt150084 /* 6986621Sbt150084 * Some SPI eeproms use the 8th address bit embedded in the 6996621Sbt150084 * opcode 7006621Sbt150084 */ 7016621Sbt150084 if ((hw->eeprom.address_bits == 8) && (offset >= 128)) 7026621Sbt150084 read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; 7036621Sbt150084 7046621Sbt150084 /* Send the READ command (opcode + addr) */ 7056621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, read_opcode, 7066621Sbt150084 IXGBE_EEPROM_OPCODE_BITS); 7076621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2), 7086621Sbt150084 hw->eeprom.address_bits); 7096621Sbt150084 7106621Sbt150084 /* Read the data. */ 7116621Sbt150084 word_in = ixgbe_shift_in_eeprom_bits(hw, 16); 7126621Sbt150084 *data = (word_in >> 8) | (word_in << 8); 7136621Sbt150084 7146621Sbt150084 /* End this read operation */ 7156621Sbt150084 ixgbe_release_eeprom(hw); 7166621Sbt150084 } 7176621Sbt150084 7186621Sbt150084 out: 7196621Sbt150084 return (status); 7206621Sbt150084 } 7216621Sbt150084 7226621Sbt150084 /* 723*10998SChenlu.Chen@Sun.COM * ixgbe_read_eerd_generic - Read EEPROM word using EERD 7246621Sbt150084 * @hw: pointer to hardware structure 7256621Sbt150084 * @offset: offset of word in the EEPROM to read 7266621Sbt150084 * @data: word read from the EEPROM 7276621Sbt150084 * 7286621Sbt150084 * Reads a 16 bit word from the EEPROM using the EERD register. 7296621Sbt150084 */ 7306621Sbt150084 s32 731*10998SChenlu.Chen@Sun.COM ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) 7326621Sbt150084 { 7336621Sbt150084 u32 eerd; 7346621Sbt150084 s32 status; 7356621Sbt150084 736*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_read_eerd_generic"); 737*10998SChenlu.Chen@Sun.COM 7386621Sbt150084 hw->eeprom.ops.init_params(hw); 7396621Sbt150084 7406621Sbt150084 if (offset >= hw->eeprom.word_size) { 7416621Sbt150084 status = IXGBE_ERR_EEPROM; 7426621Sbt150084 goto out; 7436621Sbt150084 } 7446621Sbt150084 745*10998SChenlu.Chen@Sun.COM eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) + 746*10998SChenlu.Chen@Sun.COM IXGBE_EEPROM_RW_REG_START; 7476621Sbt150084 7486621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); 749*10998SChenlu.Chen@Sun.COM status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); 750*10998SChenlu.Chen@Sun.COM 751*10998SChenlu.Chen@Sun.COM if (status == IXGBE_SUCCESS) 7526621Sbt150084 *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> 753*10998SChenlu.Chen@Sun.COM IXGBE_EEPROM_RW_REG_DATA); 754*10998SChenlu.Chen@Sun.COM else 7556621Sbt150084 DEBUGOUT("Eeprom read timed out\n"); 7566621Sbt150084 7576621Sbt150084 out: 7586621Sbt150084 return (status); 7596621Sbt150084 } 7606621Sbt150084 7616621Sbt150084 /* 762*10998SChenlu.Chen@Sun.COM * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status 7636621Sbt150084 * @hw: pointer to hardware structure 764*10998SChenlu.Chen@Sun.COM * @ee_reg: EEPROM flag for polling 7656621Sbt150084 * 766*10998SChenlu.Chen@Sun.COM * Polls the status bit (bit 1) of the EERD or EEWR to determine when the 767*10998SChenlu.Chen@Sun.COM * read or write is done respectively. 7686621Sbt150084 */ 769*10998SChenlu.Chen@Sun.COM s32 770*10998SChenlu.Chen@Sun.COM ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) 7716621Sbt150084 { 7726621Sbt150084 u32 i; 7736621Sbt150084 u32 reg; 7746621Sbt150084 s32 status = IXGBE_ERR_EEPROM; 7756621Sbt150084 776*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); 777*10998SChenlu.Chen@Sun.COM 778*10998SChenlu.Chen@Sun.COM for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { 779*10998SChenlu.Chen@Sun.COM if (ee_reg == IXGBE_NVM_POLL_READ) 780*10998SChenlu.Chen@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_EERD); 781*10998SChenlu.Chen@Sun.COM else 782*10998SChenlu.Chen@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_EEWR); 783*10998SChenlu.Chen@Sun.COM 784*10998SChenlu.Chen@Sun.COM if (reg & IXGBE_EEPROM_RW_REG_DONE) { 7856621Sbt150084 status = IXGBE_SUCCESS; 7866621Sbt150084 break; 7876621Sbt150084 } 7886621Sbt150084 usec_delay(5); 7896621Sbt150084 } 7906621Sbt150084 return (status); 7916621Sbt150084 } 7926621Sbt150084 7936621Sbt150084 /* 7946621Sbt150084 * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang 7956621Sbt150084 * @hw: pointer to hardware structure 7966621Sbt150084 * 7976621Sbt150084 * Prepares EEPROM for access using bit-bang method. This function should 7986621Sbt150084 * be called before issuing a command to the EEPROM. 7996621Sbt150084 */ 8006621Sbt150084 static s32 8016621Sbt150084 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) 8026621Sbt150084 { 8036621Sbt150084 s32 status = IXGBE_SUCCESS; 8046621Sbt150084 u32 eec; 8056621Sbt150084 u32 i; 8066621Sbt150084 807*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_acquire_eeprom"); 808*10998SChenlu.Chen@Sun.COM 8096621Sbt150084 if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) 8106621Sbt150084 status = IXGBE_ERR_SWFW_SYNC; 8116621Sbt150084 8126621Sbt150084 if (status == IXGBE_SUCCESS) { 8136621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 8146621Sbt150084 8156621Sbt150084 /* Request EEPROM Access */ 8166621Sbt150084 eec |= IXGBE_EEC_REQ; 8176621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 8186621Sbt150084 8196621Sbt150084 for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { 8206621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 8216621Sbt150084 if (eec & IXGBE_EEC_GNT) 8226621Sbt150084 break; 8236621Sbt150084 usec_delay(5); 8246621Sbt150084 } 8256621Sbt150084 8266621Sbt150084 /* Release if grant not acquired */ 8276621Sbt150084 if (!(eec & IXGBE_EEC_GNT)) { 8286621Sbt150084 eec &= ~IXGBE_EEC_REQ; 8296621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 8306621Sbt150084 DEBUGOUT("Could not acquire EEPROM grant\n"); 8316621Sbt150084 8326621Sbt150084 ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 8336621Sbt150084 status = IXGBE_ERR_EEPROM; 8346621Sbt150084 } 8356621Sbt150084 } 8366621Sbt150084 8376621Sbt150084 /* Setup EEPROM for Read/Write */ 8386621Sbt150084 if (status == IXGBE_SUCCESS) { 8396621Sbt150084 /* Clear CS and SK */ 8406621Sbt150084 eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); 8416621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 8426621Sbt150084 IXGBE_WRITE_FLUSH(hw); 8436621Sbt150084 usec_delay(1); 8446621Sbt150084 } 8456621Sbt150084 return (status); 8466621Sbt150084 } 8476621Sbt150084 8486621Sbt150084 /* 8496621Sbt150084 * ixgbe_get_eeprom_semaphore - Get hardware semaphore 8506621Sbt150084 * @hw: pointer to hardware structure 8516621Sbt150084 * 8526621Sbt150084 * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 8536621Sbt150084 */ 8546621Sbt150084 static s32 8556621Sbt150084 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) 8566621Sbt150084 { 8576621Sbt150084 s32 status = IXGBE_ERR_EEPROM; 85810305SPaul.Guo@Sun.COM u32 timeout = 2000; 8596621Sbt150084 u32 i; 8606621Sbt150084 u32 swsm; 8616621Sbt150084 862*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_eeprom_semaphore"); 863*10998SChenlu.Chen@Sun.COM 8646621Sbt150084 /* Get SMBI software semaphore between device drivers first */ 8656621Sbt150084 for (i = 0; i < timeout; i++) { 8666621Sbt150084 /* 8676621Sbt150084 * If the SMBI bit is 0 when we read it, then the bit will be 8686621Sbt150084 * set and we have the semaphore 8696621Sbt150084 */ 8706621Sbt150084 swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 8716621Sbt150084 if (!(swsm & IXGBE_SWSM_SMBI)) { 8726621Sbt150084 status = IXGBE_SUCCESS; 8736621Sbt150084 break; 8746621Sbt150084 } 87510305SPaul.Guo@Sun.COM usec_delay(50); 8766621Sbt150084 } 8776621Sbt150084 8786621Sbt150084 /* Now get the semaphore between SW/FW through the SWESMBI bit */ 8796621Sbt150084 if (status == IXGBE_SUCCESS) { 8806621Sbt150084 for (i = 0; i < timeout; i++) { 8816621Sbt150084 swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 8826621Sbt150084 8836621Sbt150084 /* Set the SW EEPROM semaphore bit to request access */ 8846621Sbt150084 swsm |= IXGBE_SWSM_SWESMBI; 8856621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 8866621Sbt150084 8876621Sbt150084 /* 8886621Sbt150084 * If we set the bit successfully then we got the 8896621Sbt150084 * semaphore. 8906621Sbt150084 */ 8916621Sbt150084 swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 8926621Sbt150084 if (swsm & IXGBE_SWSM_SWESMBI) 8936621Sbt150084 break; 8946621Sbt150084 8956621Sbt150084 usec_delay(50); 8966621Sbt150084 } 8976621Sbt150084 8986621Sbt150084 /* 8996621Sbt150084 * Release semaphores and return error if SW EEPROM semaphore 9006621Sbt150084 * was not granted because we don't have access to the EEPROM 9016621Sbt150084 */ 9026621Sbt150084 if (i >= timeout) { 9039353SSamuel.Tu@Sun.COM DEBUGOUT("SWESMBI Software EEPROM semaphore " 9046621Sbt150084 "not granted.\n"); 9056621Sbt150084 ixgbe_release_eeprom_semaphore(hw); 9066621Sbt150084 status = IXGBE_ERR_EEPROM; 9076621Sbt150084 } 9089353SSamuel.Tu@Sun.COM } else { 9099353SSamuel.Tu@Sun.COM DEBUGOUT("Software semaphore SMBI between device drivers " 9109353SSamuel.Tu@Sun.COM "not granted.\n"); 9116621Sbt150084 } 9126621Sbt150084 9136621Sbt150084 return (status); 9146621Sbt150084 } 9156621Sbt150084 9166621Sbt150084 /* 9176621Sbt150084 * ixgbe_release_eeprom_semaphore - Release hardware semaphore 9186621Sbt150084 * @hw: pointer to hardware structure 9196621Sbt150084 * 9206621Sbt150084 * This function clears hardware semaphore bits. 9216621Sbt150084 */ 9226621Sbt150084 static void 9236621Sbt150084 ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) 9246621Sbt150084 { 9256621Sbt150084 u32 swsm; 9266621Sbt150084 927*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_release_eeprom_semaphore"); 928*10998SChenlu.Chen@Sun.COM 9296621Sbt150084 swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); 9306621Sbt150084 9316621Sbt150084 /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ 9326621Sbt150084 swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); 9336621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); 9346621Sbt150084 IXGBE_WRITE_FLUSH(hw); 9356621Sbt150084 } 9366621Sbt150084 9376621Sbt150084 /* 9386621Sbt150084 * ixgbe_ready_eeprom - Polls for EEPROM ready 9396621Sbt150084 * @hw: pointer to hardware structure 9406621Sbt150084 */ 9416621Sbt150084 static s32 9426621Sbt150084 ixgbe_ready_eeprom(struct ixgbe_hw *hw) 9436621Sbt150084 { 9446621Sbt150084 s32 status = IXGBE_SUCCESS; 9456621Sbt150084 u16 i; 9466621Sbt150084 u8 spi_stat_reg; 9476621Sbt150084 948*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_ready_eeprom"); 949*10998SChenlu.Chen@Sun.COM 9506621Sbt150084 /* 9516621Sbt150084 * Read "Status Register" repeatedly until the LSB is cleared. The 9526621Sbt150084 * EEPROM will signal that the command has been completed by clearing 9536621Sbt150084 * bit 0 of the internal status register. If it's not cleared within 9546621Sbt150084 * 5 milliseconds, then error out. 9556621Sbt150084 */ 9566621Sbt150084 for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { 9576621Sbt150084 ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, 9586621Sbt150084 IXGBE_EEPROM_OPCODE_BITS); 9596621Sbt150084 spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); 9606621Sbt150084 if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) 9616621Sbt150084 break; 9626621Sbt150084 9636621Sbt150084 usec_delay(5); 9646621Sbt150084 ixgbe_standby_eeprom(hw); 9656621Sbt150084 }; 9666621Sbt150084 9676621Sbt150084 /* 9686621Sbt150084 * On some parts, SPI write time could vary from 0-20mSec on 3.3V 9696621Sbt150084 * devices (and only 0-5mSec on 5V devices) 9706621Sbt150084 */ 9716621Sbt150084 if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { 9726621Sbt150084 DEBUGOUT("SPI EEPROM Status error\n"); 9736621Sbt150084 status = IXGBE_ERR_EEPROM; 9746621Sbt150084 } 9756621Sbt150084 9766621Sbt150084 return (status); 9776621Sbt150084 } 9786621Sbt150084 9796621Sbt150084 /* 9806621Sbt150084 * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state 9816621Sbt150084 * @hw: pointer to hardware structure 9826621Sbt150084 */ 9836621Sbt150084 static void 9846621Sbt150084 ixgbe_standby_eeprom(struct ixgbe_hw *hw) 9856621Sbt150084 { 9866621Sbt150084 u32 eec; 9876621Sbt150084 988*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_standby_eeprom"); 989*10998SChenlu.Chen@Sun.COM 9906621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 9916621Sbt150084 9926621Sbt150084 /* Toggle CS to flush commands */ 9936621Sbt150084 eec |= IXGBE_EEC_CS; 9946621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 9956621Sbt150084 IXGBE_WRITE_FLUSH(hw); 9966621Sbt150084 usec_delay(1); 9976621Sbt150084 eec &= ~IXGBE_EEC_CS; 9986621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 9996621Sbt150084 IXGBE_WRITE_FLUSH(hw); 10006621Sbt150084 usec_delay(1); 10016621Sbt150084 } 10026621Sbt150084 10036621Sbt150084 /* 10046621Sbt150084 * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. 10056621Sbt150084 * @hw: pointer to hardware structure 10066621Sbt150084 * @data: data to send to the EEPROM 10076621Sbt150084 * @count: number of bits to shift out 10086621Sbt150084 */ 10096621Sbt150084 static void 10106621Sbt150084 ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, 10116621Sbt150084 u16 count) 10126621Sbt150084 { 10136621Sbt150084 u32 eec; 10146621Sbt150084 u32 mask; 10156621Sbt150084 u32 i; 10166621Sbt150084 1017*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); 1018*10998SChenlu.Chen@Sun.COM 10196621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 10206621Sbt150084 10216621Sbt150084 /* 10226621Sbt150084 * Mask is used to shift "count" bits of "data" out to the EEPROM 10236621Sbt150084 * one bit at a time. Determine the starting bit based on count 10246621Sbt150084 */ 10256621Sbt150084 mask = 0x01 << (count - 1); 10266621Sbt150084 10276621Sbt150084 for (i = 0; i < count; i++) { 10286621Sbt150084 /* 10296621Sbt150084 * A "1" is shifted out to the EEPROM by setting bit "DI" to a 10306621Sbt150084 * "1", and then raising and then lowering the clock (the SK 10316621Sbt150084 * bit controls the clock input to the EEPROM). A "0" is 10326621Sbt150084 * shifted out to the EEPROM by setting "DI" to "0" and then 10336621Sbt150084 * raising and then lowering the clock. 10346621Sbt150084 */ 10356621Sbt150084 if (data & mask) 10366621Sbt150084 eec |= IXGBE_EEC_DI; 10376621Sbt150084 else 10386621Sbt150084 eec &= ~IXGBE_EEC_DI; 10396621Sbt150084 10406621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 10416621Sbt150084 IXGBE_WRITE_FLUSH(hw); 10426621Sbt150084 10436621Sbt150084 usec_delay(1); 10446621Sbt150084 10456621Sbt150084 ixgbe_raise_eeprom_clk(hw, &eec); 10466621Sbt150084 ixgbe_lower_eeprom_clk(hw, &eec); 10476621Sbt150084 10486621Sbt150084 /* 10496621Sbt150084 * Shift mask to signify next bit of data to shift in to the 10506621Sbt150084 * EEPROM 10516621Sbt150084 */ 10526621Sbt150084 mask = mask >> 1; 10536621Sbt150084 }; 10546621Sbt150084 10556621Sbt150084 /* We leave the "DI" bit set to "0" when we leave this routine. */ 10566621Sbt150084 eec &= ~IXGBE_EEC_DI; 10576621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 10586621Sbt150084 IXGBE_WRITE_FLUSH(hw); 10596621Sbt150084 } 10606621Sbt150084 10616621Sbt150084 /* 10626621Sbt150084 * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM 10636621Sbt150084 * @hw: pointer to hardware structure 10646621Sbt150084 */ 10656621Sbt150084 static u16 10666621Sbt150084 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) 10676621Sbt150084 { 10686621Sbt150084 u32 eec; 10696621Sbt150084 u32 i; 10706621Sbt150084 u16 data = 0; 10716621Sbt150084 1072*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); 1073*10998SChenlu.Chen@Sun.COM 10746621Sbt150084 /* 10756621Sbt150084 * In order to read a register from the EEPROM, we need to shift 10766621Sbt150084 * 'count' bits in from the EEPROM. Bits are "shifted in" by raising 10776621Sbt150084 * the clock input to the EEPROM (setting the SK bit), and then reading 10786621Sbt150084 * the value of the "DO" bit. During this "shifting in" process the 10796621Sbt150084 * "DI" bit should always be clear. 10806621Sbt150084 */ 10816621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 10826621Sbt150084 10836621Sbt150084 eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); 10846621Sbt150084 10856621Sbt150084 for (i = 0; i < count; i++) { 10866621Sbt150084 data = data << 1; 10876621Sbt150084 ixgbe_raise_eeprom_clk(hw, &eec); 10886621Sbt150084 10896621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 10906621Sbt150084 10916621Sbt150084 eec &= ~(IXGBE_EEC_DI); 10926621Sbt150084 if (eec & IXGBE_EEC_DO) 10936621Sbt150084 data |= 1; 10946621Sbt150084 10956621Sbt150084 ixgbe_lower_eeprom_clk(hw, &eec); 10966621Sbt150084 } 10976621Sbt150084 10986621Sbt150084 return (data); 10996621Sbt150084 } 11006621Sbt150084 11016621Sbt150084 /* 11026621Sbt150084 * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. 11036621Sbt150084 * @hw: pointer to hardware structure 11046621Sbt150084 * @eec: EEC register's current value 11056621Sbt150084 */ 11066621Sbt150084 static void 11076621Sbt150084 ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 11086621Sbt150084 { 1109*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_raise_eeprom_clk"); 1110*10998SChenlu.Chen@Sun.COM 11116621Sbt150084 /* 11126621Sbt150084 * Raise the clock input to the EEPROM 11136621Sbt150084 * (setting the SK bit), then delay 11146621Sbt150084 */ 11156621Sbt150084 *eec = *eec | IXGBE_EEC_SK; 11166621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 11176621Sbt150084 IXGBE_WRITE_FLUSH(hw); 11186621Sbt150084 usec_delay(1); 11196621Sbt150084 } 11206621Sbt150084 11216621Sbt150084 /* 11226621Sbt150084 * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. 11236621Sbt150084 * @hw: pointer to hardware structure 11246621Sbt150084 * @eecd: EECD's current value 11256621Sbt150084 */ 11266621Sbt150084 static void 11276621Sbt150084 ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) 11286621Sbt150084 { 1129*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_lower_eeprom_clk"); 1130*10998SChenlu.Chen@Sun.COM 11316621Sbt150084 /* 11326621Sbt150084 * Lower the clock input to the EEPROM (clearing the SK bit), then 11336621Sbt150084 * delay 11346621Sbt150084 */ 11356621Sbt150084 *eec = *eec & ~IXGBE_EEC_SK; 11366621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); 11376621Sbt150084 IXGBE_WRITE_FLUSH(hw); 11386621Sbt150084 usec_delay(1); 11396621Sbt150084 } 11406621Sbt150084 11416621Sbt150084 /* 11426621Sbt150084 * ixgbe_release_eeprom - Release EEPROM, release semaphores 11436621Sbt150084 * @hw: pointer to hardware structure 11446621Sbt150084 */ 11456621Sbt150084 static void 11466621Sbt150084 ixgbe_release_eeprom(struct ixgbe_hw *hw) 11476621Sbt150084 { 11486621Sbt150084 u32 eec; 11496621Sbt150084 1150*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_release_eeprom"); 1151*10998SChenlu.Chen@Sun.COM 11526621Sbt150084 eec = IXGBE_READ_REG(hw, IXGBE_EEC); 11536621Sbt150084 11546621Sbt150084 eec |= IXGBE_EEC_CS; /* Pull CS high */ 11556621Sbt150084 eec &= ~IXGBE_EEC_SK; /* Lower SCK */ 11566621Sbt150084 11576621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 11586621Sbt150084 IXGBE_WRITE_FLUSH(hw); 11596621Sbt150084 11606621Sbt150084 usec_delay(1); 11616621Sbt150084 11626621Sbt150084 /* Stop requesting EEPROM access */ 11636621Sbt150084 eec &= ~IXGBE_EEC_REQ; 11646621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); 11656621Sbt150084 11666621Sbt150084 ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); 116710305SPaul.Guo@Sun.COM 116810305SPaul.Guo@Sun.COM /* Delay before attempt to obtain semaphore again to allow FW access */ 116910305SPaul.Guo@Sun.COM msec_delay(hw->eeprom.semaphore_delay); 11706621Sbt150084 } 11716621Sbt150084 11726621Sbt150084 /* 11736621Sbt150084 * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum 11746621Sbt150084 * @hw: pointer to hardware structure 11756621Sbt150084 */ 11766621Sbt150084 static u16 11776621Sbt150084 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw) 11786621Sbt150084 { 11796621Sbt150084 u16 i; 11806621Sbt150084 u16 j; 11816621Sbt150084 u16 checksum = 0; 11826621Sbt150084 u16 length = 0; 11836621Sbt150084 u16 pointer = 0; 11846621Sbt150084 u16 word = 0; 11856621Sbt150084 1186*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_calc_eeprom_checksum"); 1187*10998SChenlu.Chen@Sun.COM 11886621Sbt150084 /* Include 0x0-0x3F in the checksum */ 11896621Sbt150084 for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { 11906621Sbt150084 if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { 11916621Sbt150084 DEBUGOUT("EEPROM read failed\n"); 11926621Sbt150084 break; 11936621Sbt150084 } 11946621Sbt150084 checksum += word; 11956621Sbt150084 } 11966621Sbt150084 11976621Sbt150084 /* Include all data from pointers except for the fw pointer */ 11986621Sbt150084 for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { 11996621Sbt150084 hw->eeprom.ops.read(hw, i, &pointer); 12006621Sbt150084 12016621Sbt150084 /* Make sure the pointer seems valid */ 12026621Sbt150084 if (pointer != 0xFFFF && pointer != 0) { 12036621Sbt150084 hw->eeprom.ops.read(hw, pointer, &length); 12046621Sbt150084 12056621Sbt150084 if (length != 0xFFFF && length != 0) { 12066621Sbt150084 for (j = pointer+1; j <= pointer+length; j++) { 12076621Sbt150084 hw->eeprom.ops.read(hw, j, &word); 12086621Sbt150084 checksum += word; 12096621Sbt150084 } 12106621Sbt150084 } 12116621Sbt150084 } 12126621Sbt150084 } 12136621Sbt150084 12146621Sbt150084 checksum = (u16)IXGBE_EEPROM_SUM - checksum; 12156621Sbt150084 12166621Sbt150084 return (checksum); 12176621Sbt150084 } 12186621Sbt150084 12196621Sbt150084 /* 12206621Sbt150084 * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum 12216621Sbt150084 * @hw: pointer to hardware structure 12226621Sbt150084 * @checksum_val: calculated checksum 12236621Sbt150084 * 12246621Sbt150084 * Performs checksum calculation and validates the EEPROM checksum. If the 12256621Sbt150084 * caller does not need checksum_val, the value can be NULL. 12266621Sbt150084 */ 12276621Sbt150084 s32 12286621Sbt150084 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, 12296621Sbt150084 u16 *checksum_val) 12306621Sbt150084 { 12316621Sbt150084 s32 status; 12326621Sbt150084 u16 checksum; 12336621Sbt150084 u16 read_checksum = 0; 12346621Sbt150084 1235*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); 1236*10998SChenlu.Chen@Sun.COM 12376621Sbt150084 /* 12386621Sbt150084 * Read the first word from the EEPROM. If this times out or fails, do 12396621Sbt150084 * not continue or we could be in for a very long wait while every 12406621Sbt150084 * EEPROM read fails 12416621Sbt150084 */ 12426621Sbt150084 status = hw->eeprom.ops.read(hw, 0, &checksum); 12436621Sbt150084 12446621Sbt150084 if (status == IXGBE_SUCCESS) { 12456621Sbt150084 checksum = ixgbe_calc_eeprom_checksum(hw); 12466621Sbt150084 12476621Sbt150084 hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); 12486621Sbt150084 12496621Sbt150084 /* 12506621Sbt150084 * Verify read checksum from EEPROM is the same as 12516621Sbt150084 * calculated checksum 12526621Sbt150084 */ 12536621Sbt150084 if (read_checksum != checksum) 12546621Sbt150084 status = IXGBE_ERR_EEPROM_CHECKSUM; 12556621Sbt150084 12566621Sbt150084 /* If the user cares, return the calculated checksum */ 12576621Sbt150084 if (checksum_val) 12586621Sbt150084 *checksum_val = checksum; 12596621Sbt150084 } else { 12606621Sbt150084 DEBUGOUT("EEPROM read failed\n"); 12616621Sbt150084 } 12626621Sbt150084 12636621Sbt150084 return (status); 12646621Sbt150084 } 12656621Sbt150084 12666621Sbt150084 /* 12676621Sbt150084 * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum 12686621Sbt150084 * @hw: pointer to hardware structure 12696621Sbt150084 */ 12706621Sbt150084 s32 12716621Sbt150084 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) 12726621Sbt150084 { 12736621Sbt150084 s32 status; 12746621Sbt150084 u16 checksum; 12756621Sbt150084 1276*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); 1277*10998SChenlu.Chen@Sun.COM 12786621Sbt150084 /* 12796621Sbt150084 * Read the first word from the EEPROM. If this times out or fails, do 12806621Sbt150084 * not continue or we could be in for a very long wait while every 12816621Sbt150084 * EEPROM read fails 12826621Sbt150084 */ 12836621Sbt150084 status = hw->eeprom.ops.read(hw, 0, &checksum); 12846621Sbt150084 12856621Sbt150084 if (status == IXGBE_SUCCESS) { 12866621Sbt150084 checksum = ixgbe_calc_eeprom_checksum(hw); 12876621Sbt150084 status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, 12886621Sbt150084 checksum); 12896621Sbt150084 } else { 12906621Sbt150084 DEBUGOUT("EEPROM read failed\n"); 12916621Sbt150084 } 12926621Sbt150084 12936621Sbt150084 return (status); 12946621Sbt150084 } 12956621Sbt150084 12966621Sbt150084 /* 12976621Sbt150084 * ixgbe_validate_mac_addr - Validate MAC address 12986621Sbt150084 * @mac_addr: pointer to MAC address. 12996621Sbt150084 * 13006621Sbt150084 * Tests a MAC address to ensure it is a valid Individual Address 13016621Sbt150084 */ 13026621Sbt150084 s32 13036621Sbt150084 ixgbe_validate_mac_addr(u8 *mac_addr) 13046621Sbt150084 { 13056621Sbt150084 s32 status = IXGBE_SUCCESS; 13066621Sbt150084 1307*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_validate_mac_addr"); 1308*10998SChenlu.Chen@Sun.COM 13096621Sbt150084 /* Make sure it is not a multicast address */ 13106621Sbt150084 if (IXGBE_IS_MULTICAST(mac_addr)) { 13116621Sbt150084 DEBUGOUT("MAC address is multicast\n"); 13126621Sbt150084 status = IXGBE_ERR_INVALID_MAC_ADDR; 13136621Sbt150084 /* Not a broadcast address */ 13146621Sbt150084 } else if (IXGBE_IS_BROADCAST(mac_addr)) { 13156621Sbt150084 DEBUGOUT("MAC address is broadcast\n"); 13166621Sbt150084 status = IXGBE_ERR_INVALID_MAC_ADDR; 13176621Sbt150084 /* Reject the zero address */ 13186621Sbt150084 } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && 13196621Sbt150084 mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { 13206621Sbt150084 DEBUGOUT("MAC address is all zeros\n"); 13216621Sbt150084 status = IXGBE_ERR_INVALID_MAC_ADDR; 13226621Sbt150084 } 13236621Sbt150084 return (status); 13246621Sbt150084 } 13256621Sbt150084 13266621Sbt150084 /* 13276621Sbt150084 * ixgbe_set_rar_generic - Set Rx address register 13286621Sbt150084 * @hw: pointer to hardware structure 13296621Sbt150084 * @index: Receive address register to write 13306621Sbt150084 * @addr: Address to put into receive address register 13316621Sbt150084 * @vmdq: VMDq "set" or "pool" index 13326621Sbt150084 * @enable_addr: set flag that address is active 13336621Sbt150084 * 13346621Sbt150084 * Puts an ethernet address into a receive address register. 13356621Sbt150084 */ 13366621Sbt150084 s32 13376621Sbt150084 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 13386621Sbt150084 u32 enable_addr) 13396621Sbt150084 { 13406621Sbt150084 u32 rar_low, rar_high; 13416621Sbt150084 u32 rar_entries = hw->mac.num_rar_entries; 13426621Sbt150084 1343*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_rar_generic"); 1344*10998SChenlu.Chen@Sun.COM 13456621Sbt150084 /* setup VMDq pool selection before this RAR gets enabled */ 13466621Sbt150084 hw->mac.ops.set_vmdq(hw, index, vmdq); 13476621Sbt150084 13486621Sbt150084 /* Make sure we are using a valid rar index range */ 13496621Sbt150084 if (index < rar_entries) { 13506621Sbt150084 /* 13516621Sbt150084 * HW expects these in little endian so we reverse the byte 13526621Sbt150084 * order from network order (big endian) to little endian 13536621Sbt150084 */ 13546621Sbt150084 rar_low = ((u32)addr[0] | 13556621Sbt150084 ((u32)addr[1] << 8) | 13566621Sbt150084 ((u32)addr[2] << 16) | 13576621Sbt150084 ((u32)addr[3] << 24)); 13586621Sbt150084 /* 13596621Sbt150084 * Some parts put the VMDq setting in the extra RAH bits, 13606621Sbt150084 * so save everything except the lower 16 bits that hold part 13616621Sbt150084 * of the address and the address valid bit. 13626621Sbt150084 */ 13636621Sbt150084 rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 13646621Sbt150084 rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 13656621Sbt150084 rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); 13666621Sbt150084 13676621Sbt150084 if (enable_addr != 0) 13686621Sbt150084 rar_high |= IXGBE_RAH_AV; 13696621Sbt150084 13706621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); 13716621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 13726621Sbt150084 } else { 13738490SPaul.Guo@Sun.COM DEBUGOUT1("RAR index %d is out of range.\n", index); 13746621Sbt150084 } 13756621Sbt150084 13766621Sbt150084 return (IXGBE_SUCCESS); 13776621Sbt150084 } 13786621Sbt150084 13796621Sbt150084 /* 13808490SPaul.Guo@Sun.COM * ixgbe_clear_rar_generic - Remove Rx address register 13818490SPaul.Guo@Sun.COM * @hw: pointer to hardware structure 13828490SPaul.Guo@Sun.COM * @index: Receive address register to write 13838490SPaul.Guo@Sun.COM * 13848490SPaul.Guo@Sun.COM * Clears an ethernet address from a receive address register. 13858490SPaul.Guo@Sun.COM */ 13868490SPaul.Guo@Sun.COM s32 13878490SPaul.Guo@Sun.COM ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) 13888490SPaul.Guo@Sun.COM { 13898490SPaul.Guo@Sun.COM u32 rar_high; 13908490SPaul.Guo@Sun.COM u32 rar_entries = hw->mac.num_rar_entries; 13918490SPaul.Guo@Sun.COM 1392*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_clear_rar_generic"); 1393*10998SChenlu.Chen@Sun.COM 13948490SPaul.Guo@Sun.COM /* Make sure we are using a valid rar index range */ 13958490SPaul.Guo@Sun.COM if (index < rar_entries) { 13968490SPaul.Guo@Sun.COM /* 13978490SPaul.Guo@Sun.COM * Some parts put the VMDq setting in the extra RAH bits, 13988490SPaul.Guo@Sun.COM * so save everything except the lower 16 bits that hold part 13998490SPaul.Guo@Sun.COM * of the address and the address valid bit. 14008490SPaul.Guo@Sun.COM */ 14018490SPaul.Guo@Sun.COM rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); 14028490SPaul.Guo@Sun.COM rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); 14038490SPaul.Guo@Sun.COM 14048490SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); 14058490SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); 14068490SPaul.Guo@Sun.COM } else { 14078490SPaul.Guo@Sun.COM DEBUGOUT1("RAR index %d is out of range.\n", index); 14088490SPaul.Guo@Sun.COM } 14098490SPaul.Guo@Sun.COM 14108490SPaul.Guo@Sun.COM /* clear VMDq pool/queue selection for this RAR */ 14118490SPaul.Guo@Sun.COM hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); 14128490SPaul.Guo@Sun.COM 14138490SPaul.Guo@Sun.COM return (IXGBE_SUCCESS); 14148490SPaul.Guo@Sun.COM } 14158490SPaul.Guo@Sun.COM 14168490SPaul.Guo@Sun.COM /* 14176621Sbt150084 * ixgbe_init_rx_addrs_generic - Initializes receive address filters. 14186621Sbt150084 * @hw: pointer to hardware structure 14196621Sbt150084 * 14206621Sbt150084 * Places the MAC address in receive address register 0 and clears the rest 14216621Sbt150084 * of the receive address registers. Clears the multicast table. Assumes 14226621Sbt150084 * the receiver is in reset when the routine is called. 14236621Sbt150084 */ 14246621Sbt150084 s32 14256621Sbt150084 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) 14266621Sbt150084 { 14276621Sbt150084 u32 i; 14286621Sbt150084 u32 rar_entries = hw->mac.num_rar_entries; 14296621Sbt150084 1430*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_init_rx_addrs_generic"); 1431*10998SChenlu.Chen@Sun.COM 14326621Sbt150084 /* 14336621Sbt150084 * If the current mac address is valid, assume it is a software override 14346621Sbt150084 * to the permanent address. 14356621Sbt150084 * Otherwise, use the permanent address from the eeprom. 14366621Sbt150084 */ 14376621Sbt150084 if (ixgbe_validate_mac_addr(hw->mac.addr) == 14386621Sbt150084 IXGBE_ERR_INVALID_MAC_ADDR) { 14396621Sbt150084 /* Get the MAC address from the RAR0 for later reference */ 14406621Sbt150084 hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 14416621Sbt150084 14426621Sbt150084 DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", 14436621Sbt150084 hw->mac.addr[0], hw->mac.addr[1], 14446621Sbt150084 hw->mac.addr[2]); 14456621Sbt150084 DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 14466621Sbt150084 hw->mac.addr[4], hw->mac.addr[5]); 14476621Sbt150084 } else { 14486621Sbt150084 /* Setup the receive address. */ 14496621Sbt150084 DEBUGOUT("Overriding MAC Address in RAR[0]\n"); 14506621Sbt150084 DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", 14516621Sbt150084 hw->mac.addr[0], hw->mac.addr[1], 14526621Sbt150084 hw->mac.addr[2]); 14536621Sbt150084 DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], 14546621Sbt150084 hw->mac.addr[4], hw->mac.addr[5]); 14556621Sbt150084 14566621Sbt150084 hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); 14576621Sbt150084 } 14586621Sbt150084 hw->addr_ctrl.overflow_promisc = 0; 14596621Sbt150084 14606621Sbt150084 hw->addr_ctrl.rar_used_count = 1; 14616621Sbt150084 14626621Sbt150084 /* Zero out the other receive addresses. */ 14636621Sbt150084 DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); 14646621Sbt150084 for (i = 1; i < rar_entries; i++) { 14656621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 14666621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 14676621Sbt150084 } 14686621Sbt150084 14696621Sbt150084 /* Clear the MTA */ 14706621Sbt150084 hw->addr_ctrl.mta_in_use = 0; 14716621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 14726621Sbt150084 14736621Sbt150084 DEBUGOUT(" Clearing MTA\n"); 14746621Sbt150084 for (i = 0; i < hw->mac.mcft_size; i++) 14756621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 14766621Sbt150084 14779353SSamuel.Tu@Sun.COM (void) ixgbe_init_uta_tables(hw); 14788490SPaul.Guo@Sun.COM 14796621Sbt150084 return (IXGBE_SUCCESS); 14806621Sbt150084 } 14816621Sbt150084 14829353SSamuel.Tu@Sun.COM 14836621Sbt150084 /* 14846621Sbt150084 * ixgbe_add_uc_addr - Adds a secondary unicast address. 14856621Sbt150084 * @hw: pointer to hardware structure 14866621Sbt150084 * @addr: new address 14876621Sbt150084 * 14886621Sbt150084 * Adds it to unused receive address register or goes into promiscuous mode. 14896621Sbt150084 */ 14906621Sbt150084 void 14916621Sbt150084 ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 14926621Sbt150084 { 14936621Sbt150084 u32 rar_entries = hw->mac.num_rar_entries; 14946621Sbt150084 u32 rar; 14956621Sbt150084 1496*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_add_uc_addr"); 1497*10998SChenlu.Chen@Sun.COM 14986621Sbt150084 DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", 14996621Sbt150084 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 15006621Sbt150084 15016621Sbt150084 /* 15026621Sbt150084 * Place this address in the RAR if there is room, 15036621Sbt150084 * else put the controller into promiscuous mode 15046621Sbt150084 */ 15056621Sbt150084 if (hw->addr_ctrl.rar_used_count < rar_entries) { 15069353SSamuel.Tu@Sun.COM rar = hw->addr_ctrl.rar_used_count; 15076621Sbt150084 hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 15086621Sbt150084 DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); 15096621Sbt150084 hw->addr_ctrl.rar_used_count++; 15106621Sbt150084 } else { 15116621Sbt150084 hw->addr_ctrl.overflow_promisc++; 15126621Sbt150084 } 15136621Sbt150084 15146621Sbt150084 DEBUGOUT("ixgbe_add_uc_addr Complete\n"); 15156621Sbt150084 } 15166621Sbt150084 15176621Sbt150084 /* 15186621Sbt150084 * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses 15196621Sbt150084 * @hw: pointer to hardware structure 15206621Sbt150084 * @addr_list: the list of new addresses 15216621Sbt150084 * @addr_count: number of addresses 15226621Sbt150084 * @next: iterator function to walk the address list 15236621Sbt150084 * 15246621Sbt150084 * The given list replaces any existing list. Clears the secondary addrs from 15256621Sbt150084 * receive address registers. Uses unused receive address registers for the 15266621Sbt150084 * first secondary addresses, and falls back to promiscuous mode as needed. 15276621Sbt150084 * 15286621Sbt150084 * Drivers using secondary unicast addresses must set user_set_promisc when 15296621Sbt150084 * manually putting the device into promiscuous mode. 15306621Sbt150084 */ 15316621Sbt150084 s32 15326621Sbt150084 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, 15336621Sbt150084 u32 addr_count, ixgbe_mc_addr_itr next) 15346621Sbt150084 { 15356621Sbt150084 u8 *addr; 15366621Sbt150084 u32 i; 15376621Sbt150084 u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; 15386621Sbt150084 u32 uc_addr_in_use; 15396621Sbt150084 u32 fctrl; 15406621Sbt150084 u32 vmdq; 15416621Sbt150084 1542*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); 1543*10998SChenlu.Chen@Sun.COM 15446621Sbt150084 /* 15456621Sbt150084 * Clear accounting of old secondary address list, 15466621Sbt150084 * don't count RAR[0] 15476621Sbt150084 */ 15489353SSamuel.Tu@Sun.COM uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; 15496621Sbt150084 hw->addr_ctrl.rar_used_count -= uc_addr_in_use; 15506621Sbt150084 hw->addr_ctrl.overflow_promisc = 0; 15516621Sbt150084 15526621Sbt150084 /* Zero out the other receive addresses */ 15539681SPaul.Guo@Sun.COM DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use); 15549681SPaul.Guo@Sun.COM for (i = 1; i <= uc_addr_in_use; i++) { 15556621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); 15566621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); 15576621Sbt150084 } 15586621Sbt150084 15596621Sbt150084 /* Add the new addresses */ 15606621Sbt150084 for (i = 0; i < addr_count; i++) { 15616621Sbt150084 DEBUGOUT(" Adding the secondary addresses:\n"); 15626621Sbt150084 addr = next(hw, &addr_list, &vmdq); 15636621Sbt150084 ixgbe_add_uc_addr(hw, addr, vmdq); 15646621Sbt150084 } 15656621Sbt150084 15666621Sbt150084 if (hw->addr_ctrl.overflow_promisc) { 15676621Sbt150084 /* enable promisc if not already in overflow or set by user */ 15686621Sbt150084 if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 15696621Sbt150084 DEBUGOUT(" Entering address overflow promisc mode\n"); 15706621Sbt150084 fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 15716621Sbt150084 fctrl |= IXGBE_FCTRL_UPE; 15726621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 15736621Sbt150084 } 15746621Sbt150084 } else { 15756621Sbt150084 /* only disable if set by overflow, not by user */ 15766621Sbt150084 if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { 15776621Sbt150084 DEBUGOUT(" Leaving address overflow promisc mode\n"); 15786621Sbt150084 fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); 15796621Sbt150084 fctrl &= ~IXGBE_FCTRL_UPE; 15806621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); 15816621Sbt150084 } 15826621Sbt150084 } 15836621Sbt150084 15846621Sbt150084 DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); 15856621Sbt150084 return (IXGBE_SUCCESS); 15866621Sbt150084 } 15876621Sbt150084 15886621Sbt150084 /* 15896621Sbt150084 * ixgbe_mta_vector - Determines bit-vector in multicast table to set 15906621Sbt150084 * @hw: pointer to hardware structure 15916621Sbt150084 * @mc_addr: the multicast address 15926621Sbt150084 * 15936621Sbt150084 * Extracts the 12 bits, from a multicast address, to determine which 15946621Sbt150084 * bit-vector to set in the multicast table. The hardware uses 12 bits, from 15956621Sbt150084 * incoming rx multicast addresses, to determine the bit-vector to check in 15966621Sbt150084 * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set 15976621Sbt150084 * by the MO field of the MCSTCTRL. The MO field is set during initialization 15986621Sbt150084 * to mc_filter_type. 15996621Sbt150084 */ 16006621Sbt150084 static s32 16016621Sbt150084 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) 16026621Sbt150084 { 16036621Sbt150084 u32 vector = 0; 16046621Sbt150084 1605*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_mta_vector"); 1606*10998SChenlu.Chen@Sun.COM 16076621Sbt150084 switch (hw->mac.mc_filter_type) { 16086621Sbt150084 case 0: /* use bits [47:36] of the address */ 16096621Sbt150084 vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 16106621Sbt150084 break; 16116621Sbt150084 case 1: /* use bits [46:35] of the address */ 16126621Sbt150084 vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 16136621Sbt150084 break; 16146621Sbt150084 case 2: /* use bits [45:34] of the address */ 16156621Sbt150084 vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 16166621Sbt150084 break; 16176621Sbt150084 case 3: /* use bits [43:32] of the address */ 16186621Sbt150084 vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 16196621Sbt150084 break; 16206621Sbt150084 default: /* Invalid mc_filter_type */ 16216621Sbt150084 DEBUGOUT("MC filter type param set incorrectly\n"); 16226621Sbt150084 ASSERT(0); 16236621Sbt150084 break; 16246621Sbt150084 } 16256621Sbt150084 16266621Sbt150084 /* vector can only be 12-bits or boundary will be exceeded */ 16276621Sbt150084 vector &= 0xFFF; 16286621Sbt150084 return (vector); 16296621Sbt150084 } 16306621Sbt150084 16316621Sbt150084 /* 16326621Sbt150084 * ixgbe_set_mta - Set bit-vector in multicast table 16336621Sbt150084 * @hw: pointer to hardware structure 16346621Sbt150084 * @hash_value: Multicast address hash value 16356621Sbt150084 * 16366621Sbt150084 * Sets the bit-vector in the multicast table. 16376621Sbt150084 */ 16386621Sbt150084 void 16396621Sbt150084 ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) 16406621Sbt150084 { 16416621Sbt150084 u32 vector; 16426621Sbt150084 u32 vector_bit; 16436621Sbt150084 u32 vector_reg; 16446621Sbt150084 u32 mta_reg; 16456621Sbt150084 1646*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_mta"); 1647*10998SChenlu.Chen@Sun.COM 16486621Sbt150084 hw->addr_ctrl.mta_in_use++; 16496621Sbt150084 16506621Sbt150084 vector = ixgbe_mta_vector(hw, mc_addr); 16516621Sbt150084 DEBUGOUT1(" bit-vector = 0x%03X\n", vector); 16526621Sbt150084 16536621Sbt150084 /* 16546621Sbt150084 * The MTA is a register array of 128 32-bit registers. It is treated 16556621Sbt150084 * like an array of 4096 bits. We want to set bit 16566621Sbt150084 * BitArray[vector_value]. So we figure out what register the bit is 16576621Sbt150084 * in, read it, OR in the new bit, then write back the new value. The 16586621Sbt150084 * register is determined by the upper 7 bits of the vector value and 16596621Sbt150084 * the bit within that register are determined by the lower 5 bits of 16606621Sbt150084 * the value. 16616621Sbt150084 */ 16626621Sbt150084 vector_reg = (vector >> 5) & 0x7F; 16636621Sbt150084 vector_bit = vector & 0x1F; 16646621Sbt150084 mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); 16656621Sbt150084 mta_reg |= (1 << vector_bit); 16666621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); 16676621Sbt150084 } 16686621Sbt150084 16696621Sbt150084 /* 16706621Sbt150084 * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses 16716621Sbt150084 * @hw: pointer to hardware structure 16726621Sbt150084 * @mc_addr_list: the list of new multicast addresses 16736621Sbt150084 * @mc_addr_count: number of addresses 16746621Sbt150084 * @next: iterator function to walk the multicast address list 16756621Sbt150084 * 16766621Sbt150084 * The given list replaces any existing list. Clears the MC addrs from receive 16776621Sbt150084 * address registers and the multicast table. Uses unused receive address 16786621Sbt150084 * registers for the first multicast addresses, and hashes the rest into the 16796621Sbt150084 * multicast table. 16806621Sbt150084 */ 16816621Sbt150084 s32 16826621Sbt150084 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, 16836621Sbt150084 u32 mc_addr_count, ixgbe_mc_addr_itr next) 16846621Sbt150084 { 16856621Sbt150084 u32 i; 16866621Sbt150084 u32 vmdq; 16876621Sbt150084 1688*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); 1689*10998SChenlu.Chen@Sun.COM 16906621Sbt150084 /* 16916621Sbt150084 * Set the new number of MC addresses that we are being requested to 16926621Sbt150084 * use. 16936621Sbt150084 */ 16946621Sbt150084 hw->addr_ctrl.num_mc_addrs = mc_addr_count; 16956621Sbt150084 hw->addr_ctrl.mta_in_use = 0; 16966621Sbt150084 16976621Sbt150084 /* Clear the MTA */ 16986621Sbt150084 DEBUGOUT(" Clearing MTA\n"); 16996621Sbt150084 for (i = 0; i < hw->mac.mcft_size; i++) 17006621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); 17016621Sbt150084 17026621Sbt150084 /* Add the new addresses */ 17036621Sbt150084 for (i = 0; i < mc_addr_count; i++) { 17046621Sbt150084 DEBUGOUT(" Adding the multicast addresses:\n"); 17059353SSamuel.Tu@Sun.COM ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); 17066621Sbt150084 } 17076621Sbt150084 17086621Sbt150084 /* Enable mta */ 17096621Sbt150084 if (hw->addr_ctrl.mta_in_use > 0) 17106621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, 17116621Sbt150084 IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); 17126621Sbt150084 17136621Sbt150084 DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); 17146621Sbt150084 return (IXGBE_SUCCESS); 17156621Sbt150084 } 17166621Sbt150084 17176621Sbt150084 /* 17186621Sbt150084 * ixgbe_enable_mc_generic - Enable multicast address in RAR 17196621Sbt150084 * @hw: pointer to hardware structure 17206621Sbt150084 * 17216621Sbt150084 * Enables multicast address in RAR and the use of the multicast hash table. 17226621Sbt150084 */ 17236621Sbt150084 s32 17246621Sbt150084 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) 17256621Sbt150084 { 17266621Sbt150084 struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 17276621Sbt150084 1728*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_enable_mc_generic"); 1729*10998SChenlu.Chen@Sun.COM 17306621Sbt150084 if (a->mta_in_use > 0) 17316621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | 17326621Sbt150084 hw->mac.mc_filter_type); 17336621Sbt150084 17346621Sbt150084 return (IXGBE_SUCCESS); 17356621Sbt150084 } 17366621Sbt150084 17376621Sbt150084 /* 17386621Sbt150084 * ixgbe_disable_mc_generic - Disable multicast address in RAR 17396621Sbt150084 * @hw: pointer to hardware structure 17406621Sbt150084 * 17416621Sbt150084 * Disables multicast address in RAR and the use of the multicast hash table. 17426621Sbt150084 */ 17436621Sbt150084 s32 17446621Sbt150084 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) 17456621Sbt150084 { 17466621Sbt150084 struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; 17476621Sbt150084 1748*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_disable_mc_generic"); 1749*10998SChenlu.Chen@Sun.COM 17506621Sbt150084 if (a->mta_in_use > 0) 17516621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); 17526621Sbt150084 17536621Sbt150084 return (IXGBE_SUCCESS); 17546621Sbt150084 } 17556621Sbt150084 17566621Sbt150084 /* 17579353SSamuel.Tu@Sun.COM * ixgbe_fc_enable_generic - Enable flow control 17589353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 17599353SSamuel.Tu@Sun.COM * @packetbuf_num: packet buffer number (0-7) 17609353SSamuel.Tu@Sun.COM * 17619353SSamuel.Tu@Sun.COM * Enable flow control according to the current settings. 17629353SSamuel.Tu@Sun.COM */ 17639353SSamuel.Tu@Sun.COM s32 17649353SSamuel.Tu@Sun.COM ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num) 17659353SSamuel.Tu@Sun.COM { 17669353SSamuel.Tu@Sun.COM s32 ret_val = IXGBE_SUCCESS; 17679353SSamuel.Tu@Sun.COM u32 mflcn_reg, fccfg_reg; 17689353SSamuel.Tu@Sun.COM u32 reg; 176910305SPaul.Guo@Sun.COM u32 rx_pba_size; 17709353SSamuel.Tu@Sun.COM 17719353SSamuel.Tu@Sun.COM DEBUGFUNC("ixgbe_fc_enable_generic"); 17729353SSamuel.Tu@Sun.COM 17739353SSamuel.Tu@Sun.COM /* Negotiate the fc mode to use */ 17749353SSamuel.Tu@Sun.COM ret_val = ixgbe_fc_autoneg(hw); 17759353SSamuel.Tu@Sun.COM if (ret_val) 17769353SSamuel.Tu@Sun.COM goto out; 17779353SSamuel.Tu@Sun.COM 17789353SSamuel.Tu@Sun.COM /* Disable any previous flow control settings */ 17799353SSamuel.Tu@Sun.COM mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); 17809353SSamuel.Tu@Sun.COM mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE); 17819353SSamuel.Tu@Sun.COM 17829353SSamuel.Tu@Sun.COM fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); 17839353SSamuel.Tu@Sun.COM fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); 17849353SSamuel.Tu@Sun.COM 17859353SSamuel.Tu@Sun.COM /* 17869353SSamuel.Tu@Sun.COM * The possible values of fc.current_mode are: 17879353SSamuel.Tu@Sun.COM * 0: Flow control is completely disabled 17889353SSamuel.Tu@Sun.COM * 1: Rx flow control is enabled (we can receive pause frames, 17899353SSamuel.Tu@Sun.COM * but not send pause frames). 17909353SSamuel.Tu@Sun.COM * 2: Tx flow control is enabled (we can send pause frames but 17919353SSamuel.Tu@Sun.COM * we do not support receiving pause frames). 17929353SSamuel.Tu@Sun.COM * 3: Both Rx and Tx flow control (symmetric) are enabled. 17939353SSamuel.Tu@Sun.COM * other: Invalid. 17949353SSamuel.Tu@Sun.COM */ 17959353SSamuel.Tu@Sun.COM switch (hw->fc.current_mode) { 17969353SSamuel.Tu@Sun.COM case ixgbe_fc_none: 17979353SSamuel.Tu@Sun.COM /* 17989353SSamuel.Tu@Sun.COM * Flow control is disabled by software override or autoneg. 17999353SSamuel.Tu@Sun.COM * The code below will actually disable it in the HW. 18009353SSamuel.Tu@Sun.COM */ 18019353SSamuel.Tu@Sun.COM break; 18029353SSamuel.Tu@Sun.COM case ixgbe_fc_rx_pause: 18039353SSamuel.Tu@Sun.COM /* 18049353SSamuel.Tu@Sun.COM * Rx Flow control is enabled and Tx Flow control is 18059353SSamuel.Tu@Sun.COM * disabled by software override. Since there really 18069353SSamuel.Tu@Sun.COM * isn't a way to advertise that we are capable of RX 18079353SSamuel.Tu@Sun.COM * Pause ONLY, we will advertise that we support both 18089353SSamuel.Tu@Sun.COM * symmetric and asymmetric Rx PAUSE. Later, we will 18099353SSamuel.Tu@Sun.COM * disable the adapter's ability to send PAUSE frames. 18109353SSamuel.Tu@Sun.COM */ 18119353SSamuel.Tu@Sun.COM mflcn_reg |= IXGBE_MFLCN_RFCE; 18129353SSamuel.Tu@Sun.COM break; 18139353SSamuel.Tu@Sun.COM case ixgbe_fc_tx_pause: 18149353SSamuel.Tu@Sun.COM /* 18159353SSamuel.Tu@Sun.COM * Tx Flow control is enabled, and Rx Flow control is 18169353SSamuel.Tu@Sun.COM * disabled by software override. 18179353SSamuel.Tu@Sun.COM */ 18189353SSamuel.Tu@Sun.COM fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 18199353SSamuel.Tu@Sun.COM break; 18209353SSamuel.Tu@Sun.COM case ixgbe_fc_full: 18219353SSamuel.Tu@Sun.COM /* Flow control (both Rx and Tx) is enabled by SW override. */ 18229353SSamuel.Tu@Sun.COM mflcn_reg |= IXGBE_MFLCN_RFCE; 18239353SSamuel.Tu@Sun.COM fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; 18249353SSamuel.Tu@Sun.COM break; 18259353SSamuel.Tu@Sun.COM default: 18269353SSamuel.Tu@Sun.COM DEBUGOUT("Flow control param set incorrectly\n"); 1827*10998SChenlu.Chen@Sun.COM ret_val = IXGBE_ERR_CONFIG; 18289353SSamuel.Tu@Sun.COM goto out; 18299353SSamuel.Tu@Sun.COM } 18309353SSamuel.Tu@Sun.COM 18319353SSamuel.Tu@Sun.COM /* Set 802.3x based flow control settings. */ 18329353SSamuel.Tu@Sun.COM mflcn_reg |= IXGBE_MFLCN_DPF; 18339353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); 18349353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); 18359353SSamuel.Tu@Sun.COM 183610305SPaul.Guo@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_MTQC); 183710305SPaul.Guo@Sun.COM /* Thresholds are different for link flow control when in DCB mode */ 183810305SPaul.Guo@Sun.COM if (reg & IXGBE_MTQC_RT_ENA) { 183910305SPaul.Guo@Sun.COM rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num)); 184010305SPaul.Guo@Sun.COM 184110305SPaul.Guo@Sun.COM /* Always disable XON for LFC when in DCB mode */ 184210305SPaul.Guo@Sun.COM reg = (rx_pba_size >> 5) & 0xFFE0; 184310305SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), reg); 184410305SPaul.Guo@Sun.COM 184510305SPaul.Guo@Sun.COM reg = (rx_pba_size >> 2) & 0xFFE0; 184610305SPaul.Guo@Sun.COM if (hw->fc.current_mode & ixgbe_fc_tx_pause) 184710305SPaul.Guo@Sun.COM reg |= IXGBE_FCRTH_FCEN; 184810305SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), reg); 184910305SPaul.Guo@Sun.COM } else { 185010305SPaul.Guo@Sun.COM /* 185110305SPaul.Guo@Sun.COM * Set up and enable Rx high/low water mark thresholds, 185210305SPaul.Guo@Sun.COM * enable XON. 185310305SPaul.Guo@Sun.COM */ 185410305SPaul.Guo@Sun.COM if (hw->fc.current_mode & ixgbe_fc_tx_pause) { 185510305SPaul.Guo@Sun.COM if (hw->fc.send_xon) { 185610305SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, 185710305SPaul.Guo@Sun.COM IXGBE_FCRTL_82599(packetbuf_num), 185810305SPaul.Guo@Sun.COM (hw->fc.low_water | IXGBE_FCRTL_XONE)); 185910305SPaul.Guo@Sun.COM } else { 186010305SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, 186110305SPaul.Guo@Sun.COM IXGBE_FCRTL_82599(packetbuf_num), 186210305SPaul.Guo@Sun.COM hw->fc.low_water); 186310305SPaul.Guo@Sun.COM } 186410305SPaul.Guo@Sun.COM 186510305SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), 186610305SPaul.Guo@Sun.COM (hw->fc.high_water | IXGBE_FCRTH_FCEN)); 18679353SSamuel.Tu@Sun.COM } 18689353SSamuel.Tu@Sun.COM } 18699353SSamuel.Tu@Sun.COM 18709353SSamuel.Tu@Sun.COM /* Configure pause time (2 TCs per register) */ 187110305SPaul.Guo@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2)); 18729353SSamuel.Tu@Sun.COM if ((packetbuf_num & 1) == 0) 18739353SSamuel.Tu@Sun.COM reg = (reg & 0xFFFF0000) | hw->fc.pause_time; 18749353SSamuel.Tu@Sun.COM else 18759353SSamuel.Tu@Sun.COM reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16); 18769353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg); 18779353SSamuel.Tu@Sun.COM 18789353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1)); 18799353SSamuel.Tu@Sun.COM 18809353SSamuel.Tu@Sun.COM out: 18819353SSamuel.Tu@Sun.COM return (ret_val); 18829353SSamuel.Tu@Sun.COM } 18839353SSamuel.Tu@Sun.COM 18849353SSamuel.Tu@Sun.COM /* 18859353SSamuel.Tu@Sun.COM * ixgbe_fc_autoneg - Configure flow control 18869353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 18879353SSamuel.Tu@Sun.COM * 18889353SSamuel.Tu@Sun.COM * Compares our advertised flow control capabilities to those advertised by 18899353SSamuel.Tu@Sun.COM * our link partner, and determines the proper flow control mode to use. 18909353SSamuel.Tu@Sun.COM */ 18919353SSamuel.Tu@Sun.COM s32 18929353SSamuel.Tu@Sun.COM ixgbe_fc_autoneg(struct ixgbe_hw *hw) 18939353SSamuel.Tu@Sun.COM { 18949353SSamuel.Tu@Sun.COM s32 ret_val = IXGBE_SUCCESS; 18959353SSamuel.Tu@Sun.COM ixgbe_link_speed speed; 18969353SSamuel.Tu@Sun.COM u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; 1897*10998SChenlu.Chen@Sun.COM u32 links2, anlp1_reg, autoc_reg, links; 18989353SSamuel.Tu@Sun.COM bool link_up; 18999353SSamuel.Tu@Sun.COM 19009353SSamuel.Tu@Sun.COM DEBUGFUNC("ixgbe_fc_autoneg"); 19019353SSamuel.Tu@Sun.COM 19029353SSamuel.Tu@Sun.COM /* 19039353SSamuel.Tu@Sun.COM * AN should have completed when the cable was plugged in. 19049353SSamuel.Tu@Sun.COM * Look for reasons to bail out. Bail out if: 19059353SSamuel.Tu@Sun.COM * - FC autoneg is disabled, or if 1906*10998SChenlu.Chen@Sun.COM * - link is not up. 19079353SSamuel.Tu@Sun.COM * 1908*10998SChenlu.Chen@Sun.COM * Since we're being called from an LSC, link is already known to be up. 19099353SSamuel.Tu@Sun.COM * So use link_up_wait_to_complete=false. 19109353SSamuel.Tu@Sun.COM */ 19119353SSamuel.Tu@Sun.COM hw->mac.ops.check_link(hw, &speed, &link_up, false); 1912*10998SChenlu.Chen@Sun.COM 1913*10998SChenlu.Chen@Sun.COM if (hw->fc.disable_fc_autoneg || (!link_up)) { 19149353SSamuel.Tu@Sun.COM hw->fc.fc_was_autonegged = false; 19159353SSamuel.Tu@Sun.COM hw->fc.current_mode = hw->fc.requested_mode; 1916*10998SChenlu.Chen@Sun.COM goto out; 1917*10998SChenlu.Chen@Sun.COM } 1918*10998SChenlu.Chen@Sun.COM 1919*10998SChenlu.Chen@Sun.COM /* 1920*10998SChenlu.Chen@Sun.COM * On backplane, bail out if 1921*10998SChenlu.Chen@Sun.COM * - backplane autoneg was not completed, or if 1922*10998SChenlu.Chen@Sun.COM * - link partner is not AN enabled 1923*10998SChenlu.Chen@Sun.COM */ 1924*10998SChenlu.Chen@Sun.COM if (hw->phy.media_type == ixgbe_media_type_backplane) { 1925*10998SChenlu.Chen@Sun.COM links = IXGBE_READ_REG(hw, IXGBE_LINKS); 1926*10998SChenlu.Chen@Sun.COM links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); 1927*10998SChenlu.Chen@Sun.COM if (((links & IXGBE_LINKS_KX_AN_COMP) == 0) || 1928*10998SChenlu.Chen@Sun.COM ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)) { 1929*10998SChenlu.Chen@Sun.COM hw->fc.fc_was_autonegged = false; 1930*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = hw->fc.requested_mode; 1931*10998SChenlu.Chen@Sun.COM goto out; 1932*10998SChenlu.Chen@Sun.COM } 1933*10998SChenlu.Chen@Sun.COM } 1934*10998SChenlu.Chen@Sun.COM 1935*10998SChenlu.Chen@Sun.COM /* 1936*10998SChenlu.Chen@Sun.COM * On multispeed fiber at 1g, bail out if 1937*10998SChenlu.Chen@Sun.COM * - link is up but AN did not complete, or if 1938*10998SChenlu.Chen@Sun.COM * - link is up and AN completed but timed out 1939*10998SChenlu.Chen@Sun.COM */ 1940*10998SChenlu.Chen@Sun.COM if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) { 1941*10998SChenlu.Chen@Sun.COM linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); 1942*10998SChenlu.Chen@Sun.COM if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || 1943*10998SChenlu.Chen@Sun.COM ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { 1944*10998SChenlu.Chen@Sun.COM hw->fc.fc_was_autonegged = false; 1945*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = hw->fc.requested_mode; 1946*10998SChenlu.Chen@Sun.COM goto out; 1947*10998SChenlu.Chen@Sun.COM } 1948*10998SChenlu.Chen@Sun.COM } 1949*10998SChenlu.Chen@Sun.COM 1950*10998SChenlu.Chen@Sun.COM /* 1951*10998SChenlu.Chen@Sun.COM * Bail out on 1952*10998SChenlu.Chen@Sun.COM * - copper or CX4 adapters 1953*10998SChenlu.Chen@Sun.COM * - fiber adapters running at 10gig 1954*10998SChenlu.Chen@Sun.COM */ 1955*10998SChenlu.Chen@Sun.COM if ((hw->phy.media_type == ixgbe_media_type_copper) || 1956*10998SChenlu.Chen@Sun.COM (hw->phy.media_type == ixgbe_media_type_cx4) || 1957*10998SChenlu.Chen@Sun.COM ((hw->phy.media_type == ixgbe_media_type_fiber) && 1958*10998SChenlu.Chen@Sun.COM (speed == IXGBE_LINK_SPEED_10GB_FULL))) { 1959*10998SChenlu.Chen@Sun.COM hw->fc.fc_was_autonegged = false; 1960*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = hw->fc.requested_mode; 19619353SSamuel.Tu@Sun.COM goto out; 19629353SSamuel.Tu@Sun.COM } 19639353SSamuel.Tu@Sun.COM 19649353SSamuel.Tu@Sun.COM /* 19659353SSamuel.Tu@Sun.COM * Read the AN advertisement and LP ability registers and resolve 19669353SSamuel.Tu@Sun.COM * local flow control settings accordingly 19679353SSamuel.Tu@Sun.COM */ 1968*10998SChenlu.Chen@Sun.COM if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && 1969*10998SChenlu.Chen@Sun.COM (hw->phy.media_type != ixgbe_media_type_backplane)) { 1970*10998SChenlu.Chen@Sun.COM pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 1971*10998SChenlu.Chen@Sun.COM pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); 1972*10998SChenlu.Chen@Sun.COM if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 1973*10998SChenlu.Chen@Sun.COM (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { 1974*10998SChenlu.Chen@Sun.COM /* 1975*10998SChenlu.Chen@Sun.COM * Now we need to check if the user selected Rx ONLY 1976*10998SChenlu.Chen@Sun.COM * of pause frames. In this case, we had to advertise 1977*10998SChenlu.Chen@Sun.COM * FULL flow control because we could not advertise RX 1978*10998SChenlu.Chen@Sun.COM * ONLY. Hence, we must now check to see if we need to 1979*10998SChenlu.Chen@Sun.COM * turn OFF the TRANSMISSION of PAUSE frames. 1980*10998SChenlu.Chen@Sun.COM */ 1981*10998SChenlu.Chen@Sun.COM if (hw->fc.requested_mode == ixgbe_fc_full) { 1982*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_full; 1983*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = FULL.\n"); 1984*10998SChenlu.Chen@Sun.COM } else { 1985*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_rx_pause; 1986*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 1987*10998SChenlu.Chen@Sun.COM } 1988*10998SChenlu.Chen@Sun.COM } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 1989*10998SChenlu.Chen@Sun.COM (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && 1990*10998SChenlu.Chen@Sun.COM (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 1991*10998SChenlu.Chen@Sun.COM (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { 1992*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_tx_pause; 1993*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 1994*10998SChenlu.Chen@Sun.COM } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 1995*10998SChenlu.Chen@Sun.COM (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && 1996*10998SChenlu.Chen@Sun.COM !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && 1997*10998SChenlu.Chen@Sun.COM (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { 19989353SSamuel.Tu@Sun.COM hw->fc.current_mode = ixgbe_fc_rx_pause; 19999353SSamuel.Tu@Sun.COM DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 2000*10998SChenlu.Chen@Sun.COM } else { 2001*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_none; 2002*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = NONE.\n"); 20039353SSamuel.Tu@Sun.COM } 20049353SSamuel.Tu@Sun.COM } 20059353SSamuel.Tu@Sun.COM 2006*10998SChenlu.Chen@Sun.COM if (hw->phy.media_type == ixgbe_media_type_backplane) { 2007*10998SChenlu.Chen@Sun.COM /* 2008*10998SChenlu.Chen@Sun.COM * Read the 10g AN autoc and LP ability registers and resolve 2009*10998SChenlu.Chen@Sun.COM * local flow control settings accordingly 2010*10998SChenlu.Chen@Sun.COM */ 2011*10998SChenlu.Chen@Sun.COM autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 2012*10998SChenlu.Chen@Sun.COM anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); 2013*10998SChenlu.Chen@Sun.COM 2014*10998SChenlu.Chen@Sun.COM if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && 2015*10998SChenlu.Chen@Sun.COM (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) { 2016*10998SChenlu.Chen@Sun.COM /* 2017*10998SChenlu.Chen@Sun.COM * Now we need to check if the user selected Rx ONLY 2018*10998SChenlu.Chen@Sun.COM * of pause frames. In this case, we had to advertise 2019*10998SChenlu.Chen@Sun.COM * FULL flow control because we could not advertise RX 2020*10998SChenlu.Chen@Sun.COM * ONLY. Hence, we must now check to see if we need to 2021*10998SChenlu.Chen@Sun.COM * turn OFF the TRANSMISSION of PAUSE frames. 2022*10998SChenlu.Chen@Sun.COM */ 2023*10998SChenlu.Chen@Sun.COM if (hw->fc.requested_mode == ixgbe_fc_full) { 2024*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_full; 2025*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = FULL.\n"); 2026*10998SChenlu.Chen@Sun.COM } else { 2027*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_rx_pause; 2028*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control=RX PAUSE frames only\n"); 2029*10998SChenlu.Chen@Sun.COM } 2030*10998SChenlu.Chen@Sun.COM } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && 2031*10998SChenlu.Chen@Sun.COM (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && 2032*10998SChenlu.Chen@Sun.COM (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && 2033*10998SChenlu.Chen@Sun.COM (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { 2034*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_tx_pause; 2035*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); 2036*10998SChenlu.Chen@Sun.COM } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && 2037*10998SChenlu.Chen@Sun.COM (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && 2038*10998SChenlu.Chen@Sun.COM !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && 2039*10998SChenlu.Chen@Sun.COM (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { 2040*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_rx_pause; 2041*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); 2042*10998SChenlu.Chen@Sun.COM } else { 2043*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_none; 2044*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow Control = NONE.\n"); 2045*10998SChenlu.Chen@Sun.COM } 2046*10998SChenlu.Chen@Sun.COM } 20479353SSamuel.Tu@Sun.COM /* Record that current_mode is the result of a successful autoneg */ 20489353SSamuel.Tu@Sun.COM hw->fc.fc_was_autonegged = true; 20499353SSamuel.Tu@Sun.COM 20509353SSamuel.Tu@Sun.COM out: 20519353SSamuel.Tu@Sun.COM return (ret_val); 20529353SSamuel.Tu@Sun.COM } 20539353SSamuel.Tu@Sun.COM 20549353SSamuel.Tu@Sun.COM /* 20559353SSamuel.Tu@Sun.COM * ixgbe_setup_fc - Set up flow control 20569353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 20579353SSamuel.Tu@Sun.COM * 20589353SSamuel.Tu@Sun.COM * Called at init time to set up flow control. 20599353SSamuel.Tu@Sun.COM */ 20609353SSamuel.Tu@Sun.COM s32 20619353SSamuel.Tu@Sun.COM ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num) 20629353SSamuel.Tu@Sun.COM { 20639353SSamuel.Tu@Sun.COM s32 ret_val = IXGBE_SUCCESS; 20649353SSamuel.Tu@Sun.COM u32 reg; 20659353SSamuel.Tu@Sun.COM 2066*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_setup_fc"); 2067*10998SChenlu.Chen@Sun.COM 20689353SSamuel.Tu@Sun.COM /* Validate the packetbuf configuration */ 20699353SSamuel.Tu@Sun.COM if (packetbuf_num < 0 || packetbuf_num > 7) { 20709353SSamuel.Tu@Sun.COM DEBUGOUT1("Invalid packet buffer number [%d], expected range is" 20719353SSamuel.Tu@Sun.COM " 0-7\n", packetbuf_num); 20729353SSamuel.Tu@Sun.COM ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 20739353SSamuel.Tu@Sun.COM goto out; 20749353SSamuel.Tu@Sun.COM } 20759353SSamuel.Tu@Sun.COM 20769353SSamuel.Tu@Sun.COM /* 20779353SSamuel.Tu@Sun.COM * Validate the water mark configuration. Zero water marks are invalid 20789353SSamuel.Tu@Sun.COM * because it causes the controller to just blast out fc packets. 20799353SSamuel.Tu@Sun.COM */ 20809353SSamuel.Tu@Sun.COM if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) { 20819353SSamuel.Tu@Sun.COM DEBUGOUT("Invalid water mark configuration\n"); 20829353SSamuel.Tu@Sun.COM ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 20839353SSamuel.Tu@Sun.COM goto out; 20849353SSamuel.Tu@Sun.COM } 20859353SSamuel.Tu@Sun.COM 20869353SSamuel.Tu@Sun.COM /* 20879353SSamuel.Tu@Sun.COM * Validate the requested mode. Strict IEEE mode does not allow 20889353SSamuel.Tu@Sun.COM * ixgbe_fc_rx_pause because it will cause us to fail at UNH. 20899353SSamuel.Tu@Sun.COM */ 20909353SSamuel.Tu@Sun.COM if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { 20919353SSamuel.Tu@Sun.COM DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); 20929353SSamuel.Tu@Sun.COM ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; 20939353SSamuel.Tu@Sun.COM goto out; 20949353SSamuel.Tu@Sun.COM } 20959353SSamuel.Tu@Sun.COM 20969353SSamuel.Tu@Sun.COM /* 20979353SSamuel.Tu@Sun.COM * 10gig parts do not have a word in the EEPROM to determine the 20989353SSamuel.Tu@Sun.COM * default flow control setting, so we explicitly set it to full. 20999353SSamuel.Tu@Sun.COM */ 21009353SSamuel.Tu@Sun.COM if (hw->fc.requested_mode == ixgbe_fc_default) 21019353SSamuel.Tu@Sun.COM hw->fc.requested_mode = ixgbe_fc_full; 21029353SSamuel.Tu@Sun.COM 21039353SSamuel.Tu@Sun.COM /* 21049353SSamuel.Tu@Sun.COM * Set up the 1G flow control advertisement registers so the HW will be 21059353SSamuel.Tu@Sun.COM * able to do fc autoneg once the cable is plugged in. If we end up 21069353SSamuel.Tu@Sun.COM * using 10g instead, this is harmless. 21079353SSamuel.Tu@Sun.COM */ 21089353SSamuel.Tu@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); 21099353SSamuel.Tu@Sun.COM 21109353SSamuel.Tu@Sun.COM /* 21119353SSamuel.Tu@Sun.COM * The possible values of fc.requested_mode are: 21129353SSamuel.Tu@Sun.COM * 0: Flow control is completely disabled 21139353SSamuel.Tu@Sun.COM * 1: Rx flow control is enabled (we can receive pause frames, 21149353SSamuel.Tu@Sun.COM * but not send pause frames). 21159353SSamuel.Tu@Sun.COM * 2: Tx flow control is enabled (we can send pause frames but 21169353SSamuel.Tu@Sun.COM * we do not support receiving pause frames). 21179353SSamuel.Tu@Sun.COM * 3: Both Rx and Tx flow control (symmetric) are enabled. 21189353SSamuel.Tu@Sun.COM * other: Invalid. 21199353SSamuel.Tu@Sun.COM */ 21209353SSamuel.Tu@Sun.COM switch (hw->fc.requested_mode) { 21219353SSamuel.Tu@Sun.COM case ixgbe_fc_none: 21229353SSamuel.Tu@Sun.COM /* Flow control completely disabled by software override. */ 21239353SSamuel.Tu@Sun.COM reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 21249353SSamuel.Tu@Sun.COM break; 21259353SSamuel.Tu@Sun.COM case ixgbe_fc_rx_pause: 21269353SSamuel.Tu@Sun.COM /* 21279353SSamuel.Tu@Sun.COM * Rx Flow control is enabled and Tx Flow control is 21289353SSamuel.Tu@Sun.COM * disabled by software override. Since there really 21299353SSamuel.Tu@Sun.COM * isn't a way to advertise that we are capable of RX 21309353SSamuel.Tu@Sun.COM * Pause ONLY, we will advertise that we support both 21319353SSamuel.Tu@Sun.COM * symmetric and asymmetric Rx PAUSE. Later, we will 21329353SSamuel.Tu@Sun.COM * disable the adapter's ability to send PAUSE frames. 21339353SSamuel.Tu@Sun.COM */ 21349353SSamuel.Tu@Sun.COM reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 21359353SSamuel.Tu@Sun.COM break; 21369353SSamuel.Tu@Sun.COM case ixgbe_fc_tx_pause: 21379353SSamuel.Tu@Sun.COM /* 21389353SSamuel.Tu@Sun.COM * Tx Flow control is enabled, and Rx Flow control is 21399353SSamuel.Tu@Sun.COM * disabled by software override. 21409353SSamuel.Tu@Sun.COM */ 21419353SSamuel.Tu@Sun.COM reg |= (IXGBE_PCS1GANA_ASM_PAUSE); 21429353SSamuel.Tu@Sun.COM reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE); 21439353SSamuel.Tu@Sun.COM break; 21449353SSamuel.Tu@Sun.COM case ixgbe_fc_full: 21459353SSamuel.Tu@Sun.COM /* Flow control (both Rx and Tx) is enabled by SW override. */ 21469353SSamuel.Tu@Sun.COM reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); 21479353SSamuel.Tu@Sun.COM break; 21489353SSamuel.Tu@Sun.COM default: 21499353SSamuel.Tu@Sun.COM DEBUGOUT("Flow control param set incorrectly\n"); 2150*10998SChenlu.Chen@Sun.COM ret_val = IXGBE_ERR_CONFIG; 21519353SSamuel.Tu@Sun.COM goto out; 21529353SSamuel.Tu@Sun.COM } 21539353SSamuel.Tu@Sun.COM 21549353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); 21559353SSamuel.Tu@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); 21569353SSamuel.Tu@Sun.COM 21579353SSamuel.Tu@Sun.COM /* Disable AN timeout */ 21589353SSamuel.Tu@Sun.COM if (hw->fc.strict_ieee) 21599353SSamuel.Tu@Sun.COM reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; 21609353SSamuel.Tu@Sun.COM 21619353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); 21629353SSamuel.Tu@Sun.COM DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); 21639353SSamuel.Tu@Sun.COM 2164*10998SChenlu.Chen@Sun.COM /* 2165*10998SChenlu.Chen@Sun.COM * Set up the 10G flow control advertisement registers so the HW 2166*10998SChenlu.Chen@Sun.COM * can do fc autoneg once the cable is plugged in. If we end up 2167*10998SChenlu.Chen@Sun.COM * using 1g instead, this is harmless. 2168*10998SChenlu.Chen@Sun.COM */ 2169*10998SChenlu.Chen@Sun.COM reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 2170*10998SChenlu.Chen@Sun.COM 2171*10998SChenlu.Chen@Sun.COM /* 2172*10998SChenlu.Chen@Sun.COM * The possible values of fc.requested_mode are: 2173*10998SChenlu.Chen@Sun.COM * 0: Flow control is completely disabled 2174*10998SChenlu.Chen@Sun.COM * 1: Rx flow control is enabled (we can receive pause frames, 2175*10998SChenlu.Chen@Sun.COM * but not send pause frames). 2176*10998SChenlu.Chen@Sun.COM * 2: Tx flow control is enabled (we can send pause frames but 2177*10998SChenlu.Chen@Sun.COM * we do not support receiving pause frames). 2178*10998SChenlu.Chen@Sun.COM * 3: Both Rx and Tx flow control (symmetric) are enabled. 2179*10998SChenlu.Chen@Sun.COM * other: Invalid. 2180*10998SChenlu.Chen@Sun.COM */ 2181*10998SChenlu.Chen@Sun.COM switch (hw->fc.requested_mode) { 2182*10998SChenlu.Chen@Sun.COM case ixgbe_fc_none: 2183*10998SChenlu.Chen@Sun.COM /* Flow control completely disabled by software override. */ 2184*10998SChenlu.Chen@Sun.COM reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); 2185*10998SChenlu.Chen@Sun.COM break; 2186*10998SChenlu.Chen@Sun.COM case ixgbe_fc_rx_pause: 2187*10998SChenlu.Chen@Sun.COM /* 2188*10998SChenlu.Chen@Sun.COM * Rx Flow control is enabled and Tx Flow control is 2189*10998SChenlu.Chen@Sun.COM * disabled by software override. Since there really 2190*10998SChenlu.Chen@Sun.COM * isn't a way to advertise that we are capable of RX 2191*10998SChenlu.Chen@Sun.COM * Pause ONLY, we will advertise that we support both 2192*10998SChenlu.Chen@Sun.COM * symmetric and asymmetric Rx PAUSE. Later, we will 2193*10998SChenlu.Chen@Sun.COM * disable the adapter's ability to send PAUSE frames. 2194*10998SChenlu.Chen@Sun.COM */ 2195*10998SChenlu.Chen@Sun.COM reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); 2196*10998SChenlu.Chen@Sun.COM break; 2197*10998SChenlu.Chen@Sun.COM case ixgbe_fc_tx_pause: 2198*10998SChenlu.Chen@Sun.COM /* 2199*10998SChenlu.Chen@Sun.COM * Tx Flow control is enabled, and Rx Flow control is 2200*10998SChenlu.Chen@Sun.COM * disabled by software override. 2201*10998SChenlu.Chen@Sun.COM */ 2202*10998SChenlu.Chen@Sun.COM reg |= (IXGBE_AUTOC_ASM_PAUSE); 2203*10998SChenlu.Chen@Sun.COM reg &= ~(IXGBE_AUTOC_SYM_PAUSE); 2204*10998SChenlu.Chen@Sun.COM break; 2205*10998SChenlu.Chen@Sun.COM case ixgbe_fc_full: 2206*10998SChenlu.Chen@Sun.COM /* Flow control (both Rx and Tx) is enabled by SW override. */ 2207*10998SChenlu.Chen@Sun.COM reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); 2208*10998SChenlu.Chen@Sun.COM break; 2209*10998SChenlu.Chen@Sun.COM default: 2210*10998SChenlu.Chen@Sun.COM DEBUGOUT("Flow control param set incorrectly\n"); 2211*10998SChenlu.Chen@Sun.COM ret_val = IXGBE_ERR_CONFIG; 2212*10998SChenlu.Chen@Sun.COM goto out; 2213*10998SChenlu.Chen@Sun.COM } 2214*10998SChenlu.Chen@Sun.COM /* 2215*10998SChenlu.Chen@Sun.COM * AUTOC restart handles negotiation of 1G and 10G. There is 2216*10998SChenlu.Chen@Sun.COM * no need to set the PCS1GCTL register. 2217*10998SChenlu.Chen@Sun.COM */ 2218*10998SChenlu.Chen@Sun.COM reg |= IXGBE_AUTOC_AN_RESTART; 2219*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg); 2220*10998SChenlu.Chen@Sun.COM DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); 2221*10998SChenlu.Chen@Sun.COM 22229353SSamuel.Tu@Sun.COM out: 22239353SSamuel.Tu@Sun.COM return (ret_val); 22249353SSamuel.Tu@Sun.COM } 22259353SSamuel.Tu@Sun.COM 22269353SSamuel.Tu@Sun.COM /* 22276621Sbt150084 * ixgbe_disable_pcie_master - Disable PCI-express master access 22286621Sbt150084 * @hw: pointer to hardware structure 22296621Sbt150084 * 22306621Sbt150084 * Disables PCI-Express master access and verifies there are no pending 22316621Sbt150084 * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable 22326621Sbt150084 * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS 22336621Sbt150084 * is returned signifying master requests disabled. 22346621Sbt150084 */ 22356621Sbt150084 s32 22366621Sbt150084 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) 22376621Sbt150084 { 22388490SPaul.Guo@Sun.COM u32 i; 22398490SPaul.Guo@Sun.COM u32 reg_val; 22408490SPaul.Guo@Sun.COM u32 number_of_queues; 22416621Sbt150084 s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; 22426621Sbt150084 2243*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_disable_pcie_master"); 2244*10998SChenlu.Chen@Sun.COM 22458490SPaul.Guo@Sun.COM /* Disable the receive unit by stopping each queue */ 22468490SPaul.Guo@Sun.COM number_of_queues = hw->mac.max_rx_queues; 22478490SPaul.Guo@Sun.COM for (i = 0; i < number_of_queues; i++) { 22488490SPaul.Guo@Sun.COM reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); 22498490SPaul.Guo@Sun.COM if (reg_val & IXGBE_RXDCTL_ENABLE) { 22508490SPaul.Guo@Sun.COM reg_val &= ~IXGBE_RXDCTL_ENABLE; 22518490SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); 22528490SPaul.Guo@Sun.COM } 22538490SPaul.Guo@Sun.COM } 22548490SPaul.Guo@Sun.COM 22558490SPaul.Guo@Sun.COM reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL); 22568490SPaul.Guo@Sun.COM reg_val |= IXGBE_CTRL_GIO_DIS; 22578490SPaul.Guo@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); 22586621Sbt150084 22596621Sbt150084 for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { 22606621Sbt150084 if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { 22616621Sbt150084 status = IXGBE_SUCCESS; 22626621Sbt150084 break; 22636621Sbt150084 } 22646621Sbt150084 usec_delay(100); 22656621Sbt150084 } 22666621Sbt150084 22676621Sbt150084 return (status); 22686621Sbt150084 } 22696621Sbt150084 22706621Sbt150084 /* 22716621Sbt150084 * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore 22726621Sbt150084 * @hw: pointer to hardware structure 22736621Sbt150084 * @mask: Mask to specify which semaphore to acquire 22746621Sbt150084 * 22756621Sbt150084 * Acquires the SWFW semaphore thought the GSSR register for the specified 22766621Sbt150084 * function (CSR, PHY0, PHY1, EEPROM, Flash) 22776621Sbt150084 */ 22786621Sbt150084 s32 22796621Sbt150084 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) 22806621Sbt150084 { 22816621Sbt150084 u32 gssr; 22826621Sbt150084 u32 swmask = mask; 22836621Sbt150084 u32 fwmask = mask << 5; 22846621Sbt150084 s32 timeout = 200; 22856621Sbt150084 2286*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_acquire_swfw_sync"); 2287*10998SChenlu.Chen@Sun.COM 22886621Sbt150084 while (timeout) { 22899353SSamuel.Tu@Sun.COM /* 22909353SSamuel.Tu@Sun.COM * SW EEPROM semaphore bit is used for access to all 22919353SSamuel.Tu@Sun.COM * SW_FW_SYNC/GSSR bits (not just EEPROM) 22929353SSamuel.Tu@Sun.COM */ 22936621Sbt150084 if (ixgbe_get_eeprom_semaphore(hw)) 2294*10998SChenlu.Chen@Sun.COM return (IXGBE_ERR_SWFW_SYNC); 22956621Sbt150084 22966621Sbt150084 gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 22976621Sbt150084 if (!(gssr & (fwmask | swmask))) 22986621Sbt150084 break; 22996621Sbt150084 23006621Sbt150084 /* 23016621Sbt150084 * Firmware currently using resource (fwmask) or other software 23026621Sbt150084 * thread currently using resource (swmask) 23036621Sbt150084 */ 23046621Sbt150084 ixgbe_release_eeprom_semaphore(hw); 23056621Sbt150084 msec_delay(5); 23066621Sbt150084 timeout--; 23076621Sbt150084 } 23086621Sbt150084 23096621Sbt150084 if (!timeout) { 23109353SSamuel.Tu@Sun.COM DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 2311*10998SChenlu.Chen@Sun.COM return (IXGBE_ERR_SWFW_SYNC); 23126621Sbt150084 } 23136621Sbt150084 23146621Sbt150084 gssr |= swmask; 23156621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 23166621Sbt150084 23176621Sbt150084 ixgbe_release_eeprom_semaphore(hw); 23186621Sbt150084 return (IXGBE_SUCCESS); 23196621Sbt150084 } 23206621Sbt150084 23216621Sbt150084 /* 23226621Sbt150084 * ixgbe_release_swfw_sync - Release SWFW semaphore 23236621Sbt150084 * @hw: pointer to hardware structure 23246621Sbt150084 * @mask: Mask to specify which semaphore to release 23256621Sbt150084 * 23266621Sbt150084 * Releases the SWFW semaphore thought the GSSR register for the specified 23276621Sbt150084 * function (CSR, PHY0, PHY1, EEPROM, Flash) 23286621Sbt150084 */ 23296621Sbt150084 void 23306621Sbt150084 ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) 23316621Sbt150084 { 23326621Sbt150084 u32 gssr; 23336621Sbt150084 u32 swmask = mask; 23346621Sbt150084 2335*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_release_swfw_sync"); 2336*10998SChenlu.Chen@Sun.COM 23376621Sbt150084 (void) ixgbe_get_eeprom_semaphore(hw); 23386621Sbt150084 23396621Sbt150084 gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); 23406621Sbt150084 gssr &= ~swmask; 23416621Sbt150084 IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); 23426621Sbt150084 23436621Sbt150084 ixgbe_release_eeprom_semaphore(hw); 23446621Sbt150084 } 23459353SSamuel.Tu@Sun.COM 23469353SSamuel.Tu@Sun.COM /* 23479353SSamuel.Tu@Sun.COM * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit 23489353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 23499353SSamuel.Tu@Sun.COM * @regval: register value to write to RXCTRL 23509353SSamuel.Tu@Sun.COM * 23519353SSamuel.Tu@Sun.COM * Enables the Rx DMA unit 23529353SSamuel.Tu@Sun.COM */ 23539353SSamuel.Tu@Sun.COM s32 23549353SSamuel.Tu@Sun.COM ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) 23559353SSamuel.Tu@Sun.COM { 2356*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_enable_rx_dma_generic"); 2357*10998SChenlu.Chen@Sun.COM 23589353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); 23599353SSamuel.Tu@Sun.COM 23609353SSamuel.Tu@Sun.COM return (IXGBE_SUCCESS); 23619353SSamuel.Tu@Sun.COM } 23629353SSamuel.Tu@Sun.COM 23639353SSamuel.Tu@Sun.COM /* 23649353SSamuel.Tu@Sun.COM * ixgbe_blink_led_start_generic - Blink LED based on index. 23659353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 23669353SSamuel.Tu@Sun.COM * @index: led number to blink 23679353SSamuel.Tu@Sun.COM */ 23689353SSamuel.Tu@Sun.COM s32 23699353SSamuel.Tu@Sun.COM ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) 23709353SSamuel.Tu@Sun.COM { 23719353SSamuel.Tu@Sun.COM ixgbe_link_speed speed = 0; 23729353SSamuel.Tu@Sun.COM bool link_up = 0; 23739353SSamuel.Tu@Sun.COM u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 23749353SSamuel.Tu@Sun.COM u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 23759353SSamuel.Tu@Sun.COM 2376*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_blink_led_start_generic"); 2377*10998SChenlu.Chen@Sun.COM 23789353SSamuel.Tu@Sun.COM /* 23799353SSamuel.Tu@Sun.COM * Link must be up to auto-blink the LEDs; 23809353SSamuel.Tu@Sun.COM * Force it if link is down. 23819353SSamuel.Tu@Sun.COM */ 23829353SSamuel.Tu@Sun.COM hw->mac.ops.check_link(hw, &speed, &link_up, false); 23839353SSamuel.Tu@Sun.COM 23849353SSamuel.Tu@Sun.COM if (!link_up) { 238510305SPaul.Guo@Sun.COM autoc_reg |= IXGBE_AUTOC_AN_RESTART; 23869353SSamuel.Tu@Sun.COM autoc_reg |= IXGBE_AUTOC_FLU; 23879353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 23889353SSamuel.Tu@Sun.COM msec_delay(10); 23899353SSamuel.Tu@Sun.COM } 23909353SSamuel.Tu@Sun.COM 23919353SSamuel.Tu@Sun.COM led_reg &= ~IXGBE_LED_MODE_MASK(index); 23929353SSamuel.Tu@Sun.COM led_reg |= IXGBE_LED_BLINK(index); 23939353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 23949353SSamuel.Tu@Sun.COM IXGBE_WRITE_FLUSH(hw); 23959353SSamuel.Tu@Sun.COM 23969353SSamuel.Tu@Sun.COM return (IXGBE_SUCCESS); 23979353SSamuel.Tu@Sun.COM } 23989353SSamuel.Tu@Sun.COM 23999353SSamuel.Tu@Sun.COM /* 24009353SSamuel.Tu@Sun.COM * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. 24019353SSamuel.Tu@Sun.COM * @hw: pointer to hardware structure 24029353SSamuel.Tu@Sun.COM * @index: led number to stop blinking 24039353SSamuel.Tu@Sun.COM */ 24049353SSamuel.Tu@Sun.COM s32 24059353SSamuel.Tu@Sun.COM ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) 24069353SSamuel.Tu@Sun.COM { 24079353SSamuel.Tu@Sun.COM u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); 24089353SSamuel.Tu@Sun.COM u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); 24099353SSamuel.Tu@Sun.COM 2410*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_blink_led_stop_generic"); 2411*10998SChenlu.Chen@Sun.COM 24129353SSamuel.Tu@Sun.COM autoc_reg &= ~IXGBE_AUTOC_FLU; 24139353SSamuel.Tu@Sun.COM autoc_reg |= IXGBE_AUTOC_AN_RESTART; 24149353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); 24159353SSamuel.Tu@Sun.COM 24169353SSamuel.Tu@Sun.COM led_reg &= ~IXGBE_LED_MODE_MASK(index); 24179353SSamuel.Tu@Sun.COM led_reg &= ~IXGBE_LED_BLINK(index); 24189353SSamuel.Tu@Sun.COM led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); 24199353SSamuel.Tu@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); 24209353SSamuel.Tu@Sun.COM IXGBE_WRITE_FLUSH(hw); 24219353SSamuel.Tu@Sun.COM 24229353SSamuel.Tu@Sun.COM return (IXGBE_SUCCESS); 24239353SSamuel.Tu@Sun.COM } 2424*10998SChenlu.Chen@Sun.COM 2425*10998SChenlu.Chen@Sun.COM /* 2426*10998SChenlu.Chen@Sun.COM * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM 2427*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2428*10998SChenlu.Chen@Sun.COM * @san_mac_offset: SAN MAC address offset 2429*10998SChenlu.Chen@Sun.COM * 2430*10998SChenlu.Chen@Sun.COM * This function will read the EEPROM location for the SAN MAC address 2431*10998SChenlu.Chen@Sun.COM * pointer, and returns the value at that location. This is used in both 2432*10998SChenlu.Chen@Sun.COM * get and set mac_addr routines. 2433*10998SChenlu.Chen@Sun.COM */ 2434*10998SChenlu.Chen@Sun.COM static s32 2435*10998SChenlu.Chen@Sun.COM ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset) 2436*10998SChenlu.Chen@Sun.COM { 2437*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); 2438*10998SChenlu.Chen@Sun.COM 2439*10998SChenlu.Chen@Sun.COM /* 2440*10998SChenlu.Chen@Sun.COM * First read the EEPROM pointer to see if the MAC addresses are 2441*10998SChenlu.Chen@Sun.COM * available. 2442*10998SChenlu.Chen@Sun.COM */ 2443*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); 2444*10998SChenlu.Chen@Sun.COM 2445*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2446*10998SChenlu.Chen@Sun.COM } 2447*10998SChenlu.Chen@Sun.COM 2448*10998SChenlu.Chen@Sun.COM /* 2449*10998SChenlu.Chen@Sun.COM * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM 2450*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2451*10998SChenlu.Chen@Sun.COM * @san_mac_addr: SAN MAC address 2452*10998SChenlu.Chen@Sun.COM * 2453*10998SChenlu.Chen@Sun.COM * Reads the SAN MAC address from the EEPROM, if it's available. This is 2454*10998SChenlu.Chen@Sun.COM * per-port, so set_lan_id() must be called before reading the addresses. 2455*10998SChenlu.Chen@Sun.COM * set_lan_id() is called by identify_sfp(), but this cannot be relied 2456*10998SChenlu.Chen@Sun.COM * upon for non-SFP connections, so we must call it here. 2457*10998SChenlu.Chen@Sun.COM */ 2458*10998SChenlu.Chen@Sun.COM s32 2459*10998SChenlu.Chen@Sun.COM ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 2460*10998SChenlu.Chen@Sun.COM { 2461*10998SChenlu.Chen@Sun.COM u16 san_mac_data, san_mac_offset; 2462*10998SChenlu.Chen@Sun.COM u8 i; 2463*10998SChenlu.Chen@Sun.COM 2464*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); 2465*10998SChenlu.Chen@Sun.COM 2466*10998SChenlu.Chen@Sun.COM /* 2467*10998SChenlu.Chen@Sun.COM * First read the EEPROM pointer to see if the MAC addresses are 2468*10998SChenlu.Chen@Sun.COM * available. If they're not, no point in calling set_lan_id() here. 2469*10998SChenlu.Chen@Sun.COM */ 2470*10998SChenlu.Chen@Sun.COM (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 2471*10998SChenlu.Chen@Sun.COM 2472*10998SChenlu.Chen@Sun.COM if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { 2473*10998SChenlu.Chen@Sun.COM /* 2474*10998SChenlu.Chen@Sun.COM * No addresses available in this EEPROM. It's not an 2475*10998SChenlu.Chen@Sun.COM * error though, so just wipe the local address and return. 2476*10998SChenlu.Chen@Sun.COM */ 2477*10998SChenlu.Chen@Sun.COM for (i = 0; i < 6; i++) 2478*10998SChenlu.Chen@Sun.COM san_mac_addr[i] = 0xFF; 2479*10998SChenlu.Chen@Sun.COM 2480*10998SChenlu.Chen@Sun.COM goto san_mac_addr_out; 2481*10998SChenlu.Chen@Sun.COM } 2482*10998SChenlu.Chen@Sun.COM 2483*10998SChenlu.Chen@Sun.COM /* make sure we know which port we need to program */ 2484*10998SChenlu.Chen@Sun.COM hw->mac.ops.set_lan_id(hw); 2485*10998SChenlu.Chen@Sun.COM /* apply the port offset to the address offset */ 2486*10998SChenlu.Chen@Sun.COM (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 2487*10998SChenlu.Chen@Sun.COM (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 2488*10998SChenlu.Chen@Sun.COM for (i = 0; i < 3; i++) { 2489*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); 2490*10998SChenlu.Chen@Sun.COM san_mac_addr[i * 2] = (u8)(san_mac_data); 2491*10998SChenlu.Chen@Sun.COM san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); 2492*10998SChenlu.Chen@Sun.COM san_mac_offset++; 2493*10998SChenlu.Chen@Sun.COM } 2494*10998SChenlu.Chen@Sun.COM 2495*10998SChenlu.Chen@Sun.COM san_mac_addr_out: 2496*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2497*10998SChenlu.Chen@Sun.COM } 2498*10998SChenlu.Chen@Sun.COM 2499*10998SChenlu.Chen@Sun.COM /* 2500*10998SChenlu.Chen@Sun.COM * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM 2501*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2502*10998SChenlu.Chen@Sun.COM * @san_mac_addr: SAN MAC address 2503*10998SChenlu.Chen@Sun.COM * 2504*10998SChenlu.Chen@Sun.COM * Write a SAN MAC address to the EEPROM. 2505*10998SChenlu.Chen@Sun.COM */ 2506*10998SChenlu.Chen@Sun.COM s32 2507*10998SChenlu.Chen@Sun.COM ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) 2508*10998SChenlu.Chen@Sun.COM { 2509*10998SChenlu.Chen@Sun.COM s32 status = IXGBE_SUCCESS; 2510*10998SChenlu.Chen@Sun.COM u16 san_mac_data, san_mac_offset; 2511*10998SChenlu.Chen@Sun.COM u8 i; 2512*10998SChenlu.Chen@Sun.COM 2513*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); 2514*10998SChenlu.Chen@Sun.COM 2515*10998SChenlu.Chen@Sun.COM /* Look for SAN mac address pointer. If not defined, return */ 2516*10998SChenlu.Chen@Sun.COM (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); 2517*10998SChenlu.Chen@Sun.COM 2518*10998SChenlu.Chen@Sun.COM if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { 2519*10998SChenlu.Chen@Sun.COM status = IXGBE_ERR_NO_SAN_ADDR_PTR; 2520*10998SChenlu.Chen@Sun.COM goto san_mac_addr_out; 2521*10998SChenlu.Chen@Sun.COM } 2522*10998SChenlu.Chen@Sun.COM 2523*10998SChenlu.Chen@Sun.COM /* Make sure we know which port we need to write */ 2524*10998SChenlu.Chen@Sun.COM hw->mac.ops.set_lan_id(hw); 2525*10998SChenlu.Chen@Sun.COM /* Apply the port offset to the address offset */ 2526*10998SChenlu.Chen@Sun.COM (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : 2527*10998SChenlu.Chen@Sun.COM (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); 2528*10998SChenlu.Chen@Sun.COM 2529*10998SChenlu.Chen@Sun.COM for (i = 0; i < 3; i++) { 2530*10998SChenlu.Chen@Sun.COM san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); 2531*10998SChenlu.Chen@Sun.COM san_mac_data |= (u16)(san_mac_addr[i * 2]); 2532*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); 2533*10998SChenlu.Chen@Sun.COM san_mac_offset++; 2534*10998SChenlu.Chen@Sun.COM } 2535*10998SChenlu.Chen@Sun.COM 2536*10998SChenlu.Chen@Sun.COM san_mac_addr_out: 2537*10998SChenlu.Chen@Sun.COM return (status); 2538*10998SChenlu.Chen@Sun.COM } 2539*10998SChenlu.Chen@Sun.COM 2540*10998SChenlu.Chen@Sun.COM /* 2541*10998SChenlu.Chen@Sun.COM * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count 2542*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2543*10998SChenlu.Chen@Sun.COM * 2544*10998SChenlu.Chen@Sun.COM * Read PCIe configuration space, and get the MSI-X vector count from 2545*10998SChenlu.Chen@Sun.COM * the capabilities table. 2546*10998SChenlu.Chen@Sun.COM */ 2547*10998SChenlu.Chen@Sun.COM u32 2548*10998SChenlu.Chen@Sun.COM ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) 2549*10998SChenlu.Chen@Sun.COM { 2550*10998SChenlu.Chen@Sun.COM u32 msix_count = 64; 2551*10998SChenlu.Chen@Sun.COM 2552*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); 2553*10998SChenlu.Chen@Sun.COM if (hw->mac.msix_vectors_from_pcie) { 2554*10998SChenlu.Chen@Sun.COM msix_count = IXGBE_READ_PCIE_WORD(hw, 2555*10998SChenlu.Chen@Sun.COM IXGBE_PCIE_MSIX_82599_CAPS); 2556*10998SChenlu.Chen@Sun.COM msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; 2557*10998SChenlu.Chen@Sun.COM 2558*10998SChenlu.Chen@Sun.COM /* 2559*10998SChenlu.Chen@Sun.COM * MSI-X count is zero-based in HW, so increment to give 2560*10998SChenlu.Chen@Sun.COM * proper value. 2561*10998SChenlu.Chen@Sun.COM */ 2562*10998SChenlu.Chen@Sun.COM msix_count++; 2563*10998SChenlu.Chen@Sun.COM } 2564*10998SChenlu.Chen@Sun.COM 2565*10998SChenlu.Chen@Sun.COM return (msix_count); 2566*10998SChenlu.Chen@Sun.COM } 2567*10998SChenlu.Chen@Sun.COM 2568*10998SChenlu.Chen@Sun.COM /* 2569*10998SChenlu.Chen@Sun.COM * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address 2570*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2571*10998SChenlu.Chen@Sun.COM * @addr: Address to put into receive address register 2572*10998SChenlu.Chen@Sun.COM * @vmdq: VMDq pool to assign 2573*10998SChenlu.Chen@Sun.COM * 2574*10998SChenlu.Chen@Sun.COM * Puts an ethernet address into a receive address register, or 2575*10998SChenlu.Chen@Sun.COM * finds the rar that it is aleady in; adds to the pool list 2576*10998SChenlu.Chen@Sun.COM */ 2577*10998SChenlu.Chen@Sun.COM s32 2578*10998SChenlu.Chen@Sun.COM ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) 2579*10998SChenlu.Chen@Sun.COM { 2580*10998SChenlu.Chen@Sun.COM static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; 2581*10998SChenlu.Chen@Sun.COM u32 first_empty_rar = NO_EMPTY_RAR_FOUND; 2582*10998SChenlu.Chen@Sun.COM u32 rar; 2583*10998SChenlu.Chen@Sun.COM u32 rar_low, rar_high; 2584*10998SChenlu.Chen@Sun.COM u32 addr_low, addr_high; 2585*10998SChenlu.Chen@Sun.COM 2586*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_insert_mac_addr_generic"); 2587*10998SChenlu.Chen@Sun.COM 2588*10998SChenlu.Chen@Sun.COM /* swap bytes for HW little endian */ 2589*10998SChenlu.Chen@Sun.COM addr_low = addr[0] | (addr[1] << 8) 2590*10998SChenlu.Chen@Sun.COM | (addr[2] << 16) 2591*10998SChenlu.Chen@Sun.COM | (addr[3] << 24); 2592*10998SChenlu.Chen@Sun.COM addr_high = addr[4] | (addr[5] << 8); 2593*10998SChenlu.Chen@Sun.COM 2594*10998SChenlu.Chen@Sun.COM /* 2595*10998SChenlu.Chen@Sun.COM * Either find the mac_id in rar or find the first empty space. 2596*10998SChenlu.Chen@Sun.COM * rar_highwater points to just after the highest currently used 2597*10998SChenlu.Chen@Sun.COM * rar in order to shorten the search. It grows when we add a new 2598*10998SChenlu.Chen@Sun.COM * rar to the top. 2599*10998SChenlu.Chen@Sun.COM */ 2600*10998SChenlu.Chen@Sun.COM for (rar = 0; rar < hw->mac.rar_highwater; rar++) { 2601*10998SChenlu.Chen@Sun.COM rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); 2602*10998SChenlu.Chen@Sun.COM 2603*10998SChenlu.Chen@Sun.COM if (((IXGBE_RAH_AV & rar_high) == 0) && 2604*10998SChenlu.Chen@Sun.COM first_empty_rar == NO_EMPTY_RAR_FOUND) { 2605*10998SChenlu.Chen@Sun.COM first_empty_rar = rar; 2606*10998SChenlu.Chen@Sun.COM } else if ((rar_high & 0xFFFF) == addr_high) { 2607*10998SChenlu.Chen@Sun.COM rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); 2608*10998SChenlu.Chen@Sun.COM if (rar_low == addr_low) 2609*10998SChenlu.Chen@Sun.COM break; /* found it already in the rars */ 2610*10998SChenlu.Chen@Sun.COM } 2611*10998SChenlu.Chen@Sun.COM } 2612*10998SChenlu.Chen@Sun.COM 2613*10998SChenlu.Chen@Sun.COM if (rar < hw->mac.rar_highwater) { 2614*10998SChenlu.Chen@Sun.COM /* already there so just add to the pool bits */ 2615*10998SChenlu.Chen@Sun.COM (void) ixgbe_set_vmdq(hw, rar, vmdq); 2616*10998SChenlu.Chen@Sun.COM } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { 2617*10998SChenlu.Chen@Sun.COM /* stick it into first empty RAR slot we found */ 2618*10998SChenlu.Chen@Sun.COM rar = first_empty_rar; 2619*10998SChenlu.Chen@Sun.COM (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 2620*10998SChenlu.Chen@Sun.COM } else if (rar == hw->mac.rar_highwater) { 2621*10998SChenlu.Chen@Sun.COM /* add it to the top of the list and inc the highwater mark */ 2622*10998SChenlu.Chen@Sun.COM (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); 2623*10998SChenlu.Chen@Sun.COM hw->mac.rar_highwater++; 2624*10998SChenlu.Chen@Sun.COM } else if (rar >= hw->mac.num_rar_entries) { 2625*10998SChenlu.Chen@Sun.COM return (IXGBE_ERR_INVALID_MAC_ADDR); 2626*10998SChenlu.Chen@Sun.COM } 2627*10998SChenlu.Chen@Sun.COM 2628*10998SChenlu.Chen@Sun.COM /* 2629*10998SChenlu.Chen@Sun.COM * If we found rar[0], make sure the default pool bit (we use pool 0) 2630*10998SChenlu.Chen@Sun.COM * remains cleared to be sure default pool packets will get delivered 2631*10998SChenlu.Chen@Sun.COM */ 2632*10998SChenlu.Chen@Sun.COM if (rar == 0) 2633*10998SChenlu.Chen@Sun.COM (void) ixgbe_clear_vmdq(hw, rar, 0); 2634*10998SChenlu.Chen@Sun.COM 2635*10998SChenlu.Chen@Sun.COM return (rar); 2636*10998SChenlu.Chen@Sun.COM } 2637*10998SChenlu.Chen@Sun.COM 2638*10998SChenlu.Chen@Sun.COM /* 2639*10998SChenlu.Chen@Sun.COM * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address 2640*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware struct 2641*10998SChenlu.Chen@Sun.COM * @rar: receive address register index to disassociate 2642*10998SChenlu.Chen@Sun.COM * @vmdq: VMDq pool index to remove from the rar 2643*10998SChenlu.Chen@Sun.COM */ 2644*10998SChenlu.Chen@Sun.COM s32 2645*10998SChenlu.Chen@Sun.COM ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 2646*10998SChenlu.Chen@Sun.COM { 2647*10998SChenlu.Chen@Sun.COM u32 mpsar_lo, mpsar_hi; 2648*10998SChenlu.Chen@Sun.COM u32 rar_entries = hw->mac.num_rar_entries; 2649*10998SChenlu.Chen@Sun.COM 2650*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_clear_vmdq_generic"); 2651*10998SChenlu.Chen@Sun.COM 2652*10998SChenlu.Chen@Sun.COM if (rar < rar_entries) { 2653*10998SChenlu.Chen@Sun.COM mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 2654*10998SChenlu.Chen@Sun.COM mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 2655*10998SChenlu.Chen@Sun.COM 2656*10998SChenlu.Chen@Sun.COM if (!mpsar_lo && !mpsar_hi) 2657*10998SChenlu.Chen@Sun.COM goto done; 2658*10998SChenlu.Chen@Sun.COM 2659*10998SChenlu.Chen@Sun.COM if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { 2660*10998SChenlu.Chen@Sun.COM if (mpsar_lo) { 2661*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); 2662*10998SChenlu.Chen@Sun.COM mpsar_lo = 0; 2663*10998SChenlu.Chen@Sun.COM } 2664*10998SChenlu.Chen@Sun.COM if (mpsar_hi) { 2665*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); 2666*10998SChenlu.Chen@Sun.COM mpsar_hi = 0; 2667*10998SChenlu.Chen@Sun.COM } 2668*10998SChenlu.Chen@Sun.COM } else if (vmdq < 32) { 2669*10998SChenlu.Chen@Sun.COM mpsar_lo &= ~(1 << vmdq); 2670*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); 2671*10998SChenlu.Chen@Sun.COM } else { 2672*10998SChenlu.Chen@Sun.COM mpsar_hi &= ~(1 << (vmdq - 32)); 2673*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); 2674*10998SChenlu.Chen@Sun.COM } 2675*10998SChenlu.Chen@Sun.COM 2676*10998SChenlu.Chen@Sun.COM /* was that the last pool using this rar? */ 2677*10998SChenlu.Chen@Sun.COM if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) 2678*10998SChenlu.Chen@Sun.COM hw->mac.ops.clear_rar(hw, rar); 2679*10998SChenlu.Chen@Sun.COM } else { 2680*10998SChenlu.Chen@Sun.COM DEBUGOUT1("RAR index %d is out of range.\n", rar); 2681*10998SChenlu.Chen@Sun.COM } 2682*10998SChenlu.Chen@Sun.COM 2683*10998SChenlu.Chen@Sun.COM done: 2684*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2685*10998SChenlu.Chen@Sun.COM } 2686*10998SChenlu.Chen@Sun.COM 2687*10998SChenlu.Chen@Sun.COM /* 2688*10998SChenlu.Chen@Sun.COM * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address 2689*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware struct 2690*10998SChenlu.Chen@Sun.COM * @rar: receive address register index to associate with a VMDq index 2691*10998SChenlu.Chen@Sun.COM * @vmdq: VMDq pool index 2692*10998SChenlu.Chen@Sun.COM */ 2693*10998SChenlu.Chen@Sun.COM s32 2694*10998SChenlu.Chen@Sun.COM ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) 2695*10998SChenlu.Chen@Sun.COM { 2696*10998SChenlu.Chen@Sun.COM u32 mpsar; 2697*10998SChenlu.Chen@Sun.COM u32 rar_entries = hw->mac.num_rar_entries; 2698*10998SChenlu.Chen@Sun.COM 2699*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_vmdq_generic"); 2700*10998SChenlu.Chen@Sun.COM 2701*10998SChenlu.Chen@Sun.COM if (rar < rar_entries) { 2702*10998SChenlu.Chen@Sun.COM if (vmdq < 32) { 2703*10998SChenlu.Chen@Sun.COM mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); 2704*10998SChenlu.Chen@Sun.COM mpsar |= 1 << vmdq; 2705*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); 2706*10998SChenlu.Chen@Sun.COM } else { 2707*10998SChenlu.Chen@Sun.COM mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); 2708*10998SChenlu.Chen@Sun.COM mpsar |= 1 << (vmdq - 32); 2709*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); 2710*10998SChenlu.Chen@Sun.COM } 2711*10998SChenlu.Chen@Sun.COM } else { 2712*10998SChenlu.Chen@Sun.COM DEBUGOUT1("RAR index %d is out of range.\n", rar); 2713*10998SChenlu.Chen@Sun.COM } 2714*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2715*10998SChenlu.Chen@Sun.COM } 2716*10998SChenlu.Chen@Sun.COM 2717*10998SChenlu.Chen@Sun.COM /* 2718*10998SChenlu.Chen@Sun.COM * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array 2719*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2720*10998SChenlu.Chen@Sun.COM */ 2721*10998SChenlu.Chen@Sun.COM s32 2722*10998SChenlu.Chen@Sun.COM ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) 2723*10998SChenlu.Chen@Sun.COM { 2724*10998SChenlu.Chen@Sun.COM int i; 2725*10998SChenlu.Chen@Sun.COM 2726*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_init_uta_tables_generic"); 2727*10998SChenlu.Chen@Sun.COM DEBUGOUT(" Clearing UTA\n"); 2728*10998SChenlu.Chen@Sun.COM 2729*10998SChenlu.Chen@Sun.COM for (i = 0; i < 128; i++) 2730*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); 2731*10998SChenlu.Chen@Sun.COM 2732*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2733*10998SChenlu.Chen@Sun.COM } 2734*10998SChenlu.Chen@Sun.COM 2735*10998SChenlu.Chen@Sun.COM /* 2736*10998SChenlu.Chen@Sun.COM * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot 2737*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2738*10998SChenlu.Chen@Sun.COM * @vlan: VLAN id to write to VLAN filter 2739*10998SChenlu.Chen@Sun.COM * 2740*10998SChenlu.Chen@Sun.COM * return the VLVF index where this VLAN id should be placed 2741*10998SChenlu.Chen@Sun.COM * 2742*10998SChenlu.Chen@Sun.COM */ 2743*10998SChenlu.Chen@Sun.COM s32 2744*10998SChenlu.Chen@Sun.COM ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) 2745*10998SChenlu.Chen@Sun.COM { 2746*10998SChenlu.Chen@Sun.COM u32 bits = 0; 2747*10998SChenlu.Chen@Sun.COM u32 first_empty_slot = 0; 2748*10998SChenlu.Chen@Sun.COM s32 regindex; 2749*10998SChenlu.Chen@Sun.COM 2750*10998SChenlu.Chen@Sun.COM /* 2751*10998SChenlu.Chen@Sun.COM * Search for the vlan id in the VLVF entries. Save off the first empty 2752*10998SChenlu.Chen@Sun.COM * slot found along the way 2753*10998SChenlu.Chen@Sun.COM */ 2754*10998SChenlu.Chen@Sun.COM for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { 2755*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); 2756*10998SChenlu.Chen@Sun.COM if (!bits && !(first_empty_slot)) 2757*10998SChenlu.Chen@Sun.COM first_empty_slot = regindex; 2758*10998SChenlu.Chen@Sun.COM else if ((bits & 0x0FFF) == vlan) 2759*10998SChenlu.Chen@Sun.COM break; 2760*10998SChenlu.Chen@Sun.COM } 2761*10998SChenlu.Chen@Sun.COM 2762*10998SChenlu.Chen@Sun.COM /* 2763*10998SChenlu.Chen@Sun.COM * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan 2764*10998SChenlu.Chen@Sun.COM * in the VLVF. Else use the first empty VLVF register for this 2765*10998SChenlu.Chen@Sun.COM * vlan id. 2766*10998SChenlu.Chen@Sun.COM */ 2767*10998SChenlu.Chen@Sun.COM if (regindex >= IXGBE_VLVF_ENTRIES) { 2768*10998SChenlu.Chen@Sun.COM if (first_empty_slot) 2769*10998SChenlu.Chen@Sun.COM regindex = first_empty_slot; 2770*10998SChenlu.Chen@Sun.COM else { 2771*10998SChenlu.Chen@Sun.COM DEBUGOUT("No space in VLVF.\n"); 2772*10998SChenlu.Chen@Sun.COM regindex = -1; 2773*10998SChenlu.Chen@Sun.COM } 2774*10998SChenlu.Chen@Sun.COM } 2775*10998SChenlu.Chen@Sun.COM 2776*10998SChenlu.Chen@Sun.COM return (regindex); 2777*10998SChenlu.Chen@Sun.COM } 2778*10998SChenlu.Chen@Sun.COM 2779*10998SChenlu.Chen@Sun.COM /* 2780*10998SChenlu.Chen@Sun.COM * ixgbe_set_vfta_generic - Set VLAN filter table 2781*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2782*10998SChenlu.Chen@Sun.COM * @vlan: VLAN id to write to VLAN filter 2783*10998SChenlu.Chen@Sun.COM * @vind: VMDq output index that maps queue to VLAN id in VFVFB 2784*10998SChenlu.Chen@Sun.COM * @vlan_on: boolean flag to turn on/off VLAN in VFVF 2785*10998SChenlu.Chen@Sun.COM * 2786*10998SChenlu.Chen@Sun.COM * Turn on/off specified VLAN in the VLAN filter table. 2787*10998SChenlu.Chen@Sun.COM */ 2788*10998SChenlu.Chen@Sun.COM s32 2789*10998SChenlu.Chen@Sun.COM ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) 2790*10998SChenlu.Chen@Sun.COM { 2791*10998SChenlu.Chen@Sun.COM s32 regindex; 2792*10998SChenlu.Chen@Sun.COM u32 bitindex; 2793*10998SChenlu.Chen@Sun.COM u32 bits; 2794*10998SChenlu.Chen@Sun.COM u32 vt; 2795*10998SChenlu.Chen@Sun.COM 2796*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_set_vfta_generic"); 2797*10998SChenlu.Chen@Sun.COM 2798*10998SChenlu.Chen@Sun.COM if (vlan > 4095) 2799*10998SChenlu.Chen@Sun.COM return (IXGBE_ERR_PARAM); 2800*10998SChenlu.Chen@Sun.COM 2801*10998SChenlu.Chen@Sun.COM /* 2802*10998SChenlu.Chen@Sun.COM * this is a 2 part operation - first the VFTA, then the 2803*10998SChenlu.Chen@Sun.COM * VLVF and VLVFB if VT Mode is set 2804*10998SChenlu.Chen@Sun.COM */ 2805*10998SChenlu.Chen@Sun.COM 2806*10998SChenlu.Chen@Sun.COM /* 2807*10998SChenlu.Chen@Sun.COM * Part 1 2808*10998SChenlu.Chen@Sun.COM * The VFTA is a bitstring made up of 128 32-bit registers 2809*10998SChenlu.Chen@Sun.COM * that enable the particular VLAN id, much like the MTA: 2810*10998SChenlu.Chen@Sun.COM * bits[11-5]: which register 2811*10998SChenlu.Chen@Sun.COM * bits[4-0]: which bit in the register 2812*10998SChenlu.Chen@Sun.COM */ 2813*10998SChenlu.Chen@Sun.COM regindex = (vlan >> 5) & 0x7F; 2814*10998SChenlu.Chen@Sun.COM bitindex = vlan & 0x1F; 2815*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); 2816*10998SChenlu.Chen@Sun.COM if (vlan_on) 2817*10998SChenlu.Chen@Sun.COM bits |= (1 << bitindex); 2818*10998SChenlu.Chen@Sun.COM else 2819*10998SChenlu.Chen@Sun.COM bits &= ~(1 << bitindex); 2820*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); 2821*10998SChenlu.Chen@Sun.COM 2822*10998SChenlu.Chen@Sun.COM 2823*10998SChenlu.Chen@Sun.COM /* 2824*10998SChenlu.Chen@Sun.COM * Part 2 2825*10998SChenlu.Chen@Sun.COM * If VT Mode is set 2826*10998SChenlu.Chen@Sun.COM * Either vlan_on 2827*10998SChenlu.Chen@Sun.COM * make sure the vlan is in VLVF 2828*10998SChenlu.Chen@Sun.COM * set the vind bit in the matching VLVFB 2829*10998SChenlu.Chen@Sun.COM * Or !vlan_on 2830*10998SChenlu.Chen@Sun.COM * clear the pool bit and possibly the vind 2831*10998SChenlu.Chen@Sun.COM */ 2832*10998SChenlu.Chen@Sun.COM vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); 2833*10998SChenlu.Chen@Sun.COM if (vt & IXGBE_VT_CTL_VT_ENABLE) { 2834*10998SChenlu.Chen@Sun.COM if (vlan == 0) { 2835*10998SChenlu.Chen@Sun.COM regindex = 0; 2836*10998SChenlu.Chen@Sun.COM } else { 2837*10998SChenlu.Chen@Sun.COM regindex = ixgbe_find_vlvf_slot(hw, vlan); 2838*10998SChenlu.Chen@Sun.COM if (regindex < 0) 2839*10998SChenlu.Chen@Sun.COM goto out; 2840*10998SChenlu.Chen@Sun.COM } 2841*10998SChenlu.Chen@Sun.COM 2842*10998SChenlu.Chen@Sun.COM if (vlan_on) { 2843*10998SChenlu.Chen@Sun.COM /* set the pool bit */ 2844*10998SChenlu.Chen@Sun.COM if (vind < 32) { 2845*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, 2846*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB(regindex*2)); 2847*10998SChenlu.Chen@Sun.COM bits |= (1 << vind); 2848*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, 2849*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB(regindex*2), 2850*10998SChenlu.Chen@Sun.COM bits); 2851*10998SChenlu.Chen@Sun.COM } else { 2852*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, 2853*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB((regindex*2)+1)); 2854*10998SChenlu.Chen@Sun.COM bits |= (1 << vind); 2855*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, 2856*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB((regindex*2)+1), 2857*10998SChenlu.Chen@Sun.COM bits); 2858*10998SChenlu.Chen@Sun.COM } 2859*10998SChenlu.Chen@Sun.COM } else { 2860*10998SChenlu.Chen@Sun.COM /* clear the pool bit */ 2861*10998SChenlu.Chen@Sun.COM if (vind < 32) { 2862*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, 2863*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB(regindex*2)); 2864*10998SChenlu.Chen@Sun.COM bits &= ~(1 << vind); 2865*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, 2866*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB(regindex*2), 2867*10998SChenlu.Chen@Sun.COM bits); 2868*10998SChenlu.Chen@Sun.COM bits |= IXGBE_READ_REG(hw, 2869*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB((regindex*2)+1)); 2870*10998SChenlu.Chen@Sun.COM } else { 2871*10998SChenlu.Chen@Sun.COM bits = IXGBE_READ_REG(hw, 2872*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB((regindex*2)+1)); 2873*10998SChenlu.Chen@Sun.COM bits &= ~(1 << vind); 2874*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, 2875*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB((regindex*2)+1), 2876*10998SChenlu.Chen@Sun.COM bits); 2877*10998SChenlu.Chen@Sun.COM bits |= IXGBE_READ_REG(hw, 2878*10998SChenlu.Chen@Sun.COM IXGBE_VLVFB(regindex*2)); 2879*10998SChenlu.Chen@Sun.COM } 2880*10998SChenlu.Chen@Sun.COM } 2881*10998SChenlu.Chen@Sun.COM 2882*10998SChenlu.Chen@Sun.COM if (bits) 2883*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 2884*10998SChenlu.Chen@Sun.COM (IXGBE_VLVF_VIEN | vlan)); 2885*10998SChenlu.Chen@Sun.COM else 2886*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); 2887*10998SChenlu.Chen@Sun.COM } 2888*10998SChenlu.Chen@Sun.COM out: 2889*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2890*10998SChenlu.Chen@Sun.COM } 2891*10998SChenlu.Chen@Sun.COM 2892*10998SChenlu.Chen@Sun.COM /* 2893*10998SChenlu.Chen@Sun.COM * ixgbe_clear_vfta_generic - Clear VLAN filter table 2894*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2895*10998SChenlu.Chen@Sun.COM * 2896*10998SChenlu.Chen@Sun.COM * Clears the VLAN filer table, and the VMDq index associated with the filter 2897*10998SChenlu.Chen@Sun.COM */ 2898*10998SChenlu.Chen@Sun.COM s32 2899*10998SChenlu.Chen@Sun.COM ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) 2900*10998SChenlu.Chen@Sun.COM { 2901*10998SChenlu.Chen@Sun.COM u32 offset; 2902*10998SChenlu.Chen@Sun.COM 2903*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_clear_vfta_generic"); 2904*10998SChenlu.Chen@Sun.COM 2905*10998SChenlu.Chen@Sun.COM for (offset = 0; offset < hw->mac.vft_size; offset++) 2906*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); 2907*10998SChenlu.Chen@Sun.COM 2908*10998SChenlu.Chen@Sun.COM for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { 2909*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); 2910*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0); 2911*10998SChenlu.Chen@Sun.COM IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0); 2912*10998SChenlu.Chen@Sun.COM } 2913*10998SChenlu.Chen@Sun.COM 2914*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2915*10998SChenlu.Chen@Sun.COM } 2916*10998SChenlu.Chen@Sun.COM 2917*10998SChenlu.Chen@Sun.COM /* 2918*10998SChenlu.Chen@Sun.COM * ixgbe_check_mac_link_generic - Determine link and speed status 2919*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2920*10998SChenlu.Chen@Sun.COM * @speed: pointer to link speed 2921*10998SChenlu.Chen@Sun.COM * @link_up: true when link is up 2922*10998SChenlu.Chen@Sun.COM * @link_up_wait_to_complete: bool used to wait for link up or not 2923*10998SChenlu.Chen@Sun.COM * 2924*10998SChenlu.Chen@Sun.COM * Reads the links register to determine if link is up and the current speed 2925*10998SChenlu.Chen@Sun.COM */ 2926*10998SChenlu.Chen@Sun.COM s32 2927*10998SChenlu.Chen@Sun.COM ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 2928*10998SChenlu.Chen@Sun.COM bool *link_up, bool link_up_wait_to_complete) 2929*10998SChenlu.Chen@Sun.COM { 2930*10998SChenlu.Chen@Sun.COM u32 links_reg; 2931*10998SChenlu.Chen@Sun.COM u32 i; 2932*10998SChenlu.Chen@Sun.COM 2933*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_check_mac_link_generic"); 2934*10998SChenlu.Chen@Sun.COM 2935*10998SChenlu.Chen@Sun.COM links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 2936*10998SChenlu.Chen@Sun.COM if (link_up_wait_to_complete) { 2937*10998SChenlu.Chen@Sun.COM for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { 2938*10998SChenlu.Chen@Sun.COM if (links_reg & IXGBE_LINKS_UP) { 2939*10998SChenlu.Chen@Sun.COM *link_up = true; 2940*10998SChenlu.Chen@Sun.COM break; 2941*10998SChenlu.Chen@Sun.COM } else { 2942*10998SChenlu.Chen@Sun.COM *link_up = false; 2943*10998SChenlu.Chen@Sun.COM } 2944*10998SChenlu.Chen@Sun.COM msec_delay(100); 2945*10998SChenlu.Chen@Sun.COM links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 2946*10998SChenlu.Chen@Sun.COM } 2947*10998SChenlu.Chen@Sun.COM } else { 2948*10998SChenlu.Chen@Sun.COM if (links_reg & IXGBE_LINKS_UP) 2949*10998SChenlu.Chen@Sun.COM *link_up = true; 2950*10998SChenlu.Chen@Sun.COM else 2951*10998SChenlu.Chen@Sun.COM *link_up = false; 2952*10998SChenlu.Chen@Sun.COM } 2953*10998SChenlu.Chen@Sun.COM 2954*10998SChenlu.Chen@Sun.COM if ((links_reg & IXGBE_LINKS_SPEED_82599) == 2955*10998SChenlu.Chen@Sun.COM IXGBE_LINKS_SPEED_10G_82599) 2956*10998SChenlu.Chen@Sun.COM *speed = IXGBE_LINK_SPEED_10GB_FULL; 2957*10998SChenlu.Chen@Sun.COM else if ((links_reg & IXGBE_LINKS_SPEED_82599) == 2958*10998SChenlu.Chen@Sun.COM IXGBE_LINKS_SPEED_1G_82599) 2959*10998SChenlu.Chen@Sun.COM *speed = IXGBE_LINK_SPEED_1GB_FULL; 2960*10998SChenlu.Chen@Sun.COM else 2961*10998SChenlu.Chen@Sun.COM *speed = IXGBE_LINK_SPEED_100_FULL; 2962*10998SChenlu.Chen@Sun.COM 2963*10998SChenlu.Chen@Sun.COM /* if link is down, zero out the current_mode */ 2964*10998SChenlu.Chen@Sun.COM if (*link_up == false) { 2965*10998SChenlu.Chen@Sun.COM hw->fc.current_mode = ixgbe_fc_none; 2966*10998SChenlu.Chen@Sun.COM hw->fc.fc_was_autonegged = false; 2967*10998SChenlu.Chen@Sun.COM } 2968*10998SChenlu.Chen@Sun.COM 2969*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 2970*10998SChenlu.Chen@Sun.COM } 2971*10998SChenlu.Chen@Sun.COM 2972*10998SChenlu.Chen@Sun.COM /* 2973*10998SChenlu.Chen@Sun.COM * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from 2974*10998SChenlu.Chen@Sun.COM * the EEPROM 2975*10998SChenlu.Chen@Sun.COM * @hw: pointer to hardware structure 2976*10998SChenlu.Chen@Sun.COM * @wwnn_prefix: the alternative WWNN prefix 2977*10998SChenlu.Chen@Sun.COM * @wwpn_prefix: the alternative WWPN prefix 2978*10998SChenlu.Chen@Sun.COM * 2979*10998SChenlu.Chen@Sun.COM * This function will read the EEPROM from the alternative SAN MAC address 2980*10998SChenlu.Chen@Sun.COM * block to check the support for the alternative WWNN/WWPN prefix support. 2981*10998SChenlu.Chen@Sun.COM */ 2982*10998SChenlu.Chen@Sun.COM s32 2983*10998SChenlu.Chen@Sun.COM ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, 2984*10998SChenlu.Chen@Sun.COM u16 *wwpn_prefix) 2985*10998SChenlu.Chen@Sun.COM { 2986*10998SChenlu.Chen@Sun.COM u16 offset, caps; 2987*10998SChenlu.Chen@Sun.COM u16 alt_san_mac_blk_offset; 2988*10998SChenlu.Chen@Sun.COM 2989*10998SChenlu.Chen@Sun.COM DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); 2990*10998SChenlu.Chen@Sun.COM 2991*10998SChenlu.Chen@Sun.COM /* clear output first */ 2992*10998SChenlu.Chen@Sun.COM *wwnn_prefix = 0xFFFF; 2993*10998SChenlu.Chen@Sun.COM *wwpn_prefix = 0xFFFF; 2994*10998SChenlu.Chen@Sun.COM 2995*10998SChenlu.Chen@Sun.COM /* check if alternative SAN MAC is supported */ 2996*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, 2997*10998SChenlu.Chen@Sun.COM &alt_san_mac_blk_offset); 2998*10998SChenlu.Chen@Sun.COM 2999*10998SChenlu.Chen@Sun.COM if ((alt_san_mac_blk_offset == 0) || 3000*10998SChenlu.Chen@Sun.COM (alt_san_mac_blk_offset == 0xFFFF)) 3001*10998SChenlu.Chen@Sun.COM goto wwn_prefix_out; 3002*10998SChenlu.Chen@Sun.COM 3003*10998SChenlu.Chen@Sun.COM /* check capability in alternative san mac address block */ 3004*10998SChenlu.Chen@Sun.COM offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; 3005*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, offset, &caps); 3006*10998SChenlu.Chen@Sun.COM if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) 3007*10998SChenlu.Chen@Sun.COM goto wwn_prefix_out; 3008*10998SChenlu.Chen@Sun.COM 3009*10998SChenlu.Chen@Sun.COM /* get the corresponding prefix for WWNN/WWPN */ 3010*10998SChenlu.Chen@Sun.COM offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; 3011*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, offset, wwnn_prefix); 3012*10998SChenlu.Chen@Sun.COM 3013*10998SChenlu.Chen@Sun.COM offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; 3014*10998SChenlu.Chen@Sun.COM hw->eeprom.ops.read(hw, offset, wwpn_prefix); 3015*10998SChenlu.Chen@Sun.COM 3016*10998SChenlu.Chen@Sun.COM wwn_prefix_out: 3017*10998SChenlu.Chen@Sun.COM return (IXGBE_SUCCESS); 3018*10998SChenlu.Chen@Sun.COM } 3019