1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2019 3 */ 4 5 #include "ice_switch.h" 6 #include "ice_flex_type.h" 7 #include "ice_flow.h" 8 9 10 #define ICE_ETH_DA_OFFSET 0 11 #define ICE_ETH_ETHTYPE_OFFSET 12 12 #define ICE_ETH_VLAN_TCI_OFFSET 14 13 #define ICE_MAX_VLAN_ID 0xFFF 14 15 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem 16 * struct to configure any switch filter rules. 17 * {DA (6 bytes), SA(6 bytes), 18 * Ether type (2 bytes for header without VLAN tag) OR 19 * VLAN tag (4 bytes for header with VLAN tag) } 20 * 21 * Word on Hardcoded values 22 * byte 0 = 0x2: to identify it as locally administered DA MAC 23 * byte 6 = 0x2: to identify it as locally administered SA MAC 24 * byte 12 = 0x81 & byte 13 = 0x00: 25 * In case of VLAN filter first two bytes defines ether type (0x8100) 26 * and remaining two bytes are placeholder for programming a given VLAN ID 27 * In case of Ether type filter it is treated as header without VLAN tag 28 * and byte 12 and 13 is used to program a given Ether type instead 29 */ 30 #define DUMMY_ETH_HDR_LEN 16 31 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 32 0x2, 0, 0, 0, 0, 0, 33 0x81, 0, 0, 0}; 34 35 #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \ 36 (sizeof(struct ice_aqc_sw_rules_elem) - \ 37 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 38 sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1) 39 #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \ 40 (sizeof(struct ice_aqc_sw_rules_elem) - \ 41 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 42 sizeof(struct ice_sw_rule_lkup_rx_tx) - 1) 43 #define ICE_SW_RULE_LG_ACT_SIZE(n) \ 44 (sizeof(struct ice_aqc_sw_rules_elem) - \ 45 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 46 sizeof(struct ice_sw_rule_lg_act) - \ 47 sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \ 48 ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act))) 49 #define ICE_SW_RULE_VSI_LIST_SIZE(n) \ 50 (sizeof(struct ice_aqc_sw_rules_elem) - \ 51 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ 52 sizeof(struct ice_sw_rule_vsi_list) - \ 53 sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \ 54 ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi))) 55 56 struct ice_dummy_pkt_offsets { 57 enum ice_protocol_type type; 58 u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */ 59 }; 60 61 static const 62 struct ice_dummy_pkt_offsets dummy_gre_packet_offsets[] = { 63 { ICE_MAC_OFOS, 0 }, 64 { ICE_ETYPE_OL, 12 }, 65 { ICE_IPV4_OFOS, 14 }, 66 { ICE_NVGRE, 34 }, 67 { ICE_MAC_IL, 42 }, 68 { ICE_IPV4_IL, 56 }, 69 { ICE_PROTOCOL_LAST, 0 }, 70 }; 71 72 static const 73 u8 dummy_gre_packet[] = { 0, 0, 0, 0, /* ICE_MAC_OFOS 0 */ 74 0, 0, 0, 0, 75 0, 0, 0, 0, 76 0x08, 0, /* ICE_ETYPE_OL 12 */ 77 0x45, 0, 0, 0x3E, /* ICE_IPV4_OFOS 14 */ 78 0, 0, 0, 0, 79 0, 0x2F, 0, 0, 80 0, 0, 0, 0, 81 0, 0, 0, 0, 82 0x80, 0, 0x65, 0x58, /* ICE_NVGRE 34 */ 83 0, 0, 0, 0, 84 0, 0, 0, 0, /* ICE_MAC_IL 42 */ 85 0, 0, 0, 0, 86 0, 0, 0, 0, 87 0x08, 0, 88 0x45, 0, 0, 0x14, /* ICE_IPV4_IL 54 */ 89 0, 0, 0, 0, 90 0, 0, 0, 0, 91 0, 0, 0, 0, 92 0, 0, 0, 0 93 }; 94 95 static const 96 struct ice_dummy_pkt_offsets dummy_udp_tun_tcp_packet_offsets[] = { 97 { ICE_MAC_OFOS, 0 }, 98 { ICE_ETYPE_OL, 12 }, 99 { ICE_IPV4_OFOS, 14 }, 100 { ICE_UDP_OF, 34 }, 101 { ICE_VXLAN, 42 }, 102 { ICE_MAC_IL, 50 }, 103 { ICE_IPV4_IL, 64 }, 104 { ICE_TCP_IL, 84 }, 105 { ICE_PROTOCOL_LAST, 0 }, 106 }; 107 108 static const 109 u8 dummy_udp_tun_tcp_packet[] = { 110 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 111 0x00, 0x00, 0x00, 0x00, 112 0x00, 0x00, 0x00, 0x00, 113 114 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 115 116 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */ 117 0x00, 0x01, 0x00, 0x00, 118 0x40, 0x11, 0x00, 0x00, 119 0x00, 0x00, 0x00, 0x00, 120 0x00, 0x00, 0x00, 0x00, 121 122 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 123 0x00, 0x46, 0x00, 0x00, 124 125 0x04, 0x00, 0x00, 0x03, /* ICE_VXLAN 42 */ 126 0x00, 0x00, 0x00, 0x00, 127 128 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 129 0x00, 0x00, 0x00, 0x00, 130 0x00, 0x00, 0x00, 0x00, 131 0x08, 0x00, 132 133 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */ 134 0x00, 0x01, 0x00, 0x00, 135 0x40, 0x06, 0x00, 0x00, 136 0x00, 0x00, 0x00, 0x00, 137 0x00, 0x00, 0x00, 0x00, 138 139 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */ 140 0x00, 0x00, 0x00, 0x00, 141 0x00, 0x00, 0x00, 0x00, 142 0x50, 0x02, 0x20, 0x00, 143 0x00, 0x00, 0x00, 0x00 144 }; 145 146 static const 147 struct ice_dummy_pkt_offsets dummy_udp_tun_udp_packet_offsets[] = { 148 { ICE_MAC_OFOS, 0 }, 149 { ICE_ETYPE_OL, 12 }, 150 { ICE_IPV4_OFOS, 14 }, 151 { ICE_UDP_OF, 34 }, 152 { ICE_VXLAN, 42 }, 153 { ICE_MAC_IL, 50 }, 154 { ICE_IPV4_IL, 64 }, 155 { ICE_UDP_ILOS, 84 }, 156 { ICE_PROTOCOL_LAST, 0 }, 157 }; 158 159 static const 160 u8 dummy_udp_tun_udp_packet[] = { 161 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 162 0x00, 0x00, 0x00, 0x00, 163 0x00, 0x00, 0x00, 0x00, 164 165 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 166 167 0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */ 168 0x00, 0x01, 0x00, 0x00, 169 0x00, 0x11, 0x00, 0x00, 170 0x00, 0x00, 0x00, 0x00, 171 0x00, 0x00, 0x00, 0x00, 172 173 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */ 174 0x00, 0x3a, 0x00, 0x00, 175 176 0x0c, 0x00, 0x00, 0x03, /* ICE_VXLAN 42 */ 177 0x00, 0x00, 0x00, 0x00, 178 179 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */ 180 0x00, 0x00, 0x00, 0x00, 181 0x00, 0x00, 0x00, 0x00, 182 0x08, 0x00, 183 184 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */ 185 0x00, 0x01, 0x00, 0x00, 186 0x00, 0x11, 0x00, 0x00, 187 0x00, 0x00, 0x00, 0x00, 188 0x00, 0x00, 0x00, 0x00, 189 190 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */ 191 0x00, 0x08, 0x00, 0x00, 192 }; 193 194 static const 195 struct ice_dummy_pkt_offsets dummy_udp_packet_offsets[] = { 196 { ICE_MAC_OFOS, 0 }, 197 { ICE_ETYPE_OL, 12 }, 198 { ICE_IPV4_OFOS, 14 }, 199 { ICE_UDP_ILOS, 34 }, 200 { ICE_PROTOCOL_LAST, 0 }, 201 }; 202 203 static const u8 204 dummy_udp_packet[] = { 205 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 206 0x00, 0x00, 0x00, 0x00, 207 0x00, 0x00, 0x00, 0x00, 208 209 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 210 211 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */ 212 0x00, 0x01, 0x00, 0x00, 213 0x00, 0x11, 0x00, 0x00, 214 0x00, 0x00, 0x00, 0x00, 215 0x00, 0x00, 0x00, 0x00, 216 217 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */ 218 0x00, 0x08, 0x00, 0x00, 219 220 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 221 }; 222 223 static const 224 struct ice_dummy_pkt_offsets dummy_tcp_packet_offsets[] = { 225 { ICE_MAC_OFOS, 0 }, 226 { ICE_ETYPE_OL, 12 }, 227 { ICE_IPV4_OFOS, 14 }, 228 { ICE_TCP_IL, 34 }, 229 { ICE_PROTOCOL_LAST, 0 }, 230 }; 231 232 static const u8 233 dummy_tcp_packet[] = { 234 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 235 0x00, 0x00, 0x00, 0x00, 236 0x00, 0x00, 0x00, 0x00, 237 238 0x08, 0x00, /* ICE_ETYPE_OL 12 */ 239 240 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */ 241 0x00, 0x01, 0x00, 0x00, 242 0x00, 0x06, 0x00, 0x00, 243 0x00, 0x00, 0x00, 0x00, 244 0x00, 0x00, 0x00, 0x00, 245 246 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */ 247 0x00, 0x00, 0x00, 0x00, 248 0x00, 0x00, 0x00, 0x00, 249 0x50, 0x00, 0x00, 0x00, 250 0x00, 0x00, 0x00, 0x00, 251 252 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 253 }; 254 255 static const 256 struct ice_dummy_pkt_offsets dummy_tcp_ipv6_packet_offsets[] = { 257 { ICE_MAC_OFOS, 0 }, 258 { ICE_ETYPE_OL, 12 }, 259 { ICE_IPV6_OFOS, 14 }, 260 { ICE_TCP_IL, 54 }, 261 { ICE_PROTOCOL_LAST, 0 }, 262 }; 263 264 static const u8 265 dummy_tcp_ipv6_packet[] = { 266 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 267 0x00, 0x00, 0x00, 0x00, 268 0x00, 0x00, 0x00, 0x00, 269 270 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 271 272 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 273 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */ 274 0x00, 0x00, 0x00, 0x00, 275 0x00, 0x00, 0x00, 0x00, 276 0x00, 0x00, 0x00, 0x00, 277 0x00, 0x00, 0x00, 0x00, 278 0x00, 0x00, 0x00, 0x00, 279 0x00, 0x00, 0x00, 0x00, 280 0x00, 0x00, 0x00, 0x00, 281 0x00, 0x00, 0x00, 0x00, 282 283 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */ 284 0x00, 0x00, 0x00, 0x00, 285 0x00, 0x00, 0x00, 0x00, 286 0x50, 0x00, 0x00, 0x00, 287 0x00, 0x00, 0x00, 0x00, 288 289 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 290 }; 291 292 static const 293 struct ice_dummy_pkt_offsets dummy_udp_ipv6_packet_offsets[] = { 294 { ICE_MAC_OFOS, 0 }, 295 { ICE_ETYPE_OL, 12 }, 296 { ICE_IPV6_OFOS, 14 }, 297 { ICE_UDP_ILOS, 54 }, 298 { ICE_PROTOCOL_LAST, 0 }, 299 }; 300 301 static const u8 302 dummy_udp_ipv6_packet[] = { 303 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */ 304 0x00, 0x00, 0x00, 0x00, 305 0x00, 0x00, 0x00, 0x00, 306 307 0x86, 0xDD, /* ICE_ETYPE_OL 12 */ 308 309 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */ 310 0x00, 0x08, 0x11, 0x00, /* Next header UDP*/ 311 0x00, 0x00, 0x00, 0x00, 312 0x00, 0x00, 0x00, 0x00, 313 0x00, 0x00, 0x00, 0x00, 314 0x00, 0x00, 0x00, 0x00, 315 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 319 320 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */ 321 0x00, 0x08, 0x00, 0x00, 322 323 0x00, 0x00, /* 2 bytes for 4 byte alignment */ 324 }; 325 326 /* this is a recipe to profile bitmap association */ 327 static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES], 328 ICE_MAX_NUM_PROFILES); 329 static ice_declare_bitmap(available_result_ids, ICE_CHAIN_FV_INDEX_START + 1); 330 331 static void ice_get_recp_to_prof_map(struct ice_hw *hw); 332 333 /** 334 * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries 335 * @hw: pointer to hardware structure 336 * @recps: struct that we need to populate 337 * @rid: recipe ID that we are populating 338 * @refresh_required: true if we should get recipe to profile mapping from FW 339 * 340 * This function is used to populate all the necessary entries into our 341 * bookkeeping so that we have a current list of all the recipes that are 342 * programmed in the firmware. 343 */ 344 static enum ice_status 345 ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid, 346 bool *refresh_required) 347 { 348 u16 i, sub_recps, fv_word_idx = 0, result_idx = 0; 349 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_PROFILES); 350 u16 result_idxs[ICE_MAX_CHAIN_RECIPE] = { 0 }; 351 struct ice_aqc_recipe_data_elem *tmp; 352 u16 num_recps = ICE_MAX_NUM_RECIPES; 353 struct ice_prot_lkup_ext *lkup_exts; 354 enum ice_status status; 355 356 /* we need a buffer big enough to accommodate all the recipes */ 357 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw, 358 ICE_MAX_NUM_RECIPES, sizeof(*tmp)); 359 if (!tmp) 360 return ICE_ERR_NO_MEMORY; 361 362 tmp[0].recipe_indx = rid; 363 status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL); 364 /* non-zero status meaning recipe doesn't exist */ 365 if (status) 366 goto err_unroll; 367 368 /* Get recipe to profile map so that we can get the fv from lkups that 369 * we read for a recipe from FW. Since we want to minimize the number of 370 * times we make this FW call, just make one call and cache the copy 371 * until a new recipe is added. This operation is only required the 372 * first time to get the changes from FW. Then to search existing 373 * entries we don't need to update the cache again until another recipe 374 * gets added. 375 */ 376 if (*refresh_required) { 377 ice_get_recp_to_prof_map(hw); 378 *refresh_required = false; 379 } 380 lkup_exts = &recps[rid].lkup_exts; 381 /* start populating all the entries for recps[rid] based on lkups from 382 * firmware 383 */ 384 for (sub_recps = 0; sub_recps < num_recps; sub_recps++) { 385 struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps]; 386 struct ice_recp_grp_entry *rg_entry; 387 u8 prof_id, prot = 0; 388 u16 off = 0; 389 390 rg_entry = (struct ice_recp_grp_entry *) 391 ice_malloc(hw, sizeof(*rg_entry)); 392 if (!rg_entry) { 393 status = ICE_ERR_NO_MEMORY; 394 goto err_unroll; 395 } 396 /* Avoid 8th bit since its result enable bit */ 397 result_idxs[result_idx] = root_bufs.content.result_indx & 398 ~ICE_AQ_RECIPE_RESULT_EN; 399 /* Check if result enable bit is set */ 400 if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) 401 ice_clear_bit(ICE_CHAIN_FV_INDEX_START - 402 result_idxs[result_idx++], 403 available_result_ids); 404 ice_memcpy(r_bitmap, 405 recipe_to_profile[tmp[sub_recps].recipe_indx], 406 sizeof(r_bitmap), ICE_NONDMA_TO_NONDMA); 407 /* get the first profile that is associated with rid */ 408 prof_id = ice_find_first_bit(r_bitmap, ICE_MAX_NUM_PROFILES); 409 for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) { 410 u8 lkup_indx = root_bufs.content.lkup_indx[i + 1]; 411 412 rg_entry->fv_idx[i] = lkup_indx; 413 rg_entry->fv_mask[i] = 414 LE16_TO_CPU(root_bufs.content.mask[i + 1]); 415 416 /* If the recipe is a chained recipe then all its 417 * child recipe's result will have a result index. 418 * To fill fv_words we should not use those result 419 * index, we only need the protocol ids and offsets. 420 * We will skip all the fv_idx which stores result 421 * index in them. We also need to skip any fv_idx which 422 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a 423 * valid offset value. 424 */ 425 if (result_idxs[0] == rg_entry->fv_idx[i] || 426 result_idxs[1] == rg_entry->fv_idx[i] || 427 result_idxs[2] == rg_entry->fv_idx[i] || 428 result_idxs[3] == rg_entry->fv_idx[i] || 429 result_idxs[4] == rg_entry->fv_idx[i] || 430 rg_entry->fv_idx[i] == ICE_AQ_RECIPE_LKUP_IGNORE || 431 rg_entry->fv_idx[i] == 0) 432 continue; 433 434 ice_find_prot_off(hw, ICE_BLK_SW, prof_id, 435 rg_entry->fv_idx[i], &prot, &off); 436 lkup_exts->fv_words[fv_word_idx].prot_id = prot; 437 lkup_exts->fv_words[fv_word_idx].off = off; 438 fv_word_idx++; 439 } 440 /* populate rg_list with the data from the child entry of this 441 * recipe 442 */ 443 LIST_ADD(&rg_entry->l_entry, &recps[rid].rg_list); 444 } 445 lkup_exts->n_val_words = fv_word_idx; 446 recps[rid].n_grp_count = num_recps; 447 recps[rid].root_buf = (struct ice_aqc_recipe_data_elem *) 448 ice_calloc(hw, recps[rid].n_grp_count, 449 sizeof(struct ice_aqc_recipe_data_elem)); 450 if (!recps[rid].root_buf) 451 goto err_unroll; 452 453 ice_memcpy(recps[rid].root_buf, tmp, recps[rid].n_grp_count * 454 sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA); 455 recps[rid].recp_created = true; 456 if (tmp[sub_recps].content.rid & ICE_AQ_RECIPE_ID_IS_ROOT) 457 recps[rid].root_rid = rid; 458 err_unroll: 459 ice_free(hw, tmp); 460 return status; 461 } 462 463 /** 464 * ice_get_recp_to_prof_map - updates recipe to profile mapping 465 * @hw: pointer to hardware structure 466 * 467 * This function is used to populate recipe_to_profile matrix where index to 468 * this array is the recipe ID and the element is the mapping of which profiles 469 * is this recipe mapped to. 470 */ 471 static void 472 ice_get_recp_to_prof_map(struct ice_hw *hw) 473 { 474 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 475 u16 i; 476 477 for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) { 478 u16 j; 479 480 ice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 481 if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL)) 482 continue; 483 484 for (j = 0; j < ICE_MAX_NUM_RECIPES; j++) 485 if (ice_is_bit_set(r_bitmap, j)) 486 ice_set_bit(i, recipe_to_profile[j]); 487 } 488 } 489 490 /** 491 * ice_init_def_sw_recp - initialize the recipe book keeping tables 492 * @hw: pointer to the HW struct 493 * 494 * Allocate memory for the entire recipe table and initialize the structures/ 495 * entries corresponding to basic recipes. 496 */ 497 enum ice_status ice_init_def_sw_recp(struct ice_hw *hw) 498 { 499 struct ice_sw_recipe *recps; 500 u8 i; 501 502 recps = (struct ice_sw_recipe *) 503 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps)); 504 if (!recps) 505 return ICE_ERR_NO_MEMORY; 506 507 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 508 recps[i].root_rid = i; 509 INIT_LIST_HEAD(&recps[i].filt_rules); 510 INIT_LIST_HEAD(&recps[i].filt_replay_rules); 511 INIT_LIST_HEAD(&recps[i].rg_list); 512 ice_init_lock(&recps[i].filt_rule_lock); 513 } 514 515 hw->switch_info->recp_list = recps; 516 517 return ICE_SUCCESS; 518 } 519 520 /** 521 * ice_aq_get_sw_cfg - get switch configuration 522 * @hw: pointer to the hardware structure 523 * @buf: pointer to the result buffer 524 * @buf_size: length of the buffer available for response 525 * @req_desc: pointer to requested descriptor 526 * @num_elems: pointer to number of elements 527 * @cd: pointer to command details structure or NULL 528 * 529 * Get switch configuration (0x0200) to be placed in 'buff'. 530 * This admin command returns information such as initial VSI/port number 531 * and switch ID it belongs to. 532 * 533 * NOTE: *req_desc is both an input/output parameter. 534 * The caller of this function first calls this function with *request_desc set 535 * to 0. If the response from f/w has *req_desc set to 0, all the switch 536 * configuration information has been returned; if non-zero (meaning not all 537 * the information was returned), the caller should call this function again 538 * with *req_desc set to the previous value returned by f/w to get the 539 * next block of switch configuration information. 540 * 541 * *num_elems is output only parameter. This reflects the number of elements 542 * in response buffer. The caller of this function to use *num_elems while 543 * parsing the response buffer. 544 */ 545 static enum ice_status 546 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf, 547 u16 buf_size, u16 *req_desc, u16 *num_elems, 548 struct ice_sq_cd *cd) 549 { 550 struct ice_aqc_get_sw_cfg *cmd; 551 enum ice_status status; 552 struct ice_aq_desc desc; 553 554 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 555 cmd = &desc.params.get_sw_conf; 556 cmd->element = CPU_TO_LE16(*req_desc); 557 558 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 559 if (!status) { 560 *req_desc = LE16_TO_CPU(cmd->element); 561 *num_elems = LE16_TO_CPU(cmd->num_elems); 562 } 563 564 return status; 565 } 566 567 568 /** 569 * ice_alloc_sw - allocate resources specific to switch 570 * @hw: pointer to the HW struct 571 * @ena_stats: true to turn on VEB stats 572 * @shared_res: true for shared resource, false for dedicated resource 573 * @sw_id: switch ID returned 574 * @counter_id: VEB counter ID returned 575 * 576 * allocates switch resources (SWID and VEB counter) (0x0208) 577 */ 578 enum ice_status 579 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id, 580 u16 *counter_id) 581 { 582 struct ice_aqc_alloc_free_res_elem *sw_buf; 583 struct ice_aqc_res_elem *sw_ele; 584 enum ice_status status; 585 u16 buf_len; 586 587 buf_len = sizeof(*sw_buf); 588 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 589 ice_malloc(hw, buf_len); 590 if (!sw_buf) 591 return ICE_ERR_NO_MEMORY; 592 593 /* Prepare buffer for switch ID. 594 * The number of resource entries in buffer is passed as 1 since only a 595 * single switch/VEB instance is allocated, and hence a single sw_id 596 * is requested. 597 */ 598 sw_buf->num_elems = CPU_TO_LE16(1); 599 sw_buf->res_type = 600 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID | 601 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED : 602 ICE_AQC_RES_TYPE_FLAG_DEDICATED)); 603 604 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 605 ice_aqc_opc_alloc_res, NULL); 606 607 if (status) 608 goto ice_alloc_sw_exit; 609 610 sw_ele = &sw_buf->elem[0]; 611 *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp); 612 613 if (ena_stats) { 614 /* Prepare buffer for VEB Counter */ 615 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res; 616 struct ice_aqc_alloc_free_res_elem *counter_buf; 617 struct ice_aqc_res_elem *counter_ele; 618 619 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 620 ice_malloc(hw, buf_len); 621 if (!counter_buf) { 622 status = ICE_ERR_NO_MEMORY; 623 goto ice_alloc_sw_exit; 624 } 625 626 /* The number of resource entries in buffer is passed as 1 since 627 * only a single switch/VEB instance is allocated, and hence a 628 * single VEB counter is requested. 629 */ 630 counter_buf->num_elems = CPU_TO_LE16(1); 631 counter_buf->res_type = 632 CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER | 633 ICE_AQC_RES_TYPE_FLAG_DEDICATED); 634 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 635 opc, NULL); 636 637 if (status) { 638 ice_free(hw, counter_buf); 639 goto ice_alloc_sw_exit; 640 } 641 counter_ele = &counter_buf->elem[0]; 642 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp); 643 ice_free(hw, counter_buf); 644 } 645 646 ice_alloc_sw_exit: 647 ice_free(hw, sw_buf); 648 return status; 649 } 650 651 /** 652 * ice_free_sw - free resources specific to switch 653 * @hw: pointer to the HW struct 654 * @sw_id: switch ID returned 655 * @counter_id: VEB counter ID returned 656 * 657 * free switch resources (SWID and VEB counter) (0x0209) 658 * 659 * NOTE: This function frees multiple resources. It continues 660 * releasing other resources even after it encounters error. 661 * The error code returned is the last error it encountered. 662 */ 663 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id) 664 { 665 struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf; 666 enum ice_status status, ret_status; 667 u16 buf_len; 668 669 buf_len = sizeof(*sw_buf); 670 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 671 ice_malloc(hw, buf_len); 672 if (!sw_buf) 673 return ICE_ERR_NO_MEMORY; 674 675 /* Prepare buffer to free for switch ID res. 676 * The number of resource entries in buffer is passed as 1 since only a 677 * single switch/VEB instance is freed, and hence a single sw_id 678 * is released. 679 */ 680 sw_buf->num_elems = CPU_TO_LE16(1); 681 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID); 682 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id); 683 684 ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 685 ice_aqc_opc_free_res, NULL); 686 687 if (ret_status) 688 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); 689 690 /* Prepare buffer to free for VEB Counter resource */ 691 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 692 ice_malloc(hw, buf_len); 693 if (!counter_buf) { 694 ice_free(hw, sw_buf); 695 return ICE_ERR_NO_MEMORY; 696 } 697 698 /* The number of resource entries in buffer is passed as 1 since only a 699 * single switch/VEB instance is freed, and hence a single VEB counter 700 * is released 701 */ 702 counter_buf->num_elems = CPU_TO_LE16(1); 703 counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER); 704 counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 705 706 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 707 ice_aqc_opc_free_res, NULL); 708 if (status) { 709 ice_debug(hw, ICE_DBG_SW, 710 "VEB counter resource could not be freed\n"); 711 ret_status = status; 712 } 713 714 ice_free(hw, counter_buf); 715 ice_free(hw, sw_buf); 716 return ret_status; 717 } 718 719 /** 720 * ice_aq_add_vsi 721 * @hw: pointer to the HW struct 722 * @vsi_ctx: pointer to a VSI context struct 723 * @cd: pointer to command details structure or NULL 724 * 725 * Add a VSI context to the hardware (0x0210) 726 */ 727 enum ice_status 728 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 729 struct ice_sq_cd *cd) 730 { 731 struct ice_aqc_add_update_free_vsi_resp *res; 732 struct ice_aqc_add_get_update_free_vsi *cmd; 733 struct ice_aq_desc desc; 734 enum ice_status status; 735 736 cmd = &desc.params.vsi_cmd; 737 res = &desc.params.add_update_free_vsi_res; 738 739 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 740 741 if (!vsi_ctx->alloc_from_pool) 742 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | 743 ICE_AQ_VSI_IS_VALID); 744 745 cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags); 746 747 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 748 749 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 750 sizeof(vsi_ctx->info), cd); 751 752 if (!status) { 753 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M; 754 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used); 755 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free); 756 } 757 758 return status; 759 } 760 761 /** 762 * ice_aq_free_vsi 763 * @hw: pointer to the HW struct 764 * @vsi_ctx: pointer to a VSI context struct 765 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 766 * @cd: pointer to command details structure or NULL 767 * 768 * Free VSI context info from hardware (0x0213) 769 */ 770 enum ice_status 771 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 772 bool keep_vsi_alloc, struct ice_sq_cd *cd) 773 { 774 struct ice_aqc_add_update_free_vsi_resp *resp; 775 struct ice_aqc_add_get_update_free_vsi *cmd; 776 struct ice_aq_desc desc; 777 enum ice_status status; 778 779 cmd = &desc.params.vsi_cmd; 780 resp = &desc.params.add_update_free_vsi_res; 781 782 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 783 784 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 785 if (keep_vsi_alloc) 786 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC); 787 788 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 789 if (!status) { 790 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 791 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 792 } 793 794 return status; 795 } 796 797 /** 798 * ice_aq_update_vsi 799 * @hw: pointer to the HW struct 800 * @vsi_ctx: pointer to a VSI context struct 801 * @cd: pointer to command details structure or NULL 802 * 803 * Update VSI context in the hardware (0x0211) 804 */ 805 enum ice_status 806 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 807 struct ice_sq_cd *cd) 808 { 809 struct ice_aqc_add_update_free_vsi_resp *resp; 810 struct ice_aqc_add_get_update_free_vsi *cmd; 811 struct ice_aq_desc desc; 812 enum ice_status status; 813 814 cmd = &desc.params.vsi_cmd; 815 resp = &desc.params.add_update_free_vsi_res; 816 817 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 818 819 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 820 821 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 822 823 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 824 sizeof(vsi_ctx->info), cd); 825 826 if (!status) { 827 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 828 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 829 } 830 831 return status; 832 } 833 834 /** 835 * ice_is_vsi_valid - check whether the VSI is valid or not 836 * @hw: pointer to the HW struct 837 * @vsi_handle: VSI handle 838 * 839 * check whether the VSI is valid or not 840 */ 841 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 842 { 843 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 844 } 845 846 /** 847 * ice_get_hw_vsi_num - return the HW VSI number 848 * @hw: pointer to the HW struct 849 * @vsi_handle: VSI handle 850 * 851 * return the HW VSI number 852 * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 853 */ 854 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 855 { 856 return hw->vsi_ctx[vsi_handle]->vsi_num; 857 } 858 859 /** 860 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 861 * @hw: pointer to the HW struct 862 * @vsi_handle: VSI handle 863 * 864 * return the VSI context entry for a given VSI handle 865 */ 866 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 867 { 868 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 869 } 870 871 /** 872 * ice_save_vsi_ctx - save the VSI context for a given VSI handle 873 * @hw: pointer to the HW struct 874 * @vsi_handle: VSI handle 875 * @vsi: VSI context pointer 876 * 877 * save the VSI context entry for a given VSI handle 878 */ 879 static void 880 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) 881 { 882 hw->vsi_ctx[vsi_handle] = vsi; 883 } 884 885 /** 886 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs 887 * @hw: pointer to the HW struct 888 * @vsi_handle: VSI handle 889 */ 890 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) 891 { 892 struct ice_vsi_ctx *vsi; 893 u8 i; 894 895 vsi = ice_get_vsi_ctx(hw, vsi_handle); 896 if (!vsi) 897 return; 898 ice_for_each_traffic_class(i) { 899 if (vsi->lan_q_ctx[i]) { 900 ice_free(hw, vsi->lan_q_ctx[i]); 901 vsi->lan_q_ctx[i] = NULL; 902 } 903 } 904 } 905 906 /** 907 * ice_clear_vsi_ctx - clear the VSI context entry 908 * @hw: pointer to the HW struct 909 * @vsi_handle: VSI handle 910 * 911 * clear the VSI context entry 912 */ 913 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 914 { 915 struct ice_vsi_ctx *vsi; 916 917 vsi = ice_get_vsi_ctx(hw, vsi_handle); 918 if (vsi) { 919 ice_clear_vsi_q_ctx(hw, vsi_handle); 920 ice_free(hw, vsi); 921 hw->vsi_ctx[vsi_handle] = NULL; 922 } 923 } 924 925 /** 926 * ice_clear_all_vsi_ctx - clear all the VSI context entries 927 * @hw: pointer to the HW struct 928 */ 929 void ice_clear_all_vsi_ctx(struct ice_hw *hw) 930 { 931 u16 i; 932 933 for (i = 0; i < ICE_MAX_VSI; i++) 934 ice_clear_vsi_ctx(hw, i); 935 } 936 937 /** 938 * ice_add_vsi - add VSI context to the hardware and VSI handle list 939 * @hw: pointer to the HW struct 940 * @vsi_handle: unique VSI handle provided by drivers 941 * @vsi_ctx: pointer to a VSI context struct 942 * @cd: pointer to command details structure or NULL 943 * 944 * Add a VSI context to the hardware also add it into the VSI handle list. 945 * If this function gets called after reset for existing VSIs then update 946 * with the new HW VSI number in the corresponding VSI handle list entry. 947 */ 948 enum ice_status 949 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 950 struct ice_sq_cd *cd) 951 { 952 struct ice_vsi_ctx *tmp_vsi_ctx; 953 enum ice_status status; 954 955 if (vsi_handle >= ICE_MAX_VSI) 956 return ICE_ERR_PARAM; 957 status = ice_aq_add_vsi(hw, vsi_ctx, cd); 958 if (status) 959 return status; 960 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 961 if (!tmp_vsi_ctx) { 962 /* Create a new VSI context */ 963 tmp_vsi_ctx = (struct ice_vsi_ctx *) 964 ice_malloc(hw, sizeof(*tmp_vsi_ctx)); 965 if (!tmp_vsi_ctx) { 966 ice_aq_free_vsi(hw, vsi_ctx, false, cd); 967 return ICE_ERR_NO_MEMORY; 968 } 969 *tmp_vsi_ctx = *vsi_ctx; 970 971 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 972 } else { 973 /* update with new HW VSI num */ 974 if (tmp_vsi_ctx->vsi_num != vsi_ctx->vsi_num) 975 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 976 } 977 978 return ICE_SUCCESS; 979 } 980 981 /** 982 * ice_free_vsi- free VSI context from hardware and VSI handle list 983 * @hw: pointer to the HW struct 984 * @vsi_handle: unique VSI handle 985 * @vsi_ctx: pointer to a VSI context struct 986 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 987 * @cd: pointer to command details structure or NULL 988 * 989 * Free VSI context info from hardware as well as from VSI handle list 990 */ 991 enum ice_status 992 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 993 bool keep_vsi_alloc, struct ice_sq_cd *cd) 994 { 995 enum ice_status status; 996 997 if (!ice_is_vsi_valid(hw, vsi_handle)) 998 return ICE_ERR_PARAM; 999 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 1000 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 1001 if (!status) 1002 ice_clear_vsi_ctx(hw, vsi_handle); 1003 return status; 1004 } 1005 1006 /** 1007 * ice_update_vsi 1008 * @hw: pointer to the HW struct 1009 * @vsi_handle: unique VSI handle 1010 * @vsi_ctx: pointer to a VSI context struct 1011 * @cd: pointer to command details structure or NULL 1012 * 1013 * Update VSI context in the hardware 1014 */ 1015 enum ice_status 1016 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 1017 struct ice_sq_cd *cd) 1018 { 1019 if (!ice_is_vsi_valid(hw, vsi_handle)) 1020 return ICE_ERR_PARAM; 1021 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 1022 return ice_aq_update_vsi(hw, vsi_ctx, cd); 1023 } 1024 1025 /** 1026 * ice_aq_get_vsi_params 1027 * @hw: pointer to the HW struct 1028 * @vsi_ctx: pointer to a VSI context struct 1029 * @cd: pointer to command details structure or NULL 1030 * 1031 * Get VSI context info from hardware (0x0212) 1032 */ 1033 enum ice_status 1034 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 1035 struct ice_sq_cd *cd) 1036 { 1037 struct ice_aqc_add_get_update_free_vsi *cmd; 1038 struct ice_aqc_get_vsi_resp *resp; 1039 struct ice_aq_desc desc; 1040 enum ice_status status; 1041 1042 cmd = &desc.params.vsi_cmd; 1043 resp = &desc.params.get_vsi_resp; 1044 1045 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params); 1046 1047 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 1048 1049 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 1050 sizeof(vsi_ctx->info), cd); 1051 if (!status) { 1052 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) & 1053 ICE_AQ_VSI_NUM_M; 1054 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 1055 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 1056 } 1057 1058 return status; 1059 } 1060 1061 /** 1062 * ice_aq_add_update_mir_rule - add/update a mirror rule 1063 * @hw: pointer to the HW struct 1064 * @rule_type: Rule Type 1065 * @dest_vsi: VSI number to which packets will be mirrored 1066 * @count: length of the list 1067 * @mr_buf: buffer for list of mirrored VSI numbers 1068 * @cd: pointer to command details structure or NULL 1069 * @rule_id: Rule ID 1070 * 1071 * Add/Update Mirror Rule (0x260). 1072 */ 1073 enum ice_status 1074 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, 1075 u16 count, struct ice_mir_rule_buf *mr_buf, 1076 struct ice_sq_cd *cd, u16 *rule_id) 1077 { 1078 struct ice_aqc_add_update_mir_rule *cmd; 1079 struct ice_aq_desc desc; 1080 enum ice_status status; 1081 __le16 *mr_list = NULL; 1082 u16 buf_size = 0; 1083 1084 switch (rule_type) { 1085 case ICE_AQC_RULE_TYPE_VPORT_INGRESS: 1086 case ICE_AQC_RULE_TYPE_VPORT_EGRESS: 1087 /* Make sure count and mr_buf are set for these rule_types */ 1088 if (!(count && mr_buf)) 1089 return ICE_ERR_PARAM; 1090 1091 buf_size = count * sizeof(__le16); 1092 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size); 1093 if (!mr_list) 1094 return ICE_ERR_NO_MEMORY; 1095 break; 1096 case ICE_AQC_RULE_TYPE_PPORT_INGRESS: 1097 case ICE_AQC_RULE_TYPE_PPORT_EGRESS: 1098 /* Make sure count and mr_buf are not set for these 1099 * rule_types 1100 */ 1101 if (count || mr_buf) 1102 return ICE_ERR_PARAM; 1103 break; 1104 default: 1105 ice_debug(hw, ICE_DBG_SW, 1106 "Error due to unsupported rule_type %u\n", rule_type); 1107 return ICE_ERR_OUT_OF_RANGE; 1108 } 1109 1110 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule); 1111 1112 /* Pre-process 'mr_buf' items for add/update of virtual port 1113 * ingress/egress mirroring (but not physical port ingress/egress 1114 * mirroring) 1115 */ 1116 if (mr_buf) { 1117 int i; 1118 1119 for (i = 0; i < count; i++) { 1120 u16 id; 1121 1122 id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M; 1123 1124 /* Validate specified VSI number, make sure it is less 1125 * than ICE_MAX_VSI, if not return with error. 1126 */ 1127 if (id >= ICE_MAX_VSI) { 1128 ice_debug(hw, ICE_DBG_SW, 1129 "Error VSI index (%u) out-of-range\n", 1130 id); 1131 ice_free(hw, mr_list); 1132 return ICE_ERR_OUT_OF_RANGE; 1133 } 1134 1135 /* add VSI to mirror rule */ 1136 if (mr_buf[i].add) 1137 mr_list[i] = 1138 CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M); 1139 else /* remove VSI from mirror rule */ 1140 mr_list[i] = CPU_TO_LE16(id); 1141 } 1142 } 1143 1144 cmd = &desc.params.add_update_rule; 1145 if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID) 1146 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) | 1147 ICE_AQC_RULE_ID_VALID_M); 1148 cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M); 1149 cmd->num_entries = CPU_TO_LE16(count); 1150 cmd->dest = CPU_TO_LE16(dest_vsi); 1151 1152 status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd); 1153 if (!status) 1154 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M; 1155 1156 ice_free(hw, mr_list); 1157 1158 return status; 1159 } 1160 1161 /** 1162 * ice_aq_delete_mir_rule - delete a mirror rule 1163 * @hw: pointer to the HW struct 1164 * @rule_id: Mirror rule ID (to be deleted) 1165 * @keep_allocd: if set, the VSI stays part of the PF allocated res, 1166 * otherwise it is returned to the shared pool 1167 * @cd: pointer to command details structure or NULL 1168 * 1169 * Delete Mirror Rule (0x261). 1170 */ 1171 enum ice_status 1172 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, 1173 struct ice_sq_cd *cd) 1174 { 1175 struct ice_aqc_delete_mir_rule *cmd; 1176 struct ice_aq_desc desc; 1177 1178 /* rule_id should be in the range 0...63 */ 1179 if (rule_id >= ICE_MAX_NUM_MIRROR_RULES) 1180 return ICE_ERR_OUT_OF_RANGE; 1181 1182 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule); 1183 1184 cmd = &desc.params.del_rule; 1185 rule_id |= ICE_AQC_RULE_ID_VALID_M; 1186 cmd->rule_id = CPU_TO_LE16(rule_id); 1187 1188 if (keep_allocd) 1189 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M); 1190 1191 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1192 } 1193 1194 /** 1195 * ice_aq_alloc_free_vsi_list 1196 * @hw: pointer to the HW struct 1197 * @vsi_list_id: VSI list ID returned or used for lookup 1198 * @lkup_type: switch rule filter lookup type 1199 * @opc: switch rules population command type - pass in the command opcode 1200 * 1201 * allocates or free a VSI list resource 1202 */ 1203 static enum ice_status 1204 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 1205 enum ice_sw_lkup_type lkup_type, 1206 enum ice_adminq_opc opc) 1207 { 1208 struct ice_aqc_alloc_free_res_elem *sw_buf; 1209 struct ice_aqc_res_elem *vsi_ele; 1210 enum ice_status status; 1211 u16 buf_len; 1212 1213 buf_len = sizeof(*sw_buf); 1214 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 1215 ice_malloc(hw, buf_len); 1216 if (!sw_buf) 1217 return ICE_ERR_NO_MEMORY; 1218 sw_buf->num_elems = CPU_TO_LE16(1); 1219 1220 if (lkup_type == ICE_SW_LKUP_MAC || 1221 lkup_type == ICE_SW_LKUP_MAC_VLAN || 1222 lkup_type == ICE_SW_LKUP_ETHERTYPE || 1223 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 1224 lkup_type == ICE_SW_LKUP_PROMISC || 1225 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 1226 lkup_type == ICE_SW_LKUP_LAST) { 1227 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 1228 } else if (lkup_type == ICE_SW_LKUP_VLAN) { 1229 sw_buf->res_type = 1230 CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 1231 } else { 1232 status = ICE_ERR_PARAM; 1233 goto ice_aq_alloc_free_vsi_list_exit; 1234 } 1235 1236 if (opc == ice_aqc_opc_free_res) 1237 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id); 1238 1239 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); 1240 if (status) 1241 goto ice_aq_alloc_free_vsi_list_exit; 1242 1243 if (opc == ice_aqc_opc_alloc_res) { 1244 vsi_ele = &sw_buf->elem[0]; 1245 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp); 1246 } 1247 1248 ice_aq_alloc_free_vsi_list_exit: 1249 ice_free(hw, sw_buf); 1250 return status; 1251 } 1252 1253 /** 1254 * ice_aq_set_storm_ctrl - Sets storm control configuration 1255 * @hw: pointer to the HW struct 1256 * @bcast_thresh: represents the upper threshold for broadcast storm control 1257 * @mcast_thresh: represents the upper threshold for multicast storm control 1258 * @ctl_bitmask: storm control control knobs 1259 * 1260 * Sets the storm control configuration (0x0280) 1261 */ 1262 enum ice_status 1263 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, 1264 u32 ctl_bitmask) 1265 { 1266 struct ice_aqc_storm_cfg *cmd; 1267 struct ice_aq_desc desc; 1268 1269 cmd = &desc.params.storm_conf; 1270 1271 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg); 1272 1273 cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M); 1274 cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M); 1275 cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask); 1276 1277 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1278 } 1279 1280 /** 1281 * ice_aq_get_storm_ctrl - gets storm control configuration 1282 * @hw: pointer to the HW struct 1283 * @bcast_thresh: represents the upper threshold for broadcast storm control 1284 * @mcast_thresh: represents the upper threshold for multicast storm control 1285 * @ctl_bitmask: storm control control knobs 1286 * 1287 * Gets the storm control configuration (0x0281) 1288 */ 1289 enum ice_status 1290 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, 1291 u32 *ctl_bitmask) 1292 { 1293 enum ice_status status; 1294 struct ice_aq_desc desc; 1295 1296 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg); 1297 1298 status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 1299 if (!status) { 1300 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf; 1301 1302 if (bcast_thresh) 1303 *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) & 1304 ICE_AQ_THRESHOLD_M; 1305 if (mcast_thresh) 1306 *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) & 1307 ICE_AQ_THRESHOLD_M; 1308 if (ctl_bitmask) 1309 *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl); 1310 } 1311 1312 return status; 1313 } 1314 1315 /** 1316 * ice_aq_sw_rules - add/update/remove switch rules 1317 * @hw: pointer to the HW struct 1318 * @rule_list: pointer to switch rule population list 1319 * @rule_list_sz: total size of the rule list in bytes 1320 * @num_rules: number of switch rules in the rule_list 1321 * @opc: switch rules population command type - pass in the command opcode 1322 * @cd: pointer to command details structure or NULL 1323 * 1324 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 1325 */ 1326 static enum ice_status 1327 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 1328 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 1329 { 1330 struct ice_aq_desc desc; 1331 1332 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_sw_rules"); 1333 1334 if (opc != ice_aqc_opc_add_sw_rules && 1335 opc != ice_aqc_opc_update_sw_rules && 1336 opc != ice_aqc_opc_remove_sw_rules) 1337 return ICE_ERR_PARAM; 1338 1339 ice_fill_dflt_direct_cmd_desc(&desc, opc); 1340 1341 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1342 desc.params.sw_rules.num_rules_fltr_entry_index = 1343 CPU_TO_LE16(num_rules); 1344 return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 1345 } 1346 1347 /** 1348 * ice_aq_add_recipe - add switch recipe 1349 * @hw: pointer to the HW struct 1350 * @s_recipe_list: pointer to switch rule population list 1351 * @num_recipes: number of switch recipes in the list 1352 * @cd: pointer to command details structure or NULL 1353 * 1354 * Add(0x0290) 1355 */ 1356 enum ice_status 1357 ice_aq_add_recipe(struct ice_hw *hw, 1358 struct ice_aqc_recipe_data_elem *s_recipe_list, 1359 u16 num_recipes, struct ice_sq_cd *cd) 1360 { 1361 struct ice_aqc_add_get_recipe *cmd; 1362 struct ice_aq_desc desc; 1363 u16 buf_size; 1364 1365 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_add_recipe"); 1366 cmd = &desc.params.add_get_recipe; 1367 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe); 1368 1369 cmd->num_sub_recipes = CPU_TO_LE16(num_recipes); 1370 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1371 1372 buf_size = num_recipes * sizeof(*s_recipe_list); 1373 1374 return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 1375 } 1376 1377 /** 1378 * ice_aq_get_recipe - get switch recipe 1379 * @hw: pointer to the HW struct 1380 * @s_recipe_list: pointer to switch rule population list 1381 * @num_recipes: pointer to the number of recipes (input and output) 1382 * @recipe_root: root recipe number of recipe(s) to retrieve 1383 * @cd: pointer to command details structure or NULL 1384 * 1385 * Get(0x0292) 1386 * 1387 * On input, *num_recipes should equal the number of entries in s_recipe_list. 1388 * On output, *num_recipes will equal the number of entries returned in 1389 * s_recipe_list. 1390 * 1391 * The caller must supply enough space in s_recipe_list to hold all possible 1392 * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES. 1393 */ 1394 enum ice_status 1395 ice_aq_get_recipe(struct ice_hw *hw, 1396 struct ice_aqc_recipe_data_elem *s_recipe_list, 1397 u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd) 1398 { 1399 struct ice_aqc_add_get_recipe *cmd; 1400 struct ice_aq_desc desc; 1401 enum ice_status status; 1402 u16 buf_size; 1403 1404 if (*num_recipes != ICE_MAX_NUM_RECIPES) 1405 return ICE_ERR_PARAM; 1406 1407 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe"); 1408 cmd = &desc.params.add_get_recipe; 1409 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe); 1410 1411 cmd->return_index = CPU_TO_LE16(recipe_root); 1412 cmd->num_sub_recipes = 0; 1413 1414 buf_size = *num_recipes * sizeof(*s_recipe_list); 1415 1416 status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd); 1417 /* cppcheck-suppress constArgument */ 1418 *num_recipes = LE16_TO_CPU(cmd->num_sub_recipes); 1419 1420 return status; 1421 } 1422 1423 /** 1424 * ice_aq_map_recipe_to_profile - Map recipe to packet profile 1425 * @hw: pointer to the HW struct 1426 * @profile_id: package profile ID to associate the recipe with 1427 * @r_bitmap: Recipe bitmap filled in and need to be returned as response 1428 * @cd: pointer to command details structure or NULL 1429 * Recipe to profile association (0x0291) 1430 */ 1431 enum ice_status 1432 ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 1433 struct ice_sq_cd *cd) 1434 { 1435 struct ice_aqc_recipe_to_profile *cmd; 1436 struct ice_aq_desc desc; 1437 1438 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_assoc_recipe_to_prof"); 1439 cmd = &desc.params.recipe_to_profile; 1440 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile); 1441 cmd->profile_id = CPU_TO_LE16(profile_id); 1442 /* Set the recipe ID bit in the bitmask to let the device know which 1443 * profile we are associating the recipe to 1444 */ 1445 ice_memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc), 1446 ICE_NONDMA_TO_NONDMA); 1447 1448 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1449 } 1450 1451 /** 1452 * ice_aq_get_recipe_to_profile - Map recipe to packet profile 1453 * @hw: pointer to the HW struct 1454 * @profile_id: package profile ID to associate the recipe with 1455 * @r_bitmap: Recipe bitmap filled in and need to be returned as response 1456 * @cd: pointer to command details structure or NULL 1457 * Associate profile ID with given recipe (0x0293) 1458 */ 1459 enum ice_status 1460 ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap, 1461 struct ice_sq_cd *cd) 1462 { 1463 struct ice_aqc_recipe_to_profile *cmd; 1464 struct ice_aq_desc desc; 1465 enum ice_status status; 1466 1467 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe_to_prof"); 1468 cmd = &desc.params.recipe_to_profile; 1469 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile); 1470 cmd->profile_id = CPU_TO_LE16(profile_id); 1471 1472 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 1473 if (!status) 1474 ice_memcpy(r_bitmap, cmd->recipe_assoc, 1475 sizeof(cmd->recipe_assoc), ICE_NONDMA_TO_NONDMA); 1476 1477 return status; 1478 } 1479 1480 /** 1481 * ice_alloc_recipe - add recipe resource 1482 * @hw: pointer to the hardware structure 1483 * @rid: recipe ID returned as response to AQ call 1484 */ 1485 enum ice_status ice_alloc_recipe(struct ice_hw *hw, u16 *rid) 1486 { 1487 struct ice_aqc_alloc_free_res_elem *sw_buf; 1488 enum ice_status status; 1489 u16 buf_len; 1490 1491 buf_len = sizeof(*sw_buf); 1492 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 1493 if (!sw_buf) 1494 return ICE_ERR_NO_MEMORY; 1495 1496 sw_buf->num_elems = CPU_TO_LE16(1); 1497 sw_buf->res_type = CPU_TO_LE16((ICE_AQC_RES_TYPE_RECIPE << 1498 ICE_AQC_RES_TYPE_S) | 1499 ICE_AQC_RES_TYPE_FLAG_SHARED); 1500 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 1501 ice_aqc_opc_alloc_res, NULL); 1502 if (!status) 1503 *rid = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 1504 ice_free(hw, sw_buf); 1505 1506 return status; 1507 } 1508 1509 /* ice_init_port_info - Initialize port_info with switch configuration data 1510 * @pi: pointer to port_info 1511 * @vsi_port_num: VSI number or port number 1512 * @type: Type of switch element (port or VSI) 1513 * @swid: switch ID of the switch the element is attached to 1514 * @pf_vf_num: PF or VF number 1515 * @is_vf: true if the element is a VF, false otherwise 1516 */ 1517 static void 1518 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 1519 u16 swid, u16 pf_vf_num, bool is_vf) 1520 { 1521 switch (type) { 1522 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 1523 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 1524 pi->sw_id = swid; 1525 pi->pf_vf_num = pf_vf_num; 1526 pi->is_vf = is_vf; 1527 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 1528 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 1529 break; 1530 default: 1531 ice_debug(pi->hw, ICE_DBG_SW, 1532 "incorrect VSI/port type received\n"); 1533 break; 1534 } 1535 } 1536 1537 /* ice_get_initial_sw_cfg - Get initial port and default VSI data 1538 * @hw: pointer to the hardware structure 1539 */ 1540 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) 1541 { 1542 struct ice_aqc_get_sw_cfg_resp *rbuf; 1543 enum ice_status status; 1544 u16 num_total_ports; 1545 u16 req_desc = 0; 1546 u16 num_elems; 1547 u16 j = 0; 1548 u16 i; 1549 1550 num_total_ports = 1; 1551 1552 rbuf = (struct ice_aqc_get_sw_cfg_resp *) 1553 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN); 1554 1555 if (!rbuf) 1556 return ICE_ERR_NO_MEMORY; 1557 1558 /* Multiple calls to ice_aq_get_sw_cfg may be required 1559 * to get all the switch configuration information. The need 1560 * for additional calls is indicated by ice_aq_get_sw_cfg 1561 * writing a non-zero value in req_desc 1562 */ 1563 do { 1564 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 1565 &req_desc, &num_elems, NULL); 1566 1567 if (status) 1568 break; 1569 1570 for (i = 0; i < num_elems; i++) { 1571 struct ice_aqc_get_sw_cfg_resp_elem *ele; 1572 u16 pf_vf_num, swid, vsi_port_num; 1573 bool is_vf = false; 1574 u8 type; 1575 1576 ele = rbuf[i].elements; 1577 vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) & 1578 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 1579 1580 pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) & 1581 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 1582 1583 swid = LE16_TO_CPU(ele->swid); 1584 1585 if (LE16_TO_CPU(ele->pf_vf_num) & 1586 ICE_AQC_GET_SW_CONF_RESP_IS_VF) 1587 is_vf = true; 1588 1589 type = LE16_TO_CPU(ele->vsi_port_num) >> 1590 ICE_AQC_GET_SW_CONF_RESP_TYPE_S; 1591 1592 switch (type) { 1593 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 1594 case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT: 1595 if (j == num_total_ports) { 1596 ice_debug(hw, ICE_DBG_SW, 1597 "more ports than expected\n"); 1598 status = ICE_ERR_CFG; 1599 goto out; 1600 } 1601 ice_init_port_info(hw->port_info, 1602 vsi_port_num, type, swid, 1603 pf_vf_num, is_vf); 1604 j++; 1605 break; 1606 default: 1607 break; 1608 } 1609 } 1610 } while (req_desc && !status); 1611 1612 1613 out: 1614 ice_free(hw, (void *)rbuf); 1615 return status; 1616 } 1617 1618 1619 /** 1620 * ice_fill_sw_info - Helper function to populate lb_en and lan_en 1621 * @hw: pointer to the hardware structure 1622 * @fi: filter info structure to fill/update 1623 * 1624 * This helper function populates the lb_en and lan_en elements of the provided 1625 * ice_fltr_info struct using the switch's type and characteristics of the 1626 * switch rule being configured. 1627 */ 1628 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) 1629 { 1630 fi->lb_en = false; 1631 fi->lan_en = false; 1632 if ((fi->flag & ICE_FLTR_TX) && 1633 (fi->fltr_act == ICE_FWD_TO_VSI || 1634 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1635 fi->fltr_act == ICE_FWD_TO_Q || 1636 fi->fltr_act == ICE_FWD_TO_QGRP)) { 1637 /* Setting LB for prune actions will result in replicated 1638 * packets to the internal switch that will be dropped. 1639 */ 1640 if (fi->lkup_type != ICE_SW_LKUP_VLAN) 1641 fi->lb_en = true; 1642 1643 /* Set lan_en to TRUE if 1644 * 1. The switch is a VEB AND 1645 * 2 1646 * 2.1 The lookup is a directional lookup like ethertype, 1647 * promiscuous, ethertype-MAC, promiscuous-VLAN 1648 * and default-port OR 1649 * 2.2 The lookup is VLAN, OR 1650 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR 1651 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC. 1652 * 1653 * OR 1654 * 1655 * The switch is a VEPA. 1656 * 1657 * In all other cases, the LAN enable has to be set to false. 1658 */ 1659 if (hw->evb_veb) { 1660 if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE || 1661 fi->lkup_type == ICE_SW_LKUP_PROMISC || 1662 fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 1663 fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 1664 fi->lkup_type == ICE_SW_LKUP_DFLT || 1665 fi->lkup_type == ICE_SW_LKUP_VLAN || 1666 (fi->lkup_type == ICE_SW_LKUP_MAC && 1667 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) || 1668 (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN && 1669 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr))) 1670 fi->lan_en = true; 1671 } else { 1672 fi->lan_en = true; 1673 } 1674 } 1675 } 1676 1677 /** 1678 * ice_ilog2 - Calculates integer log base 2 of a number 1679 * @n: number on which to perform operation 1680 */ 1681 static int ice_ilog2(u64 n) 1682 { 1683 int i; 1684 1685 for (i = 63; i >= 0; i--) 1686 if (((u64)1 << i) & n) 1687 return i; 1688 1689 return -1; 1690 } 1691 1692 /** 1693 * ice_fill_sw_rule - Helper function to fill switch rule structure 1694 * @hw: pointer to the hardware structure 1695 * @f_info: entry containing packet forwarding information 1696 * @s_rule: switch rule structure to be filled in based on mac_entry 1697 * @opc: switch rules population command type - pass in the command opcode 1698 */ 1699 static void 1700 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 1701 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc) 1702 { 1703 u16 vlan_id = ICE_MAX_VLAN_ID + 1; 1704 void *daddr = NULL; 1705 u16 eth_hdr_sz; 1706 u8 *eth_hdr; 1707 u32 act = 0; 1708 __be16 *off; 1709 u8 q_rgn; 1710 1711 if (opc == ice_aqc_opc_remove_sw_rules) { 1712 s_rule->pdata.lkup_tx_rx.act = 0; 1713 s_rule->pdata.lkup_tx_rx.index = 1714 CPU_TO_LE16(f_info->fltr_rule_id); 1715 s_rule->pdata.lkup_tx_rx.hdr_len = 0; 1716 return; 1717 } 1718 1719 eth_hdr_sz = sizeof(dummy_eth_header); 1720 eth_hdr = s_rule->pdata.lkup_tx_rx.hdr; 1721 1722 /* initialize the ether header with a dummy header */ 1723 ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA); 1724 ice_fill_sw_info(hw, f_info); 1725 1726 switch (f_info->fltr_act) { 1727 case ICE_FWD_TO_VSI: 1728 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 1729 ICE_SINGLE_ACT_VSI_ID_M; 1730 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 1731 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 1732 ICE_SINGLE_ACT_VALID_BIT; 1733 break; 1734 case ICE_FWD_TO_VSI_LIST: 1735 act |= ICE_SINGLE_ACT_VSI_LIST; 1736 act |= (f_info->fwd_id.vsi_list_id << 1737 ICE_SINGLE_ACT_VSI_LIST_ID_S) & 1738 ICE_SINGLE_ACT_VSI_LIST_ID_M; 1739 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 1740 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 1741 ICE_SINGLE_ACT_VALID_BIT; 1742 break; 1743 case ICE_FWD_TO_Q: 1744 act |= ICE_SINGLE_ACT_TO_Q; 1745 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 1746 ICE_SINGLE_ACT_Q_INDEX_M; 1747 break; 1748 case ICE_DROP_PACKET: 1749 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 1750 ICE_SINGLE_ACT_VALID_BIT; 1751 break; 1752 case ICE_FWD_TO_QGRP: 1753 q_rgn = f_info->qgrp_size > 0 ? 1754 (u8)ice_ilog2(f_info->qgrp_size) : 0; 1755 act |= ICE_SINGLE_ACT_TO_Q; 1756 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 1757 ICE_SINGLE_ACT_Q_INDEX_M; 1758 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 1759 ICE_SINGLE_ACT_Q_REGION_M; 1760 break; 1761 default: 1762 return; 1763 } 1764 1765 if (f_info->lb_en) 1766 act |= ICE_SINGLE_ACT_LB_ENABLE; 1767 if (f_info->lan_en) 1768 act |= ICE_SINGLE_ACT_LAN_ENABLE; 1769 1770 switch (f_info->lkup_type) { 1771 case ICE_SW_LKUP_MAC: 1772 daddr = f_info->l_data.mac.mac_addr; 1773 break; 1774 case ICE_SW_LKUP_VLAN: 1775 vlan_id = f_info->l_data.vlan.vlan_id; 1776 if (f_info->fltr_act == ICE_FWD_TO_VSI || 1777 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 1778 act |= ICE_SINGLE_ACT_PRUNE; 1779 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 1780 } 1781 break; 1782 case ICE_SW_LKUP_ETHERTYPE_MAC: 1783 daddr = f_info->l_data.ethertype_mac.mac_addr; 1784 /* fall-through */ 1785 case ICE_SW_LKUP_ETHERTYPE: 1786 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 1787 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype); 1788 break; 1789 case ICE_SW_LKUP_MAC_VLAN: 1790 daddr = f_info->l_data.mac_vlan.mac_addr; 1791 vlan_id = f_info->l_data.mac_vlan.vlan_id; 1792 break; 1793 case ICE_SW_LKUP_PROMISC_VLAN: 1794 vlan_id = f_info->l_data.mac_vlan.vlan_id; 1795 /* fall-through */ 1796 case ICE_SW_LKUP_PROMISC: 1797 daddr = f_info->l_data.mac_vlan.mac_addr; 1798 break; 1799 default: 1800 break; 1801 } 1802 1803 s_rule->type = (f_info->flag & ICE_FLTR_RX) ? 1804 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) : 1805 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX); 1806 1807 /* Recipe set depending on lookup type */ 1808 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type); 1809 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src); 1810 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 1811 1812 if (daddr) 1813 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN, 1814 ICE_NONDMA_TO_NONDMA); 1815 1816 if (!(vlan_id > ICE_MAX_VLAN_ID)) { 1817 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 1818 *off = CPU_TO_BE16(vlan_id); 1819 } 1820 1821 /* Create the switch rule with the final dummy Ethernet header */ 1822 if (opc != ice_aqc_opc_update_sw_rules) 1823 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz); 1824 } 1825 1826 /** 1827 * ice_add_marker_act 1828 * @hw: pointer to the hardware structure 1829 * @m_ent: the management entry for which sw marker needs to be added 1830 * @sw_marker: sw marker to tag the Rx descriptor with 1831 * @l_id: large action resource ID 1832 * 1833 * Create a large action to hold software marker and update the switch rule 1834 * entry pointed by m_ent with newly created large action 1835 */ 1836 static enum ice_status 1837 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 1838 u16 sw_marker, u16 l_id) 1839 { 1840 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx; 1841 /* For software marker we need 3 large actions 1842 * 1. FWD action: FWD TO VSI or VSI LIST 1843 * 2. GENERIC VALUE action to hold the profile ID 1844 * 3. GENERIC VALUE action to hold the software marker ID 1845 */ 1846 const u16 num_lg_acts = 3; 1847 enum ice_status status; 1848 u16 lg_act_size; 1849 u16 rules_size; 1850 u32 act; 1851 u16 id; 1852 1853 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 1854 return ICE_ERR_PARAM; 1855 1856 /* Create two back-to-back switch rules and submit them to the HW using 1857 * one memory buffer: 1858 * 1. Large Action 1859 * 2. Look up Tx Rx 1860 */ 1861 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts); 1862 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 1863 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size); 1864 if (!lg_act) 1865 return ICE_ERR_NO_MEMORY; 1866 1867 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size); 1868 1869 /* Fill in the first switch rule i.e. large action */ 1870 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1871 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id); 1872 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts); 1873 1874 /* First action VSI forwarding or VSI list forwarding depending on how 1875 * many VSIs 1876 */ 1877 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1878 m_ent->fltr_info.fwd_id.hw_vsi_id; 1879 1880 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1881 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 1882 ICE_LG_ACT_VSI_LIST_ID_M; 1883 if (m_ent->vsi_count > 1) 1884 act |= ICE_LG_ACT_VSI_LIST; 1885 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act); 1886 1887 /* Second action descriptor type */ 1888 act = ICE_LG_ACT_GENERIC; 1889 1890 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 1891 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act); 1892 1893 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 1894 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 1895 1896 /* Third action Marker value */ 1897 act |= ICE_LG_ACT_GENERIC; 1898 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 1899 ICE_LG_ACT_GENERIC_VALUE_M; 1900 1901 lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act); 1902 1903 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1904 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1905 ice_aqc_opc_update_sw_rules); 1906 1907 /* Update the action to point to the large action ID */ 1908 rx_tx->pdata.lkup_tx_rx.act = 1909 CPU_TO_LE32(ICE_SINGLE_ACT_PTR | 1910 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 1911 ICE_SINGLE_ACT_PTR_VAL_M)); 1912 1913 /* Use the filter rule ID of the previously created rule with single 1914 * act. Once the update happens, hardware will treat this as large 1915 * action 1916 */ 1917 rx_tx->pdata.lkup_tx_rx.index = 1918 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id); 1919 1920 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 1921 ice_aqc_opc_update_sw_rules, NULL); 1922 if (!status) { 1923 m_ent->lg_act_idx = l_id; 1924 m_ent->sw_marker_id = sw_marker; 1925 } 1926 1927 ice_free(hw, lg_act); 1928 return status; 1929 } 1930 1931 /** 1932 * ice_add_counter_act - add/update filter rule with counter action 1933 * @hw: pointer to the hardware structure 1934 * @m_ent: the management entry for which counter needs to be added 1935 * @counter_id: VLAN counter ID returned as part of allocate resource 1936 * @l_id: large action resource ID 1937 */ 1938 static enum ice_status 1939 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 1940 u16 counter_id, u16 l_id) 1941 { 1942 struct ice_aqc_sw_rules_elem *lg_act; 1943 struct ice_aqc_sw_rules_elem *rx_tx; 1944 enum ice_status status; 1945 /* 2 actions will be added while adding a large action counter */ 1946 const int num_acts = 2; 1947 u16 lg_act_size; 1948 u16 rules_size; 1949 u16 f_rule_id; 1950 u32 act; 1951 u16 id; 1952 1953 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 1954 return ICE_ERR_PARAM; 1955 1956 /* Create two back-to-back switch rules and submit them to the HW using 1957 * one memory buffer: 1958 * 1. Large Action 1959 * 2. Look up Tx Rx 1960 */ 1961 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts); 1962 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 1963 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, 1964 rules_size); 1965 if (!lg_act) 1966 return ICE_ERR_NO_MEMORY; 1967 1968 rx_tx = (struct ice_aqc_sw_rules_elem *) 1969 ((u8 *)lg_act + lg_act_size); 1970 1971 /* Fill in the first switch rule i.e. large action */ 1972 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1973 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id); 1974 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts); 1975 1976 /* First action VSI forwarding or VSI list forwarding depending on how 1977 * many VSIs 1978 */ 1979 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1980 m_ent->fltr_info.fwd_id.hw_vsi_id; 1981 1982 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1983 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 1984 ICE_LG_ACT_VSI_LIST_ID_M; 1985 if (m_ent->vsi_count > 1) 1986 act |= ICE_LG_ACT_VSI_LIST; 1987 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act); 1988 1989 /* Second action counter ID */ 1990 act = ICE_LG_ACT_STAT_COUNT; 1991 act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) & 1992 ICE_LG_ACT_STAT_COUNT_M; 1993 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act); 1994 1995 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1996 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1997 ice_aqc_opc_update_sw_rules); 1998 1999 act = ICE_SINGLE_ACT_PTR; 2000 act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M; 2001 rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 2002 2003 /* Use the filter rule ID of the previously created rule with single 2004 * act. Once the update happens, hardware will treat this as large 2005 * action 2006 */ 2007 f_rule_id = m_ent->fltr_info.fltr_rule_id; 2008 rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id); 2009 2010 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 2011 ice_aqc_opc_update_sw_rules, NULL); 2012 if (!status) { 2013 m_ent->lg_act_idx = l_id; 2014 m_ent->counter_index = counter_id; 2015 } 2016 2017 ice_free(hw, lg_act); 2018 return status; 2019 } 2020 2021 /** 2022 * ice_create_vsi_list_map 2023 * @hw: pointer to the hardware structure 2024 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 2025 * @num_vsi: number of VSI handles in the array 2026 * @vsi_list_id: VSI list ID generated as part of allocate resource 2027 * 2028 * Helper function to create a new entry of VSI list ID to VSI mapping 2029 * using the given VSI list ID 2030 */ 2031 static struct ice_vsi_list_map_info * 2032 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 2033 u16 vsi_list_id) 2034 { 2035 struct ice_switch_info *sw = hw->switch_info; 2036 struct ice_vsi_list_map_info *v_map; 2037 int i; 2038 2039 v_map = (struct ice_vsi_list_map_info *)ice_calloc(hw, 1, 2040 sizeof(*v_map)); 2041 if (!v_map) 2042 return NULL; 2043 2044 v_map->vsi_list_id = vsi_list_id; 2045 v_map->ref_cnt = 1; 2046 for (i = 0; i < num_vsi; i++) 2047 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map); 2048 2049 LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head); 2050 return v_map; 2051 } 2052 2053 /** 2054 * ice_update_vsi_list_rule 2055 * @hw: pointer to the hardware structure 2056 * @vsi_handle_arr: array of VSI handles to form a VSI list 2057 * @num_vsi: number of VSI handles in the array 2058 * @vsi_list_id: VSI list ID generated as part of allocate resource 2059 * @remove: Boolean value to indicate if this is a remove action 2060 * @opc: switch rules population command type - pass in the command opcode 2061 * @lkup_type: lookup type of the filter 2062 * 2063 * Call AQ command to add a new switch rule or update existing switch rule 2064 * using the given VSI list ID 2065 */ 2066 static enum ice_status 2067 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 2068 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 2069 enum ice_sw_lkup_type lkup_type) 2070 { 2071 struct ice_aqc_sw_rules_elem *s_rule; 2072 enum ice_status status; 2073 u16 s_rule_size; 2074 u16 type; 2075 int i; 2076 2077 if (!num_vsi) 2078 return ICE_ERR_PARAM; 2079 2080 if (lkup_type == ICE_SW_LKUP_MAC || 2081 lkup_type == ICE_SW_LKUP_MAC_VLAN || 2082 lkup_type == ICE_SW_LKUP_ETHERTYPE || 2083 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 2084 lkup_type == ICE_SW_LKUP_PROMISC || 2085 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 2086 lkup_type == ICE_SW_LKUP_LAST) 2087 type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 2088 ICE_AQC_SW_RULES_T_VSI_LIST_SET; 2089 else if (lkup_type == ICE_SW_LKUP_VLAN) 2090 type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 2091 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 2092 else 2093 return ICE_ERR_PARAM; 2094 2095 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi); 2096 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size); 2097 if (!s_rule) 2098 return ICE_ERR_NO_MEMORY; 2099 for (i = 0; i < num_vsi; i++) { 2100 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 2101 status = ICE_ERR_PARAM; 2102 goto exit; 2103 } 2104 /* AQ call requires hw_vsi_id(s) */ 2105 s_rule->pdata.vsi_list.vsi[i] = 2106 CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 2107 } 2108 2109 s_rule->type = CPU_TO_LE16(type); 2110 s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi); 2111 s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id); 2112 2113 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 2114 2115 exit: 2116 ice_free(hw, s_rule); 2117 return status; 2118 } 2119 2120 /** 2121 * ice_create_vsi_list_rule - Creates and populates a VSI list rule 2122 * @hw: pointer to the HW struct 2123 * @vsi_handle_arr: array of VSI handles to form a VSI list 2124 * @num_vsi: number of VSI handles in the array 2125 * @vsi_list_id: stores the ID of the VSI list to be created 2126 * @lkup_type: switch rule filter's lookup type 2127 */ 2128 static enum ice_status 2129 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 2130 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 2131 { 2132 enum ice_status status; 2133 2134 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 2135 ice_aqc_opc_alloc_res); 2136 if (status) 2137 return status; 2138 2139 /* Update the newly created VSI list to include the specified VSIs */ 2140 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 2141 *vsi_list_id, false, 2142 ice_aqc_opc_add_sw_rules, lkup_type); 2143 } 2144 2145 /** 2146 * ice_create_pkt_fwd_rule 2147 * @hw: pointer to the hardware structure 2148 * @f_entry: entry containing packet forwarding information 2149 * 2150 * Create switch rule with given filter information and add an entry 2151 * to the corresponding filter management list to track this switch rule 2152 * and VSI mapping 2153 */ 2154 static enum ice_status 2155 ice_create_pkt_fwd_rule(struct ice_hw *hw, 2156 struct ice_fltr_list_entry *f_entry) 2157 { 2158 struct ice_fltr_mgmt_list_entry *fm_entry; 2159 struct ice_aqc_sw_rules_elem *s_rule; 2160 enum ice_sw_lkup_type l_type; 2161 struct ice_sw_recipe *recp; 2162 enum ice_status status; 2163 2164 s_rule = (struct ice_aqc_sw_rules_elem *) 2165 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE); 2166 if (!s_rule) 2167 return ICE_ERR_NO_MEMORY; 2168 fm_entry = (struct ice_fltr_mgmt_list_entry *) 2169 ice_malloc(hw, sizeof(*fm_entry)); 2170 if (!fm_entry) { 2171 status = ICE_ERR_NO_MEMORY; 2172 goto ice_create_pkt_fwd_rule_exit; 2173 } 2174 2175 fm_entry->fltr_info = f_entry->fltr_info; 2176 2177 /* Initialize all the fields for the management entry */ 2178 fm_entry->vsi_count = 1; 2179 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 2180 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 2181 fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 2182 2183 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 2184 ice_aqc_opc_add_sw_rules); 2185 2186 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 2187 ice_aqc_opc_add_sw_rules, NULL); 2188 if (status) { 2189 ice_free(hw, fm_entry); 2190 goto ice_create_pkt_fwd_rule_exit; 2191 } 2192 2193 f_entry->fltr_info.fltr_rule_id = 2194 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 2195 fm_entry->fltr_info.fltr_rule_id = 2196 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 2197 2198 /* The book keeping entries will get removed when base driver 2199 * calls remove filter AQ command 2200 */ 2201 l_type = fm_entry->fltr_info.lkup_type; 2202 recp = &hw->switch_info->recp_list[l_type]; 2203 LIST_ADD(&fm_entry->list_entry, &recp->filt_rules); 2204 2205 ice_create_pkt_fwd_rule_exit: 2206 ice_free(hw, s_rule); 2207 return status; 2208 } 2209 2210 /** 2211 * ice_update_pkt_fwd_rule 2212 * @hw: pointer to the hardware structure 2213 * @f_info: filter information for switch rule 2214 * 2215 * Call AQ command to update a previously created switch rule with a 2216 * VSI list ID 2217 */ 2218 static enum ice_status 2219 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 2220 { 2221 struct ice_aqc_sw_rules_elem *s_rule; 2222 enum ice_status status; 2223 2224 s_rule = (struct ice_aqc_sw_rules_elem *) 2225 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE); 2226 if (!s_rule) 2227 return ICE_ERR_NO_MEMORY; 2228 2229 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 2230 2231 s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id); 2232 2233 /* Update switch rule with new rule set to forward VSI list */ 2234 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1, 2235 ice_aqc_opc_update_sw_rules, NULL); 2236 2237 ice_free(hw, s_rule); 2238 return status; 2239 } 2240 2241 /** 2242 * ice_update_sw_rule_bridge_mode 2243 * @hw: pointer to the HW struct 2244 * 2245 * Updates unicast switch filter rules based on VEB/VEPA mode 2246 */ 2247 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 2248 { 2249 struct ice_switch_info *sw = hw->switch_info; 2250 struct ice_fltr_mgmt_list_entry *fm_entry; 2251 enum ice_status status = ICE_SUCCESS; 2252 struct LIST_HEAD_TYPE *rule_head; 2253 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2254 2255 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 2256 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 2257 2258 ice_acquire_lock(rule_lock); 2259 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry, 2260 list_entry) { 2261 struct ice_fltr_info *fi = &fm_entry->fltr_info; 2262 u8 *addr = fi->l_data.mac.mac_addr; 2263 2264 /* Update unicast Tx rules to reflect the selected 2265 * VEB/VEPA mode 2266 */ 2267 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) && 2268 (fi->fltr_act == ICE_FWD_TO_VSI || 2269 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 2270 fi->fltr_act == ICE_FWD_TO_Q || 2271 fi->fltr_act == ICE_FWD_TO_QGRP)) { 2272 status = ice_update_pkt_fwd_rule(hw, fi); 2273 if (status) 2274 break; 2275 } 2276 } 2277 2278 ice_release_lock(rule_lock); 2279 2280 return status; 2281 } 2282 2283 /** 2284 * ice_add_update_vsi_list 2285 * @hw: pointer to the hardware structure 2286 * @m_entry: pointer to current filter management list entry 2287 * @cur_fltr: filter information from the book keeping entry 2288 * @new_fltr: filter information with the new VSI to be added 2289 * 2290 * Call AQ command to add or update previously created VSI list with new VSI. 2291 * 2292 * Helper function to do book keeping associated with adding filter information 2293 * The algorithm to do the book keeping is described below : 2294 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 2295 * if only one VSI has been added till now 2296 * Allocate a new VSI list and add two VSIs 2297 * to this list using switch rule command 2298 * Update the previously created switch rule with the 2299 * newly created VSI list ID 2300 * if a VSI list was previously created 2301 * Add the new VSI to the previously created VSI list set 2302 * using the update switch rule command 2303 */ 2304 static enum ice_status 2305 ice_add_update_vsi_list(struct ice_hw *hw, 2306 struct ice_fltr_mgmt_list_entry *m_entry, 2307 struct ice_fltr_info *cur_fltr, 2308 struct ice_fltr_info *new_fltr) 2309 { 2310 enum ice_status status = ICE_SUCCESS; 2311 u16 vsi_list_id = 0; 2312 2313 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 2314 cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 2315 return ICE_ERR_NOT_IMPL; 2316 2317 if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 2318 new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 2319 (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 2320 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 2321 return ICE_ERR_NOT_IMPL; 2322 2323 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 2324 /* Only one entry existed in the mapping and it was not already 2325 * a part of a VSI list. So, create a VSI list with the old and 2326 * new VSIs. 2327 */ 2328 struct ice_fltr_info tmp_fltr; 2329 u16 vsi_handle_arr[2]; 2330 2331 /* A rule already exists with the new VSI being added */ 2332 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 2333 return ICE_ERR_ALREADY_EXISTS; 2334 2335 vsi_handle_arr[0] = cur_fltr->vsi_handle; 2336 vsi_handle_arr[1] = new_fltr->vsi_handle; 2337 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 2338 &vsi_list_id, 2339 new_fltr->lkup_type); 2340 if (status) 2341 return status; 2342 2343 tmp_fltr = *new_fltr; 2344 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 2345 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 2346 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 2347 /* Update the previous switch rule of "MAC forward to VSI" to 2348 * "MAC fwd to VSI list" 2349 */ 2350 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 2351 if (status) 2352 return status; 2353 2354 cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 2355 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 2356 m_entry->vsi_list_info = 2357 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 2358 vsi_list_id); 2359 2360 /* If this entry was large action then the large action needs 2361 * to be updated to point to FWD to VSI list 2362 */ 2363 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 2364 status = 2365 ice_add_marker_act(hw, m_entry, 2366 m_entry->sw_marker_id, 2367 m_entry->lg_act_idx); 2368 } else { 2369 u16 vsi_handle = new_fltr->vsi_handle; 2370 enum ice_adminq_opc opcode; 2371 2372 if (!m_entry->vsi_list_info) 2373 return ICE_ERR_CFG; 2374 2375 /* A rule already exists with the new VSI being added */ 2376 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 2377 return ICE_SUCCESS; 2378 2379 /* Update the previously created VSI list set with 2380 * the new VSI ID passed in 2381 */ 2382 vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 2383 opcode = ice_aqc_opc_update_sw_rules; 2384 2385 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 2386 vsi_list_id, false, opcode, 2387 new_fltr->lkup_type); 2388 /* update VSI list mapping info with new VSI ID */ 2389 if (!status) 2390 ice_set_bit(vsi_handle, 2391 m_entry->vsi_list_info->vsi_map); 2392 } 2393 if (!status) 2394 m_entry->vsi_count++; 2395 return status; 2396 } 2397 2398 /** 2399 * ice_find_rule_entry - Search a rule entry 2400 * @hw: pointer to the hardware structure 2401 * @recp_id: lookup type for which the specified rule needs to be searched 2402 * @f_info: rule information 2403 * 2404 * Helper function to search for a given rule entry 2405 * Returns pointer to entry storing the rule if found 2406 */ 2407 static struct ice_fltr_mgmt_list_entry * 2408 ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info) 2409 { 2410 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 2411 struct ice_switch_info *sw = hw->switch_info; 2412 struct LIST_HEAD_TYPE *list_head; 2413 2414 list_head = &sw->recp_list[recp_id].filt_rules; 2415 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 2416 list_entry) { 2417 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 2418 sizeof(f_info->l_data)) && 2419 f_info->flag == list_itr->fltr_info.flag) { 2420 ret = list_itr; 2421 break; 2422 } 2423 } 2424 return ret; 2425 } 2426 2427 /** 2428 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 2429 * @hw: pointer to the hardware structure 2430 * @recp_id: lookup type for which VSI lists needs to be searched 2431 * @vsi_handle: VSI handle to be found in VSI list 2432 * @vsi_list_id: VSI list ID found containing vsi_handle 2433 * 2434 * Helper function to search a VSI list with single entry containing given VSI 2435 * handle element. This can be extended further to search VSI list with more 2436 * than 1 vsi_count. Returns pointer to VSI list entry if found. 2437 */ 2438 static struct ice_vsi_list_map_info * 2439 ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle, 2440 u16 *vsi_list_id) 2441 { 2442 struct ice_vsi_list_map_info *map_info = NULL; 2443 struct ice_switch_info *sw = hw->switch_info; 2444 struct LIST_HEAD_TYPE *list_head; 2445 2446 list_head = &sw->recp_list[recp_id].filt_rules; 2447 if (sw->recp_list[recp_id].adv_rule) { 2448 struct ice_adv_fltr_mgmt_list_entry *list_itr; 2449 2450 LIST_FOR_EACH_ENTRY(list_itr, list_head, 2451 ice_adv_fltr_mgmt_list_entry, 2452 list_entry) { 2453 if (list_itr->vsi_list_info) { 2454 map_info = list_itr->vsi_list_info; 2455 if (ice_is_bit_set(map_info->vsi_map, 2456 vsi_handle)) { 2457 *vsi_list_id = map_info->vsi_list_id; 2458 return map_info; 2459 } 2460 } 2461 } 2462 } else { 2463 struct ice_fltr_mgmt_list_entry *list_itr; 2464 2465 LIST_FOR_EACH_ENTRY(list_itr, list_head, 2466 ice_fltr_mgmt_list_entry, 2467 list_entry) { 2468 if (list_itr->vsi_count == 1 && 2469 list_itr->vsi_list_info) { 2470 map_info = list_itr->vsi_list_info; 2471 if (ice_is_bit_set(map_info->vsi_map, 2472 vsi_handle)) { 2473 *vsi_list_id = map_info->vsi_list_id; 2474 return map_info; 2475 } 2476 } 2477 } 2478 } 2479 return NULL; 2480 } 2481 2482 /** 2483 * ice_add_rule_internal - add rule for a given lookup type 2484 * @hw: pointer to the hardware structure 2485 * @recp_id: lookup type (recipe ID) for which rule has to be added 2486 * @f_entry: structure containing MAC forwarding information 2487 * 2488 * Adds or updates the rule lists for a given recipe 2489 */ 2490 static enum ice_status 2491 ice_add_rule_internal(struct ice_hw *hw, u8 recp_id, 2492 struct ice_fltr_list_entry *f_entry) 2493 { 2494 struct ice_switch_info *sw = hw->switch_info; 2495 struct ice_fltr_info *new_fltr, *cur_fltr; 2496 struct ice_fltr_mgmt_list_entry *m_entry; 2497 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2498 enum ice_status status = ICE_SUCCESS; 2499 2500 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2501 return ICE_ERR_PARAM; 2502 2503 /* Load the hw_vsi_id only if the fwd action is fwd to VSI */ 2504 if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI) 2505 f_entry->fltr_info.fwd_id.hw_vsi_id = 2506 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2507 2508 rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 2509 2510 ice_acquire_lock(rule_lock); 2511 new_fltr = &f_entry->fltr_info; 2512 if (new_fltr->flag & ICE_FLTR_RX) 2513 new_fltr->src = hw->port_info->lport; 2514 else if (new_fltr->flag & ICE_FLTR_TX) 2515 new_fltr->src = 2516 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2517 2518 m_entry = ice_find_rule_entry(hw, recp_id, new_fltr); 2519 if (!m_entry) { 2520 status = ice_create_pkt_fwd_rule(hw, f_entry); 2521 goto exit_add_rule_internal; 2522 } 2523 2524 cur_fltr = &m_entry->fltr_info; 2525 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 2526 2527 exit_add_rule_internal: 2528 ice_release_lock(rule_lock); 2529 return status; 2530 } 2531 2532 /** 2533 * ice_remove_vsi_list_rule 2534 * @hw: pointer to the hardware structure 2535 * @vsi_list_id: VSI list ID generated as part of allocate resource 2536 * @lkup_type: switch rule filter lookup type 2537 * 2538 * The VSI list should be emptied before this function is called to remove the 2539 * VSI list. 2540 */ 2541 static enum ice_status 2542 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 2543 enum ice_sw_lkup_type lkup_type) 2544 { 2545 struct ice_aqc_sw_rules_elem *s_rule; 2546 enum ice_status status; 2547 u16 s_rule_size; 2548 2549 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0); 2550 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size); 2551 if (!s_rule) 2552 return ICE_ERR_NO_MEMORY; 2553 2554 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR); 2555 s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id); 2556 2557 /* Free the vsi_list resource that we allocated. It is assumed that the 2558 * list is empty at this point. 2559 */ 2560 status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 2561 ice_aqc_opc_free_res); 2562 2563 ice_free(hw, s_rule); 2564 return status; 2565 } 2566 2567 /** 2568 * ice_rem_update_vsi_list 2569 * @hw: pointer to the hardware structure 2570 * @vsi_handle: VSI handle of the VSI to remove 2571 * @fm_list: filter management entry for which the VSI list management needs to 2572 * be done 2573 */ 2574 static enum ice_status 2575 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 2576 struct ice_fltr_mgmt_list_entry *fm_list) 2577 { 2578 enum ice_sw_lkup_type lkup_type; 2579 enum ice_status status = ICE_SUCCESS; 2580 u16 vsi_list_id; 2581 2582 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 2583 fm_list->vsi_count == 0) 2584 return ICE_ERR_PARAM; 2585 2586 /* A rule with the VSI being removed does not exist */ 2587 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 2588 return ICE_ERR_DOES_NOT_EXIST; 2589 2590 lkup_type = fm_list->fltr_info.lkup_type; 2591 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 2592 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 2593 ice_aqc_opc_update_sw_rules, 2594 lkup_type); 2595 if (status) 2596 return status; 2597 2598 fm_list->vsi_count--; 2599 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 2600 2601 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 2602 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 2603 struct ice_vsi_list_map_info *vsi_list_info = 2604 fm_list->vsi_list_info; 2605 u16 rem_vsi_handle; 2606 2607 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 2608 ICE_MAX_VSI); 2609 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 2610 return ICE_ERR_OUT_OF_RANGE; 2611 2612 /* Make sure VSI list is empty before removing it below */ 2613 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 2614 vsi_list_id, true, 2615 ice_aqc_opc_update_sw_rules, 2616 lkup_type); 2617 if (status) 2618 return status; 2619 2620 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 2621 tmp_fltr_info.fwd_id.hw_vsi_id = 2622 ice_get_hw_vsi_num(hw, rem_vsi_handle); 2623 tmp_fltr_info.vsi_handle = rem_vsi_handle; 2624 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 2625 if (status) { 2626 ice_debug(hw, ICE_DBG_SW, 2627 "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 2628 tmp_fltr_info.fwd_id.hw_vsi_id, status); 2629 return status; 2630 } 2631 2632 fm_list->fltr_info = tmp_fltr_info; 2633 } 2634 2635 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 2636 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 2637 struct ice_vsi_list_map_info *vsi_list_info = 2638 fm_list->vsi_list_info; 2639 2640 /* Remove the VSI list since it is no longer used */ 2641 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 2642 if (status) { 2643 ice_debug(hw, ICE_DBG_SW, 2644 "Failed to remove VSI list %d, error %d\n", 2645 vsi_list_id, status); 2646 return status; 2647 } 2648 2649 LIST_DEL(&vsi_list_info->list_entry); 2650 ice_free(hw, vsi_list_info); 2651 fm_list->vsi_list_info = NULL; 2652 } 2653 2654 return status; 2655 } 2656 2657 /** 2658 * ice_remove_rule_internal - Remove a filter rule of a given type 2659 * 2660 * @hw: pointer to the hardware structure 2661 * @recp_id: recipe ID for which the rule needs to removed 2662 * @f_entry: rule entry containing filter information 2663 */ 2664 static enum ice_status 2665 ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id, 2666 struct ice_fltr_list_entry *f_entry) 2667 { 2668 struct ice_switch_info *sw = hw->switch_info; 2669 struct ice_fltr_mgmt_list_entry *list_elem; 2670 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2671 enum ice_status status = ICE_SUCCESS; 2672 bool remove_rule = false; 2673 u16 vsi_handle; 2674 2675 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2676 return ICE_ERR_PARAM; 2677 f_entry->fltr_info.fwd_id.hw_vsi_id = 2678 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2679 2680 rule_lock = &sw->recp_list[recp_id].filt_rule_lock; 2681 ice_acquire_lock(rule_lock); 2682 list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info); 2683 if (!list_elem) { 2684 status = ICE_ERR_DOES_NOT_EXIST; 2685 goto exit; 2686 } 2687 2688 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 2689 remove_rule = true; 2690 } else if (!list_elem->vsi_list_info) { 2691 status = ICE_ERR_DOES_NOT_EXIST; 2692 goto exit; 2693 } else if (list_elem->vsi_list_info->ref_cnt > 1) { 2694 /* a ref_cnt > 1 indicates that the vsi_list is being 2695 * shared by multiple rules. Decrement the ref_cnt and 2696 * remove this rule, but do not modify the list, as it 2697 * is in-use by other rules. 2698 */ 2699 list_elem->vsi_list_info->ref_cnt--; 2700 remove_rule = true; 2701 } else { 2702 /* a ref_cnt of 1 indicates the vsi_list is only used 2703 * by one rule. However, the original removal request is only 2704 * for a single VSI. Update the vsi_list first, and only 2705 * remove the rule if there are no further VSIs in this list. 2706 */ 2707 vsi_handle = f_entry->fltr_info.vsi_handle; 2708 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 2709 if (status) 2710 goto exit; 2711 /* if VSI count goes to zero after updating the VSI list */ 2712 if (list_elem->vsi_count == 0) 2713 remove_rule = true; 2714 } 2715 2716 if (remove_rule) { 2717 /* Remove the lookup rule */ 2718 struct ice_aqc_sw_rules_elem *s_rule; 2719 2720 s_rule = (struct ice_aqc_sw_rules_elem *) 2721 ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE); 2722 if (!s_rule) { 2723 status = ICE_ERR_NO_MEMORY; 2724 goto exit; 2725 } 2726 2727 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 2728 ice_aqc_opc_remove_sw_rules); 2729 2730 status = ice_aq_sw_rules(hw, s_rule, 2731 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1, 2732 ice_aqc_opc_remove_sw_rules, NULL); 2733 if (status) 2734 goto exit; 2735 2736 /* Remove a book keeping from the list */ 2737 ice_free(hw, s_rule); 2738 2739 LIST_DEL(&list_elem->list_entry); 2740 ice_free(hw, list_elem); 2741 } 2742 exit: 2743 ice_release_lock(rule_lock); 2744 return status; 2745 } 2746 2747 /** 2748 * ice_aq_get_res_alloc - get allocated resources 2749 * @hw: pointer to the HW struct 2750 * @num_entries: pointer to u16 to store the number of resource entries returned 2751 * @buf: pointer to user-supplied buffer 2752 * @buf_size: size of buff 2753 * @cd: pointer to command details structure or NULL 2754 * 2755 * The user-supplied buffer must be large enough to store the resource 2756 * information for all resource types. Each resource type is an 2757 * ice_aqc_get_res_resp_data_elem structure. 2758 */ 2759 enum ice_status 2760 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, void *buf, 2761 u16 buf_size, struct ice_sq_cd *cd) 2762 { 2763 struct ice_aqc_get_res_alloc *resp; 2764 enum ice_status status; 2765 struct ice_aq_desc desc; 2766 2767 if (!buf) 2768 return ICE_ERR_BAD_PTR; 2769 2770 if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN) 2771 return ICE_ERR_INVAL_SIZE; 2772 2773 resp = &desc.params.get_res; 2774 2775 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc); 2776 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2777 2778 if (!status && num_entries) 2779 *num_entries = LE16_TO_CPU(resp->resp_elem_num); 2780 2781 return status; 2782 } 2783 2784 /** 2785 * ice_aq_get_res_descs - get allocated resource descriptors 2786 * @hw: pointer to the hardware structure 2787 * @num_entries: number of resource entries in buffer 2788 * @buf: Indirect buffer to hold data parameters and response 2789 * @buf_size: size of buffer for indirect commands 2790 * @res_type: resource type 2791 * @res_shared: is resource shared 2792 * @desc_id: input - first desc ID to start; output - next desc ID 2793 * @cd: pointer to command details structure or NULL 2794 */ 2795 enum ice_status 2796 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries, 2797 struct ice_aqc_get_allocd_res_desc_resp *buf, 2798 u16 buf_size, u16 res_type, bool res_shared, u16 *desc_id, 2799 struct ice_sq_cd *cd) 2800 { 2801 struct ice_aqc_get_allocd_res_desc *cmd; 2802 struct ice_aq_desc desc; 2803 enum ice_status status; 2804 2805 ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_res_descs"); 2806 2807 cmd = &desc.params.get_res_desc; 2808 2809 if (!buf) 2810 return ICE_ERR_PARAM; 2811 2812 if (buf_size != (num_entries * sizeof(*buf))) 2813 return ICE_ERR_PARAM; 2814 2815 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc); 2816 2817 cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) & 2818 ICE_AQC_RES_TYPE_M) | (res_shared ? 2819 ICE_AQC_RES_TYPE_FLAG_SHARED : 0)); 2820 cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id); 2821 2822 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 2823 2824 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2825 if (!status) 2826 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc); 2827 2828 return status; 2829 } 2830 2831 /** 2832 * ice_add_mac - Add a MAC address based filter rule 2833 * @hw: pointer to the hardware structure 2834 * @m_list: list of MAC addresses and forwarding information 2835 * 2836 * IMPORTANT: When the ucast_shared flag is set to false and m_list has 2837 * multiple unicast addresses, the function assumes that all the 2838 * addresses are unique in a given add_mac call. It doesn't 2839 * check for duplicates in this case, removing duplicates from a given 2840 * list should be taken care of in the caller of this function. 2841 */ 2842 enum ice_status 2843 ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 2844 { 2845 struct ice_aqc_sw_rules_elem *s_rule, *r_iter; 2846 struct ice_fltr_list_entry *m_list_itr; 2847 struct LIST_HEAD_TYPE *rule_head; 2848 u16 elem_sent, total_elem_left; 2849 struct ice_switch_info *sw; 2850 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2851 enum ice_status status = ICE_SUCCESS; 2852 u16 num_unicast = 0; 2853 u16 s_rule_size; 2854 2855 if (!m_list || !hw) 2856 return ICE_ERR_PARAM; 2857 s_rule = NULL; 2858 sw = hw->switch_info; 2859 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 2860 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2861 list_entry) { 2862 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 2863 u16 vsi_handle; 2864 u16 hw_vsi_id; 2865 2866 m_list_itr->fltr_info.flag = ICE_FLTR_TX; 2867 vsi_handle = m_list_itr->fltr_info.vsi_handle; 2868 if (!ice_is_vsi_valid(hw, vsi_handle)) 2869 return ICE_ERR_PARAM; 2870 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2871 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 2872 /* update the src in case it is VSI num */ 2873 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 2874 return ICE_ERR_PARAM; 2875 m_list_itr->fltr_info.src = hw_vsi_id; 2876 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 2877 IS_ZERO_ETHER_ADDR(add)) 2878 return ICE_ERR_PARAM; 2879 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) { 2880 /* Don't overwrite the unicast address */ 2881 ice_acquire_lock(rule_lock); 2882 if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, 2883 &m_list_itr->fltr_info)) { 2884 ice_release_lock(rule_lock); 2885 return ICE_ERR_ALREADY_EXISTS; 2886 } 2887 ice_release_lock(rule_lock); 2888 num_unicast++; 2889 } else if (IS_MULTICAST_ETHER_ADDR(add) || 2890 (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) { 2891 m_list_itr->status = 2892 ice_add_rule_internal(hw, ICE_SW_LKUP_MAC, 2893 m_list_itr); 2894 if (m_list_itr->status) 2895 return m_list_itr->status; 2896 } 2897 } 2898 2899 ice_acquire_lock(rule_lock); 2900 /* Exit if no suitable entries were found for adding bulk switch rule */ 2901 if (!num_unicast) { 2902 status = ICE_SUCCESS; 2903 goto ice_add_mac_exit; 2904 } 2905 2906 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 2907 2908 /* Allocate switch rule buffer for the bulk update for unicast */ 2909 s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE; 2910 s_rule = (struct ice_aqc_sw_rules_elem *) 2911 ice_calloc(hw, num_unicast, s_rule_size); 2912 if (!s_rule) { 2913 status = ICE_ERR_NO_MEMORY; 2914 goto ice_add_mac_exit; 2915 } 2916 2917 r_iter = s_rule; 2918 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2919 list_entry) { 2920 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2921 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2922 2923 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2924 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 2925 ice_aqc_opc_add_sw_rules); 2926 r_iter = (struct ice_aqc_sw_rules_elem *) 2927 ((u8 *)r_iter + s_rule_size); 2928 } 2929 } 2930 2931 /* Call AQ bulk switch rule update for all unicast addresses */ 2932 r_iter = s_rule; 2933 /* Call AQ switch rule in AQ_MAX chunk */ 2934 for (total_elem_left = num_unicast; total_elem_left > 0; 2935 total_elem_left -= elem_sent) { 2936 struct ice_aqc_sw_rules_elem *entry = r_iter; 2937 2938 elem_sent = min(total_elem_left, 2939 (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size)); 2940 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 2941 elem_sent, ice_aqc_opc_add_sw_rules, 2942 NULL); 2943 if (status) 2944 goto ice_add_mac_exit; 2945 r_iter = (struct ice_aqc_sw_rules_elem *) 2946 ((u8 *)r_iter + (elem_sent * s_rule_size)); 2947 } 2948 2949 /* Fill up rule ID based on the value returned from FW */ 2950 r_iter = s_rule; 2951 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2952 list_entry) { 2953 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2954 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2955 struct ice_fltr_mgmt_list_entry *fm_entry; 2956 2957 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2958 f_info->fltr_rule_id = 2959 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index); 2960 f_info->fltr_act = ICE_FWD_TO_VSI; 2961 /* Create an entry to track this MAC address */ 2962 fm_entry = (struct ice_fltr_mgmt_list_entry *) 2963 ice_malloc(hw, sizeof(*fm_entry)); 2964 if (!fm_entry) { 2965 status = ICE_ERR_NO_MEMORY; 2966 goto ice_add_mac_exit; 2967 } 2968 fm_entry->fltr_info = *f_info; 2969 fm_entry->vsi_count = 1; 2970 /* The book keeping entries will get removed when 2971 * base driver calls remove filter AQ command 2972 */ 2973 2974 LIST_ADD(&fm_entry->list_entry, rule_head); 2975 r_iter = (struct ice_aqc_sw_rules_elem *) 2976 ((u8 *)r_iter + s_rule_size); 2977 } 2978 } 2979 2980 ice_add_mac_exit: 2981 ice_release_lock(rule_lock); 2982 if (s_rule) 2983 ice_free(hw, s_rule); 2984 return status; 2985 } 2986 2987 /** 2988 * ice_add_vlan_internal - Add one VLAN based filter rule 2989 * @hw: pointer to the hardware structure 2990 * @f_entry: filter entry containing one VLAN information 2991 */ 2992 static enum ice_status 2993 ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry) 2994 { 2995 struct ice_switch_info *sw = hw->switch_info; 2996 struct ice_fltr_mgmt_list_entry *v_list_itr; 2997 struct ice_fltr_info *new_fltr, *cur_fltr; 2998 enum ice_sw_lkup_type lkup_type; 2999 u16 vsi_list_id = 0, vsi_handle; 3000 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3001 enum ice_status status = ICE_SUCCESS; 3002 3003 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 3004 return ICE_ERR_PARAM; 3005 3006 f_entry->fltr_info.fwd_id.hw_vsi_id = 3007 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 3008 new_fltr = &f_entry->fltr_info; 3009 3010 /* VLAN ID should only be 12 bits */ 3011 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 3012 return ICE_ERR_PARAM; 3013 3014 if (new_fltr->src_id != ICE_SRC_ID_VSI) 3015 return ICE_ERR_PARAM; 3016 3017 new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 3018 lkup_type = new_fltr->lkup_type; 3019 vsi_handle = new_fltr->vsi_handle; 3020 rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 3021 ice_acquire_lock(rule_lock); 3022 v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr); 3023 if (!v_list_itr) { 3024 struct ice_vsi_list_map_info *map_info = NULL; 3025 3026 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 3027 /* All VLAN pruning rules use a VSI list. Check if 3028 * there is already a VSI list containing VSI that we 3029 * want to add. If found, use the same vsi_list_id for 3030 * this new VLAN rule or else create a new list. 3031 */ 3032 map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN, 3033 vsi_handle, 3034 &vsi_list_id); 3035 if (!map_info) { 3036 status = ice_create_vsi_list_rule(hw, 3037 &vsi_handle, 3038 1, 3039 &vsi_list_id, 3040 lkup_type); 3041 if (status) 3042 goto exit; 3043 } 3044 /* Convert the action to forwarding to a VSI list. */ 3045 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 3046 new_fltr->fwd_id.vsi_list_id = vsi_list_id; 3047 } 3048 3049 status = ice_create_pkt_fwd_rule(hw, f_entry); 3050 if (!status) { 3051 v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, 3052 new_fltr); 3053 if (!v_list_itr) { 3054 status = ICE_ERR_DOES_NOT_EXIST; 3055 goto exit; 3056 } 3057 /* reuse VSI list for new rule and increment ref_cnt */ 3058 if (map_info) { 3059 v_list_itr->vsi_list_info = map_info; 3060 map_info->ref_cnt++; 3061 } else { 3062 v_list_itr->vsi_list_info = 3063 ice_create_vsi_list_map(hw, &vsi_handle, 3064 1, vsi_list_id); 3065 } 3066 } 3067 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 3068 /* Update existing VSI list to add new VSI ID only if it used 3069 * by one VLAN rule. 3070 */ 3071 cur_fltr = &v_list_itr->fltr_info; 3072 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 3073 new_fltr); 3074 } else { 3075 /* If VLAN rule exists and VSI list being used by this rule is 3076 * referenced by more than 1 VLAN rule. Then create a new VSI 3077 * list appending previous VSI with new VSI and update existing 3078 * VLAN rule to point to new VSI list ID 3079 */ 3080 struct ice_fltr_info tmp_fltr; 3081 u16 vsi_handle_arr[2]; 3082 u16 cur_handle; 3083 3084 /* Current implementation only supports reusing VSI list with 3085 * one VSI count. We should never hit below condition 3086 */ 3087 if (v_list_itr->vsi_count > 1 && 3088 v_list_itr->vsi_list_info->ref_cnt > 1) { 3089 ice_debug(hw, ICE_DBG_SW, 3090 "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 3091 status = ICE_ERR_CFG; 3092 goto exit; 3093 } 3094 3095 cur_handle = 3096 ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map, 3097 ICE_MAX_VSI); 3098 3099 /* A rule already exists with the new VSI being added */ 3100 if (cur_handle == vsi_handle) { 3101 status = ICE_ERR_ALREADY_EXISTS; 3102 goto exit; 3103 } 3104 3105 vsi_handle_arr[0] = cur_handle; 3106 vsi_handle_arr[1] = vsi_handle; 3107 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 3108 &vsi_list_id, lkup_type); 3109 if (status) 3110 goto exit; 3111 3112 tmp_fltr = v_list_itr->fltr_info; 3113 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 3114 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 3115 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 3116 /* Update the previous switch rule to a new VSI list which 3117 * includes current VSI that is requested 3118 */ 3119 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 3120 if (status) 3121 goto exit; 3122 3123 /* before overriding VSI list map info. decrement ref_cnt of 3124 * previous VSI list 3125 */ 3126 v_list_itr->vsi_list_info->ref_cnt--; 3127 3128 /* now update to newly created list */ 3129 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 3130 v_list_itr->vsi_list_info = 3131 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 3132 vsi_list_id); 3133 v_list_itr->vsi_count++; 3134 } 3135 3136 exit: 3137 ice_release_lock(rule_lock); 3138 return status; 3139 } 3140 3141 /** 3142 * ice_add_vlan - Add VLAN based filter rule 3143 * @hw: pointer to the hardware structure 3144 * @v_list: list of VLAN entries and forwarding information 3145 */ 3146 enum ice_status 3147 ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 3148 { 3149 struct ice_fltr_list_entry *v_list_itr; 3150 3151 if (!v_list || !hw) 3152 return ICE_ERR_PARAM; 3153 3154 LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry, 3155 list_entry) { 3156 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 3157 return ICE_ERR_PARAM; 3158 v_list_itr->fltr_info.flag = ICE_FLTR_TX; 3159 v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr); 3160 if (v_list_itr->status) 3161 return v_list_itr->status; 3162 } 3163 return ICE_SUCCESS; 3164 } 3165 3166 /** 3167 * ice_add_mac_vlan - Add MAC and VLAN pair based filter rule 3168 * @hw: pointer to the hardware structure 3169 * @mv_list: list of MAC and VLAN filters 3170 * 3171 * If the VSI on which the MAC-VLAN pair has to be added has Rx and Tx VLAN 3172 * pruning bits enabled, then it is the responsibility of the caller to make 3173 * sure to add a VLAN only filter on the same VSI. Packets belonging to that 3174 * VLAN won't be received on that VSI otherwise. 3175 */ 3176 enum ice_status 3177 ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list) 3178 { 3179 struct ice_fltr_list_entry *mv_list_itr; 3180 3181 if (!mv_list || !hw) 3182 return ICE_ERR_PARAM; 3183 3184 LIST_FOR_EACH_ENTRY(mv_list_itr, mv_list, ice_fltr_list_entry, 3185 list_entry) { 3186 enum ice_sw_lkup_type l_type = 3187 mv_list_itr->fltr_info.lkup_type; 3188 3189 if (l_type != ICE_SW_LKUP_MAC_VLAN) 3190 return ICE_ERR_PARAM; 3191 mv_list_itr->fltr_info.flag = ICE_FLTR_TX; 3192 mv_list_itr->status = 3193 ice_add_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN, 3194 mv_list_itr); 3195 if (mv_list_itr->status) 3196 return mv_list_itr->status; 3197 } 3198 return ICE_SUCCESS; 3199 } 3200 3201 /** 3202 * ice_add_eth_mac - Add ethertype and MAC based filter rule 3203 * @hw: pointer to the hardware structure 3204 * @em_list: list of ether type MAC filter, MAC is optional 3205 * 3206 * This function requires the caller to populate the entries in 3207 * the filter list with the necessary fields (including flags to 3208 * indicate Tx or Rx rules). 3209 */ 3210 enum ice_status 3211 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 3212 { 3213 struct ice_fltr_list_entry *em_list_itr; 3214 3215 if (!em_list || !hw) 3216 return ICE_ERR_PARAM; 3217 3218 LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry, 3219 list_entry) { 3220 enum ice_sw_lkup_type l_type = 3221 em_list_itr->fltr_info.lkup_type; 3222 3223 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 3224 l_type != ICE_SW_LKUP_ETHERTYPE) 3225 return ICE_ERR_PARAM; 3226 3227 em_list_itr->status = ice_add_rule_internal(hw, l_type, 3228 em_list_itr); 3229 if (em_list_itr->status) 3230 return em_list_itr->status; 3231 } 3232 return ICE_SUCCESS; 3233 } 3234 3235 /** 3236 * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule 3237 * @hw: pointer to the hardware structure 3238 * @em_list: list of ethertype or ethertype MAC entries 3239 */ 3240 enum ice_status 3241 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 3242 { 3243 struct ice_fltr_list_entry *em_list_itr, *tmp; 3244 3245 if (!em_list || !hw) 3246 return ICE_ERR_PARAM; 3247 3248 LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry, 3249 list_entry) { 3250 enum ice_sw_lkup_type l_type = 3251 em_list_itr->fltr_info.lkup_type; 3252 3253 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 3254 l_type != ICE_SW_LKUP_ETHERTYPE) 3255 return ICE_ERR_PARAM; 3256 3257 em_list_itr->status = ice_remove_rule_internal(hw, l_type, 3258 em_list_itr); 3259 if (em_list_itr->status) 3260 return em_list_itr->status; 3261 } 3262 return ICE_SUCCESS; 3263 } 3264 3265 3266 /** 3267 * ice_rem_sw_rule_info 3268 * @hw: pointer to the hardware structure 3269 * @rule_head: pointer to the switch list structure that we want to delete 3270 */ 3271 static void 3272 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 3273 { 3274 if (!LIST_EMPTY(rule_head)) { 3275 struct ice_fltr_mgmt_list_entry *entry; 3276 struct ice_fltr_mgmt_list_entry *tmp; 3277 3278 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head, 3279 ice_fltr_mgmt_list_entry, list_entry) { 3280 LIST_DEL(&entry->list_entry); 3281 ice_free(hw, entry); 3282 } 3283 } 3284 } 3285 3286 /** 3287 * ice_rem_adv_rule_info 3288 * @hw: pointer to the hardware structure 3289 * @rule_head: pointer to the switch list structure that we want to delete 3290 */ 3291 static void 3292 ice_rem_adv_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 3293 { 3294 struct ice_adv_fltr_mgmt_list_entry *tmp_entry; 3295 struct ice_adv_fltr_mgmt_list_entry *lst_itr; 3296 3297 if (LIST_EMPTY(rule_head)) 3298 return; 3299 3300 LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, rule_head, 3301 ice_adv_fltr_mgmt_list_entry, list_entry) { 3302 LIST_DEL(&lst_itr->list_entry); 3303 ice_free(hw, lst_itr->lkups); 3304 ice_free(hw, lst_itr); 3305 } 3306 } 3307 3308 /** 3309 * ice_rem_all_sw_rules_info 3310 * @hw: pointer to the hardware structure 3311 */ 3312 void ice_rem_all_sw_rules_info(struct ice_hw *hw) 3313 { 3314 struct ice_switch_info *sw = hw->switch_info; 3315 u8 i; 3316 3317 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 3318 struct LIST_HEAD_TYPE *rule_head; 3319 3320 rule_head = &sw->recp_list[i].filt_rules; 3321 if (!sw->recp_list[i].adv_rule) 3322 ice_rem_sw_rule_info(hw, rule_head); 3323 else 3324 ice_rem_adv_rule_info(hw, rule_head); 3325 } 3326 } 3327 3328 /** 3329 * ice_cfg_dflt_vsi - change state of VSI to set/clear default 3330 * @pi: pointer to the port_info structure 3331 * @vsi_handle: VSI handle to set as default 3332 * @set: true to add the above mentioned switch rule, false to remove it 3333 * @direction: ICE_FLTR_RX or ICE_FLTR_TX 3334 * 3335 * add filter rule to set/unset given VSI as default VSI for the switch 3336 * (represented by swid) 3337 */ 3338 enum ice_status 3339 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set, 3340 u8 direction) 3341 { 3342 struct ice_aqc_sw_rules_elem *s_rule; 3343 struct ice_fltr_info f_info; 3344 struct ice_hw *hw = pi->hw; 3345 enum ice_adminq_opc opcode; 3346 enum ice_status status; 3347 u16 s_rule_size; 3348 u16 hw_vsi_id; 3349 3350 if (!ice_is_vsi_valid(hw, vsi_handle)) 3351 return ICE_ERR_PARAM; 3352 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3353 3354 s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE : 3355 ICE_SW_RULE_RX_TX_NO_HDR_SIZE; 3356 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size); 3357 if (!s_rule) 3358 return ICE_ERR_NO_MEMORY; 3359 3360 ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM); 3361 3362 f_info.lkup_type = ICE_SW_LKUP_DFLT; 3363 f_info.flag = direction; 3364 f_info.fltr_act = ICE_FWD_TO_VSI; 3365 f_info.fwd_id.hw_vsi_id = hw_vsi_id; 3366 3367 if (f_info.flag & ICE_FLTR_RX) { 3368 f_info.src = pi->lport; 3369 f_info.src_id = ICE_SRC_ID_LPORT; 3370 if (!set) 3371 f_info.fltr_rule_id = 3372 pi->dflt_rx_vsi_rule_id; 3373 } else if (f_info.flag & ICE_FLTR_TX) { 3374 f_info.src_id = ICE_SRC_ID_VSI; 3375 f_info.src = hw_vsi_id; 3376 if (!set) 3377 f_info.fltr_rule_id = 3378 pi->dflt_tx_vsi_rule_id; 3379 } 3380 3381 if (set) 3382 opcode = ice_aqc_opc_add_sw_rules; 3383 else 3384 opcode = ice_aqc_opc_remove_sw_rules; 3385 3386 ice_fill_sw_rule(hw, &f_info, s_rule, opcode); 3387 3388 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL); 3389 if (status || !(f_info.flag & ICE_FLTR_TX_RX)) 3390 goto out; 3391 if (set) { 3392 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 3393 3394 if (f_info.flag & ICE_FLTR_TX) { 3395 pi->dflt_tx_vsi_num = hw_vsi_id; 3396 pi->dflt_tx_vsi_rule_id = index; 3397 } else if (f_info.flag & ICE_FLTR_RX) { 3398 pi->dflt_rx_vsi_num = hw_vsi_id; 3399 pi->dflt_rx_vsi_rule_id = index; 3400 } 3401 } else { 3402 if (f_info.flag & ICE_FLTR_TX) { 3403 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL; 3404 pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT; 3405 } else if (f_info.flag & ICE_FLTR_RX) { 3406 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL; 3407 pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT; 3408 } 3409 } 3410 3411 out: 3412 ice_free(hw, s_rule); 3413 return status; 3414 } 3415 3416 /** 3417 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry 3418 * @hw: pointer to the hardware structure 3419 * @recp_id: lookup type for which the specified rule needs to be searched 3420 * @f_info: rule information 3421 * 3422 * Helper function to search for a unicast rule entry - this is to be used 3423 * to remove unicast MAC filter that is not shared with other VSIs on the 3424 * PF switch. 3425 * 3426 * Returns pointer to entry storing the rule if found 3427 */ 3428 static struct ice_fltr_mgmt_list_entry * 3429 ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id, 3430 struct ice_fltr_info *f_info) 3431 { 3432 struct ice_switch_info *sw = hw->switch_info; 3433 struct ice_fltr_mgmt_list_entry *list_itr; 3434 struct LIST_HEAD_TYPE *list_head; 3435 3436 list_head = &sw->recp_list[recp_id].filt_rules; 3437 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 3438 list_entry) { 3439 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 3440 sizeof(f_info->l_data)) && 3441 f_info->fwd_id.hw_vsi_id == 3442 list_itr->fltr_info.fwd_id.hw_vsi_id && 3443 f_info->flag == list_itr->fltr_info.flag) 3444 return list_itr; 3445 } 3446 return NULL; 3447 } 3448 3449 /** 3450 * ice_remove_mac - remove a MAC address based filter rule 3451 * @hw: pointer to the hardware structure 3452 * @m_list: list of MAC addresses and forwarding information 3453 * 3454 * This function removes either a MAC filter rule or a specific VSI from a 3455 * VSI list for a multicast MAC address. 3456 * 3457 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 3458 * ice_add_mac. Caller should be aware that this call will only work if all 3459 * the entries passed into m_list were added previously. It will not attempt to 3460 * do a partial remove of entries that were found. 3461 */ 3462 enum ice_status 3463 ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 3464 { 3465 struct ice_fltr_list_entry *list_itr, *tmp; 3466 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3467 3468 if (!m_list) 3469 return ICE_ERR_PARAM; 3470 3471 rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 3472 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry, 3473 list_entry) { 3474 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 3475 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; 3476 u16 vsi_handle; 3477 3478 if (l_type != ICE_SW_LKUP_MAC) 3479 return ICE_ERR_PARAM; 3480 3481 vsi_handle = list_itr->fltr_info.vsi_handle; 3482 if (!ice_is_vsi_valid(hw, vsi_handle)) 3483 return ICE_ERR_PARAM; 3484 3485 list_itr->fltr_info.fwd_id.hw_vsi_id = 3486 ice_get_hw_vsi_num(hw, vsi_handle); 3487 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) { 3488 /* Don't remove the unicast address that belongs to 3489 * another VSI on the switch, since it is not being 3490 * shared... 3491 */ 3492 ice_acquire_lock(rule_lock); 3493 if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC, 3494 &list_itr->fltr_info)) { 3495 ice_release_lock(rule_lock); 3496 return ICE_ERR_DOES_NOT_EXIST; 3497 } 3498 ice_release_lock(rule_lock); 3499 } 3500 list_itr->status = ice_remove_rule_internal(hw, 3501 ICE_SW_LKUP_MAC, 3502 list_itr); 3503 if (list_itr->status) 3504 return list_itr->status; 3505 } 3506 return ICE_SUCCESS; 3507 } 3508 3509 /** 3510 * ice_remove_vlan - Remove VLAN based filter rule 3511 * @hw: pointer to the hardware structure 3512 * @v_list: list of VLAN entries and forwarding information 3513 */ 3514 enum ice_status 3515 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 3516 { 3517 struct ice_fltr_list_entry *v_list_itr, *tmp; 3518 3519 if (!v_list || !hw) 3520 return ICE_ERR_PARAM; 3521 3522 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3523 list_entry) { 3524 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 3525 3526 if (l_type != ICE_SW_LKUP_VLAN) 3527 return ICE_ERR_PARAM; 3528 v_list_itr->status = ice_remove_rule_internal(hw, 3529 ICE_SW_LKUP_VLAN, 3530 v_list_itr); 3531 if (v_list_itr->status) 3532 return v_list_itr->status; 3533 } 3534 return ICE_SUCCESS; 3535 } 3536 3537 /** 3538 * ice_remove_mac_vlan - Remove MAC VLAN based filter rule 3539 * @hw: pointer to the hardware structure 3540 * @v_list: list of MAC VLAN entries and forwarding information 3541 */ 3542 enum ice_status 3543 ice_remove_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 3544 { 3545 struct ice_fltr_list_entry *v_list_itr, *tmp; 3546 3547 if (!v_list || !hw) 3548 return ICE_ERR_PARAM; 3549 3550 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3551 list_entry) { 3552 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 3553 3554 if (l_type != ICE_SW_LKUP_MAC_VLAN) 3555 return ICE_ERR_PARAM; 3556 v_list_itr->status = 3557 ice_remove_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN, 3558 v_list_itr); 3559 if (v_list_itr->status) 3560 return v_list_itr->status; 3561 } 3562 return ICE_SUCCESS; 3563 } 3564 3565 /** 3566 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 3567 * @fm_entry: filter entry to inspect 3568 * @vsi_handle: VSI handle to compare with filter info 3569 */ 3570 static bool 3571 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 3572 { 3573 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 3574 fm_entry->fltr_info.vsi_handle == vsi_handle) || 3575 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 3576 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map, 3577 vsi_handle)))); 3578 } 3579 3580 /** 3581 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 3582 * @hw: pointer to the hardware structure 3583 * @vsi_handle: VSI handle to remove filters from 3584 * @vsi_list_head: pointer to the list to add entry to 3585 * @fi: pointer to fltr_info of filter entry to copy & add 3586 * 3587 * Helper function, used when creating a list of filters to remove from 3588 * a specific VSI. The entry added to vsi_list_head is a COPY of the 3589 * original filter entry, with the exception of fltr_info.fltr_act and 3590 * fltr_info.fwd_id fields. These are set such that later logic can 3591 * extract which VSI to remove the fltr from, and pass on that information. 3592 */ 3593 static enum ice_status 3594 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3595 struct LIST_HEAD_TYPE *vsi_list_head, 3596 struct ice_fltr_info *fi) 3597 { 3598 struct ice_fltr_list_entry *tmp; 3599 3600 /* this memory is freed up in the caller function 3601 * once filters for this VSI are removed 3602 */ 3603 tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp)); 3604 if (!tmp) 3605 return ICE_ERR_NO_MEMORY; 3606 3607 tmp->fltr_info = *fi; 3608 3609 /* Overwrite these fields to indicate which VSI to remove filter from, 3610 * so find and remove logic can extract the information from the 3611 * list entries. Note that original entries will still have proper 3612 * values. 3613 */ 3614 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 3615 tmp->fltr_info.vsi_handle = vsi_handle; 3616 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3617 3618 LIST_ADD(&tmp->list_entry, vsi_list_head); 3619 3620 return ICE_SUCCESS; 3621 } 3622 3623 /** 3624 * ice_add_to_vsi_fltr_list - Add VSI filters to the list 3625 * @hw: pointer to the hardware structure 3626 * @vsi_handle: VSI handle to remove filters from 3627 * @lkup_list_head: pointer to the list that has certain lookup type filters 3628 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 3629 * 3630 * Locates all filters in lkup_list_head that are used by the given VSI, 3631 * and adds COPIES of those entries to vsi_list_head (intended to be used 3632 * to remove the listed filters). 3633 * Note that this means all entries in vsi_list_head must be explicitly 3634 * deallocated by the caller when done with list. 3635 */ 3636 static enum ice_status 3637 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3638 struct LIST_HEAD_TYPE *lkup_list_head, 3639 struct LIST_HEAD_TYPE *vsi_list_head) 3640 { 3641 struct ice_fltr_mgmt_list_entry *fm_entry; 3642 enum ice_status status = ICE_SUCCESS; 3643 3644 /* check to make sure VSI ID is valid and within boundary */ 3645 if (!ice_is_vsi_valid(hw, vsi_handle)) 3646 return ICE_ERR_PARAM; 3647 3648 LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head, 3649 ice_fltr_mgmt_list_entry, list_entry) { 3650 struct ice_fltr_info *fi; 3651 3652 fi = &fm_entry->fltr_info; 3653 if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) 3654 continue; 3655 3656 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3657 vsi_list_head, fi); 3658 if (status) 3659 return status; 3660 } 3661 return status; 3662 } 3663 3664 3665 /** 3666 * ice_determine_promisc_mask 3667 * @fi: filter info to parse 3668 * 3669 * Helper function to determine which ICE_PROMISC_ mask corresponds 3670 * to given filter into. 3671 */ 3672 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi) 3673 { 3674 u16 vid = fi->l_data.mac_vlan.vlan_id; 3675 u8 *macaddr = fi->l_data.mac.mac_addr; 3676 bool is_tx_fltr = false; 3677 u8 promisc_mask = 0; 3678 3679 if (fi->flag == ICE_FLTR_TX) 3680 is_tx_fltr = true; 3681 3682 if (IS_BROADCAST_ETHER_ADDR(macaddr)) 3683 promisc_mask |= is_tx_fltr ? 3684 ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX; 3685 else if (IS_MULTICAST_ETHER_ADDR(macaddr)) 3686 promisc_mask |= is_tx_fltr ? 3687 ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX; 3688 else if (IS_UNICAST_ETHER_ADDR(macaddr)) 3689 promisc_mask |= is_tx_fltr ? 3690 ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX; 3691 if (vid) 3692 promisc_mask |= is_tx_fltr ? 3693 ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX; 3694 3695 return promisc_mask; 3696 } 3697 3698 /** 3699 * ice_get_vsi_promisc - get promiscuous mode of given VSI 3700 * @hw: pointer to the hardware structure 3701 * @vsi_handle: VSI handle to retrieve info from 3702 * @promisc_mask: pointer to mask to be filled in 3703 * @vid: VLAN ID of promisc VLAN VSI 3704 */ 3705 enum ice_status 3706 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 3707 u16 *vid) 3708 { 3709 struct ice_switch_info *sw = hw->switch_info; 3710 struct ice_fltr_mgmt_list_entry *itr; 3711 struct LIST_HEAD_TYPE *rule_head; 3712 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3713 3714 if (!ice_is_vsi_valid(hw, vsi_handle)) 3715 return ICE_ERR_PARAM; 3716 3717 *vid = 0; 3718 *promisc_mask = 0; 3719 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules; 3720 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock; 3721 3722 ice_acquire_lock(rule_lock); 3723 LIST_FOR_EACH_ENTRY(itr, rule_head, 3724 ice_fltr_mgmt_list_entry, list_entry) { 3725 /* Continue if this filter doesn't apply to this VSI or the 3726 * VSI ID is not in the VSI map for this filter 3727 */ 3728 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3729 continue; 3730 3731 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info); 3732 } 3733 ice_release_lock(rule_lock); 3734 3735 return ICE_SUCCESS; 3736 } 3737 3738 /** 3739 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI 3740 * @hw: pointer to the hardware structure 3741 * @vsi_handle: VSI handle to retrieve info from 3742 * @promisc_mask: pointer to mask to be filled in 3743 * @vid: VLAN ID of promisc VLAN VSI 3744 */ 3745 enum ice_status 3746 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask, 3747 u16 *vid) 3748 { 3749 struct ice_switch_info *sw = hw->switch_info; 3750 struct ice_fltr_mgmt_list_entry *itr; 3751 struct LIST_HEAD_TYPE *rule_head; 3752 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3753 3754 if (!ice_is_vsi_valid(hw, vsi_handle)) 3755 return ICE_ERR_PARAM; 3756 3757 *vid = 0; 3758 *promisc_mask = 0; 3759 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules; 3760 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock; 3761 3762 ice_acquire_lock(rule_lock); 3763 LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry, 3764 list_entry) { 3765 /* Continue if this filter doesn't apply to this VSI or the 3766 * VSI ID is not in the VSI map for this filter 3767 */ 3768 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3769 continue; 3770 3771 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info); 3772 } 3773 ice_release_lock(rule_lock); 3774 3775 return ICE_SUCCESS; 3776 } 3777 3778 /** 3779 * ice_remove_promisc - Remove promisc based filter rules 3780 * @hw: pointer to the hardware structure 3781 * @recp_id: recipe ID for which the rule needs to removed 3782 * @v_list: list of promisc entries 3783 */ 3784 static enum ice_status 3785 ice_remove_promisc(struct ice_hw *hw, u8 recp_id, 3786 struct LIST_HEAD_TYPE *v_list) 3787 { 3788 struct ice_fltr_list_entry *v_list_itr, *tmp; 3789 3790 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3791 list_entry) { 3792 v_list_itr->status = 3793 ice_remove_rule_internal(hw, recp_id, v_list_itr); 3794 if (v_list_itr->status) 3795 return v_list_itr->status; 3796 } 3797 return ICE_SUCCESS; 3798 } 3799 3800 /** 3801 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 3802 * @hw: pointer to the hardware structure 3803 * @vsi_handle: VSI handle to clear mode 3804 * @promisc_mask: mask of promiscuous config bits to clear 3805 * @vid: VLAN ID to clear VLAN promiscuous 3806 */ 3807 enum ice_status 3808 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 3809 u16 vid) 3810 { 3811 struct ice_switch_info *sw = hw->switch_info; 3812 struct ice_fltr_list_entry *fm_entry, *tmp; 3813 struct LIST_HEAD_TYPE remove_list_head; 3814 struct ice_fltr_mgmt_list_entry *itr; 3815 struct LIST_HEAD_TYPE *rule_head; 3816 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3817 enum ice_status status = ICE_SUCCESS; 3818 u8 recipe_id; 3819 3820 if (!ice_is_vsi_valid(hw, vsi_handle)) 3821 return ICE_ERR_PARAM; 3822 3823 if (vid) 3824 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3825 else 3826 recipe_id = ICE_SW_LKUP_PROMISC; 3827 3828 rule_head = &sw->recp_list[recipe_id].filt_rules; 3829 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 3830 3831 INIT_LIST_HEAD(&remove_list_head); 3832 3833 ice_acquire_lock(rule_lock); 3834 LIST_FOR_EACH_ENTRY(itr, rule_head, 3835 ice_fltr_mgmt_list_entry, list_entry) { 3836 u8 fltr_promisc_mask = 0; 3837 3838 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3839 continue; 3840 3841 fltr_promisc_mask |= 3842 ice_determine_promisc_mask(&itr->fltr_info); 3843 3844 /* Skip if filter is not completely specified by given mask */ 3845 if (fltr_promisc_mask & ~promisc_mask) 3846 continue; 3847 3848 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3849 &remove_list_head, 3850 &itr->fltr_info); 3851 if (status) { 3852 ice_release_lock(rule_lock); 3853 goto free_fltr_list; 3854 } 3855 } 3856 ice_release_lock(rule_lock); 3857 3858 status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 3859 3860 free_fltr_list: 3861 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 3862 ice_fltr_list_entry, list_entry) { 3863 LIST_DEL(&fm_entry->list_entry); 3864 ice_free(hw, fm_entry); 3865 } 3866 3867 return status; 3868 } 3869 3870 /** 3871 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 3872 * @hw: pointer to the hardware structure 3873 * @vsi_handle: VSI handle to configure 3874 * @promisc_mask: mask of promiscuous config bits 3875 * @vid: VLAN ID to set VLAN promiscuous 3876 */ 3877 enum ice_status 3878 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid) 3879 { 3880 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 3881 struct ice_fltr_list_entry f_list_entry; 3882 struct ice_fltr_info new_fltr; 3883 enum ice_status status = ICE_SUCCESS; 3884 bool is_tx_fltr; 3885 u16 hw_vsi_id; 3886 int pkt_type; 3887 u8 recipe_id; 3888 3889 ice_debug(hw, ICE_DBG_TRACE, "ice_set_vsi_promisc\n"); 3890 3891 if (!ice_is_vsi_valid(hw, vsi_handle)) 3892 return ICE_ERR_PARAM; 3893 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3894 3895 ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM); 3896 3897 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) { 3898 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 3899 new_fltr.l_data.mac_vlan.vlan_id = vid; 3900 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3901 } else { 3902 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 3903 recipe_id = ICE_SW_LKUP_PROMISC; 3904 } 3905 3906 /* Separate filters must be set for each direction/packet type 3907 * combination, so we will loop over the mask value, store the 3908 * individual type, and clear it out in the input mask as it 3909 * is found. 3910 */ 3911 while (promisc_mask) { 3912 u8 *mac_addr; 3913 3914 pkt_type = 0; 3915 is_tx_fltr = false; 3916 3917 if (promisc_mask & ICE_PROMISC_UCAST_RX) { 3918 promisc_mask &= ~ICE_PROMISC_UCAST_RX; 3919 pkt_type = UCAST_FLTR; 3920 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) { 3921 promisc_mask &= ~ICE_PROMISC_UCAST_TX; 3922 pkt_type = UCAST_FLTR; 3923 is_tx_fltr = true; 3924 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) { 3925 promisc_mask &= ~ICE_PROMISC_MCAST_RX; 3926 pkt_type = MCAST_FLTR; 3927 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) { 3928 promisc_mask &= ~ICE_PROMISC_MCAST_TX; 3929 pkt_type = MCAST_FLTR; 3930 is_tx_fltr = true; 3931 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) { 3932 promisc_mask &= ~ICE_PROMISC_BCAST_RX; 3933 pkt_type = BCAST_FLTR; 3934 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) { 3935 promisc_mask &= ~ICE_PROMISC_BCAST_TX; 3936 pkt_type = BCAST_FLTR; 3937 is_tx_fltr = true; 3938 } 3939 3940 /* Check for VLAN promiscuous flag */ 3941 if (promisc_mask & ICE_PROMISC_VLAN_RX) { 3942 promisc_mask &= ~ICE_PROMISC_VLAN_RX; 3943 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) { 3944 promisc_mask &= ~ICE_PROMISC_VLAN_TX; 3945 is_tx_fltr = true; 3946 } 3947 3948 /* Set filter DA based on packet type */ 3949 mac_addr = new_fltr.l_data.mac.mac_addr; 3950 if (pkt_type == BCAST_FLTR) { 3951 ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM); 3952 } else if (pkt_type == MCAST_FLTR || 3953 pkt_type == UCAST_FLTR) { 3954 /* Use the dummy ether header DA */ 3955 ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN, 3956 ICE_NONDMA_TO_NONDMA); 3957 if (pkt_type == MCAST_FLTR) 3958 mac_addr[0] |= 0x1; /* Set multicast bit */ 3959 } 3960 3961 /* Need to reset this to zero for all iterations */ 3962 new_fltr.flag = 0; 3963 if (is_tx_fltr) { 3964 new_fltr.flag |= ICE_FLTR_TX; 3965 new_fltr.src = hw_vsi_id; 3966 } else { 3967 new_fltr.flag |= ICE_FLTR_RX; 3968 new_fltr.src = hw->port_info->lport; 3969 } 3970 3971 new_fltr.fltr_act = ICE_FWD_TO_VSI; 3972 new_fltr.vsi_handle = vsi_handle; 3973 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 3974 f_list_entry.fltr_info = new_fltr; 3975 3976 status = ice_add_rule_internal(hw, recipe_id, &f_list_entry); 3977 if (status != ICE_SUCCESS) 3978 goto set_promisc_exit; 3979 } 3980 3981 set_promisc_exit: 3982 return status; 3983 } 3984 3985 /** 3986 * ice_set_vlan_vsi_promisc 3987 * @hw: pointer to the hardware structure 3988 * @vsi_handle: VSI handle to configure 3989 * @promisc_mask: mask of promiscuous config bits 3990 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 3991 * 3992 * Configure VSI with all associated VLANs to given promiscuous mode(s) 3993 */ 3994 enum ice_status 3995 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 3996 bool rm_vlan_promisc) 3997 { 3998 struct ice_switch_info *sw = hw->switch_info; 3999 struct ice_fltr_list_entry *list_itr, *tmp; 4000 struct LIST_HEAD_TYPE vsi_list_head; 4001 struct LIST_HEAD_TYPE *vlan_head; 4002 struct ice_lock *vlan_lock; /* Lock to protect filter rule list */ 4003 enum ice_status status; 4004 u16 vlan_id; 4005 4006 INIT_LIST_HEAD(&vsi_list_head); 4007 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 4008 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 4009 ice_acquire_lock(vlan_lock); 4010 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 4011 &vsi_list_head); 4012 ice_release_lock(vlan_lock); 4013 if (status) 4014 goto free_fltr_list; 4015 4016 LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry, 4017 list_entry) { 4018 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 4019 if (rm_vlan_promisc) 4020 status = ice_clear_vsi_promisc(hw, vsi_handle, 4021 promisc_mask, vlan_id); 4022 else 4023 status = ice_set_vsi_promisc(hw, vsi_handle, 4024 promisc_mask, vlan_id); 4025 if (status) 4026 break; 4027 } 4028 4029 free_fltr_list: 4030 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head, 4031 ice_fltr_list_entry, list_entry) { 4032 LIST_DEL(&list_itr->list_entry); 4033 ice_free(hw, list_itr); 4034 } 4035 return status; 4036 } 4037 4038 /** 4039 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 4040 * @hw: pointer to the hardware structure 4041 * @vsi_handle: VSI handle to remove filters from 4042 * @lkup: switch rule filter lookup type 4043 */ 4044 static void 4045 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 4046 enum ice_sw_lkup_type lkup) 4047 { 4048 struct ice_switch_info *sw = hw->switch_info; 4049 struct ice_fltr_list_entry *fm_entry; 4050 struct LIST_HEAD_TYPE remove_list_head; 4051 struct LIST_HEAD_TYPE *rule_head; 4052 struct ice_fltr_list_entry *tmp; 4053 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4054 enum ice_status status; 4055 4056 INIT_LIST_HEAD(&remove_list_head); 4057 rule_lock = &sw->recp_list[lkup].filt_rule_lock; 4058 rule_head = &sw->recp_list[lkup].filt_rules; 4059 ice_acquire_lock(rule_lock); 4060 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 4061 &remove_list_head); 4062 ice_release_lock(rule_lock); 4063 if (status) 4064 return; 4065 4066 switch (lkup) { 4067 case ICE_SW_LKUP_MAC: 4068 ice_remove_mac(hw, &remove_list_head); 4069 break; 4070 case ICE_SW_LKUP_VLAN: 4071 ice_remove_vlan(hw, &remove_list_head); 4072 break; 4073 case ICE_SW_LKUP_PROMISC: 4074 case ICE_SW_LKUP_PROMISC_VLAN: 4075 ice_remove_promisc(hw, lkup, &remove_list_head); 4076 break; 4077 case ICE_SW_LKUP_MAC_VLAN: 4078 ice_remove_mac_vlan(hw, &remove_list_head); 4079 break; 4080 case ICE_SW_LKUP_ETHERTYPE: 4081 case ICE_SW_LKUP_ETHERTYPE_MAC: 4082 ice_remove_eth_mac(hw, &remove_list_head); 4083 break; 4084 case ICE_SW_LKUP_DFLT: 4085 ice_debug(hw, ICE_DBG_SW, 4086 "Remove filters for this lookup type hasn't been implemented yet\n"); 4087 break; 4088 case ICE_SW_LKUP_LAST: 4089 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n"); 4090 break; 4091 } 4092 4093 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 4094 ice_fltr_list_entry, list_entry) { 4095 LIST_DEL(&fm_entry->list_entry); 4096 ice_free(hw, fm_entry); 4097 } 4098 } 4099 4100 /** 4101 * ice_remove_vsi_fltr - Remove all filters for a VSI 4102 * @hw: pointer to the hardware structure 4103 * @vsi_handle: VSI handle to remove filters from 4104 */ 4105 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 4106 { 4107 ice_debug(hw, ICE_DBG_TRACE, "ice_remove_vsi_fltr\n"); 4108 4109 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC); 4110 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN); 4111 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC); 4112 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN); 4113 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT); 4114 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE); 4115 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC); 4116 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN); 4117 } 4118 4119 /** 4120 * ice_alloc_res_cntr - allocating resource counter 4121 * @hw: pointer to the hardware structure 4122 * @type: type of resource 4123 * @alloc_shared: if set it is shared else dedicated 4124 * @num_items: number of entries requested for FD resource type 4125 * @counter_id: counter index returned by AQ call 4126 */ 4127 enum ice_status 4128 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 4129 u16 *counter_id) 4130 { 4131 struct ice_aqc_alloc_free_res_elem *buf; 4132 enum ice_status status; 4133 u16 buf_len; 4134 4135 /* Allocate resource */ 4136 buf_len = sizeof(*buf); 4137 buf = (struct ice_aqc_alloc_free_res_elem *) 4138 ice_malloc(hw, buf_len); 4139 if (!buf) 4140 return ICE_ERR_NO_MEMORY; 4141 4142 buf->num_elems = CPU_TO_LE16(num_items); 4143 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 4144 ICE_AQC_RES_TYPE_M) | alloc_shared); 4145 4146 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 4147 ice_aqc_opc_alloc_res, NULL); 4148 if (status) 4149 goto exit; 4150 4151 *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp); 4152 4153 exit: 4154 ice_free(hw, buf); 4155 return status; 4156 } 4157 4158 /** 4159 * ice_free_res_cntr - free resource counter 4160 * @hw: pointer to the hardware structure 4161 * @type: type of resource 4162 * @alloc_shared: if set it is shared else dedicated 4163 * @num_items: number of entries to be freed for FD resource type 4164 * @counter_id: counter ID resource which needs to be freed 4165 */ 4166 enum ice_status 4167 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 4168 u16 counter_id) 4169 { 4170 struct ice_aqc_alloc_free_res_elem *buf; 4171 enum ice_status status; 4172 u16 buf_len; 4173 4174 /* Free resource */ 4175 buf_len = sizeof(*buf); 4176 buf = (struct ice_aqc_alloc_free_res_elem *) 4177 ice_malloc(hw, buf_len); 4178 if (!buf) 4179 return ICE_ERR_NO_MEMORY; 4180 4181 buf->num_elems = CPU_TO_LE16(num_items); 4182 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 4183 ICE_AQC_RES_TYPE_M) | alloc_shared); 4184 buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 4185 4186 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 4187 ice_aqc_opc_free_res, NULL); 4188 if (status) 4189 ice_debug(hw, ICE_DBG_SW, 4190 "counter resource could not be freed\n"); 4191 4192 ice_free(hw, buf); 4193 return status; 4194 } 4195 4196 /** 4197 * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type 4198 * @hw: pointer to the hardware structure 4199 * @counter_id: returns counter index 4200 */ 4201 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id) 4202 { 4203 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 4204 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 4205 counter_id); 4206 } 4207 4208 /** 4209 * ice_free_vlan_res_counter - Free counter resource for VLAN type 4210 * @hw: pointer to the hardware structure 4211 * @counter_id: counter index to be freed 4212 */ 4213 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id) 4214 { 4215 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 4216 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 4217 counter_id); 4218 } 4219 4220 /** 4221 * ice_alloc_res_lg_act - add large action resource 4222 * @hw: pointer to the hardware structure 4223 * @l_id: large action ID to fill it in 4224 * @num_acts: number of actions to hold with a large action entry 4225 */ 4226 static enum ice_status 4227 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts) 4228 { 4229 struct ice_aqc_alloc_free_res_elem *sw_buf; 4230 enum ice_status status; 4231 u16 buf_len; 4232 4233 if (num_acts > ICE_MAX_LG_ACT || num_acts == 0) 4234 return ICE_ERR_PARAM; 4235 4236 /* Allocate resource for large action */ 4237 buf_len = sizeof(*sw_buf); 4238 sw_buf = (struct ice_aqc_alloc_free_res_elem *) 4239 ice_malloc(hw, buf_len); 4240 if (!sw_buf) 4241 return ICE_ERR_NO_MEMORY; 4242 4243 sw_buf->num_elems = CPU_TO_LE16(1); 4244 4245 /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1. 4246 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3. 4247 * If num_acts is greater than 2, then use 4248 * ICE_AQC_RES_TYPE_WIDE_TABLE_4. 4249 * The num_acts cannot exceed 4. This was ensured at the 4250 * beginning of the function. 4251 */ 4252 if (num_acts == 1) 4253 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1); 4254 else if (num_acts == 2) 4255 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2); 4256 else 4257 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4); 4258 4259 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 4260 ice_aqc_opc_alloc_res, NULL); 4261 if (!status) 4262 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 4263 4264 ice_free(hw, sw_buf); 4265 return status; 4266 } 4267 4268 /** 4269 * ice_add_mac_with_sw_marker - add filter with sw marker 4270 * @hw: pointer to the hardware structure 4271 * @f_info: filter info structure containing the MAC filter information 4272 * @sw_marker: sw marker to tag the Rx descriptor with 4273 */ 4274 enum ice_status 4275 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info, 4276 u16 sw_marker) 4277 { 4278 struct ice_switch_info *sw = hw->switch_info; 4279 struct ice_fltr_mgmt_list_entry *m_entry; 4280 struct ice_fltr_list_entry fl_info; 4281 struct LIST_HEAD_TYPE l_head; 4282 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4283 enum ice_status ret; 4284 bool entry_exists; 4285 u16 lg_act_id; 4286 4287 if (f_info->fltr_act != ICE_FWD_TO_VSI) 4288 return ICE_ERR_PARAM; 4289 4290 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 4291 return ICE_ERR_PARAM; 4292 4293 if (sw_marker == ICE_INVAL_SW_MARKER_ID) 4294 return ICE_ERR_PARAM; 4295 4296 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 4297 return ICE_ERR_PARAM; 4298 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 4299 4300 /* Add filter if it doesn't exist so then the adding of large 4301 * action always results in update 4302 */ 4303 4304 INIT_LIST_HEAD(&l_head); 4305 fl_info.fltr_info = *f_info; 4306 LIST_ADD(&fl_info.list_entry, &l_head); 4307 4308 entry_exists = false; 4309 ret = ice_add_mac(hw, &l_head); 4310 if (ret == ICE_ERR_ALREADY_EXISTS) 4311 entry_exists = true; 4312 else if (ret) 4313 return ret; 4314 4315 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 4316 ice_acquire_lock(rule_lock); 4317 /* Get the book keeping entry for the filter */ 4318 m_entry = ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, f_info); 4319 if (!m_entry) 4320 goto exit_error; 4321 4322 /* If counter action was enabled for this rule then don't enable 4323 * sw marker large action 4324 */ 4325 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 4326 ret = ICE_ERR_PARAM; 4327 goto exit_error; 4328 } 4329 4330 /* if same marker was added before */ 4331 if (m_entry->sw_marker_id == sw_marker) { 4332 ret = ICE_ERR_ALREADY_EXISTS; 4333 goto exit_error; 4334 } 4335 4336 /* Allocate a hardware table entry to hold large act. Three actions 4337 * for marker based large action 4338 */ 4339 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3); 4340 if (ret) 4341 goto exit_error; 4342 4343 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4344 goto exit_error; 4345 4346 /* Update the switch rule to add the marker action */ 4347 ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id); 4348 if (!ret) { 4349 ice_release_lock(rule_lock); 4350 return ret; 4351 } 4352 4353 exit_error: 4354 ice_release_lock(rule_lock); 4355 /* only remove entry if it did not exist previously */ 4356 if (!entry_exists) 4357 ret = ice_remove_mac(hw, &l_head); 4358 4359 return ret; 4360 } 4361 4362 /** 4363 * ice_add_mac_with_counter - add filter with counter enabled 4364 * @hw: pointer to the hardware structure 4365 * @f_info: pointer to filter info structure containing the MAC filter 4366 * information 4367 */ 4368 enum ice_status 4369 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info) 4370 { 4371 struct ice_switch_info *sw = hw->switch_info; 4372 struct ice_fltr_mgmt_list_entry *m_entry; 4373 struct ice_fltr_list_entry fl_info; 4374 struct LIST_HEAD_TYPE l_head; 4375 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4376 enum ice_status ret; 4377 bool entry_exist; 4378 u16 counter_id; 4379 u16 lg_act_id; 4380 4381 if (f_info->fltr_act != ICE_FWD_TO_VSI) 4382 return ICE_ERR_PARAM; 4383 4384 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 4385 return ICE_ERR_PARAM; 4386 4387 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 4388 return ICE_ERR_PARAM; 4389 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 4390 4391 entry_exist = false; 4392 4393 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 4394 4395 /* Add filter if it doesn't exist so then the adding of large 4396 * action always results in update 4397 */ 4398 INIT_LIST_HEAD(&l_head); 4399 4400 fl_info.fltr_info = *f_info; 4401 LIST_ADD(&fl_info.list_entry, &l_head); 4402 4403 ret = ice_add_mac(hw, &l_head); 4404 if (ret == ICE_ERR_ALREADY_EXISTS) 4405 entry_exist = true; 4406 else if (ret) 4407 return ret; 4408 4409 ice_acquire_lock(rule_lock); 4410 m_entry = ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, f_info); 4411 if (!m_entry) { 4412 ret = ICE_ERR_BAD_PTR; 4413 goto exit_error; 4414 } 4415 4416 /* Don't enable counter for a filter for which sw marker was enabled */ 4417 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) { 4418 ret = ICE_ERR_PARAM; 4419 goto exit_error; 4420 } 4421 4422 /* If a counter was already enabled then don't need to add again */ 4423 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 4424 ret = ICE_ERR_ALREADY_EXISTS; 4425 goto exit_error; 4426 } 4427 4428 /* Allocate a hardware table entry to VLAN counter */ 4429 ret = ice_alloc_vlan_res_counter(hw, &counter_id); 4430 if (ret) 4431 goto exit_error; 4432 4433 /* Allocate a hardware table entry to hold large act. Two actions for 4434 * counter based large action 4435 */ 4436 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2); 4437 if (ret) 4438 goto exit_error; 4439 4440 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4441 goto exit_error; 4442 4443 /* Update the switch rule to add the counter action */ 4444 ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id); 4445 if (!ret) { 4446 ice_release_lock(rule_lock); 4447 return ret; 4448 } 4449 4450 exit_error: 4451 ice_release_lock(rule_lock); 4452 /* only remove entry if it did not exist previously */ 4453 if (!entry_exist) 4454 ret = ice_remove_mac(hw, &l_head); 4455 4456 return ret; 4457 } 4458 4459 /* This is mapping table entry that maps every word within a given protocol 4460 * structure to the real byte offset as per the specification of that 4461 * protocol header. 4462 * for example dst address is 3 words in ethertype header and corresponding 4463 * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8 4464 * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a 4465 * matching entry describing its field. This needs to be updated if new 4466 * structure is added to that union. 4467 */ 4468 static const struct ice_prot_ext_tbl_entry ice_prot_ext[] = { 4469 { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } }, 4470 { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } }, 4471 { ICE_ETYPE_OL, { 0 } }, 4472 { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, 4473 { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, 4474 { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 4475 26, 28, 30, 32, 34, 36, 38 } }, 4476 { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 4477 26, 28, 30, 32, 34, 36, 38 } }, 4478 { ICE_TCP_IL, { 0, 2 } }, 4479 { ICE_UDP_OF, { 0, 2 } }, 4480 { ICE_UDP_ILOS, { 0, 2 } }, 4481 { ICE_SCTP_IL, { 0, 2 } }, 4482 { ICE_VXLAN, { 8, 10, 12, 14 } }, 4483 { ICE_GENEVE, { 8, 10, 12, 14 } }, 4484 { ICE_VXLAN_GPE, { 0, 2, 4 } }, 4485 { ICE_NVGRE, { 0, 2, 4, 6 } }, 4486 { ICE_PROTOCOL_LAST, { 0 } } 4487 }; 4488 4489 /* The following table describes preferred grouping of recipes. 4490 * If a recipe that needs to be programmed is a superset or matches one of the 4491 * following combinations, then the recipe needs to be chained as per the 4492 * following policy. 4493 */ 4494 static const struct ice_pref_recipe_group ice_recipe_pack[] = { 4495 {3, { { ICE_MAC_OFOS_HW, 0, 0 }, { ICE_MAC_OFOS_HW, 2, 0 }, 4496 { ICE_MAC_OFOS_HW, 4, 0 } }, { 0xffff, 0xffff, 0xffff, 0xffff } }, 4497 {4, { { ICE_MAC_IL_HW, 0, 0 }, { ICE_MAC_IL_HW, 2, 0 }, 4498 { ICE_MAC_IL_HW, 4, 0 }, { ICE_META_DATA_ID_HW, 44, 0 } }, 4499 { 0xffff, 0xffff, 0xffff, 0xffff } }, 4500 {2, { { ICE_IPV4_IL_HW, 0, 0 }, { ICE_IPV4_IL_HW, 2, 0 } }, 4501 { 0xffff, 0xffff, 0xffff, 0xffff } }, 4502 {2, { { ICE_IPV4_IL_HW, 12, 0 }, { ICE_IPV4_IL_HW, 14, 0 } }, 4503 { 0xffff, 0xffff, 0xffff, 0xffff } }, 4504 }; 4505 4506 static const struct ice_protocol_entry ice_prot_id_tbl[] = { 4507 { ICE_MAC_OFOS, ICE_MAC_OFOS_HW }, 4508 { ICE_MAC_IL, ICE_MAC_IL_HW }, 4509 { ICE_ETYPE_OL, ICE_ETYPE_OL_HW }, 4510 { ICE_IPV4_OFOS, ICE_IPV4_OFOS_HW }, 4511 { ICE_IPV4_IL, ICE_IPV4_IL_HW }, 4512 { ICE_IPV6_OFOS, ICE_IPV6_OFOS_HW }, 4513 { ICE_IPV6_IL, ICE_IPV6_IL_HW }, 4514 { ICE_TCP_IL, ICE_TCP_IL_HW }, 4515 { ICE_UDP_OF, ICE_UDP_OF_HW }, 4516 { ICE_UDP_ILOS, ICE_UDP_ILOS_HW }, 4517 { ICE_SCTP_IL, ICE_SCTP_IL_HW }, 4518 { ICE_VXLAN, ICE_UDP_OF_HW }, 4519 { ICE_GENEVE, ICE_UDP_OF_HW }, 4520 { ICE_VXLAN_GPE, ICE_UDP_OF_HW }, 4521 { ICE_NVGRE, ICE_GRE_OF_HW }, 4522 { ICE_PROTOCOL_LAST, 0 } 4523 }; 4524 4525 /** 4526 * ice_find_recp - find a recipe 4527 * @hw: pointer to the hardware structure 4528 * @lkup_exts: extension sequence to match 4529 * 4530 * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found. 4531 */ 4532 static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts) 4533 { 4534 bool refresh_required = true; 4535 struct ice_sw_recipe *recp; 4536 u16 i; 4537 4538 /* Initialize available_result_ids which tracks available result idx */ 4539 for (i = 0; i <= ICE_CHAIN_FV_INDEX_START; i++) 4540 ice_set_bit(ICE_CHAIN_FV_INDEX_START - i, 4541 available_result_ids); 4542 4543 /* Walk through existing recipes to find a match */ 4544 recp = hw->switch_info->recp_list; 4545 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4546 /* If recipe was not created for this ID, in SW bookkeeping, 4547 * check if FW has an entry for this recipe. If the FW has an 4548 * entry update it in our SW bookkeeping and continue with the 4549 * matching. 4550 */ 4551 if (!recp[i].recp_created) 4552 if (ice_get_recp_frm_fw(hw, 4553 hw->switch_info->recp_list, i, 4554 &refresh_required)) 4555 continue; 4556 4557 /* if number of words we are looking for match */ 4558 if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) { 4559 struct ice_fv_word *a = lkup_exts->fv_words; 4560 struct ice_fv_word *b = recp[i].lkup_exts.fv_words; 4561 bool found = true; 4562 u8 p, q; 4563 4564 for (p = 0; p < lkup_exts->n_val_words; p++) { 4565 for (q = 0; q < recp[i].lkup_exts.n_val_words; 4566 q++) { 4567 if (a[p].off == b[q].off && 4568 a[p].prot_id == b[q].prot_id) 4569 /* Found the "p"th word in the 4570 * given recipe 4571 */ 4572 break; 4573 } 4574 /* After walking through all the words in the 4575 * "i"th recipe if "p"th word was not found then 4576 * this recipe is not what we are looking for. 4577 * So break out from this loop and try the next 4578 * recipe 4579 */ 4580 if (q >= recp[i].lkup_exts.n_val_words) { 4581 found = false; 4582 break; 4583 } 4584 } 4585 /* If for "i"th recipe the found was never set to false 4586 * then it means we found our match 4587 */ 4588 if (found) 4589 return i; /* Return the recipe ID */ 4590 } 4591 } 4592 return ICE_MAX_NUM_RECIPES; 4593 } 4594 4595 /** 4596 * ice_prot_type_to_id - get protocol ID from protocol type 4597 * @type: protocol type 4598 * @id: pointer to variable that will receive the ID 4599 * 4600 * Returns true if found, false otherwise 4601 */ 4602 static bool ice_prot_type_to_id(enum ice_protocol_type type, u16 *id) 4603 { 4604 u16 i; 4605 4606 for (i = 0; ice_prot_id_tbl[i].type != ICE_PROTOCOL_LAST; i++) 4607 if (ice_prot_id_tbl[i].type == type) { 4608 *id = ice_prot_id_tbl[i].protocol_id; 4609 return true; 4610 } 4611 return false; 4612 } 4613 4614 /** 4615 * ice_find_valid_words - count valid words 4616 * @rule: advanced rule with lookup information 4617 * @lkup_exts: byte offset extractions of the words that are valid 4618 * 4619 * calculate valid words in a lookup rule using mask value 4620 */ 4621 static u16 4622 ice_fill_valid_words(struct ice_adv_lkup_elem *rule, 4623 struct ice_prot_lkup_ext *lkup_exts) 4624 { 4625 u16 j, word = 0; 4626 u16 prot_id; 4627 u16 ret_val; 4628 4629 if (!ice_prot_type_to_id(rule->type, &prot_id)) 4630 return 0; 4631 4632 word = lkup_exts->n_val_words; 4633 4634 for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++) 4635 if (((u16 *)&rule->m_u)[j] && 4636 (unsigned long)rule->type < ARRAY_SIZE(ice_prot_ext)) { 4637 /* No more space to accommodate */ 4638 if (word >= ICE_MAX_CHAIN_WORDS) 4639 return 0; 4640 lkup_exts->fv_words[word].off = 4641 ice_prot_ext[rule->type].offs[j]; 4642 lkup_exts->fv_words[word].prot_id = 4643 ice_prot_id_tbl[rule->type].protocol_id; 4644 lkup_exts->field_mask[word] = ((u16 *)&rule->m_u)[j]; 4645 word++; 4646 } 4647 4648 ret_val = word - lkup_exts->n_val_words; 4649 lkup_exts->n_val_words = word; 4650 4651 return ret_val; 4652 } 4653 4654 /** 4655 * ice_find_prot_off_ind - check for specific ID and offset in rule 4656 * @lkup_exts: an array of protocol header extractions 4657 * @prot_type: protocol type to check 4658 * @off: expected offset of the extraction 4659 * 4660 * Check if the prot_ext has given protocol ID and offset 4661 */ 4662 static u8 4663 ice_find_prot_off_ind(struct ice_prot_lkup_ext *lkup_exts, u8 prot_type, 4664 u16 off) 4665 { 4666 u8 j; 4667 4668 for (j = 0; j < lkup_exts->n_val_words; j++) 4669 if (lkup_exts->fv_words[j].off == off && 4670 lkup_exts->fv_words[j].prot_id == prot_type) 4671 return j; 4672 4673 return ICE_MAX_CHAIN_WORDS; 4674 } 4675 4676 /** 4677 * ice_is_recipe_subset - check if recipe group policy is a subset of lookup 4678 * @lkup_exts: an array of protocol header extractions 4679 * @r_policy: preferred recipe grouping policy 4680 * 4681 * Helper function to check if given recipe group is subset we need to check if 4682 * all the words described by the given recipe group exist in the advanced rule 4683 * look up information 4684 */ 4685 static bool 4686 ice_is_recipe_subset(struct ice_prot_lkup_ext *lkup_exts, 4687 const struct ice_pref_recipe_group *r_policy) 4688 { 4689 u8 ind[ICE_NUM_WORDS_RECIPE]; 4690 u8 count = 0; 4691 u8 i; 4692 4693 /* check if everything in the r_policy is part of the entire rule */ 4694 for (i = 0; i < r_policy->n_val_pairs; i++) { 4695 u8 j; 4696 4697 j = ice_find_prot_off_ind(lkup_exts, r_policy->pairs[i].prot_id, 4698 r_policy->pairs[i].off); 4699 if (j >= ICE_MAX_CHAIN_WORDS) 4700 return false; 4701 4702 /* store the indexes temporarily found by the find function 4703 * this will be used to mark the words as 'done' 4704 */ 4705 ind[count++] = j; 4706 } 4707 4708 /* If the entire policy recipe was a true match, then mark the fields 4709 * that are covered by the recipe as 'done' meaning that these words 4710 * will be clumped together in one recipe. 4711 * "Done" here means in our searching if certain recipe group 4712 * matches or is subset of the given rule, then we mark all 4713 * the corresponding offsets as found. So the remaining recipes should 4714 * be created with whatever words that were left. 4715 */ 4716 for (i = 0; i < count; i++) { 4717 u8 in = ind[i]; 4718 4719 ice_set_bit(in, lkup_exts->done); 4720 } 4721 return true; 4722 } 4723 4724 /** 4725 * ice_create_first_fit_recp_def - Create a recipe grouping 4726 * @hw: pointer to the hardware structure 4727 * @lkup_exts: an array of protocol header extractions 4728 * @rg_list: pointer to a list that stores new recipe groups 4729 * @recp_cnt: pointer to a variable that stores returned number of recipe groups 4730 * 4731 * Using first fit algorithm, take all the words that are still not done 4732 * and start grouping them in 4-word groups. Each group makes up one 4733 * recipe. 4734 */ 4735 static enum ice_status 4736 ice_create_first_fit_recp_def(struct ice_hw *hw, 4737 struct ice_prot_lkup_ext *lkup_exts, 4738 struct LIST_HEAD_TYPE *rg_list, 4739 u8 *recp_cnt) 4740 { 4741 struct ice_pref_recipe_group *grp = NULL; 4742 u8 j; 4743 4744 *recp_cnt = 0; 4745 4746 /* Walk through every word in the rule to check if it is not done. If so 4747 * then this word needs to be part of a new recipe. 4748 */ 4749 for (j = 0; j < lkup_exts->n_val_words; j++) 4750 if (!ice_is_bit_set(lkup_exts->done, j)) { 4751 if (!grp || 4752 grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) { 4753 struct ice_recp_grp_entry *entry; 4754 4755 entry = (struct ice_recp_grp_entry *) 4756 ice_malloc(hw, sizeof(*entry)); 4757 if (!entry) 4758 return ICE_ERR_NO_MEMORY; 4759 LIST_ADD(&entry->l_entry, rg_list); 4760 grp = &entry->r_group; 4761 (*recp_cnt)++; 4762 } 4763 4764 grp->pairs[grp->n_val_pairs].prot_id = 4765 lkup_exts->fv_words[j].prot_id; 4766 grp->pairs[grp->n_val_pairs].off = 4767 lkup_exts->fv_words[j].off; 4768 grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j]; 4769 grp->n_val_pairs++; 4770 } 4771 4772 return ICE_SUCCESS; 4773 } 4774 4775 /** 4776 * ice_fill_fv_word_index - fill in the field vector indices for a recipe group 4777 * @hw: pointer to the hardware structure 4778 * @fv_list: field vector with the extraction sequence information 4779 * @rg_list: recipe groupings with protocol-offset pairs 4780 * 4781 * Helper function to fill in the field vector indices for protocol-offset 4782 * pairs. These indexes are then ultimately programmed into a recipe. 4783 */ 4784 static void 4785 ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list, 4786 struct LIST_HEAD_TYPE *rg_list) 4787 { 4788 struct ice_sw_fv_list_entry *fv; 4789 struct ice_recp_grp_entry *rg; 4790 struct ice_fv_word *fv_ext; 4791 4792 if (LIST_EMPTY(fv_list)) 4793 return; 4794 4795 fv = LIST_FIRST_ENTRY(fv_list, struct ice_sw_fv_list_entry, list_entry); 4796 fv_ext = fv->fv_ptr->ew; 4797 4798 LIST_FOR_EACH_ENTRY(rg, rg_list, ice_recp_grp_entry, l_entry) { 4799 u8 i; 4800 4801 for (i = 0; i < rg->r_group.n_val_pairs; i++) { 4802 struct ice_fv_word *pr; 4803 u16 mask; 4804 u8 j; 4805 4806 pr = &rg->r_group.pairs[i]; 4807 mask = rg->r_group.mask[i]; 4808 4809 for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++) 4810 if (fv_ext[j].prot_id == pr->prot_id && 4811 fv_ext[j].off == pr->off) { 4812 /* Store index of field vector */ 4813 rg->fv_idx[i] = j; 4814 /* Mask is given by caller as big 4815 * endian, but sent to FW as little 4816 * endian 4817 */ 4818 rg->fv_mask[i] = mask << 8 | mask >> 8; 4819 break; 4820 } 4821 } 4822 } 4823 } 4824 4825 /** 4826 * ice_add_sw_recipe - function to call AQ calls to create switch recipe 4827 * @hw: pointer to hardware structure 4828 * @rm: recipe management list entry 4829 * @match_tun: if field vector index for tunnel needs to be programmed 4830 */ 4831 static enum ice_status 4832 ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm, 4833 bool match_tun) 4834 { 4835 struct ice_aqc_recipe_data_elem *tmp; 4836 struct ice_aqc_recipe_data_elem *buf; 4837 struct ice_recp_grp_entry *entry; 4838 enum ice_status status; 4839 u16 recipe_count; 4840 u8 chain_idx; 4841 u8 recps = 0; 4842 4843 /* When more than one recipe are required, another recipe is needed to 4844 * chain them together. Matching a tunnel metadata ID takes up one of 4845 * the match fields in the chaining recipe reducing the number of 4846 * chained recipes by one. 4847 */ 4848 if (rm->n_grp_count > 1) 4849 rm->n_grp_count++; 4850 if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE || 4851 (match_tun && rm->n_grp_count > (ICE_MAX_CHAIN_RECIPE - 1))) 4852 return ICE_ERR_MAX_LIMIT; 4853 4854 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw, 4855 ICE_MAX_NUM_RECIPES, 4856 sizeof(*tmp)); 4857 if (!tmp) 4858 return ICE_ERR_NO_MEMORY; 4859 4860 buf = (struct ice_aqc_recipe_data_elem *) 4861 ice_calloc(hw, rm->n_grp_count, sizeof(*buf)); 4862 if (!buf) { 4863 status = ICE_ERR_NO_MEMORY; 4864 goto err_mem; 4865 } 4866 4867 ice_zero_bitmap(rm->r_bitmap, ICE_MAX_NUM_RECIPES); 4868 recipe_count = ICE_MAX_NUM_RECIPES; 4869 status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC, 4870 NULL); 4871 if (status || recipe_count == 0) 4872 goto err_unroll; 4873 4874 /* Allocate the recipe resources, and configure them according to the 4875 * match fields from protocol headers and extracted field vectors. 4876 */ 4877 chain_idx = ICE_CHAIN_FV_INDEX_START - 4878 ice_find_first_bit(available_result_ids, 4879 ICE_CHAIN_FV_INDEX_START + 1); 4880 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) { 4881 u8 i; 4882 4883 status = ice_alloc_recipe(hw, &entry->rid); 4884 if (status) 4885 goto err_unroll; 4886 4887 /* Clear the result index of the located recipe, as this will be 4888 * updated, if needed, later in the recipe creation process. 4889 */ 4890 tmp[0].content.result_indx = 0; 4891 4892 buf[recps] = tmp[0]; 4893 buf[recps].recipe_indx = (u8)entry->rid; 4894 /* if the recipe is a non-root recipe RID should be programmed 4895 * as 0 for the rules to be applied correctly. 4896 */ 4897 buf[recps].content.rid = 0; 4898 ice_memset(&buf[recps].content.lkup_indx, 0, 4899 sizeof(buf[recps].content.lkup_indx), 4900 ICE_NONDMA_MEM); 4901 4902 /* All recipes use look-up index 0 to match switch ID. */ 4903 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 4904 buf[recps].content.mask[0] = 4905 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK); 4906 /* Setup lkup_indx 1..4 to INVALID/ignore and set the mask 4907 * to be 0 4908 */ 4909 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 4910 buf[recps].content.lkup_indx[i] = 0x80; 4911 buf[recps].content.mask[i] = 0; 4912 } 4913 4914 for (i = 0; i < entry->r_group.n_val_pairs; i++) { 4915 buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i]; 4916 buf[recps].content.mask[i + 1] = 4917 CPU_TO_LE16(entry->fv_mask[i]); 4918 } 4919 4920 if (rm->n_grp_count > 1) { 4921 entry->chain_idx = chain_idx; 4922 buf[recps].content.result_indx = 4923 ICE_AQ_RECIPE_RESULT_EN | 4924 ((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) & 4925 ICE_AQ_RECIPE_RESULT_DATA_M); 4926 ice_clear_bit(ICE_CHAIN_FV_INDEX_START - chain_idx, 4927 available_result_ids); 4928 chain_idx = ICE_CHAIN_FV_INDEX_START - 4929 ice_find_first_bit(available_result_ids, 4930 ICE_CHAIN_FV_INDEX_START + 4931 1); 4932 } 4933 4934 /* fill recipe dependencies */ 4935 ice_zero_bitmap((ice_bitmap_t *)buf[recps].recipe_bitmap, 4936 ICE_MAX_NUM_RECIPES); 4937 ice_set_bit(buf[recps].recipe_indx, 4938 (ice_bitmap_t *)buf[recps].recipe_bitmap); 4939 buf[recps].content.act_ctrl_fwd_priority = rm->priority; 4940 recps++; 4941 } 4942 4943 if (rm->n_grp_count == 1) { 4944 rm->root_rid = buf[0].recipe_indx; 4945 ice_set_bit(buf[0].recipe_indx, rm->r_bitmap); 4946 buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT; 4947 if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) { 4948 ice_memcpy(buf[0].recipe_bitmap, rm->r_bitmap, 4949 sizeof(buf[0].recipe_bitmap), 4950 ICE_NONDMA_TO_NONDMA); 4951 } else { 4952 status = ICE_ERR_BAD_PTR; 4953 goto err_unroll; 4954 } 4955 /* Applicable only for ROOT_RECIPE, set the fwd_priority for 4956 * the recipe which is getting created if specified 4957 * by user. Usually any advanced switch filter, which results 4958 * into new extraction sequence, ended up creating a new recipe 4959 * of type ROOT and usually recipes are associated with profiles 4960 * Switch rule referreing newly created recipe, needs to have 4961 * either/or 'fwd' or 'join' priority, otherwise switch rule 4962 * evaluation will not happen correctly. In other words, if 4963 * switch rule to be evaluated on priority basis, then recipe 4964 * needs to have priority, otherwise it will be evaluated last. 4965 */ 4966 buf[0].content.act_ctrl_fwd_priority = rm->priority; 4967 } else { 4968 struct ice_recp_grp_entry *last_chain_entry; 4969 u16 rid, i; 4970 4971 /* Allocate the last recipe that will chain the outcomes of the 4972 * other recipes together 4973 */ 4974 status = ice_alloc_recipe(hw, &rid); 4975 if (status) 4976 goto err_unroll; 4977 4978 buf[recps].recipe_indx = (u8)rid; 4979 buf[recps].content.rid = (u8)rid; 4980 buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT; 4981 /* the new entry created should also be part of rg_list to 4982 * make sure we have complete recipe 4983 */ 4984 last_chain_entry = (struct ice_recp_grp_entry *)ice_malloc(hw, 4985 sizeof(*last_chain_entry)); 4986 if (!last_chain_entry) { 4987 status = ICE_ERR_NO_MEMORY; 4988 goto err_unroll; 4989 } 4990 last_chain_entry->rid = rid; 4991 ice_memset(&buf[recps].content.lkup_indx, 0, 4992 sizeof(buf[recps].content.lkup_indx), 4993 ICE_NONDMA_MEM); 4994 /* All recipes use look-up index 0 to match switch ID. */ 4995 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX; 4996 buf[recps].content.mask[0] = 4997 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK); 4998 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) { 4999 buf[recps].content.lkup_indx[i] = 5000 ICE_AQ_RECIPE_LKUP_IGNORE; 5001 buf[recps].content.mask[i] = 0; 5002 } 5003 5004 i = 1; 5005 /* update r_bitmap with the recp that is used for chaining */ 5006 ice_set_bit(rid, rm->r_bitmap); 5007 /* this is the recipe that chains all the other recipes so it 5008 * should not have a chaining ID to indicate the same 5009 */ 5010 last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND; 5011 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, 5012 l_entry) { 5013 last_chain_entry->fv_idx[i] = entry->chain_idx; 5014 buf[recps].content.lkup_indx[i] = entry->chain_idx; 5015 buf[recps].content.mask[i++] = CPU_TO_LE16(0xFFFF); 5016 ice_set_bit(entry->rid, rm->r_bitmap); 5017 } 5018 LIST_ADD(&last_chain_entry->l_entry, &rm->rg_list); 5019 if (sizeof(buf[recps].recipe_bitmap) >= 5020 sizeof(rm->r_bitmap)) { 5021 ice_memcpy(buf[recps].recipe_bitmap, rm->r_bitmap, 5022 sizeof(buf[recps].recipe_bitmap), 5023 ICE_NONDMA_TO_NONDMA); 5024 } else { 5025 status = ICE_ERR_BAD_PTR; 5026 goto err_unroll; 5027 } 5028 buf[recps].content.act_ctrl_fwd_priority = rm->priority; 5029 5030 /* To differentiate among different UDP tunnels, a meta data ID 5031 * flag is used. 5032 */ 5033 if (match_tun) { 5034 buf[recps].content.lkup_indx[i] = ICE_TUN_FLAG_FV_IND; 5035 buf[recps].content.mask[i] = 5036 CPU_TO_LE16(ICE_TUN_FLAG_MASK); 5037 } 5038 5039 recps++; 5040 rm->root_rid = (u8)rid; 5041 } 5042 status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 5043 if (status) 5044 goto err_unroll; 5045 5046 status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL); 5047 ice_release_change_lock(hw); 5048 if (status) 5049 goto err_unroll; 5050 5051 /* Every recipe that just got created add it to the recipe 5052 * book keeping list 5053 */ 5054 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) { 5055 struct ice_switch_info *sw = hw->switch_info; 5056 struct ice_sw_recipe *recp; 5057 5058 recp = &sw->recp_list[entry->rid]; 5059 recp->root_rid = entry->rid; 5060 ice_memcpy(&recp->ext_words, entry->r_group.pairs, 5061 entry->r_group.n_val_pairs * 5062 sizeof(struct ice_fv_word), 5063 ICE_NONDMA_TO_NONDMA); 5064 5065 recp->n_ext_words = entry->r_group.n_val_pairs; 5066 recp->chain_idx = entry->chain_idx; 5067 recp->recp_created = true; 5068 recp->big_recp = false; 5069 } 5070 rm->root_buf = buf; 5071 ice_free(hw, tmp); 5072 return status; 5073 5074 err_unroll: 5075 err_mem: 5076 ice_free(hw, tmp); 5077 ice_free(hw, buf); 5078 return status; 5079 } 5080 5081 /** 5082 * ice_create_recipe_group - creates recipe group 5083 * @hw: pointer to hardware structure 5084 * @rm: recipe management list entry 5085 * @lkup_exts: lookup elements 5086 */ 5087 static enum ice_status 5088 ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm, 5089 struct ice_prot_lkup_ext *lkup_exts) 5090 { 5091 struct ice_recp_grp_entry *entry; 5092 struct ice_recp_grp_entry *tmp; 5093 enum ice_status status; 5094 u8 recp_count = 0; 5095 u16 groups, i; 5096 5097 rm->n_grp_count = 0; 5098 5099 /* Each switch recipe can match up to 5 words or metadata. One word in 5100 * each recipe is used to match the switch ID. Four words are left for 5101 * matching other values. If the new advanced recipe requires more than 5102 * 4 words, it needs to be split into multiple recipes which are chained 5103 * together using the intermediate result that each produces as input to 5104 * the other recipes in the sequence. 5105 */ 5106 groups = ARRAY_SIZE(ice_recipe_pack); 5107 5108 /* Check if any of the preferred recipes from the grouping policy 5109 * matches. 5110 */ 5111 for (i = 0; i < groups; i++) 5112 /* Check if the recipe from the preferred grouping matches 5113 * or is a subset of the fields that needs to be looked up. 5114 */ 5115 if (ice_is_recipe_subset(lkup_exts, &ice_recipe_pack[i])) { 5116 /* This recipe can be used by itself or grouped with 5117 * other recipes. 5118 */ 5119 entry = (struct ice_recp_grp_entry *) 5120 ice_malloc(hw, sizeof(*entry)); 5121 if (!entry) { 5122 status = ICE_ERR_NO_MEMORY; 5123 goto err_unroll; 5124 } 5125 entry->r_group = ice_recipe_pack[i]; 5126 LIST_ADD(&entry->l_entry, &rm->rg_list); 5127 rm->n_grp_count++; 5128 } 5129 5130 /* Create recipes for words that are marked not done by packing them 5131 * as best fit. 5132 */ 5133 status = ice_create_first_fit_recp_def(hw, lkup_exts, 5134 &rm->rg_list, &recp_count); 5135 if (!status) { 5136 rm->n_grp_count += recp_count; 5137 rm->n_ext_words = lkup_exts->n_val_words; 5138 ice_memcpy(&rm->ext_words, lkup_exts->fv_words, 5139 sizeof(rm->ext_words), ICE_NONDMA_TO_NONDMA); 5140 ice_memcpy(rm->word_masks, lkup_exts->field_mask, 5141 sizeof(rm->word_masks), ICE_NONDMA_TO_NONDMA); 5142 goto out; 5143 } 5144 5145 err_unroll: 5146 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, &rm->rg_list, ice_recp_grp_entry, 5147 l_entry) { 5148 LIST_DEL(&entry->l_entry); 5149 ice_free(hw, entry); 5150 } 5151 5152 out: 5153 return status; 5154 } 5155 5156 /** 5157 * ice_get_fv - get field vectors/extraction sequences for spec. lookup types 5158 * @hw: pointer to hardware structure 5159 * @lkups: lookup elements or match criteria for the advanced recipe, one 5160 * structure per protocol header 5161 * @lkups_cnt: number of protocols 5162 * @fv_list: pointer to a list that holds the returned field vectors 5163 */ 5164 static enum ice_status 5165 ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 5166 struct LIST_HEAD_TYPE *fv_list) 5167 { 5168 enum ice_status status; 5169 u16 *prot_ids; 5170 u16 i; 5171 5172 prot_ids = (u16 *)ice_calloc(hw, lkups_cnt, sizeof(*prot_ids)); 5173 if (!prot_ids) 5174 return ICE_ERR_NO_MEMORY; 5175 5176 for (i = 0; i < lkups_cnt; i++) 5177 if (!ice_prot_type_to_id(lkups[i].type, &prot_ids[i])) { 5178 status = ICE_ERR_CFG; 5179 goto free_mem; 5180 } 5181 5182 /* Find field vectors that include all specified protocol types */ 5183 status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, fv_list); 5184 5185 free_mem: 5186 ice_free(hw, prot_ids); 5187 return status; 5188 } 5189 5190 /** 5191 * ice_add_adv_recipe - Add an advanced recipe that is not part of the default 5192 * @hw: pointer to hardware structure 5193 * @lkups: lookup elements or match criteria for the advanced recipe, one 5194 * structure per protocol header 5195 * @lkups_cnt: number of protocols 5196 * @rinfo: other information regarding the rule e.g. priority and action info 5197 * @rid: return the recipe ID of the recipe created 5198 */ 5199 static enum ice_status 5200 ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 5201 u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid) 5202 { 5203 struct ice_prot_lkup_ext *lkup_exts; 5204 struct ice_recp_grp_entry *r_entry; 5205 struct ice_sw_fv_list_entry *fvit; 5206 struct ice_recp_grp_entry *r_tmp; 5207 struct ice_sw_fv_list_entry *tmp; 5208 enum ice_status status = ICE_SUCCESS; 5209 struct ice_sw_recipe *rm; 5210 bool match_tun = false; 5211 u8 i; 5212 5213 if (!lkups_cnt) 5214 return ICE_ERR_PARAM; 5215 5216 lkup_exts = (struct ice_prot_lkup_ext *) 5217 ice_malloc(hw, sizeof(*lkup_exts)); 5218 if (!lkup_exts) 5219 return ICE_ERR_NO_MEMORY; 5220 5221 /* Determine the number of words to be matched and if it exceeds a 5222 * recipe's restrictions 5223 */ 5224 for (i = 0; i < lkups_cnt; i++) { 5225 u16 count; 5226 5227 if (lkups[i].type >= ICE_PROTOCOL_LAST) { 5228 status = ICE_ERR_CFG; 5229 goto err_free_lkup_exts; 5230 } 5231 5232 count = ice_fill_valid_words(&lkups[i], lkup_exts); 5233 if (!count) { 5234 status = ICE_ERR_CFG; 5235 goto err_free_lkup_exts; 5236 } 5237 } 5238 5239 *rid = ice_find_recp(hw, lkup_exts); 5240 if (*rid < ICE_MAX_NUM_RECIPES) 5241 /* Success if found a recipe that match the existing criteria */ 5242 goto err_free_lkup_exts; 5243 5244 /* Recipe we need does not exist, add a recipe */ 5245 5246 rm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm)); 5247 if (!rm) { 5248 status = ICE_ERR_NO_MEMORY; 5249 goto err_free_lkup_exts; 5250 } 5251 5252 /* Get field vectors that contain fields extracted from all the protocol 5253 * headers being programmed. 5254 */ 5255 INIT_LIST_HEAD(&rm->fv_list); 5256 INIT_LIST_HEAD(&rm->rg_list); 5257 5258 status = ice_get_fv(hw, lkups, lkups_cnt, &rm->fv_list); 5259 if (status) 5260 goto err_unroll; 5261 5262 /* Group match words into recipes using preferred recipe grouping 5263 * criteria. 5264 */ 5265 status = ice_create_recipe_group(hw, rm, lkup_exts); 5266 if (status) 5267 goto err_unroll; 5268 5269 /* There is only profile for UDP tunnels. So, it is necessary to use a 5270 * metadata ID flag to differentiate different tunnel types. A separate 5271 * recipe needs to be used for the metadata. 5272 */ 5273 if ((rinfo->tun_type == ICE_SW_TUN_VXLAN_GPE || 5274 rinfo->tun_type == ICE_SW_TUN_GENEVE || 5275 rinfo->tun_type == ICE_SW_TUN_VXLAN) && rm->n_grp_count > 1) 5276 match_tun = true; 5277 5278 /* set the recipe priority if specified */ 5279 rm->priority = rinfo->priority ? rinfo->priority : 0; 5280 5281 /* Find offsets from the field vector. Pick the first one for all the 5282 * recipes. 5283 */ 5284 ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list); 5285 status = ice_add_sw_recipe(hw, rm, match_tun); 5286 if (status) 5287 goto err_unroll; 5288 5289 /* Associate all the recipes created with all the profiles in the 5290 * common field vector. 5291 */ 5292 LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry, 5293 list_entry) { 5294 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES); 5295 5296 status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id, 5297 (u8 *)r_bitmap, NULL); 5298 if (status) 5299 goto err_unroll; 5300 5301 ice_or_bitmap(rm->r_bitmap, r_bitmap, rm->r_bitmap, 5302 ICE_MAX_NUM_RECIPES); 5303 status = ice_acquire_change_lock(hw, ICE_RES_WRITE); 5304 if (status) 5305 goto err_unroll; 5306 5307 status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id, 5308 (u8 *)rm->r_bitmap, 5309 NULL); 5310 ice_release_change_lock(hw); 5311 5312 if (status) 5313 goto err_unroll; 5314 } 5315 5316 *rid = rm->root_rid; 5317 ice_memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, 5318 lkup_exts, sizeof(*lkup_exts), ICE_NONDMA_TO_NONDMA); 5319 err_unroll: 5320 LIST_FOR_EACH_ENTRY_SAFE(r_entry, r_tmp, &rm->rg_list, 5321 ice_recp_grp_entry, l_entry) { 5322 LIST_DEL(&r_entry->l_entry); 5323 ice_free(hw, r_entry); 5324 } 5325 5326 LIST_FOR_EACH_ENTRY_SAFE(fvit, tmp, &rm->fv_list, ice_sw_fv_list_entry, 5327 list_entry) { 5328 LIST_DEL(&fvit->list_entry); 5329 ice_free(hw, fvit); 5330 } 5331 5332 if (rm->root_buf) 5333 ice_free(hw, rm->root_buf); 5334 5335 ice_free(hw, rm); 5336 5337 err_free_lkup_exts: 5338 ice_free(hw, lkup_exts); 5339 5340 return status; 5341 } 5342 5343 /** 5344 * ice_find_dummy_packet - find dummy packet by tunnel type 5345 * 5346 * @lkups: lookup elements or match criteria for the advanced recipe, one 5347 * structure per protocol header 5348 * @lkups_cnt: number of protocols 5349 * @tun_type: tunnel type from the match criteria 5350 * @pkt: dummy packet to fill according to filter match criteria 5351 * @pkt_len: packet length of dummy packet 5352 * @offsets: pointer to receive the pointer to the offsets for the packet 5353 */ 5354 static void 5355 ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 5356 enum ice_sw_tunnel_type tun_type, const u8 **pkt, 5357 u16 *pkt_len, 5358 const struct ice_dummy_pkt_offsets **offsets) 5359 { 5360 bool tcp = false, udp = false, ipv6 = false; 5361 u16 i; 5362 5363 for (i = 0; i < lkups_cnt; i++) { 5364 if (lkups[i].type == ICE_UDP_ILOS) 5365 udp = true; 5366 else if (lkups[i].type == ICE_TCP_IL) 5367 tcp = true; 5368 else if (lkups[i].type == ICE_IPV6_OFOS) 5369 ipv6 = true; 5370 } 5371 5372 if (tun_type == ICE_SW_TUN_NVGRE || tun_type == ICE_ALL_TUNNELS) { 5373 *pkt = dummy_gre_packet; 5374 *pkt_len = sizeof(dummy_gre_packet); 5375 *offsets = dummy_gre_packet_offsets; 5376 return; 5377 } 5378 5379 if (tun_type == ICE_SW_TUN_VXLAN || tun_type == ICE_SW_TUN_GENEVE || 5380 tun_type == ICE_SW_TUN_VXLAN_GPE || tun_type == ICE_SW_TUN_UDP) { 5381 if (tcp) { 5382 *pkt = dummy_udp_tun_tcp_packet; 5383 *pkt_len = sizeof(dummy_udp_tun_tcp_packet); 5384 *offsets = dummy_udp_tun_tcp_packet_offsets; 5385 return; 5386 } 5387 5388 *pkt = dummy_udp_tun_udp_packet; 5389 *pkt_len = sizeof(dummy_udp_tun_udp_packet); 5390 *offsets = dummy_udp_tun_udp_packet_offsets; 5391 return; 5392 } 5393 5394 if (udp && !ipv6) { 5395 *pkt = dummy_udp_packet; 5396 *pkt_len = sizeof(dummy_udp_packet); 5397 *offsets = dummy_udp_packet_offsets; 5398 return; 5399 } else if (udp && ipv6) { 5400 *pkt = dummy_udp_ipv6_packet; 5401 *pkt_len = sizeof(dummy_udp_ipv6_packet); 5402 *offsets = dummy_udp_ipv6_packet_offsets; 5403 return; 5404 } else if ((tcp && ipv6) || ipv6) { 5405 *pkt = dummy_tcp_ipv6_packet; 5406 *pkt_len = sizeof(dummy_tcp_ipv6_packet); 5407 *offsets = dummy_tcp_ipv6_packet_offsets; 5408 return; 5409 } 5410 5411 *pkt = dummy_tcp_packet; 5412 *pkt_len = sizeof(dummy_tcp_packet); 5413 *offsets = dummy_tcp_packet_offsets; 5414 } 5415 5416 /** 5417 * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria 5418 * 5419 * @lkups: lookup elements or match criteria for the advanced recipe, one 5420 * structure per protocol header 5421 * @lkups_cnt: number of protocols 5422 * @s_rule: stores rule information from the match criteria 5423 * @dummy_pkt: dummy packet to fill according to filter match criteria 5424 * @pkt_len: packet length of dummy packet 5425 * @offsets: offset info for the dummy packet 5426 */ 5427 static enum ice_status 5428 ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, 5429 struct ice_aqc_sw_rules_elem *s_rule, 5430 const u8 *dummy_pkt, u16 pkt_len, 5431 const struct ice_dummy_pkt_offsets *offsets) 5432 { 5433 u8 *pkt; 5434 u16 i; 5435 5436 /* Start with a packet with a pre-defined/dummy content. Then, fill 5437 * in the header values to be looked up or matched. 5438 */ 5439 pkt = s_rule->pdata.lkup_tx_rx.hdr; 5440 5441 ice_memcpy(pkt, dummy_pkt, pkt_len, ICE_NONDMA_TO_NONDMA); 5442 5443 for (i = 0; i < lkups_cnt; i++) { 5444 enum ice_protocol_type type; 5445 u16 offset = 0, len = 0, j; 5446 bool found = false; 5447 5448 /* find the start of this layer; it should be found since this 5449 * was already checked when search for the dummy packet 5450 */ 5451 type = lkups[i].type; 5452 for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) { 5453 if (type == offsets[j].type) { 5454 offset = offsets[j].offset; 5455 found = true; 5456 break; 5457 } 5458 } 5459 /* this should never happen in a correct calling sequence */ 5460 if (!found) 5461 return ICE_ERR_PARAM; 5462 5463 switch (lkups[i].type) { 5464 case ICE_MAC_OFOS: 5465 case ICE_MAC_IL: 5466 len = sizeof(struct ice_ether_hdr); 5467 break; 5468 case ICE_ETYPE_OL: 5469 len = sizeof(struct ice_ethtype_hdr); 5470 break; 5471 case ICE_IPV4_OFOS: 5472 case ICE_IPV4_IL: 5473 len = sizeof(struct ice_ipv4_hdr); 5474 break; 5475 case ICE_IPV6_OFOS: 5476 case ICE_IPV6_IL: 5477 len = sizeof(struct ice_ipv6_hdr); 5478 break; 5479 case ICE_TCP_IL: 5480 case ICE_UDP_OF: 5481 case ICE_UDP_ILOS: 5482 len = sizeof(struct ice_l4_hdr); 5483 break; 5484 case ICE_SCTP_IL: 5485 len = sizeof(struct ice_sctp_hdr); 5486 break; 5487 case ICE_NVGRE: 5488 len = sizeof(struct ice_nvgre); 5489 break; 5490 case ICE_VXLAN: 5491 case ICE_GENEVE: 5492 case ICE_VXLAN_GPE: 5493 len = sizeof(struct ice_udp_tnl_hdr); 5494 break; 5495 default: 5496 return ICE_ERR_PARAM; 5497 } 5498 5499 /* the length should be a word multiple */ 5500 if (len % ICE_BYTES_PER_WORD) 5501 return ICE_ERR_CFG; 5502 5503 /* We have the offset to the header start, the length, the 5504 * caller's header values and mask. Use this information to 5505 * copy the data into the dummy packet appropriately based on 5506 * the mask. Note that we need to only write the bits as 5507 * indicated by the mask to make sure we don't improperly write 5508 * over any significant packet data. 5509 */ 5510 for (j = 0; j < len / sizeof(u16); j++) 5511 if (((u16 *)&lkups[i].m_u)[j]) 5512 ((u16 *)(pkt + offset))[j] = 5513 (((u16 *)(pkt + offset))[j] & 5514 ~((u16 *)&lkups[i].m_u)[j]) | 5515 (((u16 *)&lkups[i].h_u)[j] & 5516 ((u16 *)&lkups[i].m_u)[j]); 5517 } 5518 5519 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(pkt_len); 5520 5521 return ICE_SUCCESS; 5522 } 5523 5524 /** 5525 * ice_find_adv_rule_entry - Search a rule entry 5526 * @hw: pointer to the hardware structure 5527 * @lkups: lookup elements or match criteria for the advanced recipe, one 5528 * structure per protocol header 5529 * @lkups_cnt: number of protocols 5530 * @recp_id: recipe ID for which we are finding the rule 5531 * @rinfo: other information regarding the rule e.g. priority and action info 5532 * 5533 * Helper function to search for a given advance rule entry 5534 * Returns pointer to entry storing the rule if found 5535 */ 5536 static struct ice_adv_fltr_mgmt_list_entry * 5537 ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 5538 u16 lkups_cnt, u8 recp_id, 5539 struct ice_adv_rule_info *rinfo) 5540 { 5541 struct ice_adv_fltr_mgmt_list_entry *list_itr; 5542 struct ice_switch_info *sw = hw->switch_info; 5543 int i; 5544 5545 LIST_FOR_EACH_ENTRY(list_itr, &sw->recp_list[recp_id].filt_rules, 5546 ice_adv_fltr_mgmt_list_entry, list_entry) { 5547 bool lkups_matched = true; 5548 5549 if (lkups_cnt != list_itr->lkups_cnt) 5550 continue; 5551 for (i = 0; i < list_itr->lkups_cnt; i++) 5552 if (memcmp(&list_itr->lkups[i], &lkups[i], 5553 sizeof(*lkups))) { 5554 lkups_matched = false; 5555 break; 5556 } 5557 if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag && 5558 rinfo->tun_type == list_itr->rule_info.tun_type && 5559 lkups_matched) 5560 return list_itr; 5561 } 5562 return NULL; 5563 } 5564 5565 /** 5566 * ice_adv_add_update_vsi_list 5567 * @hw: pointer to the hardware structure 5568 * @m_entry: pointer to current adv filter management list entry 5569 * @cur_fltr: filter information from the book keeping entry 5570 * @new_fltr: filter information with the new VSI to be added 5571 * 5572 * Call AQ command to add or update previously created VSI list with new VSI. 5573 * 5574 * Helper function to do book keeping associated with adding filter information 5575 * The algorithm to do the booking keeping is described below : 5576 * When a VSI needs to subscribe to a given advanced filter 5577 * if only one VSI has been added till now 5578 * Allocate a new VSI list and add two VSIs 5579 * to this list using switch rule command 5580 * Update the previously created switch rule with the 5581 * newly created VSI list ID 5582 * if a VSI list was previously created 5583 * Add the new VSI to the previously created VSI list set 5584 * using the update switch rule command 5585 */ 5586 static enum ice_status 5587 ice_adv_add_update_vsi_list(struct ice_hw *hw, 5588 struct ice_adv_fltr_mgmt_list_entry *m_entry, 5589 struct ice_adv_rule_info *cur_fltr, 5590 struct ice_adv_rule_info *new_fltr) 5591 { 5592 enum ice_status status; 5593 u16 vsi_list_id = 0; 5594 5595 if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 5596 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) 5597 return ICE_ERR_NOT_IMPL; 5598 5599 if (cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET && 5600 new_fltr->sw_act.fltr_act == ICE_DROP_PACKET) 5601 return ICE_ERR_ALREADY_EXISTS; 5602 5603 if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q || 5604 new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) && 5605 (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI || 5606 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)) 5607 return ICE_ERR_NOT_IMPL; 5608 5609 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 5610 /* Only one entry existed in the mapping and it was not already 5611 * a part of a VSI list. So, create a VSI list with the old and 5612 * new VSIs. 5613 */ 5614 struct ice_fltr_info tmp_fltr; 5615 u16 vsi_handle_arr[2]; 5616 5617 /* A rule already exists with the new VSI being added */ 5618 if (cur_fltr->sw_act.fwd_id.hw_vsi_id == 5619 new_fltr->sw_act.fwd_id.hw_vsi_id) 5620 return ICE_ERR_ALREADY_EXISTS; 5621 5622 vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle; 5623 vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle; 5624 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 5625 &vsi_list_id, 5626 ICE_SW_LKUP_LAST); 5627 if (status) 5628 return status; 5629 5630 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 5631 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 5632 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 5633 /* Update the previous switch rule of "forward to VSI" to 5634 * "fwd to VSI list" 5635 */ 5636 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 5637 if (status) 5638 return status; 5639 5640 cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id; 5641 cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST; 5642 m_entry->vsi_list_info = 5643 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 5644 vsi_list_id); 5645 } else { 5646 u16 vsi_handle = new_fltr->sw_act.vsi_handle; 5647 5648 if (!m_entry->vsi_list_info) 5649 return ICE_ERR_CFG; 5650 5651 /* A rule already exists with the new VSI being added */ 5652 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 5653 return ICE_SUCCESS; 5654 5655 /* Update the previously created VSI list set with 5656 * the new VSI ID passed in 5657 */ 5658 vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id; 5659 5660 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 5661 vsi_list_id, false, 5662 ice_aqc_opc_update_sw_rules, 5663 ICE_SW_LKUP_LAST); 5664 /* update VSI list mapping info with new VSI ID */ 5665 if (!status) 5666 ice_set_bit(vsi_handle, 5667 m_entry->vsi_list_info->vsi_map); 5668 } 5669 if (!status) 5670 m_entry->vsi_count++; 5671 return status; 5672 } 5673 5674 /** 5675 * ice_add_adv_rule - helper function to create an advanced switch rule 5676 * @hw: pointer to the hardware structure 5677 * @lkups: information on the words that needs to be looked up. All words 5678 * together makes one recipe 5679 * @lkups_cnt: num of entries in the lkups array 5680 * @rinfo: other information related to the rule that needs to be programmed 5681 * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be 5682 * ignored is case of error. 5683 * 5684 * This function can program only 1 rule at a time. The lkups is used to 5685 * describe the all the words that forms the "lookup" portion of the recipe. 5686 * These words can span multiple protocols. Callers to this function need to 5687 * pass in a list of protocol headers with lookup information along and mask 5688 * that determines which words are valid from the given protocol header. 5689 * rinfo describes other information related to this rule such as forwarding 5690 * IDs, priority of this rule, etc. 5691 */ 5692 enum ice_status 5693 ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 5694 u16 lkups_cnt, struct ice_adv_rule_info *rinfo, 5695 struct ice_rule_query_data *added_entry) 5696 { 5697 struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL; 5698 u16 rid = 0, i, pkt_len, rule_buf_sz, vsi_handle; 5699 const struct ice_dummy_pkt_offsets *pkt_offsets; 5700 struct ice_aqc_sw_rules_elem *s_rule = NULL; 5701 struct LIST_HEAD_TYPE *rule_head; 5702 struct ice_switch_info *sw; 5703 enum ice_status status; 5704 const u8 *pkt = NULL; 5705 bool found = false; 5706 u32 act = 0; 5707 u8 q_rgn; 5708 5709 if (!lkups_cnt) 5710 return ICE_ERR_PARAM; 5711 5712 for (i = 0; i < lkups_cnt; i++) { 5713 u16 j, *ptr; 5714 5715 /* Validate match masks to make sure that there is something 5716 * to match. 5717 */ 5718 ptr = (u16 *)&lkups[i].m_u; 5719 for (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++) 5720 if (ptr[j] != 0) { 5721 found = true; 5722 break; 5723 } 5724 } 5725 if (!found) 5726 return ICE_ERR_PARAM; 5727 5728 /* make sure that we can locate a dummy packet */ 5729 ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, &pkt_len, 5730 &pkt_offsets); 5731 if (!pkt) { 5732 status = ICE_ERR_PARAM; 5733 goto err_ice_add_adv_rule; 5734 } 5735 5736 if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI || 5737 rinfo->sw_act.fltr_act == ICE_FWD_TO_Q || 5738 rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP || 5739 rinfo->sw_act.fltr_act == ICE_DROP_PACKET)) 5740 return ICE_ERR_CFG; 5741 5742 vsi_handle = rinfo->sw_act.vsi_handle; 5743 if (!ice_is_vsi_valid(hw, vsi_handle)) 5744 return ICE_ERR_PARAM; 5745 5746 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) 5747 rinfo->sw_act.fwd_id.hw_vsi_id = 5748 ice_get_hw_vsi_num(hw, vsi_handle); 5749 if (rinfo->sw_act.flag & ICE_FLTR_TX) 5750 rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle); 5751 5752 status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid); 5753 if (status) 5754 return status; 5755 m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 5756 if (m_entry) { 5757 /* we have to add VSI to VSI_LIST and increment vsi_count. 5758 * Also Update VSI list so that we can change forwarding rule 5759 * if the rule already exists, we will check if it exists with 5760 * same vsi_id, if not then add it to the VSI list if it already 5761 * exists if not then create a VSI list and add the existing VSI 5762 * ID and the new VSI ID to the list 5763 * We will add that VSI to the list 5764 */ 5765 status = ice_adv_add_update_vsi_list(hw, m_entry, 5766 &m_entry->rule_info, 5767 rinfo); 5768 if (added_entry) { 5769 added_entry->rid = rid; 5770 added_entry->rule_id = m_entry->rule_info.fltr_rule_id; 5771 added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 5772 } 5773 return status; 5774 } 5775 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len; 5776 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rule_buf_sz); 5777 if (!s_rule) 5778 return ICE_ERR_NO_MEMORY; 5779 act |= ICE_SINGLE_ACT_LB_ENABLE | ICE_SINGLE_ACT_LAN_ENABLE; 5780 switch (rinfo->sw_act.fltr_act) { 5781 case ICE_FWD_TO_VSI: 5782 act |= (rinfo->sw_act.fwd_id.hw_vsi_id << 5783 ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M; 5784 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT; 5785 break; 5786 case ICE_FWD_TO_Q: 5787 act |= ICE_SINGLE_ACT_TO_Q; 5788 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 5789 ICE_SINGLE_ACT_Q_INDEX_M; 5790 break; 5791 case ICE_FWD_TO_QGRP: 5792 q_rgn = rinfo->sw_act.qgrp_size > 0 ? 5793 (u8)ice_ilog2(rinfo->sw_act.qgrp_size) : 0; 5794 act |= ICE_SINGLE_ACT_TO_Q; 5795 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 5796 ICE_SINGLE_ACT_Q_INDEX_M; 5797 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 5798 ICE_SINGLE_ACT_Q_REGION_M; 5799 break; 5800 case ICE_DROP_PACKET: 5801 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 5802 ICE_SINGLE_ACT_VALID_BIT; 5803 break; 5804 default: 5805 status = ICE_ERR_CFG; 5806 goto err_ice_add_adv_rule; 5807 } 5808 5809 /* set the rule LOOKUP type based on caller specified 'RX' 5810 * instead of hardcoding it to be either LOOKUP_TX/RX 5811 * 5812 * for 'RX' set the source to be the port number 5813 * for 'TX' set the source to be the source HW VSI number (determined 5814 * by caller) 5815 */ 5816 if (rinfo->rx) { 5817 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX); 5818 s_rule->pdata.lkup_tx_rx.src = 5819 CPU_TO_LE16(hw->port_info->lport); 5820 } else { 5821 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX); 5822 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(rinfo->sw_act.src); 5823 } 5824 5825 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(rid); 5826 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act); 5827 5828 ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, pkt, pkt_len, 5829 pkt_offsets); 5830 5831 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 5832 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules, 5833 NULL); 5834 if (status) 5835 goto err_ice_add_adv_rule; 5836 adv_fltr = (struct ice_adv_fltr_mgmt_list_entry *) 5837 ice_malloc(hw, sizeof(struct ice_adv_fltr_mgmt_list_entry)); 5838 if (!adv_fltr) { 5839 status = ICE_ERR_NO_MEMORY; 5840 goto err_ice_add_adv_rule; 5841 } 5842 5843 adv_fltr->lkups = (struct ice_adv_lkup_elem *) 5844 ice_memdup(hw, lkups, lkups_cnt * sizeof(*lkups), 5845 ICE_NONDMA_TO_NONDMA); 5846 if (!adv_fltr->lkups) { 5847 status = ICE_ERR_NO_MEMORY; 5848 goto err_ice_add_adv_rule; 5849 } 5850 5851 adv_fltr->lkups_cnt = lkups_cnt; 5852 adv_fltr->rule_info = *rinfo; 5853 adv_fltr->rule_info.fltr_rule_id = 5854 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 5855 sw = hw->switch_info; 5856 sw->recp_list[rid].adv_rule = true; 5857 rule_head = &sw->recp_list[rid].filt_rules; 5858 5859 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) { 5860 struct ice_fltr_info tmp_fltr; 5861 5862 tmp_fltr.fltr_rule_id = 5863 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index); 5864 tmp_fltr.fltr_act = ICE_FWD_TO_VSI; 5865 tmp_fltr.fwd_id.hw_vsi_id = 5866 ice_get_hw_vsi_num(hw, vsi_handle); 5867 tmp_fltr.vsi_handle = vsi_handle; 5868 /* Update the previous switch rule of "forward to VSI" to 5869 * "fwd to VSI list" 5870 */ 5871 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 5872 if (status) 5873 goto err_ice_add_adv_rule; 5874 adv_fltr->vsi_count = 1; 5875 } 5876 5877 /* Add rule entry to book keeping list */ 5878 LIST_ADD(&adv_fltr->list_entry, rule_head); 5879 if (added_entry) { 5880 added_entry->rid = rid; 5881 added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id; 5882 added_entry->vsi_handle = rinfo->sw_act.vsi_handle; 5883 } 5884 err_ice_add_adv_rule: 5885 if (status && adv_fltr) { 5886 ice_free(hw, adv_fltr->lkups); 5887 ice_free(hw, adv_fltr); 5888 } 5889 5890 ice_free(hw, s_rule); 5891 5892 return status; 5893 } 5894 5895 /** 5896 * ice_adv_rem_update_vsi_list 5897 * @hw: pointer to the hardware structure 5898 * @vsi_handle: VSI handle of the VSI to remove 5899 * @fm_list: filter management entry for which the VSI list management needs to 5900 * be done 5901 */ 5902 static enum ice_status 5903 ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 5904 struct ice_adv_fltr_mgmt_list_entry *fm_list) 5905 { 5906 struct ice_vsi_list_map_info *vsi_list_info; 5907 enum ice_sw_lkup_type lkup_type; 5908 enum ice_status status; 5909 u16 vsi_list_id; 5910 5911 if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST || 5912 fm_list->vsi_count == 0) 5913 return ICE_ERR_PARAM; 5914 5915 /* A rule with the VSI being removed does not exist */ 5916 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 5917 return ICE_ERR_DOES_NOT_EXIST; 5918 5919 lkup_type = ICE_SW_LKUP_LAST; 5920 vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id; 5921 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 5922 ice_aqc_opc_update_sw_rules, 5923 lkup_type); 5924 if (status) 5925 return status; 5926 5927 fm_list->vsi_count--; 5928 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 5929 vsi_list_info = fm_list->vsi_list_info; 5930 if (fm_list->vsi_count == 1) { 5931 struct ice_fltr_info tmp_fltr; 5932 u16 rem_vsi_handle; 5933 5934 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 5935 ICE_MAX_VSI); 5936 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 5937 return ICE_ERR_OUT_OF_RANGE; 5938 5939 /* Make sure VSI list is empty before removing it below */ 5940 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 5941 vsi_list_id, true, 5942 ice_aqc_opc_update_sw_rules, 5943 lkup_type); 5944 if (status) 5945 return status; 5946 tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id; 5947 fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI; 5948 tmp_fltr.fltr_act = ICE_FWD_TO_VSI; 5949 tmp_fltr.fwd_id.hw_vsi_id = 5950 ice_get_hw_vsi_num(hw, rem_vsi_handle); 5951 fm_list->rule_info.sw_act.fwd_id.hw_vsi_id = 5952 ice_get_hw_vsi_num(hw, rem_vsi_handle); 5953 5954 /* Update the previous switch rule of "MAC forward to VSI" to 5955 * "MAC fwd to VSI list" 5956 */ 5957 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 5958 if (status) { 5959 ice_debug(hw, ICE_DBG_SW, 5960 "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 5961 tmp_fltr.fwd_id.hw_vsi_id, status); 5962 return status; 5963 } 5964 } 5965 5966 if (fm_list->vsi_count == 1) { 5967 /* Remove the VSI list since it is no longer used */ 5968 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 5969 if (status) { 5970 ice_debug(hw, ICE_DBG_SW, 5971 "Failed to remove VSI list %d, error %d\n", 5972 vsi_list_id, status); 5973 return status; 5974 } 5975 5976 LIST_DEL(&vsi_list_info->list_entry); 5977 ice_free(hw, vsi_list_info); 5978 fm_list->vsi_list_info = NULL; 5979 } 5980 5981 return status; 5982 } 5983 5984 /** 5985 * ice_rem_adv_rule - removes existing advanced switch rule 5986 * @hw: pointer to the hardware structure 5987 * @lkups: information on the words that needs to be looked up. All words 5988 * together makes one recipe 5989 * @lkups_cnt: num of entries in the lkups array 5990 * @rinfo: Its the pointer to the rule information for the rule 5991 * 5992 * This function can be used to remove 1 rule at a time. The lkups is 5993 * used to describe all the words that forms the "lookup" portion of the 5994 * rule. These words can span multiple protocols. Callers to this function 5995 * need to pass in a list of protocol headers with lookup information along 5996 * and mask that determines which words are valid from the given protocol 5997 * header. rinfo describes other information related to this rule such as 5998 * forwarding IDs, priority of this rule, etc. 5999 */ 6000 enum ice_status 6001 ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, 6002 u16 lkups_cnt, struct ice_adv_rule_info *rinfo) 6003 { 6004 struct ice_adv_fltr_mgmt_list_entry *list_elem; 6005 const struct ice_dummy_pkt_offsets *offsets; 6006 struct ice_prot_lkup_ext lkup_exts; 6007 u16 rule_buf_sz, pkt_len, i, rid; 6008 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 6009 enum ice_status status = ICE_SUCCESS; 6010 bool remove_rule = false; 6011 const u8 *pkt = NULL; 6012 u16 vsi_handle; 6013 6014 ice_memset(&lkup_exts, 0, sizeof(lkup_exts), ICE_NONDMA_MEM); 6015 for (i = 0; i < lkups_cnt; i++) { 6016 u16 count; 6017 6018 if (lkups[i].type >= ICE_PROTOCOL_LAST) 6019 return ICE_ERR_CFG; 6020 6021 count = ice_fill_valid_words(&lkups[i], &lkup_exts); 6022 if (!count) 6023 return ICE_ERR_CFG; 6024 } 6025 rid = ice_find_recp(hw, &lkup_exts); 6026 /* If did not find a recipe that match the existing criteria */ 6027 if (rid == ICE_MAX_NUM_RECIPES) 6028 return ICE_ERR_PARAM; 6029 6030 rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock; 6031 list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo); 6032 /* the rule is already removed */ 6033 if (!list_elem) 6034 return ICE_SUCCESS; 6035 ice_acquire_lock(rule_lock); 6036 if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) { 6037 remove_rule = true; 6038 } else if (list_elem->vsi_count > 1) { 6039 list_elem->vsi_list_info->ref_cnt--; 6040 remove_rule = false; 6041 vsi_handle = rinfo->sw_act.vsi_handle; 6042 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 6043 } else { 6044 vsi_handle = rinfo->sw_act.vsi_handle; 6045 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem); 6046 if (status) { 6047 ice_release_lock(rule_lock); 6048 return status; 6049 } 6050 if (list_elem->vsi_count == 0) 6051 remove_rule = true; 6052 } 6053 ice_release_lock(rule_lock); 6054 if (remove_rule) { 6055 struct ice_aqc_sw_rules_elem *s_rule; 6056 6057 ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, 6058 &pkt_len, &offsets); 6059 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len; 6060 s_rule = 6061 (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, 6062 rule_buf_sz); 6063 if (!s_rule) 6064 return ICE_ERR_NO_MEMORY; 6065 s_rule->pdata.lkup_tx_rx.act = 0; 6066 s_rule->pdata.lkup_tx_rx.index = 6067 CPU_TO_LE16(list_elem->rule_info.fltr_rule_id); 6068 s_rule->pdata.lkup_tx_rx.hdr_len = 0; 6069 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, 6070 rule_buf_sz, 1, 6071 ice_aqc_opc_remove_sw_rules, NULL); 6072 if (status == ICE_SUCCESS) { 6073 ice_acquire_lock(rule_lock); 6074 LIST_DEL(&list_elem->list_entry); 6075 ice_free(hw, list_elem->lkups); 6076 ice_free(hw, list_elem); 6077 ice_release_lock(rule_lock); 6078 } 6079 ice_free(hw, s_rule); 6080 } 6081 return status; 6082 } 6083 6084 /** 6085 * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID 6086 * @hw: pointer to the hardware structure 6087 * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID 6088 * 6089 * This function is used to remove 1 rule at a time. The removal is based on 6090 * the remove_entry parameter. This function will remove rule for a given 6091 * vsi_handle with a given rule_id which is passed as parameter in remove_entry 6092 */ 6093 enum ice_status 6094 ice_rem_adv_rule_by_id(struct ice_hw *hw, 6095 struct ice_rule_query_data *remove_entry) 6096 { 6097 struct ice_adv_fltr_mgmt_list_entry *list_itr; 6098 struct LIST_HEAD_TYPE *list_head; 6099 struct ice_adv_rule_info rinfo; 6100 struct ice_switch_info *sw; 6101 6102 sw = hw->switch_info; 6103 if (!sw->recp_list[remove_entry->rid].recp_created) 6104 return ICE_ERR_PARAM; 6105 list_head = &sw->recp_list[remove_entry->rid].filt_rules; 6106 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry, 6107 list_entry) { 6108 if (list_itr->rule_info.fltr_rule_id == 6109 remove_entry->rule_id) { 6110 rinfo = list_itr->rule_info; 6111 rinfo.sw_act.vsi_handle = remove_entry->vsi_handle; 6112 return ice_rem_adv_rule(hw, list_itr->lkups, 6113 list_itr->lkups_cnt, &rinfo); 6114 } 6115 } 6116 return ICE_ERR_PARAM; 6117 } 6118 6119 /** 6120 * ice_rem_adv_for_vsi - removes existing advanced switch rules for a 6121 * given VSI handle 6122 * @hw: pointer to the hardware structure 6123 * @vsi_handle: VSI handle for which we are supposed to remove all the rules. 6124 * 6125 * This function is used to remove all the rules for a given VSI and as soon 6126 * as removing a rule fails, it will return immediately with the error code, 6127 * else it will return ICE_SUCCESS 6128 */ 6129 enum ice_status 6130 ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle) 6131 { 6132 struct ice_adv_fltr_mgmt_list_entry *list_itr; 6133 struct ice_vsi_list_map_info *map_info; 6134 struct LIST_HEAD_TYPE *list_head; 6135 struct ice_adv_rule_info rinfo; 6136 struct ice_switch_info *sw; 6137 enum ice_status status; 6138 u16 vsi_list_id = 0; 6139 u8 rid; 6140 6141 sw = hw->switch_info; 6142 for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) { 6143 if (!sw->recp_list[rid].recp_created) 6144 continue; 6145 if (!sw->recp_list[rid].adv_rule) 6146 continue; 6147 list_head = &sw->recp_list[rid].filt_rules; 6148 map_info = NULL; 6149 LIST_FOR_EACH_ENTRY(list_itr, list_head, 6150 ice_adv_fltr_mgmt_list_entry, list_entry) { 6151 map_info = ice_find_vsi_list_entry(hw, rid, vsi_handle, 6152 &vsi_list_id); 6153 if (!map_info) 6154 continue; 6155 rinfo = list_itr->rule_info; 6156 rinfo.sw_act.vsi_handle = vsi_handle; 6157 status = ice_rem_adv_rule(hw, list_itr->lkups, 6158 list_itr->lkups_cnt, &rinfo); 6159 if (status) 6160 return status; 6161 map_info = NULL; 6162 } 6163 } 6164 return ICE_SUCCESS; 6165 } 6166 6167 /** 6168 * ice_replay_fltr - Replay all the filters stored by a specific list head 6169 * @hw: pointer to the hardware structure 6170 * @list_head: list for which filters needs to be replayed 6171 * @recp_id: Recipe ID for which rules need to be replayed 6172 */ 6173 static enum ice_status 6174 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head) 6175 { 6176 struct ice_fltr_mgmt_list_entry *itr; 6177 struct LIST_HEAD_TYPE l_head; 6178 enum ice_status status = ICE_SUCCESS; 6179 6180 if (LIST_EMPTY(list_head)) 6181 return status; 6182 6183 /* Move entries from the given list_head to a temporary l_head so that 6184 * they can be replayed. Otherwise when trying to re-add the same 6185 * filter, the function will return already exists 6186 */ 6187 LIST_REPLACE_INIT(list_head, &l_head); 6188 6189 /* Mark the given list_head empty by reinitializing it so filters 6190 * could be added again by *handler 6191 */ 6192 LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry, 6193 list_entry) { 6194 struct ice_fltr_list_entry f_entry; 6195 6196 f_entry.fltr_info = itr->fltr_info; 6197 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) { 6198 status = ice_add_rule_internal(hw, recp_id, &f_entry); 6199 if (status != ICE_SUCCESS) 6200 goto end; 6201 continue; 6202 } 6203 6204 /* Add a filter per VSI separately */ 6205 while (1) { 6206 u16 vsi_handle; 6207 6208 vsi_handle = 6209 ice_find_first_bit(itr->vsi_list_info->vsi_map, 6210 ICE_MAX_VSI); 6211 if (!ice_is_vsi_valid(hw, vsi_handle)) 6212 break; 6213 6214 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 6215 f_entry.fltr_info.vsi_handle = vsi_handle; 6216 f_entry.fltr_info.fwd_id.hw_vsi_id = 6217 ice_get_hw_vsi_num(hw, vsi_handle); 6218 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 6219 if (recp_id == ICE_SW_LKUP_VLAN) 6220 status = ice_add_vlan_internal(hw, &f_entry); 6221 else 6222 status = ice_add_rule_internal(hw, recp_id, 6223 &f_entry); 6224 if (status != ICE_SUCCESS) 6225 goto end; 6226 } 6227 } 6228 end: 6229 /* Clear the filter management list */ 6230 ice_rem_sw_rule_info(hw, &l_head); 6231 return status; 6232 } 6233 6234 /** 6235 * ice_replay_all_fltr - replay all filters stored in bookkeeping lists 6236 * @hw: pointer to the hardware structure 6237 * 6238 * NOTE: This function does not clean up partially added filters on error. 6239 * It is up to caller of the function to issue a reset or fail early. 6240 */ 6241 enum ice_status ice_replay_all_fltr(struct ice_hw *hw) 6242 { 6243 struct ice_switch_info *sw = hw->switch_info; 6244 enum ice_status status = ICE_SUCCESS; 6245 u8 i; 6246 6247 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 6248 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules; 6249 6250 status = ice_replay_fltr(hw, i, head); 6251 if (status != ICE_SUCCESS) 6252 return status; 6253 } 6254 return status; 6255 } 6256 6257 /** 6258 * ice_replay_vsi_fltr - Replay filters for requested VSI 6259 * @hw: pointer to the hardware structure 6260 * @vsi_handle: driver VSI handle 6261 * @recp_id: Recipe ID for which rules need to be replayed 6262 * @list_head: list for which filters need to be replayed 6263 * 6264 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 6265 * It is required to pass valid VSI handle. 6266 */ 6267 static enum ice_status 6268 ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id, 6269 struct LIST_HEAD_TYPE *list_head) 6270 { 6271 struct ice_fltr_mgmt_list_entry *itr; 6272 enum ice_status status = ICE_SUCCESS; 6273 u16 hw_vsi_id; 6274 6275 if (LIST_EMPTY(list_head)) 6276 return status; 6277 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 6278 6279 LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry, 6280 list_entry) { 6281 struct ice_fltr_list_entry f_entry; 6282 6283 f_entry.fltr_info = itr->fltr_info; 6284 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 6285 itr->fltr_info.vsi_handle == vsi_handle) { 6286 /* update the src in case it is VSI num */ 6287 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 6288 f_entry.fltr_info.src = hw_vsi_id; 6289 status = ice_add_rule_internal(hw, recp_id, &f_entry); 6290 if (status != ICE_SUCCESS) 6291 goto end; 6292 continue; 6293 } 6294 if (!itr->vsi_list_info || 6295 !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle)) 6296 continue; 6297 /* Clearing it so that the logic can add it back */ 6298 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 6299 f_entry.fltr_info.vsi_handle = vsi_handle; 6300 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 6301 /* update the src in case it is VSI num */ 6302 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 6303 f_entry.fltr_info.src = hw_vsi_id; 6304 if (recp_id == ICE_SW_LKUP_VLAN) 6305 status = ice_add_vlan_internal(hw, &f_entry); 6306 else 6307 status = ice_add_rule_internal(hw, recp_id, &f_entry); 6308 if (status != ICE_SUCCESS) 6309 goto end; 6310 } 6311 end: 6312 return status; 6313 } 6314 6315 /** 6316 * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI 6317 * @hw: pointer to the hardware structure 6318 * @vsi_handle: driver VSI handle 6319 * @list_head: list for which filters need to be replayed 6320 * 6321 * Replay the advanced rule for the given VSI. 6322 */ 6323 static enum ice_status 6324 ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle, 6325 struct LIST_HEAD_TYPE *list_head) 6326 { 6327 struct ice_rule_query_data added_entry = { 0 }; 6328 struct ice_adv_fltr_mgmt_list_entry *adv_fltr; 6329 enum ice_status status = ICE_SUCCESS; 6330 6331 if (LIST_EMPTY(list_head)) 6332 return status; 6333 LIST_FOR_EACH_ENTRY(adv_fltr, list_head, ice_adv_fltr_mgmt_list_entry, 6334 list_entry) { 6335 struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info; 6336 u16 lk_cnt = adv_fltr->lkups_cnt; 6337 6338 if (vsi_handle != rinfo->sw_act.vsi_handle) 6339 continue; 6340 status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo, 6341 &added_entry); 6342 if (status) 6343 break; 6344 } 6345 return status; 6346 } 6347 6348 /** 6349 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 6350 * @hw: pointer to the hardware structure 6351 * @vsi_handle: driver VSI handle 6352 * 6353 * Replays filters for requested VSI via vsi_handle. 6354 */ 6355 enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle) 6356 { 6357 struct ice_switch_info *sw = hw->switch_info; 6358 enum ice_status status; 6359 u8 i; 6360 6361 /* Update the recipes that were created */ 6362 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 6363 struct LIST_HEAD_TYPE *head; 6364 6365 head = &sw->recp_list[i].filt_replay_rules; 6366 if (!sw->recp_list[i].adv_rule) 6367 status = ice_replay_vsi_fltr(hw, vsi_handle, i, head); 6368 else 6369 status = ice_replay_vsi_adv_rule(hw, vsi_handle, head); 6370 if (status != ICE_SUCCESS) 6371 return status; 6372 } 6373 6374 return ICE_SUCCESS; 6375 } 6376 6377 /** 6378 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 6379 * @hw: pointer to the HW struct 6380 * 6381 * Deletes the filter replay rules. 6382 */ 6383 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 6384 { 6385 struct ice_switch_info *sw = hw->switch_info; 6386 u8 i; 6387 6388 if (!sw) 6389 return; 6390 6391 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 6392 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) { 6393 struct LIST_HEAD_TYPE *l_head; 6394 6395 l_head = &sw->recp_list[i].filt_replay_rules; 6396 if (!sw->recp_list[i].adv_rule) 6397 ice_rem_sw_rule_info(hw, l_head); 6398 else 6399 ice_rem_adv_rule_info(hw, l_head); 6400 } 6401 } 6402 } 6403