162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 2009 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/etherdevice.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "vf.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_cistatic s32 e1000_check_for_link_vf(struct e1000_hw *hw); 962306a36Sopenharmony_cistatic s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed, 1062306a36Sopenharmony_ci u16 *duplex); 1162306a36Sopenharmony_cistatic s32 e1000_init_hw_vf(struct e1000_hw *hw); 1262306a36Sopenharmony_cistatic s32 e1000_reset_hw_vf(struct e1000_hw *hw); 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, 1562306a36Sopenharmony_ci u32, u32, u32); 1662306a36Sopenharmony_cistatic void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32); 1762306a36Sopenharmony_cistatic s32 e1000_read_mac_addr_vf(struct e1000_hw *); 1862306a36Sopenharmony_cistatic s32 e1000_set_uc_addr_vf(struct e1000_hw *hw, u32 subcmd, u8 *addr); 1962306a36Sopenharmony_cistatic s32 e1000_set_vfta_vf(struct e1000_hw *, u16, bool); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/** 2262306a36Sopenharmony_ci * e1000_init_mac_params_vf - Inits MAC params 2362306a36Sopenharmony_ci * @hw: pointer to the HW structure 2462306a36Sopenharmony_ci **/ 2562306a36Sopenharmony_cistatic s32 e1000_init_mac_params_vf(struct e1000_hw *hw) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci /* VF's have no MTA Registers - PF feature only */ 3062306a36Sopenharmony_ci mac->mta_reg_count = 128; 3162306a36Sopenharmony_ci /* VF's have no access to RAR entries */ 3262306a36Sopenharmony_ci mac->rar_entry_count = 1; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* Function pointers */ 3562306a36Sopenharmony_ci /* reset */ 3662306a36Sopenharmony_ci mac->ops.reset_hw = e1000_reset_hw_vf; 3762306a36Sopenharmony_ci /* hw initialization */ 3862306a36Sopenharmony_ci mac->ops.init_hw = e1000_init_hw_vf; 3962306a36Sopenharmony_ci /* check for link */ 4062306a36Sopenharmony_ci mac->ops.check_for_link = e1000_check_for_link_vf; 4162306a36Sopenharmony_ci /* link info */ 4262306a36Sopenharmony_ci mac->ops.get_link_up_info = e1000_get_link_up_info_vf; 4362306a36Sopenharmony_ci /* multicast address update */ 4462306a36Sopenharmony_ci mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf; 4562306a36Sopenharmony_ci /* set mac address */ 4662306a36Sopenharmony_ci mac->ops.rar_set = e1000_rar_set_vf; 4762306a36Sopenharmony_ci /* read mac address */ 4862306a36Sopenharmony_ci mac->ops.read_mac_addr = e1000_read_mac_addr_vf; 4962306a36Sopenharmony_ci /* set mac filter */ 5062306a36Sopenharmony_ci mac->ops.set_uc_addr = e1000_set_uc_addr_vf; 5162306a36Sopenharmony_ci /* set vlan filter table array */ 5262306a36Sopenharmony_ci mac->ops.set_vfta = e1000_set_vfta_vf; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return E1000_SUCCESS; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/** 5862306a36Sopenharmony_ci * e1000_init_function_pointers_vf - Inits function pointers 5962306a36Sopenharmony_ci * @hw: pointer to the HW structure 6062306a36Sopenharmony_ci **/ 6162306a36Sopenharmony_civoid e1000_init_function_pointers_vf(struct e1000_hw *hw) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci hw->mac.ops.init_params = e1000_init_mac_params_vf; 6462306a36Sopenharmony_ci hw->mbx.ops.init_params = e1000_init_mbx_params_vf; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/** 6862306a36Sopenharmony_ci * e1000_get_link_up_info_vf - Gets link info. 6962306a36Sopenharmony_ci * @hw: pointer to the HW structure 7062306a36Sopenharmony_ci * @speed: pointer to 16 bit value to store link speed. 7162306a36Sopenharmony_ci * @duplex: pointer to 16 bit value to store duplex. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * Since we cannot read the PHY and get accurate link info, we must rely upon 7462306a36Sopenharmony_ci * the status register's data which is often stale and inaccurate. 7562306a36Sopenharmony_ci **/ 7662306a36Sopenharmony_cistatic s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed, 7762306a36Sopenharmony_ci u16 *duplex) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci s32 status; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci status = er32(STATUS); 8262306a36Sopenharmony_ci if (status & E1000_STATUS_SPEED_1000) 8362306a36Sopenharmony_ci *speed = SPEED_1000; 8462306a36Sopenharmony_ci else if (status & E1000_STATUS_SPEED_100) 8562306a36Sopenharmony_ci *speed = SPEED_100; 8662306a36Sopenharmony_ci else 8762306a36Sopenharmony_ci *speed = SPEED_10; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (status & E1000_STATUS_FD) 9062306a36Sopenharmony_ci *duplex = FULL_DUPLEX; 9162306a36Sopenharmony_ci else 9262306a36Sopenharmony_ci *duplex = HALF_DUPLEX; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return E1000_SUCCESS; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/** 9862306a36Sopenharmony_ci * e1000_reset_hw_vf - Resets the HW 9962306a36Sopenharmony_ci * @hw: pointer to the HW structure 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci * VF's provide a function level reset. This is done using bit 26 of ctrl_reg. 10262306a36Sopenharmony_ci * This is all the reset we can perform on a VF. 10362306a36Sopenharmony_ci **/ 10462306a36Sopenharmony_cistatic s32 e1000_reset_hw_vf(struct e1000_hw *hw) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 10762306a36Sopenharmony_ci u32 timeout = E1000_VF_INIT_TIMEOUT; 10862306a36Sopenharmony_ci u32 ret_val = -E1000_ERR_MAC_INIT; 10962306a36Sopenharmony_ci u32 msgbuf[3]; 11062306a36Sopenharmony_ci u8 *addr = (u8 *)(&msgbuf[1]); 11162306a36Sopenharmony_ci u32 ctrl; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* assert VF queue/interrupt reset */ 11462306a36Sopenharmony_ci ctrl = er32(CTRL); 11562306a36Sopenharmony_ci ew32(CTRL, ctrl | E1000_CTRL_RST); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* we cannot initialize while the RSTI / RSTD bits are asserted */ 11862306a36Sopenharmony_ci while (!mbx->ops.check_for_rst(hw) && timeout) { 11962306a36Sopenharmony_ci timeout--; 12062306a36Sopenharmony_ci udelay(5); 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (timeout) { 12462306a36Sopenharmony_ci /* mailbox timeout can now become active */ 12562306a36Sopenharmony_ci mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* notify PF of VF reset completion */ 12862306a36Sopenharmony_ci msgbuf[0] = E1000_VF_RESET; 12962306a36Sopenharmony_ci mbx->ops.write_posted(hw, msgbuf, 1); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci mdelay(10); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* set our "perm_addr" based on info provided by PF */ 13462306a36Sopenharmony_ci ret_val = mbx->ops.read_posted(hw, msgbuf, 3); 13562306a36Sopenharmony_ci if (!ret_val) { 13662306a36Sopenharmony_ci switch (msgbuf[0]) { 13762306a36Sopenharmony_ci case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK: 13862306a36Sopenharmony_ci memcpy(hw->mac.perm_addr, addr, ETH_ALEN); 13962306a36Sopenharmony_ci break; 14062306a36Sopenharmony_ci case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK: 14162306a36Sopenharmony_ci eth_zero_addr(hw->mac.perm_addr); 14262306a36Sopenharmony_ci break; 14362306a36Sopenharmony_ci default: 14462306a36Sopenharmony_ci ret_val = -E1000_ERR_MAC_INIT; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return ret_val; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/** 15362306a36Sopenharmony_ci * e1000_init_hw_vf - Inits the HW 15462306a36Sopenharmony_ci * @hw: pointer to the HW structure 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * Not much to do here except clear the PF Reset indication if there is one. 15762306a36Sopenharmony_ci **/ 15862306a36Sopenharmony_cistatic s32 e1000_init_hw_vf(struct e1000_hw *hw) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci /* attempt to set and restore our mac address */ 16162306a36Sopenharmony_ci e1000_rar_set_vf(hw, hw->mac.addr, 0); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return E1000_SUCCESS; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/** 16762306a36Sopenharmony_ci * e1000_hash_mc_addr_vf - Generate a multicast hash value 16862306a36Sopenharmony_ci * @hw: pointer to the HW structure 16962306a36Sopenharmony_ci * @mc_addr: pointer to a multicast address 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci * Generates a multicast address hash value which is used to determine 17262306a36Sopenharmony_ci * the multicast filter table array address and new table value. See 17362306a36Sopenharmony_ci * e1000_mta_set_generic() 17462306a36Sopenharmony_ci **/ 17562306a36Sopenharmony_cistatic u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci u32 hash_value, hash_mask; 17862306a36Sopenharmony_ci u8 bit_shift = 0; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Register count multiplied by bits per register */ 18162306a36Sopenharmony_ci hash_mask = (hw->mac.mta_reg_count * 32) - 1; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* The bit_shift is the number of left-shifts 18462306a36Sopenharmony_ci * where 0xFF would still fall within the hash mask. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci while (hash_mask >> bit_shift != 0xFF) 18762306a36Sopenharmony_ci bit_shift++; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | 19062306a36Sopenharmony_ci (((u16)mc_addr[5]) << bit_shift))); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci return hash_value; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/** 19662306a36Sopenharmony_ci * e1000_update_mc_addr_list_vf - Update Multicast addresses 19762306a36Sopenharmony_ci * @hw: pointer to the HW structure 19862306a36Sopenharmony_ci * @mc_addr_list: array of multicast addresses to program 19962306a36Sopenharmony_ci * @mc_addr_count: number of multicast addresses to program 20062306a36Sopenharmony_ci * @rar_used_count: the first RAR register free to program 20162306a36Sopenharmony_ci * @rar_count: total number of supported Receive Address Registers 20262306a36Sopenharmony_ci * 20362306a36Sopenharmony_ci * Updates the Receive Address Registers and Multicast Table Array. 20462306a36Sopenharmony_ci * The caller must have a packed mc_addr_list of multicast addresses. 20562306a36Sopenharmony_ci * The parameter rar_count will usually be hw->mac.rar_entry_count 20662306a36Sopenharmony_ci * unless there are workarounds that change this. 20762306a36Sopenharmony_ci **/ 20862306a36Sopenharmony_cistatic void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, 20962306a36Sopenharmony_ci u8 *mc_addr_list, u32 mc_addr_count, 21062306a36Sopenharmony_ci u32 rar_used_count, u32 rar_count) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 21362306a36Sopenharmony_ci u32 msgbuf[E1000_VFMAILBOX_SIZE]; 21462306a36Sopenharmony_ci u16 *hash_list = (u16 *)&msgbuf[1]; 21562306a36Sopenharmony_ci u32 hash_value; 21662306a36Sopenharmony_ci u32 cnt, i; 21762306a36Sopenharmony_ci s32 ret_val; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /* Each entry in the list uses 1 16 bit word. We have 30 22062306a36Sopenharmony_ci * 16 bit words available in our HW msg buffer (minus 1 for the 22162306a36Sopenharmony_ci * msg type). That's 30 hash values if we pack 'em right. If 22262306a36Sopenharmony_ci * there are more than 30 MC addresses to add then punt the 22362306a36Sopenharmony_ci * extras for now and then add code to handle more than 30 later. 22462306a36Sopenharmony_ci * It would be unusual for a server to request that many multi-cast 22562306a36Sopenharmony_ci * addresses except for in large enterprise network environments. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; 22962306a36Sopenharmony_ci msgbuf[0] = E1000_VF_SET_MULTICAST; 23062306a36Sopenharmony_ci msgbuf[0] |= cnt << E1000_VT_MSGINFO_SHIFT; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (i = 0; i < cnt; i++) { 23362306a36Sopenharmony_ci hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list); 23462306a36Sopenharmony_ci hash_list[i] = hash_value & 0x0FFFF; 23562306a36Sopenharmony_ci mc_addr_list += ETH_ALEN; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci ret_val = mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE); 23962306a36Sopenharmony_ci if (!ret_val) 24062306a36Sopenharmony_ci mbx->ops.read_posted(hw, msgbuf, 1); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci/** 24462306a36Sopenharmony_ci * e1000_set_vfta_vf - Set/Unset vlan filter table address 24562306a36Sopenharmony_ci * @hw: pointer to the HW structure 24662306a36Sopenharmony_ci * @vid: determines the vfta register and bit to set/unset 24762306a36Sopenharmony_ci * @set: if true then set bit, else clear bit 24862306a36Sopenharmony_ci **/ 24962306a36Sopenharmony_cistatic s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 25262306a36Sopenharmony_ci u32 msgbuf[2]; 25362306a36Sopenharmony_ci s32 err; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci msgbuf[0] = E1000_VF_SET_VLAN; 25662306a36Sopenharmony_ci msgbuf[1] = vid; 25762306a36Sopenharmony_ci /* Setting the 8 bit field MSG INFO to true indicates "add" */ 25862306a36Sopenharmony_ci if (set) 25962306a36Sopenharmony_ci msgbuf[0] |= BIT(E1000_VT_MSGINFO_SHIFT); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci mbx->ops.write_posted(hw, msgbuf, 2); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci err = mbx->ops.read_posted(hw, msgbuf, 2); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* if nacked the vlan was rejected */ 26862306a36Sopenharmony_ci if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK))) 26962306a36Sopenharmony_ci err = -E1000_ERR_MAC_INIT; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci return err; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/** 27562306a36Sopenharmony_ci * e1000_rlpml_set_vf - Set the maximum receive packet length 27662306a36Sopenharmony_ci * @hw: pointer to the HW structure 27762306a36Sopenharmony_ci * @max_size: value to assign to max frame size 27862306a36Sopenharmony_ci **/ 27962306a36Sopenharmony_civoid e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 28262306a36Sopenharmony_ci u32 msgbuf[2]; 28362306a36Sopenharmony_ci s32 ret_val; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci msgbuf[0] = E1000_VF_SET_LPE; 28662306a36Sopenharmony_ci msgbuf[1] = max_size; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci ret_val = mbx->ops.write_posted(hw, msgbuf, 2); 28962306a36Sopenharmony_ci if (!ret_val) 29062306a36Sopenharmony_ci mbx->ops.read_posted(hw, msgbuf, 1); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/** 29462306a36Sopenharmony_ci * e1000_rar_set_vf - set device MAC address 29562306a36Sopenharmony_ci * @hw: pointer to the HW structure 29662306a36Sopenharmony_ci * @addr: pointer to the receive address 29762306a36Sopenharmony_ci * @index: receive address array register 29862306a36Sopenharmony_ci **/ 29962306a36Sopenharmony_cistatic void e1000_rar_set_vf(struct e1000_hw *hw, u8 *addr, u32 index) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 30262306a36Sopenharmony_ci u32 msgbuf[3]; 30362306a36Sopenharmony_ci u8 *msg_addr = (u8 *)(&msgbuf[1]); 30462306a36Sopenharmony_ci s32 ret_val; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci memset(msgbuf, 0, 12); 30762306a36Sopenharmony_ci msgbuf[0] = E1000_VF_SET_MAC_ADDR; 30862306a36Sopenharmony_ci memcpy(msg_addr, addr, ETH_ALEN); 30962306a36Sopenharmony_ci ret_val = mbx->ops.write_posted(hw, msgbuf, 3); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (!ret_val) 31262306a36Sopenharmony_ci ret_val = mbx->ops.read_posted(hw, msgbuf, 3); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* if nacked the address was rejected, use "perm_addr" */ 31762306a36Sopenharmony_ci if (!ret_val && 31862306a36Sopenharmony_ci (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK))) 31962306a36Sopenharmony_ci e1000_read_mac_addr_vf(hw); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/** 32362306a36Sopenharmony_ci * e1000_read_mac_addr_vf - Read device MAC address 32462306a36Sopenharmony_ci * @hw: pointer to the HW structure 32562306a36Sopenharmony_ci **/ 32662306a36Sopenharmony_cistatic s32 e1000_read_mac_addr_vf(struct e1000_hw *hw) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci memcpy(hw->mac.addr, hw->mac.perm_addr, ETH_ALEN); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return E1000_SUCCESS; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/** 33462306a36Sopenharmony_ci * e1000_set_uc_addr_vf - Set or clear unicast filters 33562306a36Sopenharmony_ci * @hw: pointer to the HW structure 33662306a36Sopenharmony_ci * @sub_cmd: add or clear filters 33762306a36Sopenharmony_ci * @addr: pointer to the filter MAC address 33862306a36Sopenharmony_ci **/ 33962306a36Sopenharmony_cistatic s32 e1000_set_uc_addr_vf(struct e1000_hw *hw, u32 sub_cmd, u8 *addr) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 34262306a36Sopenharmony_ci u32 msgbuf[3], msgbuf_chk; 34362306a36Sopenharmony_ci u8 *msg_addr = (u8 *)(&msgbuf[1]); 34462306a36Sopenharmony_ci s32 ret_val; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci memset(msgbuf, 0, sizeof(msgbuf)); 34762306a36Sopenharmony_ci msgbuf[0] |= sub_cmd; 34862306a36Sopenharmony_ci msgbuf[0] |= E1000_VF_SET_MAC_ADDR; 34962306a36Sopenharmony_ci msgbuf_chk = msgbuf[0]; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (addr) 35262306a36Sopenharmony_ci memcpy(msg_addr, addr, ETH_ALEN); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci ret_val = mbx->ops.write_posted(hw, msgbuf, 3); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (!ret_val) 35762306a36Sopenharmony_ci ret_val = mbx->ops.read_posted(hw, msgbuf, 3); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (!ret_val) { 36262306a36Sopenharmony_ci msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (msgbuf[0] == (msgbuf_chk | E1000_VT_MSGTYPE_NACK)) 36562306a36Sopenharmony_ci return -ENOSPC; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci return ret_val; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci/** 37262306a36Sopenharmony_ci * e1000_check_for_link_vf - Check for link for a virtual interface 37362306a36Sopenharmony_ci * @hw: pointer to the HW structure 37462306a36Sopenharmony_ci * 37562306a36Sopenharmony_ci * Checks to see if the underlying PF is still talking to the VF and 37662306a36Sopenharmony_ci * if it is then it reports the link state to the hardware, otherwise 37762306a36Sopenharmony_ci * it reports link down and returns an error. 37862306a36Sopenharmony_ci **/ 37962306a36Sopenharmony_cistatic s32 e1000_check_for_link_vf(struct e1000_hw *hw) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 38262306a36Sopenharmony_ci struct e1000_mac_info *mac = &hw->mac; 38362306a36Sopenharmony_ci s32 ret_val = E1000_SUCCESS; 38462306a36Sopenharmony_ci u32 in_msg = 0; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* We only want to run this if there has been a rst asserted. 38762306a36Sopenharmony_ci * in this case that could mean a link change, device reset, 38862306a36Sopenharmony_ci * or a virtual function reset 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci /* If we were hit with a reset or timeout drop the link */ 39262306a36Sopenharmony_ci if (!mbx->ops.check_for_rst(hw) || !mbx->timeout) 39362306a36Sopenharmony_ci mac->get_link_status = true; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (!mac->get_link_status) 39662306a36Sopenharmony_ci goto out; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* if link status is down no point in checking to see if PF is up */ 39962306a36Sopenharmony_ci if (!(er32(STATUS) & E1000_STATUS_LU)) 40062306a36Sopenharmony_ci goto out; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci /* if the read failed it could just be a mailbox collision, best wait 40362306a36Sopenharmony_ci * until we are called again and don't report an error 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci if (mbx->ops.read(hw, &in_msg, 1)) 40662306a36Sopenharmony_ci goto out; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* if incoming message isn't clear to send we are waiting on response */ 40962306a36Sopenharmony_ci if (!(in_msg & E1000_VT_MSGTYPE_CTS)) { 41062306a36Sopenharmony_ci /* msg is not CTS and is NACK we must have lost CTS status */ 41162306a36Sopenharmony_ci if (in_msg & E1000_VT_MSGTYPE_NACK) 41262306a36Sopenharmony_ci ret_val = -E1000_ERR_MAC_INIT; 41362306a36Sopenharmony_ci goto out; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci /* the PF is talking, if we timed out in the past we reinit */ 41762306a36Sopenharmony_ci if (!mbx->timeout) { 41862306a36Sopenharmony_ci ret_val = -E1000_ERR_MAC_INIT; 41962306a36Sopenharmony_ci goto out; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* if we passed all the tests above then the link is up and we no 42362306a36Sopenharmony_ci * longer need to check for link 42462306a36Sopenharmony_ci */ 42562306a36Sopenharmony_ci mac->get_link_status = false; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ciout: 42862306a36Sopenharmony_ci return ret_val; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 431