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