1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2019, Intel Corporation. */ 3 4 #include "ice_common.h" 5 #include "ice_flow.h" 6 7 /* Describe properties of a protocol header field */ 8 struct ice_flow_field_info { 9 enum ice_flow_seg_hdr hdr; 10 s16 off; /* Offset from start of a protocol header, in bits */ 11 u16 size; /* Size of fields in bits */ 12 }; 13 14 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 15 .hdr = _hdr, \ 16 .off = (_offset_bytes) * BITS_PER_BYTE, \ 17 .size = (_size_bytes) * BITS_PER_BYTE, \ 18 } 19 20 /* Table containing properties of supported protocol header fields */ 21 static const 22 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 23 /* IPv4 / IPv6 */ 24 /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 25 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)), 26 /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 27 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)), 28 /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 29 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)), 30 /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 31 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)), 32 /* Transport */ 33 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 34 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)), 35 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 36 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)), 37 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 38 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)), 39 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 40 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)), 41 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 42 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)), 43 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 44 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)), 45 46 }; 47 48 /* Bitmaps indicating relevant packet types for a particular protocol header 49 * 50 * Packet types for packets with an Outer/First/Single IPv4 header 51 */ 52 static const u32 ice_ptypes_ipv4_ofos[] = { 53 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, 54 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56 0x00000000, 0x00000000, 0x00000000, 0x00000000, 57 0x00000000, 0x00000000, 0x00000000, 0x00000000, 58 0x00000000, 0x00000000, 0x00000000, 0x00000000, 59 0x00000000, 0x00000000, 0x00000000, 0x00000000, 60 0x00000000, 0x00000000, 0x00000000, 0x00000000, 61 }; 62 63 /* Packet types for packets with an Innermost/Last IPv4 header */ 64 static const u32 ice_ptypes_ipv4_il[] = { 65 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 66 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 67 0x00000000, 0x00000000, 0x00000000, 0x00000000, 68 0x00000000, 0x00000000, 0x00000000, 0x00000000, 69 0x00000000, 0x00000000, 0x00000000, 0x00000000, 70 0x00000000, 0x00000000, 0x00000000, 0x00000000, 71 0x00000000, 0x00000000, 0x00000000, 0x00000000, 72 0x00000000, 0x00000000, 0x00000000, 0x00000000, 73 }; 74 75 /* Packet types for packets with an Outer/First/Single IPv6 header */ 76 static const u32 ice_ptypes_ipv6_ofos[] = { 77 0x00000000, 0x00000000, 0x77000000, 0x10002000, 78 0x00000000, 0x00000000, 0x00000000, 0x00000000, 79 0x00000000, 0x00000000, 0x00000000, 0x00000000, 80 0x00000000, 0x00000000, 0x00000000, 0x00000000, 81 0x00000000, 0x00000000, 0x00000000, 0x00000000, 82 0x00000000, 0x00000000, 0x00000000, 0x00000000, 83 0x00000000, 0x00000000, 0x00000000, 0x00000000, 84 0x00000000, 0x00000000, 0x00000000, 0x00000000, 85 }; 86 87 /* Packet types for packets with an Innermost/Last IPv6 header */ 88 static const u32 ice_ptypes_ipv6_il[] = { 89 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 90 0x00000770, 0x00000000, 0x00000000, 0x00000000, 91 0x00000000, 0x00000000, 0x00000000, 0x00000000, 92 0x00000000, 0x00000000, 0x00000000, 0x00000000, 93 0x00000000, 0x00000000, 0x00000000, 0x00000000, 94 0x00000000, 0x00000000, 0x00000000, 0x00000000, 95 0x00000000, 0x00000000, 0x00000000, 0x00000000, 96 0x00000000, 0x00000000, 0x00000000, 0x00000000, 97 }; 98 99 /* UDP Packet types for non-tunneled packets or tunneled 100 * packets with inner UDP. 101 */ 102 static const u32 ice_ptypes_udp_il[] = { 103 0x81000000, 0x20204040, 0x04000010, 0x80810102, 104 0x00000040, 0x00000000, 0x00000000, 0x00000000, 105 0x00000000, 0x00000000, 0x00000000, 0x00000000, 106 0x00000000, 0x00000000, 0x00000000, 0x00000000, 107 0x00000000, 0x00000000, 0x00000000, 0x00000000, 108 0x00000000, 0x00000000, 0x00000000, 0x00000000, 109 0x00000000, 0x00000000, 0x00000000, 0x00000000, 110 0x00000000, 0x00000000, 0x00000000, 0x00000000, 111 }; 112 113 /* Packet types for packets with an Innermost/Last TCP header */ 114 static const u32 ice_ptypes_tcp_il[] = { 115 0x04000000, 0x80810102, 0x10000040, 0x02040408, 116 0x00000102, 0x00000000, 0x00000000, 0x00000000, 117 0x00000000, 0x00000000, 0x00000000, 0x00000000, 118 0x00000000, 0x00000000, 0x00000000, 0x00000000, 119 0x00000000, 0x00000000, 0x00000000, 0x00000000, 120 0x00000000, 0x00000000, 0x00000000, 0x00000000, 121 0x00000000, 0x00000000, 0x00000000, 0x00000000, 122 0x00000000, 0x00000000, 0x00000000, 0x00000000, 123 }; 124 125 /* Packet types for packets with an Innermost/Last SCTP header */ 126 static const u32 ice_ptypes_sctp_il[] = { 127 0x08000000, 0x01020204, 0x20000081, 0x04080810, 128 0x00000204, 0x00000000, 0x00000000, 0x00000000, 129 0x00000000, 0x00000000, 0x00000000, 0x00000000, 130 0x00000000, 0x00000000, 0x00000000, 0x00000000, 131 0x00000000, 0x00000000, 0x00000000, 0x00000000, 132 0x00000000, 0x00000000, 0x00000000, 0x00000000, 133 0x00000000, 0x00000000, 0x00000000, 0x00000000, 134 0x00000000, 0x00000000, 0x00000000, 0x00000000, 135 }; 136 137 /* Manage parameters and info. used during the creation of a flow profile */ 138 struct ice_flow_prof_params { 139 enum ice_block blk; 140 u16 entry_length; /* # of bytes formatted entry will require */ 141 u8 es_cnt; 142 struct ice_flow_prof *prof; 143 144 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 145 * This will give us the direction flags. 146 */ 147 struct ice_fv_word es[ICE_MAX_FV_WORDS]; 148 DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); 149 }; 150 151 #define ICE_FLOW_SEG_HDRS_L3_MASK \ 152 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 153 #define ICE_FLOW_SEG_HDRS_L4_MASK \ 154 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 155 156 /** 157 * ice_flow_val_hdrs - validates packet segments for valid protocol headers 158 * @segs: array of one or more packet segments that describe the flow 159 * @segs_cnt: number of packet segments provided 160 */ 161 static enum ice_status 162 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 163 { 164 u8 i; 165 166 for (i = 0; i < segs_cnt; i++) { 167 /* Multiple L3 headers */ 168 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 169 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 170 return ICE_ERR_PARAM; 171 172 /* Multiple L4 headers */ 173 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 174 !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 175 return ICE_ERR_PARAM; 176 } 177 178 return 0; 179 } 180 181 /** 182 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 183 * @params: information about the flow to be processed 184 * 185 * This function identifies the packet types associated with the protocol 186 * headers being present in packet segments of the specified flow profile. 187 */ 188 static enum ice_status 189 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 190 { 191 struct ice_flow_prof *prof; 192 u8 i; 193 194 memset(params->ptypes, 0xff, sizeof(params->ptypes)); 195 196 prof = params->prof; 197 198 for (i = 0; i < params->prof->segs_cnt; i++) { 199 const unsigned long *src; 200 u32 hdrs; 201 202 hdrs = prof->segs[i].hdrs; 203 204 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 205 src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos : 206 (const unsigned long *)ice_ptypes_ipv4_il; 207 bitmap_and(params->ptypes, params->ptypes, src, 208 ICE_FLOW_PTYPE_MAX); 209 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 210 src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos : 211 (const unsigned long *)ice_ptypes_ipv6_il; 212 bitmap_and(params->ptypes, params->ptypes, src, 213 ICE_FLOW_PTYPE_MAX); 214 } 215 216 if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 217 src = (const unsigned long *)ice_ptypes_udp_il; 218 bitmap_and(params->ptypes, params->ptypes, src, 219 ICE_FLOW_PTYPE_MAX); 220 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 221 bitmap_and(params->ptypes, params->ptypes, 222 (const unsigned long *)ice_ptypes_tcp_il, 223 ICE_FLOW_PTYPE_MAX); 224 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 225 src = (const unsigned long *)ice_ptypes_sctp_il; 226 bitmap_and(params->ptypes, params->ptypes, src, 227 ICE_FLOW_PTYPE_MAX); 228 } 229 } 230 231 return 0; 232 } 233 234 /** 235 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 236 * @hw: pointer to the HW struct 237 * @params: information about the flow to be processed 238 * @seg: packet segment index of the field to be extracted 239 * @fld: ID of field to be extracted 240 * 241 * This function determines the protocol ID, offset, and size of the given 242 * field. It then allocates one or more extraction sequence entries for the 243 * given field, and fill the entries with protocol ID and offset information. 244 */ 245 static enum ice_status 246 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 247 u8 seg, enum ice_flow_field fld) 248 { 249 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 250 u8 fv_words = hw->blk[params->blk].es.fvw; 251 struct ice_flow_fld_info *flds; 252 u16 cnt, ese_bits, i; 253 u16 off; 254 255 flds = params->prof->segs[seg].fields; 256 257 switch (fld) { 258 case ICE_FLOW_FIELD_IDX_IPV4_SA: 259 case ICE_FLOW_FIELD_IDX_IPV4_DA: 260 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 261 break; 262 case ICE_FLOW_FIELD_IDX_IPV6_SA: 263 case ICE_FLOW_FIELD_IDX_IPV6_DA: 264 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 265 break; 266 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 267 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 268 prot_id = ICE_PROT_TCP_IL; 269 break; 270 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 271 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 272 prot_id = ICE_PROT_UDP_IL_OR_S; 273 break; 274 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 275 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 276 prot_id = ICE_PROT_SCTP_IL; 277 break; 278 default: 279 return ICE_ERR_NOT_IMPL; 280 } 281 282 /* Each extraction sequence entry is a word in size, and extracts a 283 * word-aligned offset from a protocol header. 284 */ 285 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 286 287 flds[fld].xtrct.prot_id = prot_id; 288 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 289 ICE_FLOW_FV_EXTRACT_SZ; 290 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 291 flds[fld].xtrct.idx = params->es_cnt; 292 293 /* Adjust the next field-entry index after accommodating the number of 294 * entries this field consumes 295 */ 296 cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size, 297 ese_bits); 298 299 /* Fill in the extraction sequence entries needed for this field */ 300 off = flds[fld].xtrct.off; 301 for (i = 0; i < cnt; i++) { 302 u8 idx; 303 304 /* Make sure the number of extraction sequence required 305 * does not exceed the block's capability 306 */ 307 if (params->es_cnt >= fv_words) 308 return ICE_ERR_MAX_LIMIT; 309 310 /* some blocks require a reversed field vector layout */ 311 if (hw->blk[params->blk].es.reverse) 312 idx = fv_words - params->es_cnt - 1; 313 else 314 idx = params->es_cnt; 315 316 params->es[idx].prot_id = prot_id; 317 params->es[idx].off = off; 318 params->es_cnt++; 319 320 off += ICE_FLOW_FV_EXTRACT_SZ; 321 } 322 323 return 0; 324 } 325 326 /** 327 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 328 * @hw: pointer to the HW struct 329 * @params: information about the flow to be processed 330 * 331 * This function iterates through all matched fields in the given segments, and 332 * creates an extraction sequence for the fields. 333 */ 334 static enum ice_status 335 ice_flow_create_xtrct_seq(struct ice_hw *hw, 336 struct ice_flow_prof_params *params) 337 { 338 struct ice_flow_prof *prof = params->prof; 339 enum ice_status status = 0; 340 u8 i; 341 342 for (i = 0; i < prof->segs_cnt; i++) { 343 u8 j; 344 345 for_each_set_bit(j, (unsigned long *)&prof->segs[i].match, 346 ICE_FLOW_FIELD_IDX_MAX) { 347 status = ice_flow_xtract_fld(hw, params, i, 348 (enum ice_flow_field)j); 349 if (status) 350 return status; 351 } 352 } 353 354 return status; 355 } 356 357 /** 358 * ice_flow_proc_segs - process all packet segments associated with a profile 359 * @hw: pointer to the HW struct 360 * @params: information about the flow to be processed 361 */ 362 static enum ice_status 363 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 364 { 365 enum ice_status status; 366 367 status = ice_flow_proc_seg_hdrs(params); 368 if (status) 369 return status; 370 371 status = ice_flow_create_xtrct_seq(hw, params); 372 if (status) 373 return status; 374 375 switch (params->blk) { 376 case ICE_BLK_RSS: 377 /* Only header information is provided for RSS configuration. 378 * No further processing is needed. 379 */ 380 status = 0; 381 break; 382 default: 383 return ICE_ERR_NOT_IMPL; 384 } 385 386 return status; 387 } 388 389 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 390 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 391 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 392 393 /** 394 * ice_flow_find_prof_conds - Find a profile matching headers and conditions 395 * @hw: pointer to the HW struct 396 * @blk: classification stage 397 * @dir: flow direction 398 * @segs: array of one or more packet segments that describe the flow 399 * @segs_cnt: number of packet segments provided 400 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 401 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 402 */ 403 static struct ice_flow_prof * 404 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 405 enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 406 u8 segs_cnt, u16 vsi_handle, u32 conds) 407 { 408 struct ice_flow_prof *p, *prof = NULL; 409 410 mutex_lock(&hw->fl_profs_locks[blk]); 411 list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 412 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 413 segs_cnt && segs_cnt == p->segs_cnt) { 414 u8 i; 415 416 /* Check for profile-VSI association if specified */ 417 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 418 ice_is_vsi_valid(hw, vsi_handle) && 419 !test_bit(vsi_handle, p->vsis)) 420 continue; 421 422 /* Protocol headers must be checked. Matched fields are 423 * checked if specified. 424 */ 425 for (i = 0; i < segs_cnt; i++) 426 if (segs[i].hdrs != p->segs[i].hdrs || 427 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 428 segs[i].match != p->segs[i].match)) 429 break; 430 431 /* A match is found if all segments are matched */ 432 if (i == segs_cnt) { 433 prof = p; 434 break; 435 } 436 } 437 mutex_unlock(&hw->fl_profs_locks[blk]); 438 439 return prof; 440 } 441 442 /** 443 * ice_flow_find_prof_id - Look up a profile with given profile ID 444 * @hw: pointer to the HW struct 445 * @blk: classification stage 446 * @prof_id: unique ID to identify this flow profile 447 */ 448 static struct ice_flow_prof * 449 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 450 { 451 struct ice_flow_prof *p; 452 453 list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 454 if (p->id == prof_id) 455 return p; 456 457 return NULL; 458 } 459 460 /** 461 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 462 * @hw: pointer to the HW struct 463 * @blk: classification stage 464 * @dir: flow direction 465 * @prof_id: unique ID to identify this flow profile 466 * @segs: array of one or more packet segments that describe the flow 467 * @segs_cnt: number of packet segments provided 468 * @prof: stores the returned flow profile added 469 * 470 * Assumption: the caller has acquired the lock to the profile list 471 */ 472 static enum ice_status 473 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 474 enum ice_flow_dir dir, u64 prof_id, 475 struct ice_flow_seg_info *segs, u8 segs_cnt, 476 struct ice_flow_prof **prof) 477 { 478 struct ice_flow_prof_params params; 479 enum ice_status status; 480 u8 i; 481 482 if (!prof) 483 return ICE_ERR_BAD_PTR; 484 485 memset(¶ms, 0, sizeof(params)); 486 params.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof), 487 GFP_KERNEL); 488 if (!params.prof) 489 return ICE_ERR_NO_MEMORY; 490 491 /* initialize extraction sequence to all invalid (0xff) */ 492 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 493 params.es[i].prot_id = ICE_PROT_INVALID; 494 params.es[i].off = ICE_FV_OFFSET_INVAL; 495 } 496 497 params.blk = blk; 498 params.prof->id = prof_id; 499 params.prof->dir = dir; 500 params.prof->segs_cnt = segs_cnt; 501 502 /* Make a copy of the segments that need to be persistent in the flow 503 * profile instance 504 */ 505 for (i = 0; i < segs_cnt; i++) 506 memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs)); 507 508 status = ice_flow_proc_segs(hw, ¶ms); 509 if (status) { 510 ice_debug(hw, ICE_DBG_FLOW, 511 "Error processing a flow's packet segments\n"); 512 goto out; 513 } 514 515 /* Add a HW profile for this flow profile */ 516 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es); 517 if (status) { 518 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 519 goto out; 520 } 521 522 INIT_LIST_HEAD(¶ms.prof->entries); 523 mutex_init(¶ms.prof->entries_lock); 524 *prof = params.prof; 525 526 out: 527 if (status) 528 devm_kfree(ice_hw_to_dev(hw), params.prof); 529 530 return status; 531 } 532 533 /** 534 * ice_flow_rem_prof_sync - remove a flow profile 535 * @hw: pointer to the hardware structure 536 * @blk: classification stage 537 * @prof: pointer to flow profile to remove 538 * 539 * Assumption: the caller has acquired the lock to the profile list 540 */ 541 static enum ice_status 542 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 543 struct ice_flow_prof *prof) 544 { 545 enum ice_status status; 546 547 /* Remove all hardware profiles associated with this flow profile */ 548 status = ice_rem_prof(hw, blk, prof->id); 549 if (!status) { 550 list_del(&prof->l_entry); 551 mutex_destroy(&prof->entries_lock); 552 devm_kfree(ice_hw_to_dev(hw), prof); 553 } 554 555 return status; 556 } 557 558 /** 559 * ice_flow_assoc_prof - associate a VSI with a flow profile 560 * @hw: pointer to the hardware structure 561 * @blk: classification stage 562 * @prof: pointer to flow profile 563 * @vsi_handle: software VSI handle 564 * 565 * Assumption: the caller has acquired the lock to the profile list 566 * and the software VSI handle has been validated 567 */ 568 static enum ice_status 569 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 570 struct ice_flow_prof *prof, u16 vsi_handle) 571 { 572 enum ice_status status = 0; 573 574 if (!test_bit(vsi_handle, prof->vsis)) { 575 status = ice_add_prof_id_flow(hw, blk, 576 ice_get_hw_vsi_num(hw, 577 vsi_handle), 578 prof->id); 579 if (!status) 580 set_bit(vsi_handle, prof->vsis); 581 else 582 ice_debug(hw, ICE_DBG_FLOW, 583 "HW profile add failed, %d\n", 584 status); 585 } 586 587 return status; 588 } 589 590 /** 591 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 592 * @hw: pointer to the hardware structure 593 * @blk: classification stage 594 * @prof: pointer to flow profile 595 * @vsi_handle: software VSI handle 596 * 597 * Assumption: the caller has acquired the lock to the profile list 598 * and the software VSI handle has been validated 599 */ 600 static enum ice_status 601 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 602 struct ice_flow_prof *prof, u16 vsi_handle) 603 { 604 enum ice_status status = 0; 605 606 if (test_bit(vsi_handle, prof->vsis)) { 607 status = ice_rem_prof_id_flow(hw, blk, 608 ice_get_hw_vsi_num(hw, 609 vsi_handle), 610 prof->id); 611 if (!status) 612 clear_bit(vsi_handle, prof->vsis); 613 else 614 ice_debug(hw, ICE_DBG_FLOW, 615 "HW profile remove failed, %d\n", 616 status); 617 } 618 619 return status; 620 } 621 622 /** 623 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 624 * @hw: pointer to the HW struct 625 * @blk: classification stage 626 * @dir: flow direction 627 * @prof_id: unique ID to identify this flow profile 628 * @segs: array of one or more packet segments that describe the flow 629 * @segs_cnt: number of packet segments provided 630 * @prof: stores the returned flow profile added 631 */ 632 static enum ice_status 633 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 634 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 635 struct ice_flow_prof **prof) 636 { 637 enum ice_status status; 638 639 if (segs_cnt > ICE_FLOW_SEG_MAX) 640 return ICE_ERR_MAX_LIMIT; 641 642 if (!segs_cnt) 643 return ICE_ERR_PARAM; 644 645 if (!segs) 646 return ICE_ERR_BAD_PTR; 647 648 status = ice_flow_val_hdrs(segs, segs_cnt); 649 if (status) 650 return status; 651 652 mutex_lock(&hw->fl_profs_locks[blk]); 653 654 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 655 prof); 656 if (!status) 657 list_add(&(*prof)->l_entry, &hw->fl_profs[blk]); 658 659 mutex_unlock(&hw->fl_profs_locks[blk]); 660 661 return status; 662 } 663 664 /** 665 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 666 * @hw: pointer to the HW struct 667 * @blk: the block for which the flow profile is to be removed 668 * @prof_id: unique ID of the flow profile to be removed 669 */ 670 static enum ice_status 671 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 672 { 673 struct ice_flow_prof *prof; 674 enum ice_status status; 675 676 mutex_lock(&hw->fl_profs_locks[blk]); 677 678 prof = ice_flow_find_prof_id(hw, blk, prof_id); 679 if (!prof) { 680 status = ICE_ERR_DOES_NOT_EXIST; 681 goto out; 682 } 683 684 /* prof becomes invalid after the call */ 685 status = ice_flow_rem_prof_sync(hw, blk, prof); 686 687 out: 688 mutex_unlock(&hw->fl_profs_locks[blk]); 689 690 return status; 691 } 692 693 /** 694 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 695 * @seg: packet segment the field being set belongs to 696 * @fld: field to be set 697 * @type: type of the field 698 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 699 * entry's input buffer 700 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 701 * input buffer 702 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 703 * entry's input buffer 704 * 705 * This helper function stores information of a field being matched, including 706 * the type of the field and the locations of the value to match, the mask, and 707 * and the upper-bound value in the start of the input buffer for a flow entry. 708 * This function should only be used for fixed-size data structures. 709 * 710 * This function also opportunistically determines the protocol headers to be 711 * present based on the fields being set. Some fields cannot be used alone to 712 * determine the protocol headers present. Sometimes, fields for particular 713 * protocol headers are not matched. In those cases, the protocol headers 714 * must be explicitly set. 715 */ 716 static void 717 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 718 enum ice_flow_fld_match_type type, u16 val_loc, 719 u16 mask_loc, u16 last_loc) 720 { 721 u64 bit = BIT_ULL(fld); 722 723 seg->match |= bit; 724 if (type == ICE_FLOW_FLD_TYPE_RANGE) 725 seg->range |= bit; 726 727 seg->fields[fld].type = type; 728 seg->fields[fld].src.val = val_loc; 729 seg->fields[fld].src.mask = mask_loc; 730 seg->fields[fld].src.last = last_loc; 731 732 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 733 } 734 735 /** 736 * ice_flow_set_fld - specifies locations of field from entry's input buffer 737 * @seg: packet segment the field being set belongs to 738 * @fld: field to be set 739 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 740 * entry's input buffer 741 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 742 * input buffer 743 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 744 * entry's input buffer 745 * @range: indicate if field being matched is to be in a range 746 * 747 * This function specifies the locations, in the form of byte offsets from the 748 * start of the input buffer for a flow entry, from where the value to match, 749 * the mask value, and upper value can be extracted. These locations are then 750 * stored in the flow profile. When adding a flow entry associated with the 751 * flow profile, these locations will be used to quickly extract the values and 752 * create the content of a match entry. This function should only be used for 753 * fixed-size data structures. 754 */ 755 static void 756 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 757 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 758 { 759 enum ice_flow_fld_match_type t = range ? 760 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 761 762 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 763 } 764 765 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 766 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 767 768 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 769 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 770 771 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 772 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 773 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 774 775 /** 776 * ice_flow_set_rss_seg_info - setup packet segments for RSS 777 * @segs: pointer to the flow field segment(s) 778 * @hash_fields: fields to be hashed on for the segment(s) 779 * @flow_hdr: protocol header fields within a packet segment 780 * 781 * Helper function to extract fields from hash bitmap and use flow 782 * header value to set flow field segment for further use in flow 783 * profile entry or removal. 784 */ 785 static enum ice_status 786 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, 787 u32 flow_hdr) 788 { 789 u64 val; 790 u8 i; 791 792 for_each_set_bit(i, (unsigned long *)&hash_fields, 793 ICE_FLOW_FIELD_IDX_MAX) 794 ice_flow_set_fld(segs, (enum ice_flow_field)i, 795 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 796 ICE_FLOW_FLD_OFF_INVAL, false); 797 798 ICE_FLOW_SET_HDRS(segs, flow_hdr); 799 800 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) 801 return ICE_ERR_PARAM; 802 803 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 804 if (val && !is_power_of_2(val)) 805 return ICE_ERR_CFG; 806 807 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 808 if (val && !is_power_of_2(val)) 809 return ICE_ERR_CFG; 810 811 return 0; 812 } 813 814 /** 815 * ice_rem_vsi_rss_list - remove VSI from RSS list 816 * @hw: pointer to the hardware structure 817 * @vsi_handle: software VSI handle 818 * 819 * Remove the VSI from all RSS configurations in the list. 820 */ 821 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 822 { 823 struct ice_rss_cfg *r, *tmp; 824 825 if (list_empty(&hw->rss_list_head)) 826 return; 827 828 mutex_lock(&hw->rss_locks); 829 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 830 if (test_and_clear_bit(vsi_handle, r->vsis)) 831 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 832 list_del(&r->l_entry); 833 devm_kfree(ice_hw_to_dev(hw), r); 834 } 835 mutex_unlock(&hw->rss_locks); 836 } 837 838 /** 839 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 840 * @hw: pointer to the hardware structure 841 * @vsi_handle: software VSI handle 842 * 843 * This function will iterate through all flow profiles and disassociate 844 * the VSI from that profile. If the flow profile has no VSIs it will 845 * be removed. 846 */ 847 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 848 { 849 const enum ice_block blk = ICE_BLK_RSS; 850 struct ice_flow_prof *p, *t; 851 enum ice_status status = 0; 852 853 if (!ice_is_vsi_valid(hw, vsi_handle)) 854 return ICE_ERR_PARAM; 855 856 if (list_empty(&hw->fl_profs[blk])) 857 return 0; 858 859 mutex_lock(&hw->fl_profs_locks[blk]); 860 list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry) 861 if (test_bit(vsi_handle, p->vsis)) { 862 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 863 if (status) 864 break; 865 866 if (bitmap_empty(p->vsis, ICE_MAX_VSI)) { 867 status = ice_flow_rem_prof_sync(hw, blk, p); 868 if (status) 869 break; 870 } 871 } 872 mutex_unlock(&hw->fl_profs_locks[blk]); 873 874 return status; 875 } 876 877 /** 878 * ice_rem_rss_list - remove RSS configuration from list 879 * @hw: pointer to the hardware structure 880 * @vsi_handle: software VSI handle 881 * @prof: pointer to flow profile 882 * 883 * Assumption: lock has already been acquired for RSS list 884 */ 885 static void 886 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 887 { 888 struct ice_rss_cfg *r, *tmp; 889 890 /* Search for RSS hash fields associated to the VSI that match the 891 * hash configurations associated to the flow profile. If found 892 * remove from the RSS entry list of the VSI context and delete entry. 893 */ 894 list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 895 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 896 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 897 clear_bit(vsi_handle, r->vsis); 898 if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 899 list_del(&r->l_entry); 900 devm_kfree(ice_hw_to_dev(hw), r); 901 } 902 return; 903 } 904 } 905 906 /** 907 * ice_add_rss_list - add RSS configuration to list 908 * @hw: pointer to the hardware structure 909 * @vsi_handle: software VSI handle 910 * @prof: pointer to flow profile 911 * 912 * Assumption: lock has already been acquired for RSS list 913 */ 914 static enum ice_status 915 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 916 { 917 struct ice_rss_cfg *r, *rss_cfg; 918 919 list_for_each_entry(r, &hw->rss_list_head, l_entry) 920 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 921 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 922 set_bit(vsi_handle, r->vsis); 923 return 0; 924 } 925 926 rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg), 927 GFP_KERNEL); 928 if (!rss_cfg) 929 return ICE_ERR_NO_MEMORY; 930 931 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; 932 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; 933 set_bit(vsi_handle, rss_cfg->vsis); 934 935 list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head); 936 937 return 0; 938 } 939 940 #define ICE_FLOW_PROF_HASH_S 0 941 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 942 #define ICE_FLOW_PROF_HDR_S 32 943 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 944 #define ICE_FLOW_PROF_ENCAP_S 63 945 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) 946 947 #define ICE_RSS_OUTER_HEADERS 1 948 949 /* Flow profile ID format: 950 * [0:31] - Packet match fields 951 * [32:62] - Protocol header 952 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled 953 */ 954 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ 955 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 956 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 957 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)) 958 959 /** 960 * ice_add_rss_cfg_sync - add an RSS configuration 961 * @hw: pointer to the hardware structure 962 * @vsi_handle: software VSI handle 963 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 964 * @addl_hdrs: protocol header fields 965 * @segs_cnt: packet segment count 966 * 967 * Assumption: lock has already been acquired for RSS list 968 */ 969 static enum ice_status 970 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 971 u32 addl_hdrs, u8 segs_cnt) 972 { 973 const enum ice_block blk = ICE_BLK_RSS; 974 struct ice_flow_prof *prof = NULL; 975 struct ice_flow_seg_info *segs; 976 enum ice_status status; 977 978 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX) 979 return ICE_ERR_PARAM; 980 981 segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); 982 if (!segs) 983 return ICE_ERR_NO_MEMORY; 984 985 /* Construct the packet segment info from the hashed fields */ 986 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, 987 addl_hdrs); 988 if (status) 989 goto exit; 990 991 /* Search for a flow profile that has matching headers, hash fields 992 * and has the input VSI associated to it. If found, no further 993 * operations required and exit. 994 */ 995 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 996 vsi_handle, 997 ICE_FLOW_FIND_PROF_CHK_FLDS | 998 ICE_FLOW_FIND_PROF_CHK_VSI); 999 if (prof) 1000 goto exit; 1001 1002 /* Check if a flow profile exists with the same protocol headers and 1003 * associated with the input VSI. If so disassociate the VSI from 1004 * this profile. The VSI will be added to a new profile created with 1005 * the protocol header and new hash field configuration. 1006 */ 1007 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1008 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 1009 if (prof) { 1010 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1011 if (!status) 1012 ice_rem_rss_list(hw, vsi_handle, prof); 1013 else 1014 goto exit; 1015 1016 /* Remove profile if it has no VSIs associated */ 1017 if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) { 1018 status = ice_flow_rem_prof(hw, blk, prof->id); 1019 if (status) 1020 goto exit; 1021 } 1022 } 1023 1024 /* Search for a profile that has same match fields only. If this 1025 * exists then associate the VSI to this profile. 1026 */ 1027 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1028 vsi_handle, 1029 ICE_FLOW_FIND_PROF_CHK_FLDS); 1030 if (prof) { 1031 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1032 if (!status) 1033 status = ice_add_rss_list(hw, vsi_handle, prof); 1034 goto exit; 1035 } 1036 1037 /* Create a new flow profile with generated profile and packet 1038 * segment information. 1039 */ 1040 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 1041 ICE_FLOW_GEN_PROFID(hashed_flds, 1042 segs[segs_cnt - 1].hdrs, 1043 segs_cnt), 1044 segs, segs_cnt, &prof); 1045 if (status) 1046 goto exit; 1047 1048 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1049 /* If association to a new flow profile failed then this profile can 1050 * be removed. 1051 */ 1052 if (status) { 1053 ice_flow_rem_prof(hw, blk, prof->id); 1054 goto exit; 1055 } 1056 1057 status = ice_add_rss_list(hw, vsi_handle, prof); 1058 1059 exit: 1060 kfree(segs); 1061 return status; 1062 } 1063 1064 /** 1065 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 1066 * @hw: pointer to the hardware structure 1067 * @vsi_handle: software VSI handle 1068 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 1069 * @addl_hdrs: protocol header fields 1070 * 1071 * This function will generate a flow profile based on fields associated with 1072 * the input fields to hash on, the flow type and use the VSI number to add 1073 * a flow entry to the profile. 1074 */ 1075 enum ice_status 1076 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1077 u32 addl_hdrs) 1078 { 1079 enum ice_status status; 1080 1081 if (hashed_flds == ICE_HASH_INVALID || 1082 !ice_is_vsi_valid(hw, vsi_handle)) 1083 return ICE_ERR_PARAM; 1084 1085 mutex_lock(&hw->rss_locks); 1086 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, 1087 ICE_RSS_OUTER_HEADERS); 1088 mutex_unlock(&hw->rss_locks); 1089 1090 return status; 1091 } 1092 1093 /* Mapping of AVF hash bit fields to an L3-L4 hash combination. 1094 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 1095 * convert its values to their appropriate flow L3, L4 values. 1096 */ 1097 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 1098 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 1099 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 1100 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 1101 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 1102 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 1103 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 1104 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 1105 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 1106 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 1107 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 1108 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 1109 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 1110 1111 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 1112 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 1113 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 1114 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 1115 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 1116 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 1117 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 1118 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 1119 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 1120 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 1121 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 1122 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 1123 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 1124 1125 /** 1126 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 1127 * @hw: pointer to the hardware structure 1128 * @vsi_handle: software VSI handle 1129 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 1130 * 1131 * This function will take the hash bitmap provided by the AVF driver via a 1132 * message, convert it to ICE-compatible values, and configure RSS flow 1133 * profiles. 1134 */ 1135 enum ice_status 1136 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 1137 { 1138 enum ice_status status = 0; 1139 u64 hash_flds; 1140 1141 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 1142 !ice_is_vsi_valid(hw, vsi_handle)) 1143 return ICE_ERR_PARAM; 1144 1145 /* Make sure no unsupported bits are specified */ 1146 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 1147 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 1148 return ICE_ERR_CFG; 1149 1150 hash_flds = avf_hash; 1151 1152 /* Always create an L3 RSS configuration for any L4 RSS configuration */ 1153 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 1154 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 1155 1156 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 1157 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 1158 1159 /* Create the corresponding RSS configuration for each valid hash bit */ 1160 while (hash_flds) { 1161 u64 rss_hash = ICE_HASH_INVALID; 1162 1163 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 1164 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 1165 rss_hash = ICE_FLOW_HASH_IPV4; 1166 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 1167 } else if (hash_flds & 1168 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 1169 rss_hash = ICE_FLOW_HASH_IPV4 | 1170 ICE_FLOW_HASH_TCP_PORT; 1171 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 1172 } else if (hash_flds & 1173 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 1174 rss_hash = ICE_FLOW_HASH_IPV4 | 1175 ICE_FLOW_HASH_UDP_PORT; 1176 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 1177 } else if (hash_flds & 1178 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 1179 rss_hash = ICE_FLOW_HASH_IPV4 | 1180 ICE_FLOW_HASH_SCTP_PORT; 1181 hash_flds &= 1182 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 1183 } 1184 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 1185 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 1186 rss_hash = ICE_FLOW_HASH_IPV6; 1187 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 1188 } else if (hash_flds & 1189 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 1190 rss_hash = ICE_FLOW_HASH_IPV6 | 1191 ICE_FLOW_HASH_TCP_PORT; 1192 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 1193 } else if (hash_flds & 1194 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 1195 rss_hash = ICE_FLOW_HASH_IPV6 | 1196 ICE_FLOW_HASH_UDP_PORT; 1197 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 1198 } else if (hash_flds & 1199 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 1200 rss_hash = ICE_FLOW_HASH_IPV6 | 1201 ICE_FLOW_HASH_SCTP_PORT; 1202 hash_flds &= 1203 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 1204 } 1205 } 1206 1207 if (rss_hash == ICE_HASH_INVALID) 1208 return ICE_ERR_OUT_OF_RANGE; 1209 1210 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash, 1211 ICE_FLOW_SEG_HDR_NONE); 1212 if (status) 1213 break; 1214 } 1215 1216 return status; 1217 } 1218 1219 /** 1220 * ice_replay_rss_cfg - replay RSS configurations associated with VSI 1221 * @hw: pointer to the hardware structure 1222 * @vsi_handle: software VSI handle 1223 */ 1224 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1225 { 1226 enum ice_status status = 0; 1227 struct ice_rss_cfg *r; 1228 1229 if (!ice_is_vsi_valid(hw, vsi_handle)) 1230 return ICE_ERR_PARAM; 1231 1232 mutex_lock(&hw->rss_locks); 1233 list_for_each_entry(r, &hw->rss_list_head, l_entry) { 1234 if (test_bit(vsi_handle, r->vsis)) { 1235 status = ice_add_rss_cfg_sync(hw, vsi_handle, 1236 r->hashed_flds, 1237 r->packet_hdr, 1238 ICE_RSS_OUTER_HEADERS); 1239 if (status) 1240 break; 1241 } 1242 } 1243 mutex_unlock(&hw->rss_locks); 1244 1245 return status; 1246 } 1247 1248 /** 1249 * ice_get_rss_cfg - returns hashed fields for the given header types 1250 * @hw: pointer to the hardware structure 1251 * @vsi_handle: software VSI handle 1252 * @hdrs: protocol header type 1253 * 1254 * This function will return the match fields of the first instance of flow 1255 * profile having the given header types and containing input VSI 1256 */ 1257 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 1258 { 1259 struct ice_rss_cfg *r, *rss_cfg = NULL; 1260 1261 /* verify if the protocol header is non zero and VSI is valid */ 1262 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 1263 return ICE_HASH_INVALID; 1264 1265 mutex_lock(&hw->rss_locks); 1266 list_for_each_entry(r, &hw->rss_list_head, l_entry) 1267 if (test_bit(vsi_handle, r->vsis) && 1268 r->packet_hdr == hdrs) { 1269 rss_cfg = r; 1270 break; 1271 } 1272 mutex_unlock(&hw->rss_locks); 1273 1274 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID; 1275 } 1276