1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2022, Intel Corporation. */ 3 4 #include "rss.h" 5 #include "ice_vf_lib_private.h" 6 #include "ice.h" 7 8 #define FIELD_SELECTOR(proto_hdr_field) \ 9 BIT((proto_hdr_field) & PROTO_HDR_FIELD_MASK) 10 11 struct ice_vc_hdr_match_type { 12 u32 vc_hdr; /* virtchnl headers (VIRTCHNL_PROTO_HDR_XXX) */ 13 u32 ice_hdr; /* ice headers (ICE_FLOW_SEG_HDR_XXX) */ 14 }; 15 16 static const struct ice_vc_hdr_match_type ice_vc_hdr_list[] = { 17 {VIRTCHNL_PROTO_HDR_NONE, ICE_FLOW_SEG_HDR_NONE}, 18 {VIRTCHNL_PROTO_HDR_ETH, ICE_FLOW_SEG_HDR_ETH}, 19 {VIRTCHNL_PROTO_HDR_S_VLAN, ICE_FLOW_SEG_HDR_VLAN}, 20 {VIRTCHNL_PROTO_HDR_C_VLAN, ICE_FLOW_SEG_HDR_VLAN}, 21 {VIRTCHNL_PROTO_HDR_IPV4, ICE_FLOW_SEG_HDR_IPV4 | 22 ICE_FLOW_SEG_HDR_IPV_OTHER}, 23 {VIRTCHNL_PROTO_HDR_IPV6, ICE_FLOW_SEG_HDR_IPV6 | 24 ICE_FLOW_SEG_HDR_IPV_OTHER}, 25 {VIRTCHNL_PROTO_HDR_TCP, ICE_FLOW_SEG_HDR_TCP}, 26 {VIRTCHNL_PROTO_HDR_UDP, ICE_FLOW_SEG_HDR_UDP}, 27 {VIRTCHNL_PROTO_HDR_SCTP, ICE_FLOW_SEG_HDR_SCTP}, 28 {VIRTCHNL_PROTO_HDR_PPPOE, ICE_FLOW_SEG_HDR_PPPOE}, 29 {VIRTCHNL_PROTO_HDR_GTPU_IP, ICE_FLOW_SEG_HDR_GTPU_IP}, 30 {VIRTCHNL_PROTO_HDR_GTPU_EH, ICE_FLOW_SEG_HDR_GTPU_EH}, 31 {VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN, 32 ICE_FLOW_SEG_HDR_GTPU_DWN}, 33 {VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP, 34 ICE_FLOW_SEG_HDR_GTPU_UP}, 35 {VIRTCHNL_PROTO_HDR_L2TPV3, ICE_FLOW_SEG_HDR_L2TPV3}, 36 {VIRTCHNL_PROTO_HDR_ESP, ICE_FLOW_SEG_HDR_ESP}, 37 {VIRTCHNL_PROTO_HDR_AH, ICE_FLOW_SEG_HDR_AH}, 38 {VIRTCHNL_PROTO_HDR_PFCP, ICE_FLOW_SEG_HDR_PFCP_SESSION}, 39 }; 40 41 struct ice_vc_hash_field_match_type { 42 u32 vc_hdr; /* virtchnl headers 43 * (VIRTCHNL_PROTO_HDR_XXX) 44 */ 45 u32 vc_hash_field; /* virtchnl hash fields selector 46 * FIELD_SELECTOR((VIRTCHNL_PROTO_HDR_ETH_XXX)) 47 */ 48 u64 ice_hash_field; /* ice hash fields 49 * (BIT_ULL(ICE_FLOW_FIELD_IDX_XXX)) 50 */ 51 }; 52 53 static const struct 54 ice_vc_hash_field_match_type ice_vc_hash_field_list[] = { 55 {VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC), 56 BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_SA)}, 57 {VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST), 58 BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_DA)}, 59 {VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC) | 60 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST), 61 ICE_FLOW_HASH_ETH}, 62 {VIRTCHNL_PROTO_HDR_ETH, 63 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE), 64 BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_TYPE)}, 65 {VIRTCHNL_PROTO_HDR_S_VLAN, 66 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_S_VLAN_ID), 67 BIT_ULL(ICE_FLOW_FIELD_IDX_S_VLAN)}, 68 {VIRTCHNL_PROTO_HDR_C_VLAN, 69 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_C_VLAN_ID), 70 BIT_ULL(ICE_FLOW_FIELD_IDX_C_VLAN)}, 71 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC), 72 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, 73 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST), 74 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, 75 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) | 76 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST), 77 ICE_FLOW_HASH_IPV4}, 78 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) | 79 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT), 80 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | 81 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)}, 82 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) | 83 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT), 84 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | 85 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)}, 86 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) | 87 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) | 88 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT), 89 ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)}, 90 {VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT), 91 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)}, 92 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC), 93 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, 94 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST), 95 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, 96 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) | 97 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST), 98 ICE_FLOW_HASH_IPV6}, 99 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) | 100 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT), 101 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | 102 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)}, 103 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) | 104 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT), 105 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | 106 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)}, 107 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) | 108 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) | 109 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT), 110 ICE_FLOW_HASH_IPV6 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)}, 111 {VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT), 112 BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)}, 113 {VIRTCHNL_PROTO_HDR_TCP, 114 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT), 115 BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, 116 {VIRTCHNL_PROTO_HDR_TCP, 117 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT), 118 BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, 119 {VIRTCHNL_PROTO_HDR_TCP, 120 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) | 121 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT), 122 ICE_FLOW_HASH_TCP_PORT}, 123 {VIRTCHNL_PROTO_HDR_UDP, 124 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT), 125 BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, 126 {VIRTCHNL_PROTO_HDR_UDP, 127 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT), 128 BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, 129 {VIRTCHNL_PROTO_HDR_UDP, 130 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) | 131 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT), 132 ICE_FLOW_HASH_UDP_PORT}, 133 {VIRTCHNL_PROTO_HDR_SCTP, 134 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT), 135 BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, 136 {VIRTCHNL_PROTO_HDR_SCTP, 137 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT), 138 BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, 139 {VIRTCHNL_PROTO_HDR_SCTP, 140 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) | 141 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT), 142 ICE_FLOW_HASH_SCTP_PORT}, 143 {VIRTCHNL_PROTO_HDR_PPPOE, 144 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID), 145 BIT_ULL(ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID)}, 146 {VIRTCHNL_PROTO_HDR_GTPU_IP, 147 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPU_IP_TEID), 148 BIT_ULL(ICE_FLOW_FIELD_IDX_GTPU_IP_TEID)}, 149 {VIRTCHNL_PROTO_HDR_L2TPV3, 150 FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID), 151 BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID)}, 152 {VIRTCHNL_PROTO_HDR_ESP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ESP_SPI), 153 BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI)}, 154 {VIRTCHNL_PROTO_HDR_AH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_AH_SPI), 155 BIT_ULL(ICE_FLOW_FIELD_IDX_AH_SPI)}, 156 {VIRTCHNL_PROTO_HDR_PFCP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID), 157 BIT_ULL(ICE_FLOW_FIELD_IDX_PFCP_SEID)}, 158 }; 159 160 /** 161 * ice_vc_validate_pattern 162 * @vf: pointer to the VF info 163 * @proto: virtchnl protocol headers 164 * 165 * validate the pattern is supported or not. 166 * 167 * Return: true on success, false on error. 168 */ 169 bool 170 ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto) 171 { 172 bool is_ipv4 = false; 173 bool is_ipv6 = false; 174 bool is_udp = false; 175 u16 ptype = -1; 176 int i = 0; 177 178 while (i < proto->count && 179 proto->proto_hdr[i].type != VIRTCHNL_PROTO_HDR_NONE) { 180 switch (proto->proto_hdr[i].type) { 181 case VIRTCHNL_PROTO_HDR_ETH: 182 ptype = ICE_PTYPE_MAC_PAY; 183 break; 184 case VIRTCHNL_PROTO_HDR_IPV4: 185 ptype = ICE_PTYPE_IPV4_PAY; 186 is_ipv4 = true; 187 break; 188 case VIRTCHNL_PROTO_HDR_IPV6: 189 ptype = ICE_PTYPE_IPV6_PAY; 190 is_ipv6 = true; 191 break; 192 case VIRTCHNL_PROTO_HDR_UDP: 193 if (is_ipv4) 194 ptype = ICE_PTYPE_IPV4_UDP_PAY; 195 else if (is_ipv6) 196 ptype = ICE_PTYPE_IPV6_UDP_PAY; 197 is_udp = true; 198 break; 199 case VIRTCHNL_PROTO_HDR_TCP: 200 if (is_ipv4) 201 ptype = ICE_PTYPE_IPV4_TCP_PAY; 202 else if (is_ipv6) 203 ptype = ICE_PTYPE_IPV6_TCP_PAY; 204 break; 205 case VIRTCHNL_PROTO_HDR_SCTP: 206 if (is_ipv4) 207 ptype = ICE_PTYPE_IPV4_SCTP_PAY; 208 else if (is_ipv6) 209 ptype = ICE_PTYPE_IPV6_SCTP_PAY; 210 break; 211 case VIRTCHNL_PROTO_HDR_GTPU_IP: 212 case VIRTCHNL_PROTO_HDR_GTPU_EH: 213 if (is_ipv4) 214 ptype = ICE_MAC_IPV4_GTPU; 215 else if (is_ipv6) 216 ptype = ICE_MAC_IPV6_GTPU; 217 goto out; 218 case VIRTCHNL_PROTO_HDR_L2TPV3: 219 if (is_ipv4) 220 ptype = ICE_MAC_IPV4_L2TPV3; 221 else if (is_ipv6) 222 ptype = ICE_MAC_IPV6_L2TPV3; 223 goto out; 224 case VIRTCHNL_PROTO_HDR_ESP: 225 if (is_ipv4) 226 ptype = is_udp ? ICE_MAC_IPV4_NAT_T_ESP : 227 ICE_MAC_IPV4_ESP; 228 else if (is_ipv6) 229 ptype = is_udp ? ICE_MAC_IPV6_NAT_T_ESP : 230 ICE_MAC_IPV6_ESP; 231 goto out; 232 case VIRTCHNL_PROTO_HDR_AH: 233 if (is_ipv4) 234 ptype = ICE_MAC_IPV4_AH; 235 else if (is_ipv6) 236 ptype = ICE_MAC_IPV6_AH; 237 goto out; 238 case VIRTCHNL_PROTO_HDR_PFCP: 239 if (is_ipv4) 240 ptype = ICE_MAC_IPV4_PFCP_SESSION; 241 else if (is_ipv6) 242 ptype = ICE_MAC_IPV6_PFCP_SESSION; 243 goto out; 244 default: 245 break; 246 } 247 i++; 248 } 249 250 out: 251 return ice_hw_ptype_ena(&vf->pf->hw, ptype); 252 } 253 254 /** 255 * ice_vc_parse_rss_cfg - parses hash fields and headers from 256 * a specific virtchnl RSS cfg 257 * @hw: pointer to the hardware 258 * @rss_cfg: pointer to the virtchnl RSS cfg 259 * @hash_cfg: pointer to the HW hash configuration 260 * 261 * Return true if all the protocol header and hash fields in the RSS cfg could 262 * be parsed, else return false 263 * 264 * This function parses the virtchnl RSS cfg to be the intended 265 * hash fields and the intended header for RSS configuration 266 */ 267 static bool ice_vc_parse_rss_cfg(struct ice_hw *hw, 268 struct virtchnl_rss_cfg *rss_cfg, 269 struct ice_rss_hash_cfg *hash_cfg) 270 { 271 const struct ice_vc_hash_field_match_type *hf_list; 272 const struct ice_vc_hdr_match_type *hdr_list; 273 int i, hf_list_len, hdr_list_len; 274 u32 *addl_hdrs = &hash_cfg->addl_hdrs; 275 u64 *hash_flds = &hash_cfg->hash_flds; 276 277 /* set outer layer RSS as default */ 278 hash_cfg->hdr_type = ICE_RSS_OUTER_HEADERS; 279 280 if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) 281 hash_cfg->symm = true; 282 else 283 hash_cfg->symm = false; 284 285 hf_list = ice_vc_hash_field_list; 286 hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list); 287 hdr_list = ice_vc_hdr_list; 288 hdr_list_len = ARRAY_SIZE(ice_vc_hdr_list); 289 290 for (i = 0; i < rss_cfg->proto_hdrs.count; i++) { 291 struct virtchnl_proto_hdr *proto_hdr = 292 &rss_cfg->proto_hdrs.proto_hdr[i]; 293 bool hdr_found = false; 294 int j; 295 296 /* Find matched ice headers according to virtchnl headers. */ 297 for (j = 0; j < hdr_list_len; j++) { 298 struct ice_vc_hdr_match_type hdr_map = hdr_list[j]; 299 300 if (proto_hdr->type == hdr_map.vc_hdr) { 301 *addl_hdrs |= hdr_map.ice_hdr; 302 hdr_found = true; 303 } 304 } 305 306 if (!hdr_found) 307 return false; 308 309 /* Find matched ice hash fields according to 310 * virtchnl hash fields. 311 */ 312 for (j = 0; j < hf_list_len; j++) { 313 struct ice_vc_hash_field_match_type hf_map = hf_list[j]; 314 315 if (proto_hdr->type == hf_map.vc_hdr && 316 proto_hdr->field_selector == hf_map.vc_hash_field) { 317 *hash_flds |= hf_map.ice_hash_field; 318 break; 319 } 320 } 321 } 322 323 return true; 324 } 325 326 /** 327 * ice_vf_adv_rss_offload_ena - determine if capabilities support advanced 328 * RSS offloads 329 * @caps: VF driver negotiated capabilities 330 * 331 * Return true if VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF capability is set, 332 * else return false 333 */ 334 static bool ice_vf_adv_rss_offload_ena(u32 caps) 335 { 336 return !!(caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF); 337 } 338 339 /** 340 * ice_vc_handle_rss_cfg 341 * @vf: pointer to the VF info 342 * @msg: pointer to the message buffer 343 * @add: add a RSS config if true, otherwise delete a RSS config 344 * 345 * This function adds/deletes a RSS config 346 */ 347 int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add) 348 { 349 u32 v_opcode = add ? VIRTCHNL_OP_ADD_RSS_CFG : VIRTCHNL_OP_DEL_RSS_CFG; 350 struct virtchnl_rss_cfg *rss_cfg = (struct virtchnl_rss_cfg *)msg; 351 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 352 struct device *dev = ice_pf_to_dev(vf->pf); 353 struct ice_hw *hw = &vf->pf->hw; 354 struct ice_vsi *vsi; 355 356 if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { 357 dev_dbg(dev, "VF %d attempting to configure RSS, but RSS is not supported by the PF\n", 358 vf->vf_id); 359 v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED; 360 goto error_param; 361 } 362 363 if (!ice_vf_adv_rss_offload_ena(vf->driver_caps)) { 364 dev_dbg(dev, "VF %d attempting to configure RSS, but Advanced RSS offload is not supported\n", 365 vf->vf_id); 366 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 367 goto error_param; 368 } 369 370 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 371 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 372 goto error_param; 373 } 374 375 if (rss_cfg->proto_hdrs.count > VIRTCHNL_MAX_NUM_PROTO_HDRS || 376 rss_cfg->rss_algorithm < VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC || 377 rss_cfg->rss_algorithm > VIRTCHNL_RSS_ALG_XOR_SYMMETRIC) { 378 dev_dbg(dev, "VF %d attempting to configure RSS, but RSS configuration is not valid\n", 379 vf->vf_id); 380 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 381 goto error_param; 382 } 383 384 vsi = ice_get_vf_vsi(vf); 385 if (!vsi) { 386 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 387 goto error_param; 388 } 389 390 if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) { 391 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 392 goto error_param; 393 } 394 395 if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) { 396 struct ice_vsi_ctx *ctx; 397 u8 lut_type, hash_type; 398 int status; 399 400 lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 401 hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR : 402 ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; 403 404 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 405 if (!ctx) { 406 v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 407 goto error_param; 408 } 409 410 ctx->info.q_opt_rss = 411 FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_LUT_M, lut_type) | 412 FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hash_type); 413 414 /* Preserve existing queueing option setting */ 415 ctx->info.q_opt_rss |= (vsi->info.q_opt_rss & 416 ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M); 417 ctx->info.q_opt_tc = vsi->info.q_opt_tc; 418 ctx->info.q_opt_flags = vsi->info.q_opt_rss; 419 420 ctx->info.valid_sections = 421 cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); 422 423 status = ice_update_vsi(hw, vsi->idx, ctx, NULL); 424 if (status) { 425 dev_err(dev, "update VSI for RSS failed, err %d aq_err %s\n", 426 status, libie_aq_str(hw->adminq.sq_last_status)); 427 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 428 } else { 429 vsi->info.q_opt_rss = ctx->info.q_opt_rss; 430 } 431 432 kfree(ctx); 433 } else { 434 struct ice_rss_hash_cfg cfg; 435 436 /* Only check for none raw pattern case */ 437 if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) { 438 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 439 goto error_param; 440 } 441 cfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; 442 cfg.hash_flds = ICE_HASH_INVALID; 443 cfg.hdr_type = ICE_RSS_ANY_HEADERS; 444 445 if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &cfg)) { 446 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 447 goto error_param; 448 } 449 450 if (add) { 451 if (ice_add_rss_cfg(hw, vsi, &cfg)) { 452 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 453 dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n", 454 vsi->vsi_num, v_ret); 455 } 456 } else { 457 int status; 458 459 status = ice_rem_rss_cfg(hw, vsi->idx, &cfg); 460 /* We just ignore -ENOENT, because if two configurations 461 * share the same profile remove one of them actually 462 * removes both, since the profile is deleted. 463 */ 464 if (status && status != -ENOENT) { 465 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 466 dev_err(dev, "ice_rem_rss_cfg failed for VF ID:%d, error:%d\n", 467 vf->vf_id, status); 468 } 469 } 470 } 471 472 error_param: 473 return ice_vc_send_msg_to_vf(vf, v_opcode, v_ret, NULL, 0); 474 } 475 476 /** 477 * ice_vc_config_rss_key 478 * @vf: pointer to the VF info 479 * @msg: pointer to the msg buffer 480 * 481 * Configure the VF's RSS key 482 */ 483 int ice_vc_config_rss_key(struct ice_vf *vf, u8 *msg) 484 { 485 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 486 struct virtchnl_rss_key *vrk = 487 (struct virtchnl_rss_key *)msg; 488 struct ice_vsi *vsi; 489 490 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 491 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 492 goto error_param; 493 } 494 495 if (!ice_vc_isvalid_vsi_id(vf, vrk->vsi_id)) { 496 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 497 goto error_param; 498 } 499 500 if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) { 501 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 502 goto error_param; 503 } 504 505 if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { 506 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 507 goto error_param; 508 } 509 510 vsi = ice_get_vf_vsi(vf); 511 if (!vsi) { 512 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 513 goto error_param; 514 } 515 516 if (ice_set_rss_key(vsi, vrk->key)) 517 v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; 518 error_param: 519 return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_KEY, v_ret, 520 NULL, 0); 521 } 522 523 /** 524 * ice_vc_config_rss_lut 525 * @vf: pointer to the VF info 526 * @msg: pointer to the msg buffer 527 * 528 * Configure the VF's RSS LUT 529 */ 530 int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg) 531 { 532 struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg; 533 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 534 struct ice_vsi *vsi; 535 536 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 537 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 538 goto error_param; 539 } 540 541 if (!ice_vc_isvalid_vsi_id(vf, vrl->vsi_id)) { 542 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 543 goto error_param; 544 } 545 546 if (vrl->lut_entries != ICE_LUT_VSI_SIZE) { 547 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 548 goto error_param; 549 } 550 551 if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { 552 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 553 goto error_param; 554 } 555 556 vsi = ice_get_vf_vsi(vf); 557 if (!vsi) { 558 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 559 goto error_param; 560 } 561 562 if (ice_set_rss_lut(vsi, vrl->lut, ICE_LUT_VSI_SIZE)) 563 v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; 564 error_param: 565 return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT, v_ret, 566 NULL, 0); 567 } 568 569 /** 570 * ice_vc_config_rss_hfunc 571 * @vf: pointer to the VF info 572 * @msg: pointer to the msg buffer 573 * 574 * Configure the VF's RSS Hash function 575 */ 576 int ice_vc_config_rss_hfunc(struct ice_vf *vf, u8 *msg) 577 { 578 struct virtchnl_rss_hfunc *vrh = (struct virtchnl_rss_hfunc *)msg; 579 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 580 u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ; 581 struct ice_vsi *vsi; 582 583 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 584 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 585 goto error_param; 586 } 587 588 if (!ice_vc_isvalid_vsi_id(vf, vrh->vsi_id)) { 589 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 590 goto error_param; 591 } 592 593 if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { 594 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 595 goto error_param; 596 } 597 598 vsi = ice_get_vf_vsi(vf); 599 if (!vsi) { 600 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 601 goto error_param; 602 } 603 604 if (vrh->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) 605 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ; 606 607 if (ice_set_rss_hfunc(vsi, hfunc)) 608 v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR; 609 error_param: 610 return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_HFUNC, v_ret, 611 NULL, 0); 612 } 613 614 /** 615 * ice_vc_get_rss_hashcfg - return the RSS Hash configuration 616 * @vf: pointer to the VF info 617 */ 618 int ice_vc_get_rss_hashcfg(struct ice_vf *vf) 619 { 620 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 621 struct virtchnl_rss_hashcfg *vrh = NULL; 622 int len = 0, ret; 623 624 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 625 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 626 goto err; 627 } 628 629 if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) { 630 dev_err(ice_pf_to_dev(vf->pf), "RSS not supported by PF\n"); 631 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 632 goto err; 633 } 634 635 len = sizeof(struct virtchnl_rss_hashcfg); 636 vrh = kzalloc(len, GFP_KERNEL); 637 if (!vrh) { 638 v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; 639 len = 0; 640 goto err; 641 } 642 643 vrh->hashcfg = ICE_DEFAULT_RSS_HASHCFG; 644 err: 645 /* send the response back to the VF */ 646 ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HASHCFG_CAPS, v_ret, 647 (u8 *)vrh, len); 648 kfree(vrh); 649 return ret; 650 } 651 652 /** 653 * ice_vc_set_rss_hashcfg - set RSS Hash configuration bits for the VF 654 * @vf: pointer to the VF info 655 * @msg: pointer to the msg buffer 656 */ 657 int ice_vc_set_rss_hashcfg(struct ice_vf *vf, u8 *msg) 658 { 659 struct virtchnl_rss_hashcfg *vrh = (struct virtchnl_rss_hashcfg *)msg; 660 enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; 661 struct ice_pf *pf = vf->pf; 662 struct ice_vsi *vsi; 663 struct device *dev; 664 int status; 665 666 dev = ice_pf_to_dev(pf); 667 668 if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { 669 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 670 goto err; 671 } 672 673 if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 674 dev_err(dev, "RSS not supported by PF\n"); 675 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 676 goto err; 677 } 678 679 vsi = ice_get_vf_vsi(vf); 680 if (!vsi) { 681 v_ret = VIRTCHNL_STATUS_ERR_PARAM; 682 goto err; 683 } 684 685 /* clear all previously programmed RSS configuration to allow VF drivers 686 * the ability to customize the RSS configuration and/or completely 687 * disable RSS 688 */ 689 status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx); 690 if (status && !vrh->hashcfg) { 691 /* only report failure to clear the current RSS configuration if 692 * that was clearly the VF's intention (i.e. vrh->hashcfg = 0) 693 */ 694 v_ret = ice_err_to_virt_err(status); 695 goto err; 696 } else if (status) { 697 /* allow the VF to update the RSS configuration even on failure 698 * to clear the current RSS confguration in an attempt to keep 699 * RSS in a working state 700 */ 701 dev_warn(dev, "Failed to clear the RSS configuration for VF %u\n", 702 vf->vf_id); 703 } 704 705 if (vrh->hashcfg) { 706 status = ice_add_avf_rss_cfg(&pf->hw, vsi, vrh->hashcfg); 707 v_ret = ice_err_to_virt_err(status); 708 } 709 710 /* save the requested VF configuration */ 711 if (!v_ret) 712 vf->rss_hashcfg = vrh->hashcfg; 713 714 /* send the response to the VF */ 715 err: 716 return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_SET_RSS_HASHCFG, v_ret, 717 NULL, 0); 718 } 719 720