1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2024 Intel Corporation 3 */ 4 5 #include "ixgbe_common.h" 6 #include "ixgbe_vf.h" 7 #include "ixgbe_hv_vf.h" 8 9 /* Reading these PCI configuration bytes resets a VF on Hyper-V. */ 10 #define IXGBE_HV_RESET_OFFSET 0x201 11 12 /* Hyper-V emulates the VF queue limit in PCI configuration space. */ 13 #define IXGBE_HV_QUEUE_COUNT_OFFSET 0x207 14 15 /* E610 exposes VFLINKS in four emulated PCI configuration bytes. */ 16 #define IXGBE_HV_LINK_STATUS_OFFSET 0x209 17 #define IXGBE_HV_LINK_STATUS_SIZE 4 18 19 /** 20 * ixgbevf_hv_get_queues - Discover supported Hyper-V RSS queues at attach 21 * @hw: pointer to hardware structure 22 */ 23 u32 24 ixgbevf_hv_get_queues(struct ixgbe_hw *hw) 25 { 26 u32 grant, queues = 1; 27 28 switch (hw->mac.type) { 29 case ixgbe_mac_X550_vf: 30 case ixgbe_mac_X550EM_x_vf: 31 case ixgbe_mac_X550EM_a_vf: 32 /* 0x208 is a separate DCB flag on these PFs, not count bits. */ 33 grant = IXGBE_READ_PCIE_BYTE(hw, IXGBE_HV_QUEUE_COUNT_OFFSET); 34 break; 35 case ixgbe_mac_E610_vf: 36 /* E610 reports the assigned count as a little-endian word. */ 37 grant = IXGBE_READ_PCIE_BYTE(hw, IXGBE_HV_QUEUE_COUNT_OFFSET); 38 grant |= (u32)IXGBE_READ_PCIE_BYTE(hw, 39 IXGBE_HV_QUEUE_COUNT_OFFSET + 1) << NBBY; 40 break; 41 default: 42 /* Older PFs do not provide VF-owned RSS on Hyper-V. */ 43 grant = 1; 44 break; 45 } 46 /* Valid limits are 1, 2 and 4; use at most two symmetric RSS queues. */ 47 if (grant == 2 || grant == 4) 48 queues = 2; 49 50 /* Shared stop must disable every queue that iflib can initialize. */ 51 hw->mac.max_tx_queues = queues; 52 hw->mac.max_rx_queues = queues; 53 return (queues); 54 } 55 56 /** 57 * ixgbevf_hv_update_mc_addr_list_vf - Hyper-V variant - just a stub. 58 * @hw: unused 59 * @mc_addr_list: unused 60 * @mc_addr_count: unused 61 * @next: unused 62 * @clear: unused 63 */ 64 static s32 65 ixgbevf_hv_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list, 66 u32 mc_addr_count, ixgbe_mc_addr_itr next, bool clear) 67 { 68 UNREFERENCED_5PARAMETER(hw, mc_addr_list, mc_addr_count, next, clear); 69 70 return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); 71 } 72 73 /** 74 * ixgbevf_hv_update_xcast_mode - Leave receive-mode policy to Hyper-V 75 * @hw: unused 76 * @xcast_mode: unused 77 */ 78 static s32 79 ixgbevf_hv_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode) 80 { 81 UNREFERENCED_2PARAMETER(hw, xcast_mode); 82 83 return (IXGBE_SUCCESS); 84 } 85 86 /** 87 * ixgbevf_hv_set_vfta_vf - Hyper-V variant - just a stub. 88 * @hw: unused 89 * @vlan: unused 90 * @vind: unused 91 * @vlan_on: unused 92 * @vlvf_bypass: unused 93 */ 94 static s32 95 ixgbevf_hv_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, 96 bool vlan_on, bool vlvf_bypass) 97 { 98 UNREFERENCED_5PARAMETER(hw, vlan, vind, vlan_on, vlvf_bypass); 99 100 return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); 101 } 102 103 static s32 104 ixgbevf_hv_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr) 105 { 106 UNREFERENCED_3PARAMETER(hw, index, addr); 107 108 return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); 109 } 110 111 /** 112 * ixgbevf_hv_reset_hw_vf - Reset through the Hyper-V PCI side channel 113 * @hw: pointer to hardware structure 114 * 115 * Hyper-V returns the permanent VF address when the guest reads six bytes 116 * beginning at offset 0x201 in PCI configuration space. The reads also 117 * perform the host-side VF reset handshake. 118 */ 119 static s32 120 ixgbevf_hv_reset_hw_vf(struct ixgbe_hw *hw) 121 { 122 int i; 123 124 hw->api_version = ixgbe_mbox_api_10; 125 for (i = 0; i < IXGBE_ETH_LENGTH_OF_ADDRESS; i++) 126 hw->mac.perm_addr[i] = IXGBE_READ_PCIE_BYTE(hw, 127 IXGBE_HV_RESET_OFFSET + i); 128 if (ixgbe_validate_mac_addr(hw->mac.perm_addr) != IXGBE_SUCCESS) 129 return (IXGBE_ERR_INVALID_MAC_ADDR); 130 131 return (IXGBE_SUCCESS); 132 } 133 134 /** 135 * ixgbevf_hv_set_rar_vf - Hyper-V variant - just a stub. 136 * @hw: unused 137 * @index: unused 138 * @addr: unused 139 * @vmdq: unused 140 * @enable_addr: unused 141 */ 142 static s32 143 ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, 144 u32 enable_addr) 145 { 146 UNREFERENCED_5PARAMETER(hw, index, addr, vmdq, enable_addr); 147 148 return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); 149 } 150 151 static u32 152 ixgbevf_hv_read_links(struct ixgbe_hw *hw) 153 { 154 u32 links_reg; 155 int i; 156 157 if (hw->mac.type != ixgbe_mac_E610_vf) 158 return (IXGBE_READ_REG(hw, IXGBE_VFLINKS)); 159 160 links_reg = 0; 161 for (i = 0; i < IXGBE_HV_LINK_STATUS_SIZE; i++) 162 links_reg |= (u32)IXGBE_READ_PCIE_BYTE(hw, 163 IXGBE_HV_LINK_STATUS_OFFSET + i) << (i * NBBY); 164 return (links_reg); 165 } 166 167 /** 168 * ixgbevf_hv_check_mac_link_vf - Check link without mailbox communication 169 * @hw: pointer to hardware structure 170 * @speed: pointer to link speed 171 * @link_up: true is link is up, false otherwise 172 * @autoneg_wait_to_complete: unused 173 */ 174 static s32 175 ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed, 176 bool *link_up, bool autoneg_wait_to_complete) 177 { 178 struct ixgbe_mbx_info *mbx = &hw->mbx; 179 struct ixgbe_mac_info *mac = &hw->mac; 180 u32 links_reg; 181 182 UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); 183 184 /* If we were hit with a reset, drop the cached link state. */ 185 if (!mbx->ops[0].check_for_rst(hw, 0) || !mbx->timeout) 186 mac->get_link_status = true; 187 if (!mac->get_link_status) 188 goto out; 189 190 links_reg = ixgbevf_hv_read_links(hw); 191 if (hw->mac.type == ixgbe_mac_E610_vf) { 192 *speed = IXGBE_LINK_SPEED_UNKNOWN; 193 if (links_reg == UINT32_MAX) 194 goto out; 195 if (links_reg == 0) { 196 /* 197 * Some hosts do not emulate the PCI link-status query. 198 * VFLINKS still reports carrier, but its speed is not the 199 * negotiated line rate. Do not report its default 10 Gb/s. 200 */ 201 links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS); 202 if (links_reg != UINT32_MAX && 203 (links_reg & IXGBE_LINKS_UP) != 0) 204 mac->get_link_status = false; 205 goto out; 206 } 207 } 208 if (!(links_reg & IXGBE_LINKS_UP)) 209 goto out; 210 211 /* Link status can take up to 500 usec to settle on 82599. */ 212 if (mac->type == ixgbe_mac_82599_vf) { 213 int i; 214 215 for (i = 0; i < 5; i++) { 216 usec_delay(100); 217 links_reg = ixgbevf_hv_read_links(hw); 218 if (!(links_reg & IXGBE_LINKS_UP)) 219 goto out; 220 } 221 } 222 223 switch (links_reg & IXGBE_LINKS_SPEED_82599) { 224 case IXGBE_LINKS_SPEED_10G_82599: 225 *speed = IXGBE_LINK_SPEED_10GB_FULL; 226 if (hw->mac.type >= ixgbe_mac_X550_vf && 227 (links_reg & IXGBE_LINKS_SPEED_NON_STD) != 0) 228 *speed = IXGBE_LINK_SPEED_2_5GB_FULL; 229 break; 230 case IXGBE_LINKS_SPEED_1G_82599: 231 *speed = IXGBE_LINK_SPEED_1GB_FULL; 232 break; 233 case IXGBE_LINKS_SPEED_100_82599: 234 *speed = IXGBE_LINK_SPEED_100_FULL; 235 if ((hw->mac.type == ixgbe_mac_X550_vf || 236 hw->mac.type == ixgbe_mac_E610_vf) && 237 (links_reg & IXGBE_LINKS_SPEED_NON_STD) != 0) 238 *speed = IXGBE_LINK_SPEED_5GB_FULL; 239 break; 240 case IXGBE_LINKS_SPEED_10_X550EM_A: 241 *speed = IXGBE_LINK_SPEED_UNKNOWN; 242 if (hw->mac.type >= ixgbe_mac_X550_vf) 243 *speed = IXGBE_LINK_SPEED_10_FULL; 244 break; 245 default: 246 *speed = IXGBE_LINK_SPEED_UNKNOWN; 247 } 248 249 mac->get_link_status = false; 250 251 out: 252 *link_up = !mac->get_link_status; 253 return (IXGBE_SUCCESS); 254 } 255 256 /** 257 * ixgbevf_hv_get_link_state_vf - Hyper-V has no mailbox link policy 258 * @hw: unused 259 * @link_state: unused 260 */ 261 static s32 262 ixgbevf_hv_get_link_state_vf(struct ixgbe_hw *hw, bool *link_state) 263 { 264 UNREFERENCED_2PARAMETER(hw, link_state); 265 266 return (IXGBE_ERR_FEATURE_NOT_SUPPORTED); 267 } 268 269 /** 270 * ixgbevf_hv_set_rlpml_vf - Set the maximum receive packet length 271 * @hw: pointer to hardware structure 272 * @max_size: maximum frame size 273 */ 274 static s32 275 ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size) 276 { 277 u32 i, reg; 278 279 /* RLPML is not implemented by the 82599 VF. */ 280 if (hw->mac.type == ixgbe_mac_82599_vf) 281 return (IXGBE_SUCCESS); 282 283 for (i = 0; i < hw->mac.max_rx_queues; i++) { 284 reg = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); 285 reg &= ~IXGBE_RXDCTL_RLPMLMASK; 286 reg |= ((max_size + 4) & IXGBE_RXDCTL_RLPMLMASK) | 287 IXGBE_RXDCTL_RLPML_EN; 288 IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), reg); 289 } 290 291 return (IXGBE_SUCCESS); 292 } 293 294 /** 295 * ixgbevf_hv_negotiate_api_version_vf - Negotiate the Hyper-V API version 296 * @hw: pointer to hardware structure 297 * @api: requested API version 298 */ 299 static int 300 ixgbevf_hv_negotiate_api_version_vf(struct ixgbe_hw *hw, int api) 301 { 302 if (api != ixgbe_mbox_api_10) 303 return (IXGBE_ERR_INVALID_ARGUMENT); 304 305 hw->api_version = api; 306 return (IXGBE_SUCCESS); 307 } 308 309 /** 310 * ixgbevf_hv_init_ops_vf - Initialize Hyper-V VF operations 311 * @hw: pointer to hardware structure 312 */ 313 s32 314 ixgbevf_hv_init_ops_vf(struct ixgbe_hw *hw) 315 { 316 s32 status; 317 318 status = ixgbe_init_ops_vf(hw); 319 if (status != IXGBE_SUCCESS) 320 return (status); 321 322 hw->mac.ops.reset_hw = ixgbevf_hv_reset_hw_vf; 323 hw->mac.ops.check_link = ixgbevf_hv_check_mac_link_vf; 324 hw->mac.ops.negotiate_api_version = 325 ixgbevf_hv_negotiate_api_version_vf; 326 hw->mac.ops.set_rar = ixgbevf_hv_set_rar_vf; 327 hw->mac.ops.update_mc_addr_list = 328 ixgbevf_hv_update_mc_addr_list_vf; 329 hw->mac.ops.update_xcast_mode = ixgbevf_hv_update_xcast_mode; 330 hw->mac.ops.get_link_state = ixgbevf_hv_get_link_state_vf; 331 hw->mac.ops.set_uc_addr = ixgbevf_hv_set_uc_addr_vf; 332 hw->mac.ops.set_vfta = ixgbevf_hv_set_vfta_vf; 333 hw->mac.ops.set_rlpml = ixgbevf_hv_set_rlpml_vf; 334 335 return (IXGBE_SUCCESS); 336 } 337