// SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2022 - 2024 Mucse Corporation. */ #include "vf.h" #include "rnpgbevf.h" static int rnpgbevf_reset_pf(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; s32 ret_val; memset(msgbuf, 0, sizeof(msgbuf)); msgbuf[0] = RNPGBE_VF_RESET_PF; ret_val = mbx->ops.write_posted(hw, msgbuf, 2, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 2, false); return ret_val; } static int rnpgbevf_get_mtu(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; s32 ret_val; memset(msgbuf, 0, sizeof(msgbuf)); msgbuf[0] = RNPGBE_VF_GET_MTU; ret_val = mbx->ops.write_posted(hw, msgbuf, 2, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 2, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && (msgbuf[0] == (RNPGBE_VF_GET_MTU | RNPGBE_VT_MSGTYPE_NACK))) { return -1; } hw->mtu = msgbuf[1]; return ret_val; } static int rnpgbevf_set_mtu(struct rnpgbevf_hw *hw, int mtu) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; s32 ret_val; memset(msgbuf, 0, sizeof(msgbuf)); msgbuf[0] = RNPGBE_VF_SET_MTU; msgbuf[1] = mtu; ret_val = mbx->ops.write_posted(hw, msgbuf, 2, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 2, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && (msgbuf[0] == (RNPGBE_VF_SET_MTU | RNPGBE_VT_MSGTYPE_NACK))) { return -1; } return ret_val; } static int rnpgbevf_read_eth_reg(struct rnpgbevf_hw *hw, int reg, u32 *value) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; int err; msgbuf[0] = RNPGBE_VF_REG_RD; msgbuf[1] = reg; err = mbx->ops.write_posted(hw, msgbuf, 2, false); if (err) goto mbx_err; err = mbx->ops.read_posted(hw, msgbuf, 2, false); if (err) goto mbx_err; /* remove extra bits from the message */ msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; msgbuf[0] &= ~(0xFF << RNPGBE_VT_MSGINFO_SHIFT); if (msgbuf[0] != (RNPGBE_VF_REG_RD | RNPGBE_VT_MSGTYPE_ACK)) err = RNPGBE_ERR_INVALID_ARGUMENT; *value = msgbuf[1]; mbx_err: return err; } /** * rnpgbevf_start_hw_vf - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ static s32 rnpgbevf_start_hw_vf(struct rnpgbevf_hw *hw) { /* Clear adapter stopped flag */ hw->adapter_stopped = false; return 0; } /** * rnpgbevf_init_hw_vf - virtual function hardware initialization * @hw: pointer to hardware structure * * Initialize the hardware by resetting the hardware and then starting * the hardware **/ static s32 rnpgbevf_init_hw_vf(struct rnpgbevf_hw *hw) { s32 status; status = hw->mac.ops.start_hw(hw); hw->mac.ops.get_mac_addr(hw, hw->mac.addr); return status; } /** * rnpgbevf_reset_hw_vf - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts. **/ static s32 rnpgbevf_reset_hw_vf(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; struct rnpgbevf_adapter *adapter = hw->back; s32 ret_val = RNPGBE_ERR_INVALID_MAC_ADDR; u32 msgbuf[RNPGBE_VF_PERMADDR_MSG_LEN]; u8 *addr = (u8 *)(&msgbuf[1]); u32 vlan; int try_cnt = 10; /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); /* reset the api version */ hw->api_version = 0; /* mailbox timeout can now become active */ mbx->timeout = RNPGBE_VF_MBX_INIT_TIMEOUT; while (try_cnt--) { msgbuf[0] = RNPGBE_VF_RESET; mbx->ops.write_posted(hw, msgbuf, 1, false); /* ack write back maybe too fast */ mdelay(20); /* set our "perm_addr" based on info provided by PF */ /* also set up the mc_filter_type which is piggy backed * on the mac address in word 3 */ ret_val = mbx->ops.read_posted(hw, msgbuf, RNPGBE_VF_PERMADDR_MSG_LEN, false); if (ret_val == 0) break; } if (ret_val) { dev_info(&hw->pdev->dev, "echo vf reset timeout\n"); return ret_val; } /* New versions of the PF may NACK the reset return message * to indicate that no MAC address has yet been assigned for * the VF. */ if (msgbuf[0] != (RNPGBE_VF_RESET | RNPGBE_VT_MSGTYPE_ACK) && msgbuf[0] != (RNPGBE_VF_RESET | RNPGBE_VT_MSGTYPE_NACK)) return RNPGBE_ERR_INVALID_MAC_ADDR; /* we get mac address from mailbox */ memcpy(hw->mac.perm_addr, addr, ETH_ALEN); hw->mac.mc_filter_type = msgbuf[RNPGBE_VF_MC_TYPE_WORD] & 0xff; /* ft padding */ if ((msgbuf[RNPGBE_VF_MC_TYPE_WORD] >> 8) & 0xff) adapter->priv_flags |= RNPVF_PRIV_FLAG_FT_PADDING; else adapter->priv_flags = 0; /* fc mode */ hw->fc.current_mode = (msgbuf[RNPGBE_VF_MC_TYPE_WORD] >> 16) & 0xff; /* phy status */ hw->phy_type = (msgbuf[RNPGBE_VF_PHY_TYPE_WORD] & 0xffff); hw->mac.dma_version = msgbuf[RNPGBE_VF_DMA_VERSION_WORD]; hw->dma_version = hw->mac.dma_version; /* vlan status */ vlan = msgbuf[RNPGBE_VF_VLAN_WORD]; if (vlan & 0xffff) { adapter->vf_vlan = vlan & 0xffff; adapter->flags |= RNPVF_FLAG_PF_SET_VLAN; } hw->ops.set_veb_vlan(hw, vlan, VFNUM(mbx, hw->vfnum)); hw->fw_version = msgbuf[RNPGBE_VF_FW_VERSION_WORD]; if (msgbuf[RNPGBE_VF_LINK_STATUS_WORD] & RNPGBE_PF_LINK_UP) { hw->link = true; hw->speed = msgbuf[RNPGBE_VF_LINK_STATUS_WORD] & 0xffff; } else { hw->link = false; hw->speed = 0; } hw->usecstocount = msgbuf[RNPGBE_VF_AXI_MHZ]; DPRINTK(PROBE, INFO, "dma_version:%x vlan %d\n", hw->mac.dma_version, adapter->vf_vlan); DPRINTK(PROBE, INFO, "axi:%x\n", hw->usecstocount); DPRINTK(PROBE, INFO, "firmware :%x\n", hw->fw_version); DPRINTK(PROBE, INFO, "link speed :%x\n", hw->speed); DPRINTK(PROBE, INFO, "link status :%s\n", hw->link ? "up" : "down"); hw->pf_feature = msgbuf[RNPGBE_VF_FEATURE]; return 0; } /** * rnpgbevf_stop_hw_vf - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within rnpgbevf_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ static s32 rnpgbevf_stop_hw_vf(struct rnpgbevf_hw *hw) { u16 i; struct rnpgbevf_adapter *adapter = hw->back; struct rnpgbevf_ring *ring; /* Set the adapter_stopped flag so other driver functions stop touching * the hardware */ hw->adapter_stopped = true; /* Disable the receive unit by stopped each queue */ for (i = 0; i < adapter->num_rx_queues; i++) { ring = adapter->rx_ring[i]; ring_wr32(ring, RNPGBE_DMA_RX_START, 0); } return 0; } /** * rnpgbevf_mta_vector - Determines bit-vector in multicast table to set * @hw: pointer to hardware structure * @mc_addr: the multicast address * * Extracts the 12 bits, from a multicast address, to determine which * bit-vector to set in the multicast table. The hardware uses 12 bits, from * incoming rx multicast addresses, to determine the bit-vector to check in * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ static s32 rnpgbevf_mta_vector(struct rnpgbevf_hw *hw, u8 *mc_addr) { u32 vector = 0; switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] << 8) | (((u16)mc_addr[5]))); break; case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] << 7) | (((u16)mc_addr[5]) >> 1)); break; case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] << 6) | (((u16)mc_addr[5]) >> 2)); break; case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) << 4 | (((u16)mc_addr[5]) >> 4)); break; case 4: /* use bits [32:43] of the address */ vector = ((mc_addr[0] << 8) | (((u16)mc_addr[1]))); vector = (vector >> 4); break; case 5: /* use bits [32:43] of the address */ vector = ((mc_addr[0] << 8) | (((u16)mc_addr[1]))); vector = (vector >> 3); break; case 6: /* use bits [32:43] of the address */ vector = ((mc_addr[0] << 8) | (((u16)mc_addr[1]))); vector = (vector >> 2); break; case 7: /* use bits [32:43] of the address */ vector = ((mc_addr[0] << 8) | (((u16)mc_addr[1]))); break; default: /* Invalid mc_filter_type */ break; } /* vector can only be 12-bits or boundary will be exceeded */ vector &= 0xFFF; return vector; } /** * rnpgbevf_get_mac_addr_vf - Read device MAC address * @hw: pointer to the HW structure * @mac_addr: pointer to storage for retrieved MAC address **/ static s32 rnpgbevf_get_mac_addr_vf(struct rnpgbevf_hw *hw, u8 *mac_addr) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val = 0; memset(msgbuf, 0, sizeof(msgbuf)); /* If index is one then this is the start of a new list and needs * indication to the PF so it can do it's own list management. * If it is zero then that tells the PF to just clear all of * this VF's macvlans and there is no new list. */ msgbuf[0] |= RNPGBE_VF_SET_MACVLAN; ret_val = mbx->ops.write_posted(hw, msgbuf, 1, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; if (!ret_val) { if (msgbuf[0] == (RNPGBE_VF_GET_MACVLAN | RNPGBE_VT_MSGTYPE_NACK)) ret_val = -ENOMEM; } memcpy(mac_addr, msg_addr, 6); return 0; } /** * rnpgbevf_get_queues_vf - Read device MAC address * @hw: pointer to the HW structure **/ static s32 rnpgbevf_get_queues_vf(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; s32 ret_val = 0; u32 msgbuf[7]; memset(msgbuf, 0, sizeof(msgbuf)); msgbuf[0] |= RNPGBE_VF_GET_QUEUE; ret_val = mbx->ops.write_posted(hw, msgbuf, 1, false); mdelay(10); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 7, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; if (!ret_val) if (msgbuf[0] == (RNPGBE_VF_GET_QUEUE | RNPGBE_VT_MSGTYPE_NACK)) ret_val = -ENOMEM; #define MSG_TX_NUM_WORD 1 #define MSG_RX_NUM_WORD 2 #define MSG_RING_BASE_WORD 5 #define MSG_RING_DEPTH 6 hw->queue_ring_base = msgbuf[MSG_RING_BASE_WORD]; hw->mac.max_tx_queues = msgbuf[MSG_TX_NUM_WORD]; hw->mac.max_rx_queues = msgbuf[MSG_RX_NUM_WORD]; hw->tx_items_count = 0xffff & (msgbuf[MSG_RING_DEPTH] >> 16); hw->rx_items_count = 0xffff & (msgbuf[MSG_RING_DEPTH] >> 0); return 0; } static s32 rnpgbevf_set_uc_addr_vf(struct rnpgbevf_hw *hw, u32 index, u8 *addr) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val = 0; memset(msgbuf, 0, sizeof(msgbuf)); /* If index is one then this is the start of a new list and needs * indication to the PF so it can do it's own list management. * If it is zero then that tells the PF to just clear all of * this VF's macvlans and there is no new list. */ msgbuf[0] |= index << RNPGBE_VT_MSGINFO_SHIFT; msgbuf[0] |= RNPGBE_VF_SET_MACVLAN; if (addr) memcpy(msg_addr, addr, 6); ret_val = mbx->ops.write_posted(hw, msgbuf, 3, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; if (!ret_val) if (msgbuf[0] == (RNPGBE_VF_SET_MACVLAN | RNPGBE_VT_MSGTYPE_NACK)) ret_val = -ENOMEM; return ret_val; } /** * rnpgbevf_set_rar_vf - set device MAC address * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: Unused in this implementation **/ static s32 rnpgbevf_set_rar_vf(struct rnpgbevf_hw *hw, u32 index, u8 *addr, u32 vmdq) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val; memset(msgbuf, 0, sizeof(msgbuf)); msgbuf[0] = RNPGBE_VF_SET_MAC_ADDR; memcpy(msg_addr, addr, 6); ret_val = mbx->ops.write_posted(hw, msgbuf, 3, false); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, false); msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && (msgbuf[0] == (RNPGBE_VF_SET_MAC_ADDR | RNPGBE_VT_MSGTYPE_NACK))) { rnpgbevf_get_mac_addr_vf(hw, hw->mac.addr); return -1; } return ret_val; } static void rnpgbevf_write_msg_read_ack(struct rnpgbevf_hw *hw, u32 *msg, u16 size) { u32 retmsg[RNPGBE_VFMAILBOX_SIZE]; s32 retval; struct rnp_mbx_info *mbx = &hw->mbx; retval = mbx->ops.write_posted(hw, msg, size, false); if (!retval) mbx->ops.read_posted(hw, retmsg, size, false); } static u8 *rnpgbevf_addr_list_itr(struct rnpgbevf_hw __maybe_unused *hw, u8 **mc_addr_ptr) { struct netdev_hw_addr *mc_ptr; u8 *addr = *mc_addr_ptr; mc_ptr = container_of(addr, struct netdev_hw_addr, addr[0]); if (mc_ptr->list.next) { struct netdev_hw_addr *ha; ha = list_entry(mc_ptr->list.next, struct netdev_hw_addr, list); *mc_addr_ptr = ha->addr; } else { *mc_addr_ptr = NULL; } return addr; } /** * rnpgbevf_update_mc_addr_list_vf - Update Multicast addresses * @hw: pointer to the HW structure * @netdev: pointer to net device structure * * Updates the Multicast Table Array. **/ static s32 rnpgbevf_update_mc_addr_list_vf(struct rnpgbevf_hw *hw, struct net_device *netdev) { struct netdev_hw_addr *ha; u32 msgbuf[RNPGBE_VFMAILBOX_SIZE]; u16 *vector_list = (u16 *)&msgbuf[1]; u32 cnt, i; int addr_count = 0; u8 *addr_list = NULL; /* Each entry in the list uses 1 16 bit word. We have 30 * 16 bit words available in our HW msg buffer (minus 1 for the * msg type). That's 30 hash values if we pack 'em right. If * there are more than 30 MC addresses to add then punt the * extras for now and then add code to handle more than 30 later. * It would be unusual for a server to request that many multi-cast * addresses except for in large enterprise network environments. */ cnt = netdev_mc_count(netdev); if (cnt > 30) cnt = 30; msgbuf[0] = RNPGBE_VF_SET_MULTICAST; msgbuf[0] |= cnt << RNPGBE_VT_MSGINFO_SHIFT; addr_count = netdev_mc_count(netdev); ha = list_first_entry(&netdev->mc.list, struct netdev_hw_addr, list); addr_list = ha->addr; for (i = 0; i < addr_count; i++) { vector_list[i] = rnpgbevf_mta_vector(hw, rnpgbevf_addr_list_itr(hw, &addr_list)); } rnpgbevf_write_msg_read_ack(hw, msgbuf, RNPGBE_VFMAILBOX_SIZE); return 0; } /** * rnpgbevf_set_vfta_vf - Set/Unset vlan filter table address * @hw: pointer to the HW structure * @vlan: 12 bit VLAN ID * @vind: unused by VF drivers * @vlan_on: if true then set bit, else clear bit **/ static s32 rnpgbevf_set_vfta_vf(struct rnpgbevf_hw *hw, u32 vlan, u32 vind, bool vlan_on) { struct rnp_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; s32 err; msgbuf[0] = RNPGBE_VF_SET_VLAN; msgbuf[1] = vlan; /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ msgbuf[0] |= vlan_on << RNPGBE_VT_MSGINFO_SHIFT; err = mbx->ops.write_posted(hw, msgbuf, 2, false); if (err) goto mbx_err; err = mbx->ops.read_posted(hw, msgbuf, 2, false); if (err) goto mbx_err; /* remove extra bits from the message */ msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; msgbuf[0] &= ~(0xFF << RNPGBE_VT_MSGINFO_SHIFT); if (msgbuf[0] != (RNPGBE_VF_SET_VLAN | RNPGBE_VT_MSGTYPE_ACK)) err = RNPGBE_ERR_INVALID_ARGUMENT; mbx_err: return err; } static s32 rnpgbevf_set_vlan_strip(struct rnpgbevf_hw *hw, bool vlan_on) { struct rnp_mbx_info *mbx = &hw->mbx; struct rnpgbevf_adapter *adapter = (struct rnpgbevf_adapter *)hw->back; u32 msgbuf[4]; s32 err; int i; if (adapter->num_rx_queues > 2) { err = -EINVAL; goto mbx_err; } msgbuf[0] = RNPGBE_VF_SET_VLAN_STRIP; msgbuf[1] = (vlan_on << 31) | adapter->num_rx_queues; for (i = 0; i < adapter->num_rx_queues; i++) msgbuf[2 + i] = adapter->rx_ring[i]->rnpgbevf_queue_idx; err = mbx->ops.write_posted(hw, msgbuf, 2 + adapter->num_rx_queues, false); if (err) goto mbx_err; err = mbx->ops.read_posted(hw, msgbuf, 1, false); if (err) goto mbx_err; /* remove extra bits from the message */ msgbuf[0] &= ~RNPGBE_VT_MSGTYPE_CTS; msgbuf[0] &= ~(0xFF << RNPGBE_VT_MSGINFO_SHIFT); if (msgbuf[0] != (RNPGBE_VF_SET_VLAN_STRIP | RNPGBE_VT_MSGTYPE_ACK)) err = RNPGBE_ERR_INVALID_ARGUMENT; mbx_err: return err; } /** * rnpgbevf_setup_mac_link_vf - Setup MAC link settings * @hw: pointer to hardware structure * @speed: Unused in this implementation * @autoneg: Unused in this implementation * @autoneg_wait_to_complete: Unused in this implementation * * Do nothing and return success. VF drivers are not allowed to change * global settings. Maintained for driver compatibility. **/ static s32 rnpgbevf_setup_mac_link_vf(struct rnpgbevf_hw *hw, rnp_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { return 0; } /** * rnpgbevf_check_mac_link_vf - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise * @autoneg_wait_to_complete: true when waiting for completion is needed * * Reads the links register to determine if link is up and the current speed **/ static s32 rnpgbevf_check_mac_link_vf(struct rnpgbevf_hw *hw, rnp_link_speed *speed, bool *link_up, bool autoneg_wait_to_complete) { *speed = hw->speed; *link_up = hw->link; return 0; } /** * rnpgbevf_rlpml_set_vf - Set the maximum receive packet length * @hw: pointer to the HW structure * @max_size: value to assign to max frame size **/ void rnpgbevf_rlpml_set_vf(struct rnpgbevf_hw *hw, u16 max_size) { u32 msgbuf[2]; msgbuf[0] = RNPGBE_VF_SET_LPE; msgbuf[1] = max_size; rnpgbevf_write_msg_read_ack(hw, msgbuf, 2); } static void rnpgbevf_set_veb_mac_n500(struct rnpgbevf_hw *hw, u8 *mac, u32 vf_num, u32 ring) { u32 maclow, machi; maclow = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5]; machi = (mac[0] << 8) | mac[1]; wr32(hw, RNPGBE_DMA_PORT_VBE_MAC_LO_TBL_N500, maclow); wr32(hw, RNPGBE_DMA_PORT_VBE_MAC_HI_TBL_N500, machi); wr32(hw, RNPGBE_DMA_PORT_VEB_VF_RING_TBL_N500, ring); } static void rnpgbevf_set_vlan_n500(struct rnpgbevf_hw *hw, u16 vid, u32 vf_num) { wr32(hw, RNPGBE_DMA_PORT_VEB_VID_TBL_N500, vid); } static const struct rnpgbevf_hw_operations rnpgbevf_hw_ops_n500 = { .set_veb_mac = rnpgbevf_set_veb_mac_n500, .set_veb_vlan = rnpgbevf_set_vlan_n500, }; static s32 rnpgbevf_get_invariants_n500(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; hw->feature_flags |= RNPVF_NET_FEATURE_SG | RNPVF_NET_FEATURE_TX_CHECKSUM | RNPVF_NET_FEATURE_RX_CHECKSUM | RNPVF_NET_FEATURE_TSO | RNPVF_NET_FEATURE_VLAN_OFFLOAD | RNPVF_NET_FEATURE_STAG_OFFLOAD | RNPVF_NET_FEATURE_USO | RNPVF_NET_FEATURE_RX_HASH; mbx->pf2vf_mbox_vec_base = 0x28800; mbx->vf2pf_mbox_vec_base = 0x28900; mbx->cpu2vf_mbox_vec_base = 0x28a00; mbx->cpu2pf_mbox_vec = 0x28b00; mbx->pf_vf_shm_base = 0x29000; mbx->cpu_vf_shm_base = 0x2b000; mbx->vf2cpu_mbox_ctrl_base = 0x2c000; mbx->cpu_vf_mbox_mask_lo_base = 0x2c200; mbx->cpu_vf_mbox_mask_hi_base = 0; mbx->mbx_mem_size = 64; mbx->vf2pf_mbox_ctrl_base = 0x2a000; mbx->pf2vf_mbox_ctrl_base = 0x2a100; mbx->pf_vf_mbox_mask_lo = 0x2a200; mbx->pf_vf_mbox_mask_hi = 0; mbx->cpu_pf_shm_base = 0x2d040; mbx->pf2cpu_mbox_ctrl = 0x2e000; mbx->pf2cpu_mbox_mask = 0x2e200; mbx->vf_num_mask = 0x1f; hw->min_length = RNPVF_MIN_MTU; hw->max_length = RNPVF_N500_MAX_JUMBO_FRAME_SIZE; memcpy(&hw->ops, &rnpgbevf_hw_ops_n500, sizeof(hw->ops)); return 0; } static s32 rnpgbevf_get_invariants_n210(struct rnpgbevf_hw *hw) { struct rnp_mbx_info *mbx = &hw->mbx; hw->feature_flags |= RNPVF_NET_FEATURE_SG | RNPVF_NET_FEATURE_TX_CHECKSUM | RNPVF_NET_FEATURE_RX_CHECKSUM | RNPVF_NET_FEATURE_TSO | RNPVF_NET_FEATURE_VLAN_OFFLOAD | RNPVF_NET_FEATURE_STAG_OFFLOAD | RNPVF_NET_FEATURE_USO | RNPVF_NET_FEATURE_RX_HASH; mbx->pf2vf_mbox_vec_base = 0x29100; mbx->vf2pf_mbox_vec_base = 0x29200; mbx->cpu2vf_mbox_vec_base = 0x29300; mbx->cpu2pf_mbox_vec = 0x29400; mbx->pf_vf_shm_base = 0x29900; mbx->cpu_vf_shm_base = 0x2b900; mbx->vf2cpu_mbox_ctrl_base = 0x2c900; mbx->cpu_vf_mbox_mask_lo_base = 0x2cb00; mbx->cpu_vf_mbox_mask_hi_base = 0; mbx->mbx_mem_size = 64; mbx->vf2pf_mbox_ctrl_base = 0x2a900; mbx->pf2vf_mbox_ctrl_base = 0x2aa00; mbx->pf_vf_mbox_mask_lo = 0x2a200; mbx->pf_vf_mbox_mask_hi = 0; mbx->cpu_pf_shm_base = 0x2d940; mbx->pf2cpu_mbox_ctrl = 0x2e900; mbx->pf2cpu_mbox_mask = 0x2eb00; mbx->vf_num_mask = 0x1f; hw->min_length = RNPVF_MIN_MTU; hw->max_length = RNPVF_N500_MAX_JUMBO_FRAME_SIZE; memcpy(&hw->ops, &rnpgbevf_hw_ops_n500, sizeof(hw->ops)); return 0; } static const struct rnp_mac_operations rnpgbevf_mac_ops = { .init_hw = rnpgbevf_init_hw_vf, .reset_hw = rnpgbevf_reset_hw_vf, .start_hw = rnpgbevf_start_hw_vf, .get_mac_addr = rnpgbevf_get_mac_addr_vf, .get_queues = rnpgbevf_get_queues_vf, .stop_adapter = rnpgbevf_stop_hw_vf, .setup_link = rnpgbevf_setup_mac_link_vf, .check_link = rnpgbevf_check_mac_link_vf, .set_rar = rnpgbevf_set_rar_vf, .update_mc_addr_list = rnpgbevf_update_mc_addr_list_vf, .set_uc_addr = rnpgbevf_set_uc_addr_vf, .set_vfta = rnpgbevf_set_vfta_vf, .set_vlan_strip = rnpgbevf_set_vlan_strip, .read_eth_reg = rnpgbevf_read_eth_reg, .get_mtu = rnpgbevf_get_mtu, .set_mtu = rnpgbevf_set_mtu, .req_reset_pf = rnpgbevf_reset_pf, }; const struct rnpgbevf_info rnp_n500_vf_info = { .mac = rnp_mac_2port_40G, .mac_ops = &rnpgbevf_mac_ops, .board_type = rnp_board_n500, .get_invariants = &rnpgbevf_get_invariants_n500, }; const struct rnpgbevf_info rnp_n210_vf_info = { .mac = rnp_mac_2port_40G, .mac_ops = &rnpgbevf_mac_ops, .board_type = rnp_board_n210, .get_invariants = &rnpgbevf_get_invariants_n210, };