1950820f1SZaiyu Wang /* SPDX-License-Identifier: BSD-3-Clause 2950820f1SZaiyu Wang * Copyright(c) 2018-2025 Beijing WangXun Technology Co., Ltd. 3950820f1SZaiyu Wang * Copyright(c) 2010-2017 Intel Corporation 4950820f1SZaiyu Wang */ 5950820f1SZaiyu Wang 6950820f1SZaiyu Wang #include "ngbe_type.h" 7ace44974SZaiyu Wang #include "ngbe_mbx.h" 8950820f1SZaiyu Wang #include "ngbe_vf.h" 9950820f1SZaiyu Wang 1066070ca4SZaiyu Wang /* ngbe_virt_clr_reg - Set register to default (power on) state. 1166070ca4SZaiyu Wang * @hw: pointer to hardware structure 1266070ca4SZaiyu Wang */ 1366070ca4SZaiyu Wang static void ngbe_virt_clr_reg(struct ngbe_hw *hw) 1466070ca4SZaiyu Wang { 1566070ca4SZaiyu Wang u32 vfsrrctl; 1666070ca4SZaiyu Wang 1766070ca4SZaiyu Wang /* default values (BUF_SIZE = 2048, HDR_SIZE = 256) */ 1866070ca4SZaiyu Wang vfsrrctl = NGBE_RXCFG_HDRLEN(NGBE_RX_HDR_SIZE); 1966070ca4SZaiyu Wang vfsrrctl |= NGBE_RXCFG_PKTLEN(NGBE_RX_BUF_SIZE); 2066070ca4SZaiyu Wang 2166070ca4SZaiyu Wang wr32m(hw, NGBE_RXCFG(0), 2266070ca4SZaiyu Wang (NGBE_RXCFG_HDRLEN_MASK | NGBE_RXCFG_PKTLEN_MASK), 2366070ca4SZaiyu Wang vfsrrctl); 2466070ca4SZaiyu Wang 2566070ca4SZaiyu Wang 2666070ca4SZaiyu Wang ngbe_flush(hw); 2766070ca4SZaiyu Wang } 2866070ca4SZaiyu Wang 2966070ca4SZaiyu Wang /** 3066070ca4SZaiyu Wang * ngbe_start_hw_vf - Prepare hardware for Tx/Rx 3166070ca4SZaiyu Wang * @hw: pointer to hardware structure 3266070ca4SZaiyu Wang * 3366070ca4SZaiyu Wang * Starts the hardware by filling the bus info structure and media type, clears 3466070ca4SZaiyu Wang * all on chip counters, initializes receive address registers, multicast 3566070ca4SZaiyu Wang * table, VLAN filter table, calls routine to set up link and flow control 3666070ca4SZaiyu Wang * settings, and leaves transmit and receive units disabled and uninitialized 3766070ca4SZaiyu Wang **/ 3866070ca4SZaiyu Wang s32 ngbe_start_hw_vf(struct ngbe_hw *hw) 3966070ca4SZaiyu Wang { 4066070ca4SZaiyu Wang /* Clear adapter stopped flag */ 4166070ca4SZaiyu Wang hw->adapter_stopped = false; 4266070ca4SZaiyu Wang 4366070ca4SZaiyu Wang return 0; 4466070ca4SZaiyu Wang } 4566070ca4SZaiyu Wang 4666070ca4SZaiyu Wang /** 4766070ca4SZaiyu Wang * ngbe_init_hw_vf - virtual function hardware initialization 4866070ca4SZaiyu Wang * @hw: pointer to hardware structure 4966070ca4SZaiyu Wang * 5066070ca4SZaiyu Wang * Initialize the hardware by resetting the hardware and then starting 5166070ca4SZaiyu Wang * the hardware 5266070ca4SZaiyu Wang **/ 5366070ca4SZaiyu Wang s32 ngbe_init_hw_vf(struct ngbe_hw *hw) 5466070ca4SZaiyu Wang { 5566070ca4SZaiyu Wang s32 status = hw->mac.start_hw(hw); 5666070ca4SZaiyu Wang 5766070ca4SZaiyu Wang hw->mac.get_mac_addr(hw, hw->mac.addr); 5866070ca4SZaiyu Wang 5966070ca4SZaiyu Wang return status; 6066070ca4SZaiyu Wang } 6166070ca4SZaiyu Wang 6266070ca4SZaiyu Wang /** 6366070ca4SZaiyu Wang * ngbe_reset_hw_vf - Performs hardware reset 6466070ca4SZaiyu Wang * @hw: pointer to hardware structure 6566070ca4SZaiyu Wang * 6666070ca4SZaiyu Wang * Resets the hardware by resetting the transmit and receive units, masks and 6766070ca4SZaiyu Wang * clears all interrupts. 6866070ca4SZaiyu Wang **/ 6966070ca4SZaiyu Wang s32 ngbe_reset_hw_vf(struct ngbe_hw *hw) 7066070ca4SZaiyu Wang { 7166070ca4SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 7266070ca4SZaiyu Wang u32 timeout = NGBE_VF_INIT_TIMEOUT; 7366070ca4SZaiyu Wang s32 ret_val = NGBE_ERR_INVALID_MAC_ADDR; 7466070ca4SZaiyu Wang u32 msgbuf[NGBE_VF_PERMADDR_MSG_LEN]; 7566070ca4SZaiyu Wang u8 *addr = (u8 *)(&msgbuf[1]); 7666070ca4SZaiyu Wang 7766070ca4SZaiyu Wang /* Call adapter stop to disable tx/rx and clear interrupts */ 7866070ca4SZaiyu Wang hw->mac.stop_hw(hw); 7966070ca4SZaiyu Wang 8066070ca4SZaiyu Wang /* reset the api version */ 8166070ca4SZaiyu Wang hw->api_version = ngbe_mbox_api_10; 8266070ca4SZaiyu Wang 8366070ca4SZaiyu Wang /* backup msix vectors */ 8466070ca4SZaiyu Wang mbx->timeout = NGBE_VF_MBX_INIT_TIMEOUT; 8566070ca4SZaiyu Wang msgbuf[0] = NGBE_VF_BACKUP; 8666070ca4SZaiyu Wang mbx->write_posted(hw, msgbuf, 1, 0); 8766070ca4SZaiyu Wang msec_delay(10); 8866070ca4SZaiyu Wang 8966070ca4SZaiyu Wang DEBUGOUT("Issuing a function level reset to MAC"); 9066070ca4SZaiyu Wang wr32(hw, NGBE_VFRST, NGBE_VFRST_SET); 9166070ca4SZaiyu Wang ngbe_flush(hw); 9266070ca4SZaiyu Wang msec_delay(50); 9366070ca4SZaiyu Wang 9466070ca4SZaiyu Wang hw->offset_loaded = 1; 9566070ca4SZaiyu Wang 9666070ca4SZaiyu Wang /* we cannot reset while the RSTI / RSTD bits are asserted */ 9766070ca4SZaiyu Wang while (!mbx->check_for_rst(hw, 0) && timeout) { 9866070ca4SZaiyu Wang timeout--; 9966070ca4SZaiyu Wang usec_delay(5); 10066070ca4SZaiyu Wang } 10166070ca4SZaiyu Wang 10266070ca4SZaiyu Wang if (!timeout) 10366070ca4SZaiyu Wang return NGBE_ERR_RESET_FAILED; 10466070ca4SZaiyu Wang 10566070ca4SZaiyu Wang /* Reset VF registers to initial values */ 10666070ca4SZaiyu Wang ngbe_virt_clr_reg(hw); 10766070ca4SZaiyu Wang 10866070ca4SZaiyu Wang /* mailbox timeout can now become active */ 10966070ca4SZaiyu Wang mbx->timeout = NGBE_VF_MBX_INIT_TIMEOUT; 11066070ca4SZaiyu Wang 11166070ca4SZaiyu Wang msgbuf[0] = NGBE_VF_RESET; 11266070ca4SZaiyu Wang mbx->write_posted(hw, msgbuf, 1, 0); 11366070ca4SZaiyu Wang 11466070ca4SZaiyu Wang msec_delay(10); 11566070ca4SZaiyu Wang 11666070ca4SZaiyu Wang /* 11766070ca4SZaiyu Wang * set our "perm_addr" based on info provided by PF 11866070ca4SZaiyu Wang * also set up the mc_filter_type which is piggy backed 11966070ca4SZaiyu Wang * on the mac address in word 3 12066070ca4SZaiyu Wang */ 12166070ca4SZaiyu Wang ret_val = mbx->read_posted(hw, msgbuf, 12266070ca4SZaiyu Wang NGBE_VF_PERMADDR_MSG_LEN, 0); 12366070ca4SZaiyu Wang if (ret_val) 12466070ca4SZaiyu Wang return ret_val; 12566070ca4SZaiyu Wang 12666070ca4SZaiyu Wang if (msgbuf[0] != (NGBE_VF_RESET | NGBE_VT_MSGTYPE_ACK) && 12766070ca4SZaiyu Wang msgbuf[0] != (NGBE_VF_RESET | NGBE_VT_MSGTYPE_NACK)) 12866070ca4SZaiyu Wang return NGBE_ERR_INVALID_MAC_ADDR; 12966070ca4SZaiyu Wang 13066070ca4SZaiyu Wang if (msgbuf[0] == (NGBE_VF_RESET | NGBE_VT_MSGTYPE_ACK)) 13166070ca4SZaiyu Wang memcpy(hw->mac.perm_addr, addr, ETH_ADDR_LEN); 13266070ca4SZaiyu Wang 13366070ca4SZaiyu Wang hw->mac.mc_filter_type = msgbuf[NGBE_VF_MC_TYPE_WORD]; 13466070ca4SZaiyu Wang 13566070ca4SZaiyu Wang return ret_val; 13666070ca4SZaiyu Wang } 13766070ca4SZaiyu Wang 13866070ca4SZaiyu Wang /** 13966070ca4SZaiyu Wang * ngbe_stop_hw_vf - Generic stop Tx/Rx units 14066070ca4SZaiyu Wang * @hw: pointer to hardware structure 14166070ca4SZaiyu Wang * 14266070ca4SZaiyu Wang * Sets the adapter_stopped flag within ngbe_hw struct. Clears interrupts, 14366070ca4SZaiyu Wang * disables transmit and receive units. The adapter_stopped flag is used by 14466070ca4SZaiyu Wang * the shared code and drivers to determine if the adapter is in a stopped 14566070ca4SZaiyu Wang * state and should not touch the hardware. 14666070ca4SZaiyu Wang **/ 14766070ca4SZaiyu Wang s32 ngbe_stop_hw_vf(struct ngbe_hw *hw) 14866070ca4SZaiyu Wang { 14966070ca4SZaiyu Wang u16 i; 15066070ca4SZaiyu Wang 15166070ca4SZaiyu Wang /* 15266070ca4SZaiyu Wang * Set the adapter_stopped flag so other driver functions stop touching 15366070ca4SZaiyu Wang * the hardware 15466070ca4SZaiyu Wang */ 15566070ca4SZaiyu Wang hw->adapter_stopped = true; 15666070ca4SZaiyu Wang 15766070ca4SZaiyu Wang /* Clear interrupt mask to stop from interrupts being generated */ 15866070ca4SZaiyu Wang wr32(hw, NGBE_VFIMC, NGBE_VFIMC_MASK); 15966070ca4SZaiyu Wang 16066070ca4SZaiyu Wang /* Clear any pending interrupts, flush previous writes */ 16166070ca4SZaiyu Wang wr32(hw, NGBE_VFICR, NGBE_VFICR_MASK); 16266070ca4SZaiyu Wang 16366070ca4SZaiyu Wang /* Disable the transmit unit. Each queue must be disabled. */ 16466070ca4SZaiyu Wang for (i = 0; i < hw->mac.max_tx_queues; i++) 16566070ca4SZaiyu Wang wr32(hw, NGBE_TXCFG(i), NGBE_TXCFG_FLUSH); 16666070ca4SZaiyu Wang 16766070ca4SZaiyu Wang /* Disable the receive unit by stopping each queue */ 16866070ca4SZaiyu Wang for (i = 0; i < hw->mac.max_rx_queues; i++) 16966070ca4SZaiyu Wang wr32m(hw, NGBE_RXCFG(i), NGBE_RXCFG_ENA, 0); 17066070ca4SZaiyu Wang 17166070ca4SZaiyu Wang /* Clear packet split and pool config */ 17266070ca4SZaiyu Wang wr32(hw, NGBE_VFPLCFG, 0); 17366070ca4SZaiyu Wang hw->rx_loaded = 1; 17466070ca4SZaiyu Wang 17566070ca4SZaiyu Wang /* flush all queues disables */ 17666070ca4SZaiyu Wang ngbe_flush(hw); 17766070ca4SZaiyu Wang msec_delay(2); 17866070ca4SZaiyu Wang 17966070ca4SZaiyu Wang return 0; 18066070ca4SZaiyu Wang } 18166070ca4SZaiyu Wang 182*e0c29b2fSZaiyu Wang /** 183*e0c29b2fSZaiyu Wang * ngbe_mta_vector - Determines bit-vector in multicast table to set 184*e0c29b2fSZaiyu Wang * @hw: pointer to hardware structure 185*e0c29b2fSZaiyu Wang * @mc_addr: the multicast address 186*e0c29b2fSZaiyu Wang **/ 187*e0c29b2fSZaiyu Wang STATIC s32 ngbe_mta_vector(struct ngbe_hw *hw, u8 *mc_addr) 188*e0c29b2fSZaiyu Wang { 189*e0c29b2fSZaiyu Wang u32 vector = 0; 190*e0c29b2fSZaiyu Wang 191*e0c29b2fSZaiyu Wang switch (hw->mac.mc_filter_type) { 192*e0c29b2fSZaiyu Wang case 0: /* use bits [47:36] of the address */ 193*e0c29b2fSZaiyu Wang vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 194*e0c29b2fSZaiyu Wang break; 195*e0c29b2fSZaiyu Wang case 1: /* use bits [46:35] of the address */ 196*e0c29b2fSZaiyu Wang vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 197*e0c29b2fSZaiyu Wang break; 198*e0c29b2fSZaiyu Wang case 2: /* use bits [45:34] of the address */ 199*e0c29b2fSZaiyu Wang vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 200*e0c29b2fSZaiyu Wang break; 201*e0c29b2fSZaiyu Wang case 3: /* use bits [43:32] of the address */ 202*e0c29b2fSZaiyu Wang vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 203*e0c29b2fSZaiyu Wang break; 204*e0c29b2fSZaiyu Wang default: /* Invalid mc_filter_type */ 205*e0c29b2fSZaiyu Wang DEBUGOUT("MC filter type param set incorrectly"); 206*e0c29b2fSZaiyu Wang ASSERT(0); 207*e0c29b2fSZaiyu Wang break; 208*e0c29b2fSZaiyu Wang } 209*e0c29b2fSZaiyu Wang 210*e0c29b2fSZaiyu Wang /* vector can only be 12-bits or boundary will be exceeded */ 211*e0c29b2fSZaiyu Wang vector &= 0xFFF; 212*e0c29b2fSZaiyu Wang return vector; 213*e0c29b2fSZaiyu Wang } 214*e0c29b2fSZaiyu Wang 215ace44974SZaiyu Wang STATIC s32 ngbevf_write_msg_read_ack(struct ngbe_hw *hw, u32 *msg, 216ace44974SZaiyu Wang u32 *retmsg, u16 size) 217ace44974SZaiyu Wang { 218ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 219ace44974SZaiyu Wang s32 retval = mbx->write_posted(hw, msg, size, 0); 220ace44974SZaiyu Wang 221ace44974SZaiyu Wang if (retval) 222ace44974SZaiyu Wang return retval; 223ace44974SZaiyu Wang 224ace44974SZaiyu Wang return mbx->read_posted(hw, retmsg, size, 0); 225ace44974SZaiyu Wang } 226ace44974SZaiyu Wang 227ace44974SZaiyu Wang /** 2282aba42f6SZaiyu Wang * ngbe_set_rar_vf - set device MAC address 2292aba42f6SZaiyu Wang * @hw: pointer to hardware structure 2302aba42f6SZaiyu Wang * @index: Receive address register to write 2312aba42f6SZaiyu Wang * @addr: Address to put into receive address register 2322aba42f6SZaiyu Wang * @vmdq: VMDq "set" or "pool" index 2332aba42f6SZaiyu Wang * @enable_addr: set flag that address is active 2342aba42f6SZaiyu Wang **/ 2352aba42f6SZaiyu Wang s32 ngbe_set_rar_vf(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 2362aba42f6SZaiyu Wang u32 enable_addr) 2372aba42f6SZaiyu Wang { 2382aba42f6SZaiyu Wang u32 msgbuf[3]; 2392aba42f6SZaiyu Wang u8 *msg_addr = (u8 *)(&msgbuf[1]); 2402aba42f6SZaiyu Wang s32 ret_val; 2412aba42f6SZaiyu Wang 2422aba42f6SZaiyu Wang UNREFERENCED_PARAMETER(vmdq, enable_addr, index); 2432aba42f6SZaiyu Wang 2442aba42f6SZaiyu Wang memset(msgbuf, 0, 12); 2452aba42f6SZaiyu Wang msgbuf[0] = NGBE_VF_SET_MAC_ADDR; 2462aba42f6SZaiyu Wang memcpy(msg_addr, addr, 6); 2472aba42f6SZaiyu Wang ret_val = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3); 2482aba42f6SZaiyu Wang 2492aba42f6SZaiyu Wang msgbuf[0] &= ~NGBE_VT_MSGTYPE_CTS; 2502aba42f6SZaiyu Wang 2512aba42f6SZaiyu Wang /* if nacked the address was rejected, use "perm_addr" */ 2522aba42f6SZaiyu Wang if (!ret_val && 2532aba42f6SZaiyu Wang (msgbuf[0] == (NGBE_VF_SET_MAC_ADDR | NGBE_VT_MSGTYPE_NACK))) { 2542aba42f6SZaiyu Wang ngbe_get_mac_addr_vf(hw, hw->mac.addr); 2552aba42f6SZaiyu Wang return NGBE_ERR_MBX; 2562aba42f6SZaiyu Wang } 2572aba42f6SZaiyu Wang 2582aba42f6SZaiyu Wang return ret_val; 2592aba42f6SZaiyu Wang } 2602aba42f6SZaiyu Wang 2612aba42f6SZaiyu Wang /** 262*e0c29b2fSZaiyu Wang * ngbe_update_mc_addr_list_vf - Update Multicast addresses 263*e0c29b2fSZaiyu Wang * @hw: pointer to the HW structure 264*e0c29b2fSZaiyu Wang * @mc_addr_list: array of multicast addresses to program 265*e0c29b2fSZaiyu Wang * @mc_addr_count: number of multicast addresses to program 266*e0c29b2fSZaiyu Wang * @next: caller supplied function to return next address in list 267*e0c29b2fSZaiyu Wang * @clear: unused 268*e0c29b2fSZaiyu Wang * 269*e0c29b2fSZaiyu Wang * Updates the Multicast Table Array. 270*e0c29b2fSZaiyu Wang **/ 271*e0c29b2fSZaiyu Wang s32 ngbe_update_mc_addr_list_vf(struct ngbe_hw *hw, u8 *mc_addr_list, 272*e0c29b2fSZaiyu Wang u32 mc_addr_count, ngbe_mc_addr_itr next, 273*e0c29b2fSZaiyu Wang bool clear) 274*e0c29b2fSZaiyu Wang { 275*e0c29b2fSZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 276*e0c29b2fSZaiyu Wang u32 msgbuf[NGBE_P2VMBX_SIZE]; 277*e0c29b2fSZaiyu Wang u16 *vector_list = (u16 *)&msgbuf[1]; 278*e0c29b2fSZaiyu Wang u32 vector; 279*e0c29b2fSZaiyu Wang u32 cnt, i; 280*e0c29b2fSZaiyu Wang u32 vmdq; 281*e0c29b2fSZaiyu Wang 282*e0c29b2fSZaiyu Wang UNREFERENCED_PARAMETER(clear); 283*e0c29b2fSZaiyu Wang 284*e0c29b2fSZaiyu Wang /* Each entry in the list uses 1 16 bit word. We have 30 285*e0c29b2fSZaiyu Wang * 16 bit words available in our HW msg buffer (minus 1 for the 286*e0c29b2fSZaiyu Wang * msg type). That's 30 hash values if we pack 'em right. If 287*e0c29b2fSZaiyu Wang * there are more than 30 MC addresses to add then punt the 288*e0c29b2fSZaiyu Wang * extras for now and then add code to handle more than 30 later. 289*e0c29b2fSZaiyu Wang * It would be unusual for a server to request that many multi-cast 290*e0c29b2fSZaiyu Wang * addresses except for in large enterprise network environments. 291*e0c29b2fSZaiyu Wang */ 292*e0c29b2fSZaiyu Wang 293*e0c29b2fSZaiyu Wang DEBUGOUT("MC Addr Count = %d", mc_addr_count); 294*e0c29b2fSZaiyu Wang 295*e0c29b2fSZaiyu Wang cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; 296*e0c29b2fSZaiyu Wang msgbuf[0] = NGBE_VF_SET_MULTICAST; 297*e0c29b2fSZaiyu Wang msgbuf[0] |= cnt << NGBE_VT_MSGINFO_SHIFT; 298*e0c29b2fSZaiyu Wang 299*e0c29b2fSZaiyu Wang for (i = 0; i < cnt; i++) { 300*e0c29b2fSZaiyu Wang vector = ngbe_mta_vector(hw, next(hw, &mc_addr_list, &vmdq)); 301*e0c29b2fSZaiyu Wang DEBUGOUT("Hash value = 0x%03X", vector); 302*e0c29b2fSZaiyu Wang vector_list[i] = (u16)vector; 303*e0c29b2fSZaiyu Wang } 304*e0c29b2fSZaiyu Wang 305*e0c29b2fSZaiyu Wang return mbx->write_posted(hw, msgbuf, NGBE_P2VMBX_SIZE, 0); 306*e0c29b2fSZaiyu Wang } 307*e0c29b2fSZaiyu Wang 308*e0c29b2fSZaiyu Wang /** 3097744e908SZaiyu Wang * ngbevf_update_xcast_mode - Update Multicast mode 3107744e908SZaiyu Wang * @hw: pointer to the HW structure 3117744e908SZaiyu Wang * @xcast_mode: new multicast mode 3127744e908SZaiyu Wang * 3137744e908SZaiyu Wang * Updates the Multicast Mode of VF. 3147744e908SZaiyu Wang **/ 3157744e908SZaiyu Wang s32 ngbevf_update_xcast_mode(struct ngbe_hw *hw, int xcast_mode) 3167744e908SZaiyu Wang { 3177744e908SZaiyu Wang u32 msgbuf[2]; 3187744e908SZaiyu Wang s32 err; 3197744e908SZaiyu Wang 3207744e908SZaiyu Wang switch (hw->api_version) { 3217744e908SZaiyu Wang case ngbe_mbox_api_12: 3227744e908SZaiyu Wang /* New modes were introduced in 1.3 version */ 3237744e908SZaiyu Wang if (xcast_mode > NGBEVF_XCAST_MODE_ALLMULTI) 3247744e908SZaiyu Wang return NGBE_ERR_FEATURE_NOT_SUPPORTED; 3257744e908SZaiyu Wang /* Fall through */ 3267744e908SZaiyu Wang case ngbe_mbox_api_13: 3277744e908SZaiyu Wang break; 3287744e908SZaiyu Wang default: 3297744e908SZaiyu Wang return NGBE_ERR_FEATURE_NOT_SUPPORTED; 3307744e908SZaiyu Wang } 3317744e908SZaiyu Wang 3327744e908SZaiyu Wang msgbuf[0] = NGBE_VF_UPDATE_XCAST_MODE; 3337744e908SZaiyu Wang msgbuf[1] = xcast_mode; 3347744e908SZaiyu Wang 3357744e908SZaiyu Wang err = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); 3367744e908SZaiyu Wang if (err) 3377744e908SZaiyu Wang return err; 3387744e908SZaiyu Wang 3397744e908SZaiyu Wang msgbuf[0] &= ~NGBE_VT_MSGTYPE_CTS; 3407744e908SZaiyu Wang if (msgbuf[0] == (NGBE_VF_UPDATE_XCAST_MODE | NGBE_VT_MSGTYPE_NACK)) 3417744e908SZaiyu Wang return NGBE_ERR_FEATURE_NOT_SUPPORTED; 3427744e908SZaiyu Wang return 0; 3437744e908SZaiyu Wang } 3447744e908SZaiyu Wang 3457744e908SZaiyu Wang /** 346f47dc03cSZaiyu Wang * ngbe_set_vfta_vf - Set/Unset vlan filter table address 347f47dc03cSZaiyu Wang * @hw: pointer to the HW structure 348f47dc03cSZaiyu Wang * @vlan: 12 bit VLAN ID 349f47dc03cSZaiyu Wang * @vind: unused by VF drivers 350f47dc03cSZaiyu Wang * @vlan_on: if true then set bit, else clear bit 351f47dc03cSZaiyu Wang * @vlvf_bypass: boolean flag indicating updating default pool is okay 352f47dc03cSZaiyu Wang * 353f47dc03cSZaiyu Wang * Turn on/off specified VLAN in the VLAN filter table. 354f47dc03cSZaiyu Wang **/ 355f47dc03cSZaiyu Wang s32 ngbe_set_vfta_vf(struct ngbe_hw *hw, u32 vlan, u32 vind, 356f47dc03cSZaiyu Wang bool vlan_on, bool vlvf_bypass) 357f47dc03cSZaiyu Wang { 358f47dc03cSZaiyu Wang u32 msgbuf[2]; 359f47dc03cSZaiyu Wang s32 ret_val; 360f47dc03cSZaiyu Wang 361f47dc03cSZaiyu Wang UNREFERENCED_PARAMETER(vind, vlvf_bypass); 362f47dc03cSZaiyu Wang 363f47dc03cSZaiyu Wang msgbuf[0] = NGBE_VF_SET_VLAN; 364f47dc03cSZaiyu Wang msgbuf[1] = vlan; 365f47dc03cSZaiyu Wang /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ 366f47dc03cSZaiyu Wang msgbuf[0] |= vlan_on << NGBE_VT_MSGINFO_SHIFT; 367f47dc03cSZaiyu Wang 368f47dc03cSZaiyu Wang ret_val = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); 369f47dc03cSZaiyu Wang if (!ret_val && (msgbuf[0] & NGBE_VT_MSGTYPE_ACK)) 370f47dc03cSZaiyu Wang return 0; 371f47dc03cSZaiyu Wang 372f47dc03cSZaiyu Wang return ret_val | (msgbuf[0] & NGBE_VT_MSGTYPE_NACK); 373f47dc03cSZaiyu Wang } 374f47dc03cSZaiyu Wang 375f47dc03cSZaiyu Wang /** 3762aba42f6SZaiyu Wang * ngbe_get_mac_addr_vf - Read device MAC address 3772aba42f6SZaiyu Wang * @hw: pointer to the HW structure 3782aba42f6SZaiyu Wang * @mac_addr: the MAC address 3792aba42f6SZaiyu Wang **/ 3802aba42f6SZaiyu Wang s32 ngbe_get_mac_addr_vf(struct ngbe_hw *hw, u8 *mac_addr) 3812aba42f6SZaiyu Wang { 3822aba42f6SZaiyu Wang int i; 3832aba42f6SZaiyu Wang 3842aba42f6SZaiyu Wang for (i = 0; i < ETH_ADDR_LEN; i++) 3852aba42f6SZaiyu Wang mac_addr[i] = hw->mac.perm_addr[i]; 3862aba42f6SZaiyu Wang 3872aba42f6SZaiyu Wang return 0; 3882aba42f6SZaiyu Wang } 3892aba42f6SZaiyu Wang 3902aba42f6SZaiyu Wang s32 ngbevf_set_uc_addr_vf(struct ngbe_hw *hw, u32 index, u8 *addr) 3912aba42f6SZaiyu Wang { 3922aba42f6SZaiyu Wang u32 msgbuf[3], msgbuf_chk; 3932aba42f6SZaiyu Wang u8 *msg_addr = (u8 *)(&msgbuf[1]); 3942aba42f6SZaiyu Wang s32 ret_val; 3952aba42f6SZaiyu Wang 3962aba42f6SZaiyu Wang memset(msgbuf, 0, sizeof(msgbuf)); 3972aba42f6SZaiyu Wang /* 3982aba42f6SZaiyu Wang * If index is one then this is the start of a new list and needs 3992aba42f6SZaiyu Wang * indication to the PF so it can do it's own list management. 4002aba42f6SZaiyu Wang * If it is zero then that tells the PF to just clear all of 4012aba42f6SZaiyu Wang * this VF's macvlans and there is no new list. 4022aba42f6SZaiyu Wang */ 4032aba42f6SZaiyu Wang msgbuf[0] |= index << NGBE_VT_MSGINFO_SHIFT; 4042aba42f6SZaiyu Wang msgbuf[0] |= NGBE_VF_SET_MACVLAN; 4052aba42f6SZaiyu Wang msgbuf_chk = msgbuf[0]; 4062aba42f6SZaiyu Wang if (addr) 4072aba42f6SZaiyu Wang memcpy(msg_addr, addr, 6); 4082aba42f6SZaiyu Wang 4092aba42f6SZaiyu Wang ret_val = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3); 4102aba42f6SZaiyu Wang if (!ret_val) { 4112aba42f6SZaiyu Wang msgbuf[0] &= ~NGBE_VT_MSGTYPE_CTS; 4122aba42f6SZaiyu Wang 4132aba42f6SZaiyu Wang if (msgbuf[0] == (msgbuf_chk | NGBE_VT_MSGTYPE_NACK)) 4142aba42f6SZaiyu Wang return NGBE_ERR_OUT_OF_MEM; 4152aba42f6SZaiyu Wang } 4162aba42f6SZaiyu Wang 4172aba42f6SZaiyu Wang return ret_val; 4182aba42f6SZaiyu Wang } 4192aba42f6SZaiyu Wang 4202aba42f6SZaiyu Wang /** 42162c072c0SZaiyu Wang * ngbe_check_mac_link_vf - Get link/speed status 42262c072c0SZaiyu Wang * @hw: pointer to hardware structure 42362c072c0SZaiyu Wang * @speed: pointer to link speed 42462c072c0SZaiyu Wang * @link_up: true is link is up, false otherwise 42562c072c0SZaiyu Wang * @autoneg_wait_to_complete: true when waiting for completion is needed 42662c072c0SZaiyu Wang * 42762c072c0SZaiyu Wang * Reads the links register to determine if link is up and the current speed 42862c072c0SZaiyu Wang **/ 42962c072c0SZaiyu Wang s32 ngbe_check_mac_link_vf(struct ngbe_hw *hw, u32 *speed, 43062c072c0SZaiyu Wang bool *link_up, bool wait_to_complete) 43162c072c0SZaiyu Wang { 43262c072c0SZaiyu Wang /** 43362c072c0SZaiyu Wang * for a quick link status checking, wait_to_compelet == 0, 43462c072c0SZaiyu Wang * skip PF link status checking 43562c072c0SZaiyu Wang */ 43662c072c0SZaiyu Wang bool no_pflink_check = 0; 43762c072c0SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 43862c072c0SZaiyu Wang struct ngbe_mac_info *mac = &hw->mac; 43962c072c0SZaiyu Wang s32 ret_val = 0; 44062c072c0SZaiyu Wang u32 links_reg; 44162c072c0SZaiyu Wang u32 in_msg = 0; 44262c072c0SZaiyu Wang 44362c072c0SZaiyu Wang UNREFERENCED_PARAMETER(wait_to_complete); 44462c072c0SZaiyu Wang 44562c072c0SZaiyu Wang /* If we were hit with a reset drop the link */ 44662c072c0SZaiyu Wang if (!mbx->check_for_rst(hw, 0) || !mbx->timeout) 44762c072c0SZaiyu Wang mac->get_link_status = true; 44862c072c0SZaiyu Wang 44962c072c0SZaiyu Wang if (!mac->get_link_status) 45062c072c0SZaiyu Wang goto out; 45162c072c0SZaiyu Wang 45262c072c0SZaiyu Wang /* if link status is down no point in checking to see if pf is up */ 45362c072c0SZaiyu Wang links_reg = rd32(hw, NGBE_VFSTATUS); 45462c072c0SZaiyu Wang if (!(links_reg & NGBE_VFSTATUS_BW_MASK)) 45562c072c0SZaiyu Wang goto out; 45662c072c0SZaiyu Wang 45762c072c0SZaiyu Wang /* for SFP+ modules and DA cables it can take up to 500usecs 45862c072c0SZaiyu Wang * before the link status is correct 45962c072c0SZaiyu Wang */ 46062c072c0SZaiyu Wang if (mac->type == ngbe_mac_em_vf) { 46162c072c0SZaiyu Wang if (po32m(hw, NGBE_VFSTATUS, NGBE_VFSTATUS_BW_MASK, 46262c072c0SZaiyu Wang 0, NULL, 5, 100)) 46362c072c0SZaiyu Wang goto out; 46462c072c0SZaiyu Wang } 46562c072c0SZaiyu Wang 46662c072c0SZaiyu Wang if (links_reg & NGBE_VFSTATUS_BW_1G) 46762c072c0SZaiyu Wang *speed = NGBE_LINK_SPEED_1GB_FULL; 46862c072c0SZaiyu Wang else if (links_reg & NGBE_VFSTATUS_BW_100M) 46962c072c0SZaiyu Wang *speed = NGBE_LINK_SPEED_100M_FULL; 47062c072c0SZaiyu Wang else if (links_reg & NGBE_VFSTATUS_BW_10M) 47162c072c0SZaiyu Wang *speed = NGBE_LINK_SPEED_10M_FULL; 47262c072c0SZaiyu Wang else 47362c072c0SZaiyu Wang *speed = NGBE_LINK_SPEED_UNKNOWN; 47462c072c0SZaiyu Wang 47562c072c0SZaiyu Wang if (no_pflink_check) { 47662c072c0SZaiyu Wang if (*speed == NGBE_LINK_SPEED_UNKNOWN) 47762c072c0SZaiyu Wang mac->get_link_status = true; 47862c072c0SZaiyu Wang else 47962c072c0SZaiyu Wang mac->get_link_status = false; 48062c072c0SZaiyu Wang 48162c072c0SZaiyu Wang goto out; 48262c072c0SZaiyu Wang } 48362c072c0SZaiyu Wang 48462c072c0SZaiyu Wang /* if the read failed it could just be a mailbox collision, best wait 48562c072c0SZaiyu Wang * until we are called again and don't report an error 48662c072c0SZaiyu Wang */ 48762c072c0SZaiyu Wang if (mbx->read(hw, &in_msg, 1, 0)) 48862c072c0SZaiyu Wang goto out; 48962c072c0SZaiyu Wang 49062c072c0SZaiyu Wang if (!(in_msg & NGBE_VT_MSGTYPE_CTS)) { 49162c072c0SZaiyu Wang /* msg is not CTS and is NACK we must have lost CTS status */ 49262c072c0SZaiyu Wang if (in_msg & NGBE_VT_MSGTYPE_NACK) 49362c072c0SZaiyu Wang ret_val = -1; 49462c072c0SZaiyu Wang goto out; 49562c072c0SZaiyu Wang } 49662c072c0SZaiyu Wang 49762c072c0SZaiyu Wang /* the pf is talking, if we timed out in the past we reinit */ 49862c072c0SZaiyu Wang if (!mbx->timeout) { 49962c072c0SZaiyu Wang ret_val = -1; 50062c072c0SZaiyu Wang goto out; 50162c072c0SZaiyu Wang } 50262c072c0SZaiyu Wang 50362c072c0SZaiyu Wang /* if we passed all the tests above then the link is up and we no 50462c072c0SZaiyu Wang * longer need to check for link 50562c072c0SZaiyu Wang */ 50662c072c0SZaiyu Wang mac->get_link_status = false; 50762c072c0SZaiyu Wang 50862c072c0SZaiyu Wang out: 50962c072c0SZaiyu Wang *link_up = !mac->get_link_status; 51062c072c0SZaiyu Wang return ret_val; 51162c072c0SZaiyu Wang } 51262c072c0SZaiyu Wang 51362c072c0SZaiyu Wang /** 51477102375SZaiyu Wang * ngbevf_rlpml_set_vf - Set the maximum receive packet length 51577102375SZaiyu Wang * @hw: pointer to the HW structure 51677102375SZaiyu Wang * @max_size: value to assign to max frame size 51777102375SZaiyu Wang **/ 51877102375SZaiyu Wang s32 ngbevf_rlpml_set_vf(struct ngbe_hw *hw, u16 max_size) 51977102375SZaiyu Wang { 52077102375SZaiyu Wang u32 msgbuf[2]; 52177102375SZaiyu Wang s32 retval; 52277102375SZaiyu Wang 52377102375SZaiyu Wang msgbuf[0] = NGBE_VF_SET_LPE; 52477102375SZaiyu Wang msgbuf[1] = max_size; 52577102375SZaiyu Wang 52677102375SZaiyu Wang retval = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2); 52777102375SZaiyu Wang if (retval) 52877102375SZaiyu Wang return retval; 52977102375SZaiyu Wang if ((msgbuf[0] & NGBE_VF_SET_LPE) && 53077102375SZaiyu Wang (msgbuf[0] & NGBE_VT_MSGTYPE_NACK)) 53177102375SZaiyu Wang return NGBE_ERR_MBX; 53277102375SZaiyu Wang 53377102375SZaiyu Wang return 0; 53477102375SZaiyu Wang } 53577102375SZaiyu Wang 53677102375SZaiyu Wang /** 537ace44974SZaiyu Wang * ngbevf_negotiate_api_version - Negotiate supported API version 538ace44974SZaiyu Wang * @hw: pointer to the HW structure 539ace44974SZaiyu Wang * @api: integer containing requested API version 540ace44974SZaiyu Wang **/ 541ace44974SZaiyu Wang int ngbevf_negotiate_api_version(struct ngbe_hw *hw, int api) 542ace44974SZaiyu Wang { 543ace44974SZaiyu Wang int err; 544ace44974SZaiyu Wang u32 msg[3]; 545ace44974SZaiyu Wang 546ace44974SZaiyu Wang /* Negotiate the mailbox API version */ 547ace44974SZaiyu Wang msg[0] = NGBE_VF_API_NEGOTIATE; 548ace44974SZaiyu Wang msg[1] = api; 549ace44974SZaiyu Wang msg[2] = 0; 550ace44974SZaiyu Wang 551ace44974SZaiyu Wang err = ngbevf_write_msg_read_ack(hw, msg, msg, 3); 552ace44974SZaiyu Wang if (!err) { 553ace44974SZaiyu Wang msg[0] &= ~NGBE_VT_MSGTYPE_CTS; 554ace44974SZaiyu Wang 555ace44974SZaiyu Wang /* Store value and return 0 on success */ 556ace44974SZaiyu Wang if (msg[0] == (NGBE_VF_API_NEGOTIATE | NGBE_VT_MSGTYPE_ACK)) { 557ace44974SZaiyu Wang hw->api_version = api; 558ace44974SZaiyu Wang return 0; 559ace44974SZaiyu Wang } 560ace44974SZaiyu Wang 561ace44974SZaiyu Wang err = NGBE_ERR_INVALID_ARGUMENT; 562ace44974SZaiyu Wang } 563ace44974SZaiyu Wang 564ace44974SZaiyu Wang return err; 565ace44974SZaiyu Wang } 566ace44974SZaiyu Wang 56766070ca4SZaiyu Wang int ngbevf_get_queues(struct ngbe_hw *hw, unsigned int *num_tcs, 56866070ca4SZaiyu Wang unsigned int *default_tc) 56966070ca4SZaiyu Wang { 57066070ca4SZaiyu Wang int err, i; 57166070ca4SZaiyu Wang u32 msg[5]; 57266070ca4SZaiyu Wang 57366070ca4SZaiyu Wang /* do nothing if API doesn't support ngbevf_get_queues */ 57466070ca4SZaiyu Wang switch (hw->api_version) { 57566070ca4SZaiyu Wang case ngbe_mbox_api_11: 57666070ca4SZaiyu Wang case ngbe_mbox_api_12: 57766070ca4SZaiyu Wang case ngbe_mbox_api_13: 57866070ca4SZaiyu Wang break; 57966070ca4SZaiyu Wang default: 58066070ca4SZaiyu Wang return 0; 58166070ca4SZaiyu Wang } 58266070ca4SZaiyu Wang 58366070ca4SZaiyu Wang /* Fetch queue configuration from the PF */ 58466070ca4SZaiyu Wang msg[0] = NGBE_VF_GET_QUEUES; 58566070ca4SZaiyu Wang for (i = 1; i < 5; i++) 58666070ca4SZaiyu Wang msg[i] = 0; 58766070ca4SZaiyu Wang 58866070ca4SZaiyu Wang err = ngbevf_write_msg_read_ack(hw, msg, msg, 5); 58966070ca4SZaiyu Wang if (!err) { 59066070ca4SZaiyu Wang msg[0] &= ~NGBE_VT_MSGTYPE_CTS; 59166070ca4SZaiyu Wang 59266070ca4SZaiyu Wang /* 59366070ca4SZaiyu Wang * if we didn't get an ACK there must have been 59466070ca4SZaiyu Wang * some sort of mailbox error so we should treat it 59566070ca4SZaiyu Wang * as such 59666070ca4SZaiyu Wang */ 59766070ca4SZaiyu Wang if (msg[0] != (NGBE_VF_GET_QUEUES | NGBE_VT_MSGTYPE_ACK)) 59866070ca4SZaiyu Wang return NGBE_ERR_MBX; 59966070ca4SZaiyu Wang 60066070ca4SZaiyu Wang /* record and validate values from message */ 60166070ca4SZaiyu Wang hw->mac.max_tx_queues = msg[NGBE_VF_TX_QUEUES]; 60266070ca4SZaiyu Wang if (hw->mac.max_tx_queues == 0 || 60366070ca4SZaiyu Wang hw->mac.max_tx_queues > NGBE_VF_MAX_TX_QUEUES) 60466070ca4SZaiyu Wang hw->mac.max_tx_queues = NGBE_VF_MAX_TX_QUEUES; 60566070ca4SZaiyu Wang 60666070ca4SZaiyu Wang hw->mac.max_rx_queues = msg[NGBE_VF_RX_QUEUES]; 60766070ca4SZaiyu Wang if (hw->mac.max_rx_queues == 0 || 60866070ca4SZaiyu Wang hw->mac.max_rx_queues > NGBE_VF_MAX_RX_QUEUES) 60966070ca4SZaiyu Wang hw->mac.max_rx_queues = NGBE_VF_MAX_RX_QUEUES; 61066070ca4SZaiyu Wang 61166070ca4SZaiyu Wang *num_tcs = msg[NGBE_VF_TRANS_VLAN]; 61266070ca4SZaiyu Wang /* in case of unknown state assume we cannot tag frames */ 61366070ca4SZaiyu Wang if (*num_tcs > hw->mac.max_rx_queues) 61466070ca4SZaiyu Wang *num_tcs = 1; 61566070ca4SZaiyu Wang 61666070ca4SZaiyu Wang *default_tc = msg[NGBE_VF_DEF_QUEUE]; 61766070ca4SZaiyu Wang /* default to queue 0 on out-of-bounds queue number */ 61866070ca4SZaiyu Wang if (*default_tc >= hw->mac.max_tx_queues) 61966070ca4SZaiyu Wang *default_tc = 0; 62066070ca4SZaiyu Wang } 62166070ca4SZaiyu Wang 62266070ca4SZaiyu Wang return err; 62366070ca4SZaiyu Wang } 62466070ca4SZaiyu Wang 625950820f1SZaiyu Wang /** 626950820f1SZaiyu Wang * ngbe_init_ops_vf - Initialize the pointers for vf 627950820f1SZaiyu Wang * @hw: pointer to hardware structure 628950820f1SZaiyu Wang * 629950820f1SZaiyu Wang * This will assign function pointers, adapter-specific functions can 630950820f1SZaiyu Wang * override the assignment of generic function pointers by assigning 631950820f1SZaiyu Wang * their own adapter-specific function pointers. 632950820f1SZaiyu Wang * Does not touch the hardware. 633950820f1SZaiyu Wang **/ 634950820f1SZaiyu Wang s32 ngbe_init_ops_vf(struct ngbe_hw *hw) 635950820f1SZaiyu Wang { 636950820f1SZaiyu Wang struct ngbe_mac_info *mac = &hw->mac; 637ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 638ace44974SZaiyu Wang 63966070ca4SZaiyu Wang /* MAC */ 64066070ca4SZaiyu Wang mac->init_hw = ngbe_init_hw_vf; 64166070ca4SZaiyu Wang mac->reset_hw = ngbe_reset_hw_vf; 64266070ca4SZaiyu Wang mac->start_hw = ngbe_start_hw_vf; 64366070ca4SZaiyu Wang mac->stop_hw = ngbe_stop_hw_vf; 6442aba42f6SZaiyu Wang mac->get_mac_addr = ngbe_get_mac_addr_vf; 645ace44974SZaiyu Wang mac->negotiate_api_version = ngbevf_negotiate_api_version; 646950820f1SZaiyu Wang 64762c072c0SZaiyu Wang /* Link */ 64862c072c0SZaiyu Wang mac->check_link = ngbe_check_mac_link_vf; 64962c072c0SZaiyu Wang 650f47dc03cSZaiyu Wang /* RAR, Multicast, VLAN */ 6512aba42f6SZaiyu Wang mac->set_rar = ngbe_set_rar_vf; 6522aba42f6SZaiyu Wang mac->set_uc_addr = ngbevf_set_uc_addr_vf; 653*e0c29b2fSZaiyu Wang mac->update_mc_addr_list = ngbe_update_mc_addr_list_vf; 6547744e908SZaiyu Wang mac->update_xcast_mode = ngbevf_update_xcast_mode; 655f47dc03cSZaiyu Wang mac->set_vfta = ngbe_set_vfta_vf; 65677102375SZaiyu Wang mac->set_rlpml = ngbevf_rlpml_set_vf; 6577744e908SZaiyu Wang 658950820f1SZaiyu Wang mac->max_tx_queues = 1; 659950820f1SZaiyu Wang mac->max_rx_queues = 1; 660950820f1SZaiyu Wang 661ace44974SZaiyu Wang mbx->init_params = ngbe_init_mbx_params_vf; 662ace44974SZaiyu Wang mbx->read = ngbe_read_mbx_vf; 663ace44974SZaiyu Wang mbx->write = ngbe_write_mbx_vf; 664ace44974SZaiyu Wang mbx->read_posted = ngbe_read_posted_mbx; 665ace44974SZaiyu Wang mbx->write_posted = ngbe_write_posted_mbx; 666ace44974SZaiyu Wang mbx->check_for_msg = ngbe_check_for_msg_vf; 667ace44974SZaiyu Wang mbx->check_for_ack = ngbe_check_for_ack_vf; 668ace44974SZaiyu Wang mbx->check_for_rst = ngbe_check_for_rst_vf; 669ace44974SZaiyu Wang 670950820f1SZaiyu Wang return 0; 671950820f1SZaiyu Wang } 672