1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2024, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "ice_common.h" 33 #include "ice_switch.h" 34 #include "ice_flex_type.h" 35 #include "ice_flow.h" 36 37 #define ICE_ETH_DA_OFFSET 0 38 #define ICE_ETH_ETHTYPE_OFFSET 12 39 #define ICE_ETH_VLAN_TCI_OFFSET 14 40 #define ICE_MAX_VLAN_ID 0xFFF 41 #define ICE_IPV6_ETHER_ID 0x86DD 42 #define ICE_PPP_IPV6_PROTO_ID 0x0057 43 #define ICE_ETH_P_8021Q 0x8100 44 45 /* Dummy ethernet header needed in the ice_sw_rule_* 46 * struct to configure any switch filter rules. 47 * {DA (6 bytes), SA(6 bytes), 48 * Ether type (2 bytes for header without VLAN tag) OR 49 * VLAN tag (4 bytes for header with VLAN tag) } 50 * 51 * Word on Hardcoded values 52 * byte 0 = 0x2: to identify it as locally administered DA MAC 53 * byte 6 = 0x2: to identify it as locally administered SA MAC 54 * byte 12 = 0x81 & byte 13 = 0x00: 55 * In case of VLAN filter first two bytes defines ether type (0x8100) 56 * and remaining two bytes are placeholder for programming a given VLAN ID 57 * In case of Ether type filter it is treated as header without VLAN tag 58 * and byte 12 and 13 is used to program a given Ether type instead 59 */ 60 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 61 0x2, 0, 0, 0, 0, 0, 62 0x81, 0, 0, 0}; 63 64 static bool 65 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle); 66 67 /** 68 * ice_init_def_sw_recp - initialize the recipe book keeping tables 69 * @hw: pointer to the HW struct 70 * @recp_list: pointer to sw recipe list 71 * 72 * Allocate memory for the entire recipe table and initialize the structures/ 73 * entries corresponding to basic recipes. 74 */ 75 enum ice_status 76 ice_init_def_sw_recp(struct ice_hw *hw, struct ice_sw_recipe **recp_list) 77 { 78 struct ice_sw_recipe *recps; 79 u8 i; 80 81 recps = (struct ice_sw_recipe *) 82 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps)); 83 if (!recps) 84 return ICE_ERR_NO_MEMORY; 85 86 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 87 recps[i].root_rid = i; 88 INIT_LIST_HEAD(&recps[i].filt_rules); 89 INIT_LIST_HEAD(&recps[i].filt_replay_rules); 90 INIT_LIST_HEAD(&recps[i].rg_list); 91 ice_init_lock(&recps[i].filt_rule_lock); 92 } 93 94 *recp_list = recps; 95 96 return ICE_SUCCESS; 97 } 98 99 /** 100 * ice_aq_get_sw_cfg - get switch configuration 101 * @hw: pointer to the hardware structure 102 * @buf: pointer to the result buffer 103 * @buf_size: length of the buffer available for response 104 * @req_desc: pointer to requested descriptor 105 * @num_elems: pointer to number of elements 106 * @cd: pointer to command details structure or NULL 107 * 108 * Get switch configuration (0x0200) to be placed in buf. 109 * This admin command returns information such as initial VSI/port number 110 * and switch ID it belongs to. 111 * 112 * NOTE: *req_desc is both an input/output parameter. 113 * The caller of this function first calls this function with *request_desc set 114 * to 0. If the response from f/w has *req_desc set to 0, all the switch 115 * configuration information has been returned; if non-zero (meaning not all 116 * the information was returned), the caller should call this function again 117 * with *req_desc set to the previous value returned by f/w to get the 118 * next block of switch configuration information. 119 * 120 * *num_elems is output only parameter. This reflects the number of elements 121 * in response buffer. The caller of this function to use *num_elems while 122 * parsing the response buffer. 123 */ 124 static enum ice_status 125 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf, 126 u16 buf_size, u16 *req_desc, u16 *num_elems, 127 struct ice_sq_cd *cd) 128 { 129 struct ice_aqc_get_sw_cfg *cmd; 130 struct ice_aq_desc desc; 131 enum ice_status status; 132 133 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); 134 cmd = &desc.params.get_sw_conf; 135 cmd->element = CPU_TO_LE16(*req_desc); 136 137 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 138 if (!status) { 139 *req_desc = LE16_TO_CPU(cmd->element); 140 *num_elems = LE16_TO_CPU(cmd->num_elems); 141 } 142 143 return status; 144 } 145 146 /** 147 * ice_alloc_rss_global_lut - allocate a RSS global LUT 148 * @hw: pointer to the HW struct 149 * @shared_res: true to allocate as a shared resource and false to allocate as a dedicated resource 150 * @global_lut_id: output parameter for the RSS global LUT's ID 151 */ 152 enum ice_status ice_alloc_rss_global_lut(struct ice_hw *hw, bool shared_res, u16 *global_lut_id) 153 { 154 struct ice_aqc_alloc_free_res_elem *sw_buf; 155 enum ice_status status; 156 u16 buf_len; 157 158 buf_len = ice_struct_size(sw_buf, elem, 1); 159 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 160 if (!sw_buf) 161 return ICE_ERR_NO_MEMORY; 162 163 sw_buf->num_elems = CPU_TO_LE16(1); 164 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH | 165 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED : 166 ICE_AQC_RES_TYPE_FLAG_DEDICATED)); 167 168 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, ice_aqc_opc_alloc_res, NULL); 169 if (status) { 170 ice_debug(hw, ICE_DBG_RES, "Failed to allocate %s RSS global LUT, status %d\n", 171 shared_res ? "shared" : "dedicated", status); 172 goto ice_alloc_global_lut_exit; 173 } 174 175 *global_lut_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 176 177 ice_alloc_global_lut_exit: 178 ice_free(hw, sw_buf); 179 return status; 180 } 181 182 /** 183 * ice_free_rss_global_lut - free a RSS global LUT 184 * @hw: pointer to the HW struct 185 * @global_lut_id: ID of the RSS global LUT to free 186 */ 187 enum ice_status ice_free_rss_global_lut(struct ice_hw *hw, u16 global_lut_id) 188 { 189 struct ice_aqc_alloc_free_res_elem *sw_buf; 190 u16 buf_len, num_elems = 1; 191 enum ice_status status; 192 193 buf_len = ice_struct_size(sw_buf, elem, num_elems); 194 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 195 if (!sw_buf) 196 return ICE_ERR_NO_MEMORY; 197 198 sw_buf->num_elems = CPU_TO_LE16(num_elems); 199 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH); 200 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(global_lut_id); 201 202 status = ice_aq_alloc_free_res(hw, num_elems, sw_buf, buf_len, ice_aqc_opc_free_res, NULL); 203 if (status) 204 ice_debug(hw, ICE_DBG_RES, "Failed to free RSS global LUT %d, status %d\n", 205 global_lut_id, status); 206 207 ice_free(hw, sw_buf); 208 return status; 209 } 210 211 /** 212 * ice_alloc_sw - allocate resources specific to switch 213 * @hw: pointer to the HW struct 214 * @ena_stats: true to turn on VEB stats 215 * @shared_res: true for shared resource, false for dedicated resource 216 * @sw_id: switch ID returned 217 * @counter_id: VEB counter ID returned 218 * 219 * allocates switch resources (SWID and VEB counter) (0x0208) 220 */ 221 enum ice_status 222 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id, 223 u16 *counter_id) 224 { 225 struct ice_aqc_alloc_free_res_elem *sw_buf; 226 struct ice_aqc_res_elem *sw_ele; 227 enum ice_status status; 228 u16 buf_len; 229 230 buf_len = ice_struct_size(sw_buf, elem, 1); 231 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 232 if (!sw_buf) 233 return ICE_ERR_NO_MEMORY; 234 235 /* Prepare buffer for switch ID. 236 * The number of resource entries in buffer is passed as 1 since only a 237 * single switch/VEB instance is allocated, and hence a single sw_id 238 * is requested. 239 */ 240 sw_buf->num_elems = CPU_TO_LE16(1); 241 sw_buf->res_type = 242 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID | 243 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED : 244 ICE_AQC_RES_TYPE_FLAG_DEDICATED)); 245 246 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 247 ice_aqc_opc_alloc_res, NULL); 248 249 if (status) 250 goto ice_alloc_sw_exit; 251 252 sw_ele = &sw_buf->elem[0]; 253 *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp); 254 255 if (ena_stats) { 256 /* Prepare buffer for VEB Counter */ 257 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res; 258 struct ice_aqc_alloc_free_res_elem *counter_buf; 259 struct ice_aqc_res_elem *counter_ele; 260 261 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 262 ice_malloc(hw, buf_len); 263 if (!counter_buf) { 264 status = ICE_ERR_NO_MEMORY; 265 goto ice_alloc_sw_exit; 266 } 267 268 /* The number of resource entries in buffer is passed as 1 since 269 * only a single switch/VEB instance is allocated, and hence a 270 * single VEB counter is requested. 271 */ 272 counter_buf->num_elems = CPU_TO_LE16(1); 273 counter_buf->res_type = 274 CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER | 275 ICE_AQC_RES_TYPE_FLAG_DEDICATED); 276 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 277 opc, NULL); 278 279 if (status) { 280 ice_free(hw, counter_buf); 281 goto ice_alloc_sw_exit; 282 } 283 counter_ele = &counter_buf->elem[0]; 284 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp); 285 ice_free(hw, counter_buf); 286 } 287 288 ice_alloc_sw_exit: 289 ice_free(hw, sw_buf); 290 return status; 291 } 292 293 /** 294 * ice_free_sw - free resources specific to switch 295 * @hw: pointer to the HW struct 296 * @sw_id: switch ID returned 297 * @counter_id: VEB counter ID returned 298 * 299 * free switch resources (SWID and VEB counter) (0x0209) 300 * 301 * NOTE: This function frees multiple resources. It continues 302 * releasing other resources even after it encounters error. 303 * The error code returned is the last error it encountered. 304 */ 305 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id) 306 { 307 struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf; 308 enum ice_status status, ret_status; 309 u16 buf_len; 310 311 buf_len = ice_struct_size(sw_buf, elem, 1); 312 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 313 if (!sw_buf) 314 return ICE_ERR_NO_MEMORY; 315 316 /* Prepare buffer to free for switch ID res. 317 * The number of resource entries in buffer is passed as 1 since only a 318 * single switch/VEB instance is freed, and hence a single sw_id 319 * is released. 320 */ 321 sw_buf->num_elems = CPU_TO_LE16(1); 322 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID); 323 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id); 324 325 ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 326 ice_aqc_opc_free_res, NULL); 327 328 if (ret_status) 329 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n"); 330 331 /* Prepare buffer to free for VEB Counter resource */ 332 counter_buf = (struct ice_aqc_alloc_free_res_elem *) 333 ice_malloc(hw, buf_len); 334 if (!counter_buf) { 335 ice_free(hw, sw_buf); 336 return ICE_ERR_NO_MEMORY; 337 } 338 339 /* The number of resource entries in buffer is passed as 1 since only a 340 * single switch/VEB instance is freed, and hence a single VEB counter 341 * is released 342 */ 343 counter_buf->num_elems = CPU_TO_LE16(1); 344 counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER); 345 counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 346 347 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len, 348 ice_aqc_opc_free_res, NULL); 349 if (status) { 350 ice_debug(hw, ICE_DBG_SW, "VEB counter resource could not be freed\n"); 351 ret_status = status; 352 } 353 354 ice_free(hw, counter_buf); 355 ice_free(hw, sw_buf); 356 return ret_status; 357 } 358 359 /** 360 * ice_aq_add_vsi 361 * @hw: pointer to the HW struct 362 * @vsi_ctx: pointer to a VSI context struct 363 * @cd: pointer to command details structure or NULL 364 * 365 * Add a VSI context to the hardware (0x0210) 366 */ 367 enum ice_status 368 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 369 struct ice_sq_cd *cd) 370 { 371 struct ice_aqc_add_update_free_vsi_resp *res; 372 struct ice_aqc_add_get_update_free_vsi *cmd; 373 struct ice_aq_desc desc; 374 enum ice_status status; 375 376 cmd = &desc.params.vsi_cmd; 377 res = &desc.params.add_update_free_vsi_res; 378 379 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi); 380 381 if (!vsi_ctx->alloc_from_pool) 382 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | 383 ICE_AQ_VSI_IS_VALID); 384 cmd->vf_id = vsi_ctx->vf_num; 385 386 cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags); 387 388 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 389 390 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 391 sizeof(vsi_ctx->info), cd); 392 393 if (!status) { 394 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M; 395 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used); 396 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free); 397 } 398 399 return status; 400 } 401 402 /** 403 * ice_aq_free_vsi 404 * @hw: pointer to the HW struct 405 * @vsi_ctx: pointer to a VSI context struct 406 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 407 * @cd: pointer to command details structure or NULL 408 * 409 * Free VSI context info from hardware (0x0213) 410 */ 411 enum ice_status 412 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 413 bool keep_vsi_alloc, struct ice_sq_cd *cd) 414 { 415 struct ice_aqc_add_update_free_vsi_resp *resp; 416 struct ice_aqc_add_get_update_free_vsi *cmd; 417 struct ice_aq_desc desc; 418 enum ice_status status; 419 420 cmd = &desc.params.vsi_cmd; 421 resp = &desc.params.add_update_free_vsi_res; 422 423 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi); 424 425 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 426 if (keep_vsi_alloc) 427 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC); 428 429 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 430 if (!status) { 431 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 432 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 433 } 434 435 return status; 436 } 437 438 /** 439 * ice_aq_update_vsi 440 * @hw: pointer to the HW struct 441 * @vsi_ctx: pointer to a VSI context struct 442 * @cd: pointer to command details structure or NULL 443 * 444 * Update VSI context in the hardware (0x0211) 445 */ 446 enum ice_status 447 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 448 struct ice_sq_cd *cd) 449 { 450 struct ice_aqc_add_update_free_vsi_resp *resp; 451 struct ice_aqc_add_get_update_free_vsi *cmd; 452 struct ice_aq_desc desc; 453 enum ice_status status; 454 455 cmd = &desc.params.vsi_cmd; 456 resp = &desc.params.add_update_free_vsi_res; 457 458 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi); 459 460 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 461 462 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 463 464 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 465 sizeof(vsi_ctx->info), cd); 466 467 if (!status) { 468 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 469 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 470 } 471 472 return status; 473 } 474 475 /** 476 * ice_is_vsi_valid - check whether the VSI is valid or not 477 * @hw: pointer to the HW struct 478 * @vsi_handle: VSI handle 479 * 480 * check whether the VSI is valid or not 481 */ 482 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle) 483 { 484 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle]; 485 } 486 487 /** 488 * ice_get_hw_vsi_num - return the HW VSI number 489 * @hw: pointer to the HW struct 490 * @vsi_handle: VSI handle 491 * 492 * return the HW VSI number 493 * Caution: call this function only if VSI is valid (ice_is_vsi_valid) 494 */ 495 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle) 496 { 497 return hw->vsi_ctx[vsi_handle]->vsi_num; 498 } 499 500 /** 501 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle 502 * @hw: pointer to the HW struct 503 * @vsi_handle: VSI handle 504 * 505 * return the VSI context entry for a given VSI handle 506 */ 507 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 508 { 509 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle]; 510 } 511 512 /** 513 * ice_save_vsi_ctx - save the VSI context for a given VSI handle 514 * @hw: pointer to the HW struct 515 * @vsi_handle: VSI handle 516 * @vsi: VSI context pointer 517 * 518 * save the VSI context entry for a given VSI handle 519 */ 520 static void 521 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) 522 { 523 hw->vsi_ctx[vsi_handle] = vsi; 524 } 525 526 /** 527 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs 528 * @hw: pointer to the HW struct 529 * @vsi_handle: VSI handle 530 */ 531 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) 532 { 533 struct ice_vsi_ctx *vsi; 534 u8 i; 535 536 vsi = ice_get_vsi_ctx(hw, vsi_handle); 537 if (!vsi) 538 return; 539 ice_for_each_traffic_class(i) { 540 if (vsi->lan_q_ctx[i]) { 541 ice_free(hw, vsi->lan_q_ctx[i]); 542 vsi->lan_q_ctx[i] = NULL; 543 } 544 if (vsi->rdma_q_ctx[i]) { 545 ice_free(hw, vsi->rdma_q_ctx[i]); 546 vsi->rdma_q_ctx[i] = NULL; 547 } 548 } 549 } 550 551 /** 552 * ice_clear_vsi_ctx - clear the VSI context entry 553 * @hw: pointer to the HW struct 554 * @vsi_handle: VSI handle 555 * 556 * clear the VSI context entry 557 */ 558 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 559 { 560 struct ice_vsi_ctx *vsi; 561 562 vsi = ice_get_vsi_ctx(hw, vsi_handle); 563 if (vsi) { 564 ice_clear_vsi_q_ctx(hw, vsi_handle); 565 ice_free(hw, vsi); 566 hw->vsi_ctx[vsi_handle] = NULL; 567 } 568 } 569 570 /** 571 * ice_clear_all_vsi_ctx - clear all the VSI context entries 572 * @hw: pointer to the HW struct 573 */ 574 void ice_clear_all_vsi_ctx(struct ice_hw *hw) 575 { 576 u16 i; 577 578 for (i = 0; i < ICE_MAX_VSI; i++) 579 ice_clear_vsi_ctx(hw, i); 580 } 581 582 /** 583 * ice_add_vsi - add VSI context to the hardware and VSI handle list 584 * @hw: pointer to the HW struct 585 * @vsi_handle: unique VSI handle provided by drivers 586 * @vsi_ctx: pointer to a VSI context struct 587 * @cd: pointer to command details structure or NULL 588 * 589 * Add a VSI context to the hardware also add it into the VSI handle list. 590 * If this function gets called after reset for existing VSIs then update 591 * with the new HW VSI number in the corresponding VSI handle list entry. 592 */ 593 enum ice_status 594 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 595 struct ice_sq_cd *cd) 596 { 597 struct ice_vsi_ctx *tmp_vsi_ctx; 598 enum ice_status status; 599 600 if (vsi_handle >= ICE_MAX_VSI) 601 return ICE_ERR_PARAM; 602 status = ice_aq_add_vsi(hw, vsi_ctx, cd); 603 if (status) 604 return status; 605 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle); 606 if (!tmp_vsi_ctx) { 607 /* Create a new VSI context */ 608 tmp_vsi_ctx = (struct ice_vsi_ctx *) 609 ice_malloc(hw, sizeof(*tmp_vsi_ctx)); 610 if (!tmp_vsi_ctx) { 611 ice_aq_free_vsi(hw, vsi_ctx, false, cd); 612 return ICE_ERR_NO_MEMORY; 613 } 614 *tmp_vsi_ctx = *vsi_ctx; 615 616 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx); 617 } else { 618 /* update with new HW VSI num */ 619 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num; 620 } 621 622 return ICE_SUCCESS; 623 } 624 625 /** 626 * ice_free_vsi- free VSI context from hardware and VSI handle list 627 * @hw: pointer to the HW struct 628 * @vsi_handle: unique VSI handle 629 * @vsi_ctx: pointer to a VSI context struct 630 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources 631 * @cd: pointer to command details structure or NULL 632 * 633 * Free VSI context info from hardware as well as from VSI handle list 634 */ 635 enum ice_status 636 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 637 bool keep_vsi_alloc, struct ice_sq_cd *cd) 638 { 639 enum ice_status status; 640 641 if (!ice_is_vsi_valid(hw, vsi_handle)) 642 return ICE_ERR_PARAM; 643 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 644 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd); 645 if (!status) 646 ice_clear_vsi_ctx(hw, vsi_handle); 647 return status; 648 } 649 650 /** 651 * ice_update_vsi 652 * @hw: pointer to the HW struct 653 * @vsi_handle: unique VSI handle 654 * @vsi_ctx: pointer to a VSI context struct 655 * @cd: pointer to command details structure or NULL 656 * 657 * Update VSI context in the hardware 658 */ 659 enum ice_status 660 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, 661 struct ice_sq_cd *cd) 662 { 663 if (!ice_is_vsi_valid(hw, vsi_handle)) 664 return ICE_ERR_PARAM; 665 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle); 666 return ice_aq_update_vsi(hw, vsi_ctx, cd); 667 } 668 669 /** 670 * ice_cfg_iwarp_fltr - enable/disable iWARP filtering on VSI 671 * @hw: pointer to HW struct 672 * @vsi_handle: VSI SW index 673 * @enable: boolean for enable/disable 674 */ 675 enum ice_status 676 ice_cfg_iwarp_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable) 677 { 678 struct ice_vsi_ctx *ctx, *cached_ctx; 679 enum ice_status status; 680 681 cached_ctx = ice_get_vsi_ctx(hw, vsi_handle); 682 if (!cached_ctx) 683 return ICE_ERR_DOES_NOT_EXIST; 684 685 ctx = (struct ice_vsi_ctx *)ice_calloc(hw, 1, sizeof(*ctx)); 686 if (!ctx) 687 return ICE_ERR_NO_MEMORY; 688 689 ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss; 690 ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc; 691 ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags; 692 693 ctx->info.valid_sections = CPU_TO_LE16(ICE_AQ_VSI_PROP_Q_OPT_VALID); 694 695 if (enable) 696 ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 697 else 698 ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 699 700 status = ice_update_vsi(hw, vsi_handle, ctx, NULL); 701 if (!status) { 702 cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags; 703 cached_ctx->info.valid_sections |= ctx->info.valid_sections; 704 } 705 706 ice_free(hw, ctx); 707 return status; 708 } 709 710 /** 711 * ice_aq_get_vsi_params 712 * @hw: pointer to the HW struct 713 * @vsi_ctx: pointer to a VSI context struct 714 * @cd: pointer to command details structure or NULL 715 * 716 * Get VSI context info from hardware (0x0212) 717 */ 718 enum ice_status 719 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 720 struct ice_sq_cd *cd) 721 { 722 struct ice_aqc_add_get_update_free_vsi *cmd; 723 struct ice_aqc_get_vsi_resp *resp; 724 struct ice_aq_desc desc; 725 enum ice_status status; 726 727 cmd = &desc.params.vsi_cmd; 728 resp = &desc.params.get_vsi_resp; 729 730 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params); 731 732 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); 733 734 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, 735 sizeof(vsi_ctx->info), cd); 736 if (!status) { 737 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) & 738 ICE_AQ_VSI_NUM_M; 739 vsi_ctx->vf_num = resp->vf_id; 740 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); 741 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); 742 } 743 744 return status; 745 } 746 747 /** 748 * ice_aq_add_update_mir_rule - add/update a mirror rule 749 * @hw: pointer to the HW struct 750 * @rule_type: Rule Type 751 * @dest_vsi: VSI number to which packets will be mirrored 752 * @count: length of the list 753 * @mr_buf: buffer for list of mirrored VSI numbers 754 * @cd: pointer to command details structure or NULL 755 * @rule_id: Rule ID 756 * 757 * Add/Update Mirror Rule (0x260). 758 */ 759 enum ice_status 760 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, 761 u16 count, struct ice_mir_rule_buf *mr_buf, 762 struct ice_sq_cd *cd, u16 *rule_id) 763 { 764 struct ice_aqc_add_update_mir_rule *cmd; 765 struct ice_aq_desc desc; 766 enum ice_status status; 767 __le16 *mr_list = NULL; 768 u16 buf_size = 0; 769 770 switch (rule_type) { 771 case ICE_AQC_RULE_TYPE_VPORT_INGRESS: 772 case ICE_AQC_RULE_TYPE_VPORT_EGRESS: 773 /* Make sure count and mr_buf are set for these rule_types */ 774 if (!(count && mr_buf)) 775 return ICE_ERR_PARAM; 776 777 buf_size = count * sizeof(__le16); 778 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size); 779 if (!mr_list) 780 return ICE_ERR_NO_MEMORY; 781 break; 782 case ICE_AQC_RULE_TYPE_PPORT_INGRESS: 783 case ICE_AQC_RULE_TYPE_PPORT_EGRESS: 784 /* Make sure count and mr_buf are not set for these 785 * rule_types 786 */ 787 if (count || mr_buf) 788 return ICE_ERR_PARAM; 789 break; 790 default: 791 ice_debug(hw, ICE_DBG_SW, "Error due to unsupported rule_type %u\n", rule_type); 792 return ICE_ERR_OUT_OF_RANGE; 793 } 794 795 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule); 796 797 /* Pre-process 'mr_buf' items for add/update of virtual port 798 * ingress/egress mirroring (but not physical port ingress/egress 799 * mirroring) 800 */ 801 if (mr_buf) { 802 int i; 803 804 for (i = 0; i < count; i++) { 805 u16 id; 806 807 id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M; 808 809 /* Validate specified VSI number, make sure it is less 810 * than ICE_MAX_VSI, if not return with error. 811 */ 812 if (id >= ICE_MAX_VSI) { 813 ice_debug(hw, ICE_DBG_SW, "Error VSI index (%u) out-of-range\n", 814 id); 815 ice_free(hw, mr_list); 816 return ICE_ERR_OUT_OF_RANGE; 817 } 818 819 /* add VSI to mirror rule */ 820 if (mr_buf[i].add) 821 mr_list[i] = 822 CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M); 823 else /* remove VSI from mirror rule */ 824 mr_list[i] = CPU_TO_LE16(id); 825 } 826 827 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 828 } 829 830 cmd = &desc.params.add_update_rule; 831 if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID) 832 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) | 833 ICE_AQC_RULE_ID_VALID_M); 834 cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M); 835 cmd->num_entries = CPU_TO_LE16(count); 836 cmd->dest = CPU_TO_LE16(dest_vsi); 837 838 status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd); 839 if (!status) 840 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M; 841 842 ice_free(hw, mr_list); 843 844 return status; 845 } 846 847 /** 848 * ice_aq_delete_mir_rule - delete a mirror rule 849 * @hw: pointer to the HW struct 850 * @rule_id: Mirror rule ID (to be deleted) 851 * @keep_allocd: if set, the VSI stays part of the PF allocated res, 852 * otherwise it is returned to the shared pool 853 * @cd: pointer to command details structure or NULL 854 * 855 * Delete Mirror Rule (0x261). 856 */ 857 enum ice_status 858 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, 859 struct ice_sq_cd *cd) 860 { 861 struct ice_aqc_delete_mir_rule *cmd; 862 struct ice_aq_desc desc; 863 864 /* rule_id should be in the range 0...63 */ 865 if (rule_id >= ICE_MAX_NUM_MIRROR_RULES) 866 return ICE_ERR_OUT_OF_RANGE; 867 868 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule); 869 870 cmd = &desc.params.del_rule; 871 rule_id |= ICE_AQC_RULE_ID_VALID_M; 872 cmd->rule_id = CPU_TO_LE16(rule_id); 873 874 if (keep_allocd) 875 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M); 876 877 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); 878 } 879 880 /** 881 * ice_aq_alloc_free_vsi_list 882 * @hw: pointer to the HW struct 883 * @vsi_list_id: VSI list ID returned or used for lookup 884 * @lkup_type: switch rule filter lookup type 885 * @opc: switch rules population command type - pass in the command opcode 886 * 887 * allocates or free a VSI list resource 888 */ 889 static enum ice_status 890 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, 891 enum ice_sw_lkup_type lkup_type, 892 enum ice_adminq_opc opc) 893 { 894 struct ice_aqc_alloc_free_res_elem *sw_buf; 895 struct ice_aqc_res_elem *vsi_ele; 896 enum ice_status status; 897 u16 buf_len; 898 899 buf_len = ice_struct_size(sw_buf, elem, 1); 900 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 901 if (!sw_buf) 902 return ICE_ERR_NO_MEMORY; 903 sw_buf->num_elems = CPU_TO_LE16(1); 904 905 if (lkup_type == ICE_SW_LKUP_MAC || 906 lkup_type == ICE_SW_LKUP_MAC_VLAN || 907 lkup_type == ICE_SW_LKUP_ETHERTYPE || 908 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 909 lkup_type == ICE_SW_LKUP_PROMISC || 910 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 911 lkup_type == ICE_SW_LKUP_DFLT || 912 lkup_type == ICE_SW_LKUP_LAST) { 913 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP); 914 } else if (lkup_type == ICE_SW_LKUP_VLAN) { 915 sw_buf->res_type = 916 CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE); 917 } else { 918 status = ICE_ERR_PARAM; 919 goto ice_aq_alloc_free_vsi_list_exit; 920 } 921 922 if (opc == ice_aqc_opc_free_res) 923 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id); 924 925 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL); 926 if (status) 927 goto ice_aq_alloc_free_vsi_list_exit; 928 929 if (opc == ice_aqc_opc_alloc_res) { 930 vsi_ele = &sw_buf->elem[0]; 931 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp); 932 } 933 934 ice_aq_alloc_free_vsi_list_exit: 935 ice_free(hw, sw_buf); 936 return status; 937 } 938 939 /** 940 * ice_aq_set_storm_ctrl - Sets storm control configuration 941 * @hw: pointer to the HW struct 942 * @bcast_thresh: represents the upper threshold for broadcast storm control 943 * @mcast_thresh: represents the upper threshold for multicast storm control 944 * @ctl_bitmask: storm control knobs 945 * 946 * Sets the storm control configuration (0x0280) 947 */ 948 enum ice_status 949 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, 950 u32 ctl_bitmask) 951 { 952 struct ice_aqc_storm_cfg *cmd; 953 struct ice_aq_desc desc; 954 955 cmd = &desc.params.storm_conf; 956 957 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg); 958 959 cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M); 960 cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M); 961 cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask); 962 963 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 964 } 965 966 /** 967 * ice_aq_get_storm_ctrl - gets storm control configuration 968 * @hw: pointer to the HW struct 969 * @bcast_thresh: represents the upper threshold for broadcast storm control 970 * @mcast_thresh: represents the upper threshold for multicast storm control 971 * @ctl_bitmask: storm control knobs 972 * 973 * Gets the storm control configuration (0x0281) 974 */ 975 enum ice_status 976 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, 977 u32 *ctl_bitmask) 978 { 979 enum ice_status status; 980 struct ice_aq_desc desc; 981 982 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg); 983 984 status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); 985 if (!status) { 986 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf; 987 988 if (bcast_thresh) 989 *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) & 990 ICE_AQ_THRESHOLD_M; 991 if (mcast_thresh) 992 *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) & 993 ICE_AQ_THRESHOLD_M; 994 if (ctl_bitmask) 995 *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl); 996 } 997 998 return status; 999 } 1000 1001 /** 1002 * ice_aq_sw_rules - add/update/remove switch rules 1003 * @hw: pointer to the HW struct 1004 * @rule_list: pointer to switch rule population list 1005 * @rule_list_sz: total size of the rule list in bytes 1006 * @num_rules: number of switch rules in the rule_list 1007 * @opc: switch rules population command type - pass in the command opcode 1008 * @cd: pointer to command details structure or NULL 1009 * 1010 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware 1011 */ 1012 enum ice_status 1013 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, 1014 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) 1015 { 1016 struct ice_aq_desc desc; 1017 enum ice_status status; 1018 1019 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 1020 1021 if (opc != ice_aqc_opc_add_sw_rules && 1022 opc != ice_aqc_opc_update_sw_rules && 1023 opc != ice_aqc_opc_remove_sw_rules) 1024 return ICE_ERR_PARAM; 1025 1026 ice_fill_dflt_direct_cmd_desc(&desc, opc); 1027 1028 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); 1029 desc.params.sw_rules.num_rules_fltr_entry_index = 1030 CPU_TO_LE16(num_rules); 1031 status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); 1032 if (opc != ice_aqc_opc_add_sw_rules && 1033 hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) 1034 status = ICE_ERR_DOES_NOT_EXIST; 1035 1036 return status; 1037 } 1038 1039 /* ice_init_port_info - Initialize port_info with switch configuration data 1040 * @pi: pointer to port_info 1041 * @vsi_port_num: VSI number or port number 1042 * @type: Type of switch element (port or VSI) 1043 * @swid: switch ID of the switch the element is attached to 1044 * @pf_vf_num: PF or VF number 1045 * @is_vf: true if the element is a VF, false otherwise 1046 */ 1047 static void 1048 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, 1049 u16 swid, u16 pf_vf_num, bool is_vf) 1050 { 1051 switch (type) { 1052 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 1053 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK); 1054 pi->sw_id = swid; 1055 pi->pf_vf_num = pf_vf_num; 1056 pi->is_vf = is_vf; 1057 break; 1058 default: 1059 ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n"); 1060 break; 1061 } 1062 } 1063 1064 /* ice_get_initial_sw_cfg - Get initial port and default VSI data 1065 * @hw: pointer to the hardware structure 1066 */ 1067 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) 1068 { 1069 struct ice_aqc_get_sw_cfg_resp_elem *rbuf; 1070 enum ice_status status; 1071 u8 num_total_ports; 1072 u16 req_desc = 0; 1073 u16 num_elems; 1074 u8 j = 0; 1075 u16 i; 1076 1077 num_total_ports = 1; 1078 1079 rbuf = (struct ice_aqc_get_sw_cfg_resp_elem *) 1080 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN); 1081 1082 if (!rbuf) 1083 return ICE_ERR_NO_MEMORY; 1084 1085 /* Multiple calls to ice_aq_get_sw_cfg may be required 1086 * to get all the switch configuration information. The need 1087 * for additional calls is indicated by ice_aq_get_sw_cfg 1088 * writing a non-zero value in req_desc 1089 */ 1090 do { 1091 struct ice_aqc_get_sw_cfg_resp_elem *ele; 1092 1093 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, 1094 &req_desc, &num_elems, NULL); 1095 1096 if (status) 1097 break; 1098 1099 for (i = 0, ele = rbuf; i < num_elems; i++, ele++) { 1100 u16 pf_vf_num, swid, vsi_port_num; 1101 bool is_vf = false; 1102 u8 res_type; 1103 1104 vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) & 1105 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; 1106 1107 pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) & 1108 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M; 1109 1110 swid = LE16_TO_CPU(ele->swid); 1111 1112 if (LE16_TO_CPU(ele->pf_vf_num) & 1113 ICE_AQC_GET_SW_CONF_RESP_IS_VF) 1114 is_vf = true; 1115 1116 res_type = (u8)(LE16_TO_CPU(ele->vsi_port_num) >> 1117 ICE_AQC_GET_SW_CONF_RESP_TYPE_S); 1118 1119 switch (res_type) { 1120 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT: 1121 case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT: 1122 if (j == num_total_ports) { 1123 ice_debug(hw, ICE_DBG_SW, "more ports than expected\n"); 1124 status = ICE_ERR_CFG; 1125 goto out; 1126 } 1127 ice_init_port_info(hw->port_info, 1128 vsi_port_num, res_type, swid, 1129 pf_vf_num, is_vf); 1130 j++; 1131 break; 1132 default: 1133 break; 1134 } 1135 } 1136 } while (req_desc && !status); 1137 1138 out: 1139 ice_free(hw, rbuf); 1140 return status; 1141 } 1142 1143 /** 1144 * ice_fill_sw_info - Helper function to populate lb_en and lan_en 1145 * @hw: pointer to the hardware structure 1146 * @fi: filter info structure to fill/update 1147 * 1148 * This helper function populates the lb_en and lan_en elements of the provided 1149 * ice_fltr_info struct using the switch's type and characteristics of the 1150 * switch rule being configured. 1151 */ 1152 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi) 1153 { 1154 fi->lb_en = false; 1155 fi->lan_en = false; 1156 if ((fi->flag & ICE_FLTR_TX) && 1157 (fi->fltr_act == ICE_FWD_TO_VSI || 1158 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1159 fi->fltr_act == ICE_FWD_TO_Q || 1160 fi->fltr_act == ICE_FWD_TO_QGRP)) { 1161 /* Setting LB for prune actions will result in replicated 1162 * packets to the internal switch that will be dropped. 1163 */ 1164 if (fi->lkup_type != ICE_SW_LKUP_VLAN) 1165 fi->lb_en = true; 1166 1167 /* Set lan_en to TRUE if 1168 * 1. The switch is a VEB AND 1169 * 2 1170 * 2.1 The lookup is a directional lookup like ethertype, 1171 * promiscuous, ethertype-MAC, promiscuous-VLAN 1172 * and default-port OR 1173 * 2.2 The lookup is VLAN, OR 1174 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR 1175 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC. 1176 * 1177 * OR 1178 * 1179 * The switch is a VEPA. 1180 * 1181 * In all other cases, the LAN enable has to be set to false. 1182 */ 1183 1184 if (hw->evb_veb) { 1185 if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE || 1186 fi->lkup_type == ICE_SW_LKUP_PROMISC || 1187 fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 1188 fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 1189 fi->lkup_type == ICE_SW_LKUP_DFLT || 1190 fi->lkup_type == ICE_SW_LKUP_VLAN || 1191 (fi->lkup_type == ICE_SW_LKUP_MAC && 1192 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) || 1193 (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN && 1194 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr))) 1195 fi->lan_en = true; 1196 } else { 1197 fi->lan_en = true; 1198 } 1199 } 1200 /* To be able to receive packets coming from the VF on the same PF, 1201 * unicast filter needs to be added without LB_EN bit 1202 */ 1203 if (fi->flag & ICE_FLTR_RX_LB) { 1204 fi->lb_en = false; 1205 fi->lan_en = true; 1206 } 1207 } 1208 1209 /** 1210 * ice_fill_sw_rule - Helper function to fill switch rule structure 1211 * @hw: pointer to the hardware structure 1212 * @f_info: entry containing packet forwarding information 1213 * @s_rule: switch rule structure to be filled in based on mac_entry 1214 * @opc: switch rules population command type - pass in the command opcode 1215 */ 1216 static void 1217 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info, 1218 struct ice_sw_rule_lkup_rx_tx *s_rule, 1219 enum ice_adminq_opc opc) 1220 { 1221 u16 vlan_id = ICE_MAX_VLAN_ID + 1; 1222 u16 vlan_tpid = ICE_ETH_P_8021Q; 1223 void *daddr = NULL; 1224 u16 eth_hdr_sz; 1225 u8 *eth_hdr; 1226 u32 act = 0; 1227 __be16 *off; 1228 u8 q_rgn; 1229 1230 if (opc == ice_aqc_opc_remove_sw_rules) { 1231 s_rule->act = 0; 1232 s_rule->index = CPU_TO_LE16(f_info->fltr_rule_id); 1233 s_rule->hdr_len = 0; 1234 return; 1235 } 1236 1237 eth_hdr_sz = sizeof(dummy_eth_header); 1238 eth_hdr = s_rule->hdr_data; 1239 1240 /* initialize the ether header with a dummy header */ 1241 ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA); 1242 ice_fill_sw_info(hw, f_info); 1243 1244 switch (f_info->fltr_act) { 1245 case ICE_FWD_TO_VSI: 1246 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & 1247 ICE_SINGLE_ACT_VSI_ID_M; 1248 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 1249 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 1250 ICE_SINGLE_ACT_VALID_BIT; 1251 break; 1252 case ICE_FWD_TO_VSI_LIST: 1253 act |= ICE_SINGLE_ACT_VSI_LIST; 1254 act |= (f_info->fwd_id.vsi_list_id << 1255 ICE_SINGLE_ACT_VSI_LIST_ID_S) & 1256 ICE_SINGLE_ACT_VSI_LIST_ID_M; 1257 if (f_info->lkup_type != ICE_SW_LKUP_VLAN) 1258 act |= ICE_SINGLE_ACT_VSI_FORWARDING | 1259 ICE_SINGLE_ACT_VALID_BIT; 1260 break; 1261 case ICE_FWD_TO_Q: 1262 act |= ICE_SINGLE_ACT_TO_Q; 1263 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 1264 ICE_SINGLE_ACT_Q_INDEX_M; 1265 break; 1266 case ICE_DROP_PACKET: 1267 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP | 1268 ICE_SINGLE_ACT_VALID_BIT; 1269 break; 1270 case ICE_FWD_TO_QGRP: 1271 q_rgn = f_info->qgrp_size > 0 ? 1272 (u8)ice_ilog2(f_info->qgrp_size) : 0; 1273 act |= ICE_SINGLE_ACT_TO_Q; 1274 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) & 1275 ICE_SINGLE_ACT_Q_INDEX_M; 1276 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) & 1277 ICE_SINGLE_ACT_Q_REGION_M; 1278 break; 1279 default: 1280 return; 1281 } 1282 1283 if (f_info->lb_en) 1284 act |= ICE_SINGLE_ACT_LB_ENABLE; 1285 if (f_info->lan_en) 1286 act |= ICE_SINGLE_ACT_LAN_ENABLE; 1287 1288 switch (f_info->lkup_type) { 1289 case ICE_SW_LKUP_MAC: 1290 daddr = f_info->l_data.mac.mac_addr; 1291 break; 1292 case ICE_SW_LKUP_VLAN: 1293 vlan_id = f_info->l_data.vlan.vlan_id; 1294 if (f_info->l_data.vlan.tpid_valid) 1295 vlan_tpid = f_info->l_data.vlan.tpid; 1296 if (f_info->fltr_act == ICE_FWD_TO_VSI || 1297 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) { 1298 act |= ICE_SINGLE_ACT_PRUNE; 1299 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS; 1300 } 1301 break; 1302 case ICE_SW_LKUP_ETHERTYPE_MAC: 1303 daddr = f_info->l_data.ethertype_mac.mac_addr; 1304 /* fall-through */ 1305 case ICE_SW_LKUP_ETHERTYPE: 1306 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 1307 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype); 1308 break; 1309 case ICE_SW_LKUP_MAC_VLAN: 1310 daddr = f_info->l_data.mac_vlan.mac_addr; 1311 vlan_id = f_info->l_data.mac_vlan.vlan_id; 1312 break; 1313 case ICE_SW_LKUP_PROMISC_VLAN: 1314 vlan_id = f_info->l_data.mac_vlan.vlan_id; 1315 /* fall-through */ 1316 case ICE_SW_LKUP_PROMISC: 1317 daddr = f_info->l_data.mac_vlan.mac_addr; 1318 break; 1319 default: 1320 break; 1321 } 1322 1323 s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ? 1324 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) : 1325 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX); 1326 1327 /* Recipe set depending on lookup type */ 1328 s_rule->recipe_id = CPU_TO_LE16(f_info->lkup_type); 1329 s_rule->src = CPU_TO_LE16(f_info->src); 1330 s_rule->act = CPU_TO_LE32(act); 1331 1332 if (daddr) 1333 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN, 1334 ICE_NONDMA_TO_NONDMA); 1335 1336 if (!(vlan_id > ICE_MAX_VLAN_ID)) { 1337 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET); 1338 *off = CPU_TO_BE16(vlan_id); 1339 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET); 1340 *off = CPU_TO_BE16(vlan_tpid); 1341 } 1342 1343 /* Create the switch rule with the final dummy Ethernet header */ 1344 if (opc != ice_aqc_opc_update_sw_rules) 1345 s_rule->hdr_len = CPU_TO_LE16(eth_hdr_sz); 1346 } 1347 1348 /** 1349 * ice_add_marker_act 1350 * @hw: pointer to the hardware structure 1351 * @m_ent: the management entry for which sw marker needs to be added 1352 * @sw_marker: sw marker to tag the Rx descriptor with 1353 * @l_id: large action resource ID 1354 * 1355 * Create a large action to hold software marker and update the switch rule 1356 * entry pointed by m_ent with newly created large action 1357 */ 1358 static enum ice_status 1359 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 1360 u16 sw_marker, u16 l_id) 1361 { 1362 struct ice_sw_rule_lkup_rx_tx *rx_tx; 1363 struct ice_sw_rule_lg_act *lg_act; 1364 /* For software marker we need 3 large actions 1365 * 1. FWD action: FWD TO VSI or VSI LIST 1366 * 2. GENERIC VALUE action to hold the profile ID 1367 * 3. GENERIC VALUE action to hold the software marker ID 1368 */ 1369 const u16 num_lg_acts = 3; 1370 enum ice_status status; 1371 u16 lg_act_size; 1372 u16 rules_size; 1373 u32 act; 1374 u16 id; 1375 1376 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 1377 return ICE_ERR_PARAM; 1378 1379 /* Create two back-to-back switch rules and submit them to the HW using 1380 * one memory buffer: 1381 * 1. Large Action 1382 * 2. Look up Tx Rx 1383 */ 1384 lg_act_size = (u16)ice_struct_size(lg_act, act, num_lg_acts); 1385 rules_size = lg_act_size + 1386 ice_struct_size(rx_tx, hdr_data, DUMMY_ETH_HDR_LEN); 1387 lg_act = (struct ice_sw_rule_lg_act *)ice_malloc(hw, rules_size); 1388 if (!lg_act) 1389 return ICE_ERR_NO_MEMORY; 1390 1391 rx_tx = (struct ice_sw_rule_lkup_rx_tx *)((u8 *)lg_act + lg_act_size); 1392 1393 /* Fill in the first switch rule i.e. large action */ 1394 lg_act->hdr.type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1395 lg_act->index = CPU_TO_LE16(l_id); 1396 lg_act->size = CPU_TO_LE16(num_lg_acts); 1397 1398 /* First action VSI forwarding or VSI list forwarding depending on how 1399 * many VSIs 1400 */ 1401 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1402 m_ent->fltr_info.fwd_id.hw_vsi_id; 1403 1404 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1405 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M; 1406 if (m_ent->vsi_count > 1) 1407 act |= ICE_LG_ACT_VSI_LIST; 1408 lg_act->act[0] = CPU_TO_LE32(act); 1409 1410 /* Second action descriptor type */ 1411 act = ICE_LG_ACT_GENERIC; 1412 1413 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 1414 lg_act->act[1] = CPU_TO_LE32(act); 1415 1416 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 1417 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 1418 1419 /* Third action Marker value */ 1420 act |= ICE_LG_ACT_GENERIC; 1421 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 1422 ICE_LG_ACT_GENERIC_VALUE_M; 1423 1424 lg_act->act[2] = CPU_TO_LE32(act); 1425 1426 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1427 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1428 ice_aqc_opc_update_sw_rules); 1429 1430 /* Update the action to point to the large action ID */ 1431 rx_tx->act = CPU_TO_LE32(ICE_SINGLE_ACT_PTR | 1432 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 1433 ICE_SINGLE_ACT_PTR_VAL_M)); 1434 1435 /* Use the filter rule ID of the previously created rule with single 1436 * act. Once the update happens, hardware will treat this as large 1437 * action 1438 */ 1439 rx_tx->index = CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id); 1440 1441 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 1442 ice_aqc_opc_update_sw_rules, NULL); 1443 if (!status) { 1444 m_ent->lg_act_idx = l_id; 1445 m_ent->sw_marker_id = sw_marker; 1446 } 1447 1448 ice_free(hw, lg_act); 1449 return status; 1450 } 1451 1452 /** 1453 * ice_add_counter_act - add/update filter rule with counter action 1454 * @hw: pointer to the hardware structure 1455 * @m_ent: the management entry for which counter needs to be added 1456 * @counter_id: VLAN counter ID returned as part of allocate resource 1457 * @l_id: large action resource ID 1458 */ 1459 static enum ice_status 1460 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, 1461 u16 counter_id, u16 l_id) 1462 { 1463 struct ice_sw_rule_lkup_rx_tx *rx_tx; 1464 struct ice_sw_rule_lg_act *lg_act; 1465 enum ice_status status; 1466 /* 2 actions will be added while adding a large action counter */ 1467 const int num_acts = 2; 1468 u16 lg_act_size; 1469 u16 rules_size; 1470 u16 f_rule_id; 1471 u32 act; 1472 u16 id; 1473 1474 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 1475 return ICE_ERR_PARAM; 1476 1477 /* Create two back-to-back switch rules and submit them to the HW using 1478 * one memory buffer: 1479 * 1. Large Action 1480 * 2. Look up Tx Rx 1481 */ 1482 lg_act_size = (u16)ice_struct_size(lg_act, act, num_acts); 1483 rules_size = lg_act_size + 1484 ice_struct_size(rx_tx, hdr_data, DUMMY_ETH_HDR_LEN); 1485 lg_act = (struct ice_sw_rule_lg_act *)ice_malloc(hw, rules_size); 1486 if (!lg_act) 1487 return ICE_ERR_NO_MEMORY; 1488 1489 rx_tx = (struct ice_sw_rule_lkup_rx_tx *)((u8 *)lg_act + 1490 lg_act_size); 1491 1492 /* Fill in the first switch rule i.e. large action */ 1493 lg_act->hdr.type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1494 lg_act->index = CPU_TO_LE16(l_id); 1495 lg_act->size = CPU_TO_LE16(num_acts); 1496 1497 /* First action VSI forwarding or VSI list forwarding depending on how 1498 * many VSIs 1499 */ 1500 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1501 m_ent->fltr_info.fwd_id.hw_vsi_id; 1502 1503 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1504 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 1505 ICE_LG_ACT_VSI_LIST_ID_M; 1506 if (m_ent->vsi_count > 1) 1507 act |= ICE_LG_ACT_VSI_LIST; 1508 lg_act->act[0] = CPU_TO_LE32(act); 1509 1510 /* Second action counter ID */ 1511 act = ICE_LG_ACT_STAT_COUNT; 1512 act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) & 1513 ICE_LG_ACT_STAT_COUNT_M; 1514 lg_act->act[1] = CPU_TO_LE32(act); 1515 1516 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1517 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1518 ice_aqc_opc_update_sw_rules); 1519 1520 act = ICE_SINGLE_ACT_PTR; 1521 act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M; 1522 rx_tx->act = CPU_TO_LE32(act); 1523 1524 /* Use the filter rule ID of the previously created rule with single 1525 * act. Once the update happens, hardware will treat this as large 1526 * action 1527 */ 1528 f_rule_id = m_ent->fltr_info.fltr_rule_id; 1529 rx_tx->index = CPU_TO_LE16(f_rule_id); 1530 1531 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 1532 ice_aqc_opc_update_sw_rules, NULL); 1533 if (!status) { 1534 m_ent->lg_act_idx = l_id; 1535 m_ent->counter_index = (u8)counter_id; 1536 } 1537 1538 ice_free(hw, lg_act); 1539 return status; 1540 } 1541 1542 /** 1543 * ice_create_vsi_list_map 1544 * @hw: pointer to the hardware structure 1545 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 1546 * @num_vsi: number of VSI handles in the array 1547 * @vsi_list_id: VSI list ID generated as part of allocate resource 1548 * 1549 * Helper function to create a new entry of VSI list ID to VSI mapping 1550 * using the given VSI list ID 1551 */ 1552 static struct ice_vsi_list_map_info * 1553 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1554 u16 vsi_list_id) 1555 { 1556 struct ice_switch_info *sw = hw->switch_info; 1557 struct ice_vsi_list_map_info *v_map; 1558 int i; 1559 1560 v_map = (struct ice_vsi_list_map_info *)ice_malloc(hw, sizeof(*v_map)); 1561 if (!v_map) 1562 return NULL; 1563 1564 v_map->vsi_list_id = vsi_list_id; 1565 v_map->ref_cnt = 1; 1566 for (i = 0; i < num_vsi; i++) 1567 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map); 1568 1569 LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head); 1570 return v_map; 1571 } 1572 1573 /** 1574 * ice_update_vsi_list_rule 1575 * @hw: pointer to the hardware structure 1576 * @vsi_handle_arr: array of VSI handles to form a VSI list 1577 * @num_vsi: number of VSI handles in the array 1578 * @vsi_list_id: VSI list ID generated as part of allocate resource 1579 * @remove: Boolean value to indicate if this is a remove action 1580 * @opc: switch rules population command type - pass in the command opcode 1581 * @lkup_type: lookup type of the filter 1582 * 1583 * Call AQ command to add a new switch rule or update existing switch rule 1584 * using the given VSI list ID 1585 */ 1586 static enum ice_status 1587 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1588 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 1589 enum ice_sw_lkup_type lkup_type) 1590 { 1591 struct ice_sw_rule_vsi_list *s_rule; 1592 enum ice_status status; 1593 u16 s_rule_size; 1594 u16 rule_type; 1595 int i; 1596 1597 if (!num_vsi) 1598 return ICE_ERR_PARAM; 1599 1600 if (lkup_type == ICE_SW_LKUP_MAC || 1601 lkup_type == ICE_SW_LKUP_MAC_VLAN || 1602 lkup_type == ICE_SW_LKUP_ETHERTYPE || 1603 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 1604 lkup_type == ICE_SW_LKUP_PROMISC || 1605 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 1606 lkup_type == ICE_SW_LKUP_DFLT || 1607 lkup_type == ICE_SW_LKUP_LAST) 1608 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 1609 ICE_AQC_SW_RULES_T_VSI_LIST_SET; 1610 else if (lkup_type == ICE_SW_LKUP_VLAN) 1611 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 1612 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 1613 else 1614 return ICE_ERR_PARAM; 1615 1616 s_rule_size = (u16)ice_struct_size(s_rule, vsi, num_vsi); 1617 s_rule = (struct ice_sw_rule_vsi_list *)ice_malloc(hw, s_rule_size); 1618 if (!s_rule) 1619 return ICE_ERR_NO_MEMORY; 1620 for (i = 0; i < num_vsi; i++) { 1621 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 1622 status = ICE_ERR_PARAM; 1623 goto exit; 1624 } 1625 /* AQ call requires hw_vsi_id(s) */ 1626 s_rule->vsi[i] = 1627 CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 1628 } 1629 1630 s_rule->hdr.type = CPU_TO_LE16(rule_type); 1631 s_rule->number_vsi = CPU_TO_LE16(num_vsi); 1632 s_rule->index = CPU_TO_LE16(vsi_list_id); 1633 1634 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 1635 1636 exit: 1637 ice_free(hw, s_rule); 1638 return status; 1639 } 1640 1641 /** 1642 * ice_create_vsi_list_rule - Creates and populates a VSI list rule 1643 * @hw: pointer to the HW struct 1644 * @vsi_handle_arr: array of VSI handles to form a VSI list 1645 * @num_vsi: number of VSI handles in the array 1646 * @vsi_list_id: stores the ID of the VSI list to be created 1647 * @lkup_type: switch rule filter's lookup type 1648 */ 1649 static enum ice_status 1650 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1651 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 1652 { 1653 enum ice_status status; 1654 1655 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 1656 ice_aqc_opc_alloc_res); 1657 if (status) 1658 return status; 1659 1660 /* Update the newly created VSI list to include the specified VSIs */ 1661 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 1662 *vsi_list_id, false, 1663 ice_aqc_opc_add_sw_rules, lkup_type); 1664 } 1665 1666 /** 1667 * ice_create_pkt_fwd_rule 1668 * @hw: pointer to the hardware structure 1669 * @recp_list: corresponding filter management list 1670 * @f_entry: entry containing packet forwarding information 1671 * 1672 * Create switch rule with given filter information and add an entry 1673 * to the corresponding filter management list to track this switch rule 1674 * and VSI mapping 1675 */ 1676 static enum ice_status 1677 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 1678 struct ice_fltr_list_entry *f_entry) 1679 { 1680 struct ice_fltr_mgmt_list_entry *fm_entry; 1681 struct ice_sw_rule_lkup_rx_tx *s_rule; 1682 enum ice_status status; 1683 1684 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 1685 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 1686 DUMMY_ETH_HDR_LEN)); 1687 if (!s_rule) 1688 return ICE_ERR_NO_MEMORY; 1689 fm_entry = (struct ice_fltr_mgmt_list_entry *) 1690 ice_malloc(hw, sizeof(*fm_entry)); 1691 if (!fm_entry) { 1692 status = ICE_ERR_NO_MEMORY; 1693 goto ice_create_pkt_fwd_rule_exit; 1694 } 1695 1696 fm_entry->fltr_info = f_entry->fltr_info; 1697 1698 /* Initialize all the fields for the management entry */ 1699 fm_entry->vsi_count = 1; 1700 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 1701 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 1702 fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 1703 1704 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 1705 ice_aqc_opc_add_sw_rules); 1706 1707 status = ice_aq_sw_rules(hw, s_rule, 1708 ice_struct_size(s_rule, hdr_data, 1709 DUMMY_ETH_HDR_LEN), 1710 1, ice_aqc_opc_add_sw_rules, NULL); 1711 if (status) { 1712 ice_free(hw, fm_entry); 1713 goto ice_create_pkt_fwd_rule_exit; 1714 } 1715 1716 f_entry->fltr_info.fltr_rule_id = LE16_TO_CPU(s_rule->index); 1717 fm_entry->fltr_info.fltr_rule_id = LE16_TO_CPU(s_rule->index); 1718 1719 /* The book keeping entries will get removed when base driver 1720 * calls remove filter AQ command 1721 */ 1722 LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules); 1723 1724 ice_create_pkt_fwd_rule_exit: 1725 ice_free(hw, s_rule); 1726 return status; 1727 } 1728 1729 /** 1730 * ice_update_pkt_fwd_rule 1731 * @hw: pointer to the hardware structure 1732 * @f_info: filter information for switch rule 1733 * 1734 * Call AQ command to update a previously created switch rule with a 1735 * VSI list ID 1736 */ 1737 static enum ice_status 1738 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 1739 { 1740 struct ice_sw_rule_lkup_rx_tx *s_rule; 1741 enum ice_status status; 1742 1743 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 1744 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 1745 DUMMY_ETH_HDR_LEN)); 1746 if (!s_rule) 1747 return ICE_ERR_NO_MEMORY; 1748 1749 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 1750 1751 s_rule->index = CPU_TO_LE16(f_info->fltr_rule_id); 1752 1753 /* Update switch rule with new rule set to forward VSI list */ 1754 status = ice_aq_sw_rules(hw, s_rule, 1755 ice_struct_size(s_rule, hdr_data, 1756 DUMMY_ETH_HDR_LEN), 1757 1, ice_aqc_opc_update_sw_rules, NULL); 1758 1759 ice_free(hw, s_rule); 1760 return status; 1761 } 1762 1763 /** 1764 * ice_update_sw_rule_bridge_mode 1765 * @hw: pointer to the HW struct 1766 * 1767 * Updates unicast switch filter rules based on VEB/VEPA mode 1768 */ 1769 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 1770 { 1771 struct ice_fltr_mgmt_list_entry *fm_entry; 1772 enum ice_status status = ICE_SUCCESS; 1773 struct ice_switch_info *sw = NULL; 1774 struct LIST_HEAD_TYPE *rule_head; 1775 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 1776 sw = hw->switch_info; 1777 1778 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 1779 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 1780 1781 ice_acquire_lock(rule_lock); 1782 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry, 1783 list_entry) { 1784 struct ice_fltr_info *fi = &fm_entry->fltr_info; 1785 u8 *addr = fi->l_data.mac.mac_addr; 1786 1787 /* Update unicast Tx rules to reflect the selected 1788 * VEB/VEPA mode 1789 */ 1790 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) && 1791 (fi->fltr_act == ICE_FWD_TO_VSI || 1792 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1793 fi->fltr_act == ICE_FWD_TO_Q || 1794 fi->fltr_act == ICE_FWD_TO_QGRP)) { 1795 status = ice_update_pkt_fwd_rule(hw, fi); 1796 if (status) 1797 break; 1798 } 1799 } 1800 1801 ice_release_lock(rule_lock); 1802 1803 return status; 1804 } 1805 1806 /** 1807 * ice_add_update_vsi_list 1808 * @hw: pointer to the hardware structure 1809 * @m_entry: pointer to current filter management list entry 1810 * @cur_fltr: filter information from the book keeping entry 1811 * @new_fltr: filter information with the new VSI to be added 1812 * 1813 * Call AQ command to add or update previously created VSI list with new VSI. 1814 * 1815 * Helper function to do book keeping associated with adding filter information 1816 * The algorithm to do the book keeping is described below : 1817 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 1818 * if only one VSI has been added till now 1819 * Allocate a new VSI list and add two VSIs 1820 * to this list using switch rule command 1821 * Update the previously created switch rule with the 1822 * newly created VSI list ID 1823 * if a VSI list was previously created 1824 * Add the new VSI to the previously created VSI list set 1825 * using the update switch rule command 1826 */ 1827 static enum ice_status 1828 ice_add_update_vsi_list(struct ice_hw *hw, 1829 struct ice_fltr_mgmt_list_entry *m_entry, 1830 struct ice_fltr_info *cur_fltr, 1831 struct ice_fltr_info *new_fltr) 1832 { 1833 enum ice_status status = ICE_SUCCESS; 1834 u16 vsi_list_id = 0; 1835 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 1836 cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 1837 return ICE_ERR_NOT_IMPL; 1838 1839 if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 1840 new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 1841 (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 1842 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 1843 return ICE_ERR_NOT_IMPL; 1844 1845 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 1846 /* Only one entry existed in the mapping and it was not already 1847 * a part of a VSI list. So, create a VSI list with the old and 1848 * new VSIs. 1849 */ 1850 struct ice_fltr_info tmp_fltr; 1851 u16 vsi_handle_arr[2]; 1852 1853 /* A rule already exists with the new VSI being added */ 1854 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 1855 return ICE_ERR_ALREADY_EXISTS; 1856 1857 vsi_handle_arr[0] = cur_fltr->vsi_handle; 1858 vsi_handle_arr[1] = new_fltr->vsi_handle; 1859 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 1860 &vsi_list_id, 1861 new_fltr->lkup_type); 1862 if (status) 1863 return status; 1864 1865 tmp_fltr = *new_fltr; 1866 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 1867 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 1868 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 1869 /* Update the previous switch rule of "MAC forward to VSI" to 1870 * "MAC fwd to VSI list" 1871 */ 1872 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 1873 if (status) 1874 return status; 1875 1876 cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 1877 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 1878 m_entry->vsi_list_info = 1879 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 1880 vsi_list_id); 1881 1882 if (!m_entry->vsi_list_info) 1883 return ICE_ERR_NO_MEMORY; 1884 1885 /* If this entry was large action then the large action needs 1886 * to be updated to point to FWD to VSI list 1887 */ 1888 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 1889 status = 1890 ice_add_marker_act(hw, m_entry, 1891 m_entry->sw_marker_id, 1892 m_entry->lg_act_idx); 1893 } else { 1894 u16 vsi_handle = new_fltr->vsi_handle; 1895 enum ice_adminq_opc opcode; 1896 1897 if (!m_entry->vsi_list_info) 1898 return ICE_ERR_CFG; 1899 1900 /* A rule already exists with the new VSI being added */ 1901 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 1902 return ICE_SUCCESS; 1903 1904 /* Update the previously created VSI list set with 1905 * the new VSI ID passed in 1906 */ 1907 vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 1908 opcode = ice_aqc_opc_update_sw_rules; 1909 1910 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 1911 vsi_list_id, false, opcode, 1912 new_fltr->lkup_type); 1913 /* update VSI list mapping info with new VSI ID */ 1914 if (!status) 1915 ice_set_bit(vsi_handle, 1916 m_entry->vsi_list_info->vsi_map); 1917 } 1918 if (!status) 1919 m_entry->vsi_count++; 1920 return status; 1921 } 1922 1923 /** 1924 * ice_find_rule_entry - Search a rule entry 1925 * @list_head: head of rule list 1926 * @f_info: rule information 1927 * 1928 * Helper function to search for a given rule entry 1929 * Returns pointer to entry storing the rule if found 1930 */ 1931 static struct ice_fltr_mgmt_list_entry * 1932 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head, 1933 struct ice_fltr_info *f_info) 1934 { 1935 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 1936 1937 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 1938 list_entry) { 1939 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 1940 sizeof(f_info->l_data)) && 1941 f_info->flag == list_itr->fltr_info.flag) { 1942 ret = list_itr; 1943 break; 1944 } 1945 } 1946 return ret; 1947 } 1948 1949 /** 1950 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 1951 * @recp_list: VSI lists needs to be searched 1952 * @vsi_handle: VSI handle to be found in VSI list 1953 * @vsi_list_id: VSI list ID found containing vsi_handle 1954 * 1955 * Helper function to search a VSI list with single entry containing given VSI 1956 * handle element. This can be extended further to search VSI list with more 1957 * than 1 vsi_count. Returns pointer to VSI list entry if found. 1958 */ 1959 struct ice_vsi_list_map_info * 1960 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle, 1961 u16 *vsi_list_id) 1962 { 1963 struct ice_vsi_list_map_info *map_info = NULL; 1964 struct LIST_HEAD_TYPE *list_head; 1965 1966 list_head = &recp_list->filt_rules; 1967 if (recp_list->adv_rule) { 1968 struct ice_adv_fltr_mgmt_list_entry *list_itr; 1969 1970 LIST_FOR_EACH_ENTRY(list_itr, list_head, 1971 ice_adv_fltr_mgmt_list_entry, 1972 list_entry) { 1973 if (list_itr->vsi_list_info) { 1974 map_info = list_itr->vsi_list_info; 1975 if (ice_is_bit_set(map_info->vsi_map, 1976 vsi_handle)) { 1977 *vsi_list_id = map_info->vsi_list_id; 1978 return map_info; 1979 } 1980 } 1981 } 1982 } else { 1983 struct ice_fltr_mgmt_list_entry *list_itr; 1984 1985 LIST_FOR_EACH_ENTRY(list_itr, list_head, 1986 ice_fltr_mgmt_list_entry, 1987 list_entry) { 1988 if (list_itr->vsi_count == 1 && 1989 list_itr->vsi_list_info) { 1990 map_info = list_itr->vsi_list_info; 1991 if (ice_is_bit_set(map_info->vsi_map, 1992 vsi_handle)) { 1993 *vsi_list_id = map_info->vsi_list_id; 1994 return map_info; 1995 } 1996 } 1997 } 1998 } 1999 return NULL; 2000 } 2001 2002 /** 2003 * ice_add_rule_internal - add rule for a given lookup type 2004 * @hw: pointer to the hardware structure 2005 * @recp_list: recipe list for which rule has to be added 2006 * @lport: logic port number on which function add rule 2007 * @f_entry: structure containing MAC forwarding information 2008 * 2009 * Adds or updates the rule lists for a given recipe 2010 */ 2011 static enum ice_status 2012 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2013 u8 lport, struct ice_fltr_list_entry *f_entry) 2014 { 2015 struct ice_fltr_info *new_fltr, *cur_fltr; 2016 struct ice_fltr_mgmt_list_entry *m_entry; 2017 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2018 enum ice_status status = ICE_SUCCESS; 2019 2020 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2021 return ICE_ERR_PARAM; 2022 2023 /* Load the hw_vsi_id only if the fwd action is fwd to VSI */ 2024 if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI) 2025 f_entry->fltr_info.fwd_id.hw_vsi_id = 2026 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2027 2028 rule_lock = &recp_list->filt_rule_lock; 2029 2030 ice_acquire_lock(rule_lock); 2031 new_fltr = &f_entry->fltr_info; 2032 if (new_fltr->flag & ICE_FLTR_RX) 2033 new_fltr->src = lport; 2034 else if (new_fltr->flag & (ICE_FLTR_TX | ICE_FLTR_RX_LB)) 2035 new_fltr->src = 2036 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2037 2038 m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 2039 if (!m_entry) { 2040 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 2041 goto exit_add_rule_internal; 2042 } 2043 2044 cur_fltr = &m_entry->fltr_info; 2045 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 2046 2047 exit_add_rule_internal: 2048 ice_release_lock(rule_lock); 2049 return status; 2050 } 2051 2052 /** 2053 * ice_remove_vsi_list_rule 2054 * @hw: pointer to the hardware structure 2055 * @vsi_list_id: VSI list ID generated as part of allocate resource 2056 * @lkup_type: switch rule filter lookup type 2057 * 2058 * The VSI list should be emptied before this function is called to remove the 2059 * VSI list. 2060 */ 2061 static enum ice_status 2062 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 2063 enum ice_sw_lkup_type lkup_type) 2064 { 2065 /* Free the vsi_list resource that we allocated. It is assumed that the 2066 * list is empty at this point. 2067 */ 2068 return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 2069 ice_aqc_opc_free_res); 2070 } 2071 2072 /** 2073 * ice_rem_update_vsi_list 2074 * @hw: pointer to the hardware structure 2075 * @vsi_handle: VSI handle of the VSI to remove 2076 * @fm_list: filter management entry for which the VSI list management needs to 2077 * be done 2078 */ 2079 static enum ice_status 2080 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 2081 struct ice_fltr_mgmt_list_entry *fm_list) 2082 { 2083 enum ice_sw_lkup_type lkup_type; 2084 enum ice_status status = ICE_SUCCESS; 2085 u16 vsi_list_id; 2086 2087 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 2088 fm_list->vsi_count == 0) 2089 return ICE_ERR_PARAM; 2090 2091 /* A rule with the VSI being removed does not exist */ 2092 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 2093 return ICE_ERR_DOES_NOT_EXIST; 2094 2095 lkup_type = fm_list->fltr_info.lkup_type; 2096 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 2097 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 2098 ice_aqc_opc_update_sw_rules, 2099 lkup_type); 2100 if (status) 2101 return status; 2102 2103 fm_list->vsi_count--; 2104 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 2105 2106 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 2107 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 2108 struct ice_vsi_list_map_info *vsi_list_info = 2109 fm_list->vsi_list_info; 2110 u16 rem_vsi_handle; 2111 2112 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 2113 ICE_MAX_VSI); 2114 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 2115 return ICE_ERR_OUT_OF_RANGE; 2116 2117 /* Make sure VSI list is empty before removing it below */ 2118 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 2119 vsi_list_id, true, 2120 ice_aqc_opc_update_sw_rules, 2121 lkup_type); 2122 if (status) 2123 return status; 2124 2125 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 2126 tmp_fltr_info.fwd_id.hw_vsi_id = 2127 ice_get_hw_vsi_num(hw, rem_vsi_handle); 2128 tmp_fltr_info.vsi_handle = rem_vsi_handle; 2129 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 2130 if (status) { 2131 ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 2132 tmp_fltr_info.fwd_id.hw_vsi_id, status); 2133 return status; 2134 } 2135 2136 fm_list->fltr_info = tmp_fltr_info; 2137 } 2138 2139 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 2140 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 2141 struct ice_vsi_list_map_info *vsi_list_info = 2142 fm_list->vsi_list_info; 2143 2144 /* Remove the VSI list since it is no longer used */ 2145 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 2146 if (status) { 2147 ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n", 2148 vsi_list_id, status); 2149 return status; 2150 } 2151 2152 LIST_DEL(&vsi_list_info->list_entry); 2153 ice_free(hw, vsi_list_info); 2154 fm_list->vsi_list_info = NULL; 2155 } 2156 2157 return status; 2158 } 2159 2160 /** 2161 * ice_remove_rule_internal - Remove a filter rule of a given type 2162 * @hw: pointer to the hardware structure 2163 * @recp_list: recipe list for which the rule needs to removed 2164 * @f_entry: rule entry containing filter information 2165 */ 2166 static enum ice_status 2167 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2168 struct ice_fltr_list_entry *f_entry) 2169 { 2170 struct ice_fltr_mgmt_list_entry *list_elem; 2171 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2172 enum ice_status status = ICE_SUCCESS; 2173 bool remove_rule = false; 2174 u16 vsi_handle; 2175 2176 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2177 return ICE_ERR_PARAM; 2178 f_entry->fltr_info.fwd_id.hw_vsi_id = 2179 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2180 2181 rule_lock = &recp_list->filt_rule_lock; 2182 ice_acquire_lock(rule_lock); 2183 list_elem = ice_find_rule_entry(&recp_list->filt_rules, 2184 &f_entry->fltr_info); 2185 if (!list_elem) { 2186 status = ICE_ERR_DOES_NOT_EXIST; 2187 goto exit; 2188 } 2189 2190 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 2191 remove_rule = true; 2192 } else if (!list_elem->vsi_list_info) { 2193 status = ICE_ERR_DOES_NOT_EXIST; 2194 goto exit; 2195 } else if (list_elem->vsi_list_info->ref_cnt > 1) { 2196 /* a ref_cnt > 1 indicates that the vsi_list is being 2197 * shared by multiple rules. Decrement the ref_cnt and 2198 * remove this rule, but do not modify the list, as it 2199 * is in-use by other rules. 2200 */ 2201 list_elem->vsi_list_info->ref_cnt--; 2202 remove_rule = true; 2203 } else { 2204 /* a ref_cnt of 1 indicates the vsi_list is only used 2205 * by one rule. However, the original removal request is only 2206 * for a single VSI. Update the vsi_list first, and only 2207 * remove the rule if there are no further VSIs in this list. 2208 */ 2209 vsi_handle = f_entry->fltr_info.vsi_handle; 2210 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 2211 if (status) 2212 goto exit; 2213 /* if VSI count goes to zero after updating the VSI list */ 2214 if (list_elem->vsi_count == 0) 2215 remove_rule = true; 2216 } 2217 2218 if (remove_rule) { 2219 /* Remove the lookup rule */ 2220 struct ice_sw_rule_lkup_rx_tx *s_rule; 2221 2222 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 2223 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 0)); 2224 if (!s_rule) { 2225 status = ICE_ERR_NO_MEMORY; 2226 goto exit; 2227 } 2228 2229 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 2230 ice_aqc_opc_remove_sw_rules); 2231 2232 status = ice_aq_sw_rules(hw, s_rule, 2233 ice_struct_size(s_rule, hdr_data, 0), 2234 1, ice_aqc_opc_remove_sw_rules, NULL); 2235 2236 /* Remove a book keeping from the list */ 2237 ice_free(hw, s_rule); 2238 2239 if (status) 2240 goto exit; 2241 2242 LIST_DEL(&list_elem->list_entry); 2243 ice_free(hw, list_elem); 2244 } 2245 exit: 2246 ice_release_lock(rule_lock); 2247 return status; 2248 } 2249 2250 /** 2251 * ice_aq_get_res_alloc - get allocated resources 2252 * @hw: pointer to the HW struct 2253 * @num_entries: pointer to u16 to store the number of resource entries returned 2254 * @buf: pointer to buffer 2255 * @buf_size: size of buf 2256 * @cd: pointer to command details structure or NULL 2257 * 2258 * The caller-supplied buffer must be large enough to store the resource 2259 * information for all resource types. Each resource type is an 2260 * ice_aqc_get_res_resp_elem structure. 2261 */ 2262 enum ice_status 2263 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, 2264 struct ice_aqc_get_res_resp_elem *buf, u16 buf_size, 2265 struct ice_sq_cd *cd) 2266 { 2267 struct ice_aqc_get_res_alloc *resp; 2268 enum ice_status status; 2269 struct ice_aq_desc desc; 2270 2271 if (!buf) 2272 return ICE_ERR_BAD_PTR; 2273 2274 if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN) 2275 return ICE_ERR_INVAL_SIZE; 2276 2277 resp = &desc.params.get_res; 2278 2279 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc); 2280 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2281 2282 if (!status && num_entries) 2283 *num_entries = LE16_TO_CPU(resp->resp_elem_num); 2284 2285 return status; 2286 } 2287 2288 /** 2289 * ice_aq_get_res_descs - get allocated resource descriptors 2290 * @hw: pointer to the hardware structure 2291 * @num_entries: number of resource entries in buffer 2292 * @buf: structure to hold response data buffer 2293 * @buf_size: size of buffer 2294 * @res_type: resource type 2295 * @res_shared: is resource shared 2296 * @desc_id: input - first desc ID to start; output - next desc ID 2297 * @cd: pointer to command details structure or NULL 2298 */ 2299 enum ice_status 2300 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries, 2301 struct ice_aqc_res_elem *buf, u16 buf_size, u16 res_type, 2302 bool res_shared, u16 *desc_id, struct ice_sq_cd *cd) 2303 { 2304 struct ice_aqc_get_allocd_res_desc *cmd; 2305 struct ice_aq_desc desc; 2306 enum ice_status status; 2307 2308 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2309 2310 cmd = &desc.params.get_res_desc; 2311 2312 if (!buf) 2313 return ICE_ERR_PARAM; 2314 2315 if (buf_size != (num_entries * sizeof(*buf))) 2316 return ICE_ERR_PARAM; 2317 2318 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc); 2319 2320 cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) & 2321 ICE_AQC_RES_TYPE_M) | (res_shared ? 2322 ICE_AQC_RES_TYPE_FLAG_SHARED : 0)); 2323 cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id); 2324 2325 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2326 if (!status) 2327 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc); 2328 2329 return status; 2330 } 2331 2332 /** 2333 * ice_add_mac_rule - Add a MAC address based filter rule 2334 * @hw: pointer to the hardware structure 2335 * @m_list: list of MAC addresses and forwarding information 2336 * @sw: pointer to switch info struct for which function add rule 2337 * @lport: logic port number on which function add rule 2338 * 2339 * IMPORTANT: When the umac_shared flag is set to false and m_list has 2340 * multiple unicast addresses, the function assumes that all the 2341 * addresses are unique in a given add_mac call. It doesn't 2342 * check for duplicates in this case, removing duplicates from a given 2343 * list should be taken care of in the caller of this function. 2344 */ 2345 static enum ice_status 2346 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 2347 struct ice_switch_info *sw, u8 lport) 2348 { 2349 struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC]; 2350 struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter; 2351 struct ice_fltr_list_entry *m_list_itr; 2352 struct LIST_HEAD_TYPE *rule_head; 2353 u16 total_elem_left, s_rule_size; 2354 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2355 enum ice_status status = ICE_SUCCESS; 2356 u16 num_unicast = 0; 2357 u8 elem_sent; 2358 2359 s_rule = NULL; 2360 rule_lock = &recp_list->filt_rule_lock; 2361 rule_head = &recp_list->filt_rules; 2362 2363 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2364 list_entry) { 2365 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 2366 u16 vsi_handle; 2367 u16 hw_vsi_id; 2368 2369 m_list_itr->fltr_info.flag = ICE_FLTR_TX; 2370 vsi_handle = m_list_itr->fltr_info.vsi_handle; 2371 if (!ice_is_vsi_valid(hw, vsi_handle)) 2372 return ICE_ERR_PARAM; 2373 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2374 if (m_list_itr->fltr_info.fltr_act == ICE_FWD_TO_VSI) 2375 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 2376 /* update the src in case it is VSI num */ 2377 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 2378 return ICE_ERR_PARAM; 2379 m_list_itr->fltr_info.src = hw_vsi_id; 2380 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 2381 IS_ZERO_ETHER_ADDR(add)) 2382 return ICE_ERR_PARAM; 2383 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) { 2384 /* Don't overwrite the unicast address */ 2385 ice_acquire_lock(rule_lock); 2386 if (ice_find_rule_entry(rule_head, 2387 &m_list_itr->fltr_info)) { 2388 ice_release_lock(rule_lock); 2389 continue; 2390 } 2391 ice_release_lock(rule_lock); 2392 num_unicast++; 2393 } else if (IS_MULTICAST_ETHER_ADDR(add) || 2394 (IS_UNICAST_ETHER_ADDR(add) && hw->umac_shared)) { 2395 m_list_itr->status = 2396 ice_add_rule_internal(hw, recp_list, lport, 2397 m_list_itr); 2398 if (m_list_itr->status) 2399 return m_list_itr->status; 2400 } 2401 } 2402 2403 ice_acquire_lock(rule_lock); 2404 /* Exit if no suitable entries were found for adding bulk switch rule */ 2405 if (!num_unicast) { 2406 status = ICE_SUCCESS; 2407 goto ice_add_mac_exit; 2408 } 2409 2410 /* Allocate switch rule buffer for the bulk update for unicast */ 2411 s_rule_size = ice_struct_size(s_rule, hdr_data, DUMMY_ETH_HDR_LEN); 2412 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 2413 ice_calloc(hw, num_unicast, s_rule_size); 2414 if (!s_rule) { 2415 status = ICE_ERR_NO_MEMORY; 2416 goto ice_add_mac_exit; 2417 } 2418 2419 r_iter = s_rule; 2420 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2421 list_entry) { 2422 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2423 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2424 2425 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2426 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 2427 ice_aqc_opc_add_sw_rules); 2428 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2429 ((u8 *)r_iter + s_rule_size); 2430 } 2431 } 2432 2433 /* Call AQ bulk switch rule update for all unicast addresses */ 2434 r_iter = s_rule; 2435 /* Call AQ switch rule in AQ_MAX chunk */ 2436 for (total_elem_left = num_unicast; total_elem_left > 0; 2437 total_elem_left -= elem_sent) { 2438 struct ice_sw_rule_lkup_rx_tx *entry = r_iter; 2439 2440 elem_sent = MIN_T(u8, total_elem_left, 2441 (ICE_AQ_MAX_BUF_LEN / s_rule_size)); 2442 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 2443 elem_sent, ice_aqc_opc_add_sw_rules, 2444 NULL); 2445 if (status) 2446 goto ice_add_mac_exit; 2447 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2448 ((u8 *)r_iter + (elem_sent * s_rule_size)); 2449 } 2450 2451 /* Fill up rule ID based on the value returned from FW */ 2452 r_iter = s_rule; 2453 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2454 list_entry) { 2455 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2456 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2457 struct ice_fltr_mgmt_list_entry *fm_entry; 2458 2459 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2460 f_info->fltr_rule_id = 2461 LE16_TO_CPU(r_iter->index); 2462 f_info->fltr_act = ICE_FWD_TO_VSI; 2463 /* Create an entry to track this MAC address */ 2464 fm_entry = (struct ice_fltr_mgmt_list_entry *) 2465 ice_malloc(hw, sizeof(*fm_entry)); 2466 if (!fm_entry) { 2467 status = ICE_ERR_NO_MEMORY; 2468 goto ice_add_mac_exit; 2469 } 2470 fm_entry->fltr_info = *f_info; 2471 fm_entry->vsi_count = 1; 2472 /* The book keeping entries will get removed when 2473 * base driver calls remove filter AQ command 2474 */ 2475 2476 LIST_ADD(&fm_entry->list_entry, rule_head); 2477 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2478 ((u8 *)r_iter + s_rule_size); 2479 } 2480 } 2481 2482 ice_add_mac_exit: 2483 ice_release_lock(rule_lock); 2484 if (s_rule) 2485 ice_free(hw, s_rule); 2486 return status; 2487 } 2488 2489 /** 2490 * ice_add_mac - Add a MAC address based filter rule 2491 * @hw: pointer to the hardware structure 2492 * @m_list: list of MAC addresses and forwarding information 2493 * 2494 * Function add MAC rule for logical port from HW struct 2495 */ 2496 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 2497 { 2498 if (!m_list || !hw) 2499 return ICE_ERR_PARAM; 2500 2501 return ice_add_mac_rule(hw, m_list, hw->switch_info, 2502 hw->port_info->lport); 2503 } 2504 2505 /** 2506 * ice_add_vlan_internal - Add one VLAN based filter rule 2507 * @hw: pointer to the hardware structure 2508 * @recp_list: recipe list for which rule has to be added 2509 * @f_entry: filter entry containing one VLAN information 2510 */ 2511 static enum ice_status 2512 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2513 struct ice_fltr_list_entry *f_entry) 2514 { 2515 struct ice_fltr_mgmt_list_entry *v_list_itr; 2516 struct ice_fltr_info *new_fltr, *cur_fltr; 2517 enum ice_sw_lkup_type lkup_type; 2518 u16 vsi_list_id = 0, vsi_handle; 2519 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2520 enum ice_status status = ICE_SUCCESS; 2521 2522 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2523 return ICE_ERR_PARAM; 2524 2525 f_entry->fltr_info.fwd_id.hw_vsi_id = 2526 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2527 new_fltr = &f_entry->fltr_info; 2528 2529 /* VLAN ID should only be 12 bits */ 2530 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 2531 return ICE_ERR_PARAM; 2532 2533 if (new_fltr->src_id != ICE_SRC_ID_VSI) 2534 return ICE_ERR_PARAM; 2535 2536 new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 2537 lkup_type = new_fltr->lkup_type; 2538 vsi_handle = new_fltr->vsi_handle; 2539 rule_lock = &recp_list->filt_rule_lock; 2540 ice_acquire_lock(rule_lock); 2541 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 2542 if (!v_list_itr) { 2543 struct ice_vsi_list_map_info *map_info = NULL; 2544 2545 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 2546 /* All VLAN pruning rules use a VSI list. Check if 2547 * there is already a VSI list containing VSI that we 2548 * want to add. If found, use the same vsi_list_id for 2549 * this new VLAN rule or else create a new list. 2550 */ 2551 map_info = ice_find_vsi_list_entry(recp_list, 2552 vsi_handle, 2553 &vsi_list_id); 2554 if (!map_info) { 2555 status = ice_create_vsi_list_rule(hw, 2556 &vsi_handle, 2557 1, 2558 &vsi_list_id, 2559 lkup_type); 2560 if (status) 2561 goto exit; 2562 } 2563 /* Convert the action to forwarding to a VSI list. */ 2564 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 2565 new_fltr->fwd_id.vsi_list_id = vsi_list_id; 2566 } 2567 2568 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 2569 if (!status) { 2570 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, 2571 new_fltr); 2572 if (!v_list_itr) { 2573 status = ICE_ERR_DOES_NOT_EXIST; 2574 goto exit; 2575 } 2576 /* reuse VSI list for new rule and increment ref_cnt */ 2577 if (map_info) { 2578 v_list_itr->vsi_list_info = map_info; 2579 map_info->ref_cnt++; 2580 } else { 2581 v_list_itr->vsi_list_info = 2582 ice_create_vsi_list_map(hw, &vsi_handle, 2583 1, vsi_list_id); 2584 } 2585 } 2586 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 2587 /* Update existing VSI list to add new VSI ID only if it used 2588 * by one VLAN rule. 2589 */ 2590 cur_fltr = &v_list_itr->fltr_info; 2591 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 2592 new_fltr); 2593 } else { 2594 /* If VLAN rule exists and VSI list being used by this rule is 2595 * referenced by more than 1 VLAN rule. Then create a new VSI 2596 * list appending previous VSI with new VSI and update existing 2597 * VLAN rule to point to new VSI list ID 2598 */ 2599 struct ice_fltr_info tmp_fltr; 2600 u16 vsi_handle_arr[2]; 2601 u16 cur_handle; 2602 2603 /* Current implementation only supports reusing VSI list with 2604 * one VSI count. We should never hit below condition 2605 */ 2606 if (v_list_itr->vsi_count > 1 && 2607 v_list_itr->vsi_list_info->ref_cnt > 1) { 2608 ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 2609 status = ICE_ERR_CFG; 2610 goto exit; 2611 } 2612 2613 cur_handle = 2614 ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map, 2615 ICE_MAX_VSI); 2616 2617 /* A rule already exists with the new VSI being added */ 2618 if (cur_handle == vsi_handle) { 2619 status = ICE_ERR_ALREADY_EXISTS; 2620 goto exit; 2621 } 2622 2623 vsi_handle_arr[0] = cur_handle; 2624 vsi_handle_arr[1] = vsi_handle; 2625 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 2626 &vsi_list_id, lkup_type); 2627 if (status) 2628 goto exit; 2629 2630 tmp_fltr = v_list_itr->fltr_info; 2631 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 2632 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 2633 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 2634 /* Update the previous switch rule to a new VSI list which 2635 * includes current VSI that is requested 2636 */ 2637 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 2638 if (status) 2639 goto exit; 2640 2641 /* before overriding VSI list map info. decrement ref_cnt of 2642 * previous VSI list 2643 */ 2644 v_list_itr->vsi_list_info->ref_cnt--; 2645 2646 /* now update to newly created list */ 2647 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 2648 v_list_itr->vsi_list_info = 2649 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 2650 vsi_list_id); 2651 v_list_itr->vsi_count++; 2652 } 2653 2654 exit: 2655 ice_release_lock(rule_lock); 2656 return status; 2657 } 2658 2659 /** 2660 * ice_add_vlan_rule - Add VLAN based filter rule 2661 * @hw: pointer to the hardware structure 2662 * @v_list: list of VLAN entries and forwarding information 2663 * @sw: pointer to switch info struct for which function add rule 2664 */ 2665 static enum ice_status 2666 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 2667 struct ice_switch_info *sw) 2668 { 2669 struct ice_fltr_list_entry *v_list_itr; 2670 struct ice_sw_recipe *recp_list; 2671 2672 recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN]; 2673 LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry, 2674 list_entry) { 2675 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 2676 return ICE_ERR_PARAM; 2677 v_list_itr->fltr_info.flag = ICE_FLTR_TX; 2678 v_list_itr->status = ice_add_vlan_internal(hw, recp_list, 2679 v_list_itr); 2680 if (v_list_itr->status) 2681 return v_list_itr->status; 2682 } 2683 return ICE_SUCCESS; 2684 } 2685 2686 /** 2687 * ice_add_vlan - Add a VLAN based filter rule 2688 * @hw: pointer to the hardware structure 2689 * @v_list: list of VLAN and forwarding information 2690 * 2691 * Function add VLAN rule for logical port from HW struct 2692 */ 2693 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 2694 { 2695 if (!v_list || !hw) 2696 return ICE_ERR_PARAM; 2697 2698 return ice_add_vlan_rule(hw, v_list, hw->switch_info); 2699 } 2700 2701 /** 2702 * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule 2703 * @hw: pointer to the hardware structure 2704 * @em_list: list of ether type MAC filter, MAC is optional 2705 * @sw: pointer to switch info struct for which function add rule 2706 * @lport: logic port number on which function add rule 2707 * 2708 * This function requires the caller to populate the entries in 2709 * the filter list with the necessary fields (including flags to 2710 * indicate Tx or Rx rules). 2711 */ 2712 static enum ice_status 2713 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 2714 struct ice_switch_info *sw, u8 lport) 2715 { 2716 struct ice_fltr_list_entry *em_list_itr; 2717 2718 LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry, 2719 list_entry) { 2720 struct ice_sw_recipe *recp_list; 2721 enum ice_sw_lkup_type l_type; 2722 2723 l_type = em_list_itr->fltr_info.lkup_type; 2724 recp_list = &sw->recp_list[l_type]; 2725 2726 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 2727 l_type != ICE_SW_LKUP_ETHERTYPE) 2728 return ICE_ERR_PARAM; 2729 2730 em_list_itr->status = ice_add_rule_internal(hw, recp_list, 2731 lport, 2732 em_list_itr); 2733 if (em_list_itr->status) 2734 return em_list_itr->status; 2735 } 2736 return ICE_SUCCESS; 2737 } 2738 2739 /** 2740 * ice_add_eth_mac - Add a ethertype based filter rule 2741 * @hw: pointer to the hardware structure 2742 * @em_list: list of ethertype and forwarding information 2743 * 2744 * Function add ethertype rule for logical port from HW struct 2745 */ 2746 enum ice_status 2747 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 2748 { 2749 if (!em_list || !hw) 2750 return ICE_ERR_PARAM; 2751 2752 return ice_add_eth_mac_rule(hw, em_list, hw->switch_info, 2753 hw->port_info->lport); 2754 } 2755 2756 /** 2757 * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule 2758 * @hw: pointer to the hardware structure 2759 * @em_list: list of ethertype or ethertype MAC entries 2760 * @sw: pointer to switch info struct for which function add rule 2761 */ 2762 static enum ice_status 2763 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 2764 struct ice_switch_info *sw) 2765 { 2766 struct ice_fltr_list_entry *em_list_itr, *tmp; 2767 2768 LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry, 2769 list_entry) { 2770 struct ice_sw_recipe *recp_list; 2771 enum ice_sw_lkup_type l_type; 2772 2773 l_type = em_list_itr->fltr_info.lkup_type; 2774 2775 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 2776 l_type != ICE_SW_LKUP_ETHERTYPE) 2777 return ICE_ERR_PARAM; 2778 2779 recp_list = &sw->recp_list[l_type]; 2780 em_list_itr->status = ice_remove_rule_internal(hw, recp_list, 2781 em_list_itr); 2782 if (em_list_itr->status) 2783 return em_list_itr->status; 2784 } 2785 return ICE_SUCCESS; 2786 } 2787 2788 /** 2789 * ice_remove_eth_mac - remove a ethertype based filter rule 2790 * @hw: pointer to the hardware structure 2791 * @em_list: list of ethertype and forwarding information 2792 * 2793 */ 2794 enum ice_status 2795 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 2796 { 2797 if (!em_list || !hw) 2798 return ICE_ERR_PARAM; 2799 2800 return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info); 2801 } 2802 2803 /** 2804 * ice_get_lg_act_aqc_res_type - get resource type for a large action 2805 * @res_type: resource type to be filled in case of function success 2806 * @num_acts: number of actions to hold with a large action entry 2807 * 2808 * Get resource type for a large action depending on the number 2809 * of single actions that it contains. 2810 */ 2811 static enum ice_status 2812 ice_get_lg_act_aqc_res_type(u16 *res_type, int num_acts) 2813 { 2814 if (!res_type) 2815 return ICE_ERR_BAD_PTR; 2816 2817 /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1. 2818 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3. 2819 * If num_acts is greater than 2, then use 2820 * ICE_AQC_RES_TYPE_WIDE_TABLE_4. 2821 * The num_acts cannot be equal to 0 or greater than 4. 2822 */ 2823 switch (num_acts) { 2824 case 1: 2825 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_1; 2826 break; 2827 case 2: 2828 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_2; 2829 break; 2830 case 3: 2831 case 4: 2832 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_4; 2833 break; 2834 default: 2835 return ICE_ERR_PARAM; 2836 } 2837 2838 return ICE_SUCCESS; 2839 } 2840 2841 /** 2842 * ice_alloc_res_lg_act - add large action resource 2843 * @hw: pointer to the hardware structure 2844 * @l_id: large action ID to fill it in 2845 * @num_acts: number of actions to hold with a large action entry 2846 */ 2847 static enum ice_status 2848 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts) 2849 { 2850 struct ice_aqc_alloc_free_res_elem *sw_buf; 2851 enum ice_status status; 2852 u16 buf_len, res_type; 2853 2854 if (!l_id) 2855 return ICE_ERR_BAD_PTR; 2856 2857 status = ice_get_lg_act_aqc_res_type(&res_type, num_acts); 2858 if (status) 2859 return status; 2860 2861 /* Allocate resource for large action */ 2862 buf_len = ice_struct_size(sw_buf, elem, 1); 2863 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 2864 if (!sw_buf) 2865 return ICE_ERR_NO_MEMORY; 2866 2867 sw_buf->res_type = CPU_TO_LE16(res_type); 2868 sw_buf->num_elems = CPU_TO_LE16(1); 2869 2870 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 2871 ice_aqc_opc_alloc_res, NULL); 2872 if (!status) 2873 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 2874 2875 ice_free(hw, sw_buf); 2876 2877 return status; 2878 } 2879 2880 /** 2881 * ice_rem_sw_rule_info 2882 * @hw: pointer to the hardware structure 2883 * @rule_head: pointer to the switch list structure that we want to delete 2884 */ 2885 static void 2886 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 2887 { 2888 if (!LIST_EMPTY(rule_head)) { 2889 struct ice_fltr_mgmt_list_entry *entry; 2890 struct ice_fltr_mgmt_list_entry *tmp; 2891 2892 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head, 2893 ice_fltr_mgmt_list_entry, list_entry) { 2894 LIST_DEL(&entry->list_entry); 2895 ice_free(hw, entry); 2896 } 2897 } 2898 } 2899 2900 /** 2901 * ice_rem_all_sw_rules_info 2902 * @hw: pointer to the hardware structure 2903 */ 2904 void ice_rem_all_sw_rules_info(struct ice_hw *hw) 2905 { 2906 struct ice_switch_info *sw = hw->switch_info; 2907 u8 i; 2908 2909 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 2910 struct LIST_HEAD_TYPE *rule_head; 2911 2912 rule_head = &sw->recp_list[i].filt_rules; 2913 if (!sw->recp_list[i].adv_rule) 2914 ice_rem_sw_rule_info(hw, rule_head); 2915 } 2916 } 2917 2918 /** 2919 * ice_cfg_dflt_vsi - change state of VSI to set/clear default 2920 * @pi: pointer to the port_info structure 2921 * @vsi_handle: VSI handle to set as default 2922 * @set: true to add the above mentioned switch rule, false to remove it 2923 * @direction: ICE_FLTR_RX or ICE_FLTR_TX 2924 * 2925 * add filter rule to set/unset given VSI as default VSI for the switch 2926 * (represented by swid) 2927 */ 2928 enum ice_status 2929 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set, 2930 u8 direction) 2931 { 2932 struct ice_fltr_list_entry f_list_entry; 2933 struct ice_sw_recipe *recp_list = NULL; 2934 struct ice_fltr_info f_info; 2935 struct ice_hw *hw = pi->hw; 2936 enum ice_status status; 2937 u8 lport = pi->lport; 2938 u16 hw_vsi_id; 2939 recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT]; 2940 2941 if (!ice_is_vsi_valid(hw, vsi_handle)) 2942 return ICE_ERR_PARAM; 2943 2944 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2945 2946 ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM); 2947 2948 f_info.lkup_type = ICE_SW_LKUP_DFLT; 2949 f_info.flag = direction; 2950 f_info.fltr_act = ICE_FWD_TO_VSI; 2951 f_info.fwd_id.hw_vsi_id = hw_vsi_id; 2952 f_info.vsi_handle = vsi_handle; 2953 2954 if (f_info.flag & ICE_FLTR_RX) { 2955 f_info.src = pi->lport; 2956 f_info.src_id = ICE_SRC_ID_LPORT; 2957 } else if (f_info.flag & ICE_FLTR_TX) { 2958 f_info.src_id = ICE_SRC_ID_VSI; 2959 f_info.src = hw_vsi_id; 2960 } 2961 f_list_entry.fltr_info = f_info; 2962 2963 if (set) 2964 status = ice_add_rule_internal(hw, recp_list, lport, 2965 &f_list_entry); 2966 else 2967 status = ice_remove_rule_internal(hw, recp_list, 2968 &f_list_entry); 2969 2970 return status; 2971 } 2972 2973 /** 2974 * ice_check_if_dflt_vsi - check if VSI is default VSI 2975 * @pi: pointer to the port_info structure 2976 * @vsi_handle: vsi handle to check for in filter list 2977 * @rule_exists: indicates if there are any VSI's in the rule list 2978 * 2979 * checks if the VSI is in a default VSI list, and also indicates 2980 * if the default VSI list is empty 2981 */ 2982 bool ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, 2983 bool *rule_exists) 2984 { 2985 struct ice_fltr_mgmt_list_entry *fm_entry; 2986 struct LIST_HEAD_TYPE *rule_head; 2987 struct ice_sw_recipe *recp_list; 2988 struct ice_lock *rule_lock; 2989 bool ret = false; 2990 recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT]; 2991 rule_lock = &recp_list->filt_rule_lock; 2992 rule_head = &recp_list->filt_rules; 2993 2994 ice_acquire_lock(rule_lock); 2995 2996 if (rule_exists && !LIST_EMPTY(rule_head)) 2997 *rule_exists = true; 2998 2999 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, 3000 ice_fltr_mgmt_list_entry, list_entry) { 3001 if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) { 3002 ret = true; 3003 break; 3004 } 3005 } 3006 3007 ice_release_lock(rule_lock); 3008 return ret; 3009 } 3010 3011 /** 3012 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry 3013 * @list_head: head of rule list 3014 * @f_info: rule information 3015 * 3016 * Helper function to search for a unicast rule entry - this is to be used 3017 * to remove unicast MAC filter that is not shared with other VSIs on the 3018 * PF switch. 3019 * 3020 * Returns pointer to entry storing the rule if found 3021 */ 3022 static struct ice_fltr_mgmt_list_entry * 3023 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head, 3024 struct ice_fltr_info *f_info) 3025 { 3026 struct ice_fltr_mgmt_list_entry *list_itr; 3027 3028 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 3029 list_entry) { 3030 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 3031 sizeof(f_info->l_data)) && 3032 f_info->fwd_id.hw_vsi_id == 3033 list_itr->fltr_info.fwd_id.hw_vsi_id && 3034 f_info->flag == list_itr->fltr_info.flag) 3035 return list_itr; 3036 } 3037 return NULL; 3038 } 3039 3040 /** 3041 * ice_remove_mac_rule - remove a MAC based filter rule 3042 * @hw: pointer to the hardware structure 3043 * @m_list: list of MAC addresses and forwarding information 3044 * @recp_list: list from which function remove MAC address 3045 * 3046 * This function removes either a MAC filter rule or a specific VSI from a 3047 * VSI list for a multicast MAC address. 3048 * 3049 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 3050 * ice_add_mac. Caller should be aware that this call will only work if all 3051 * the entries passed into m_list were added previously. It will not attempt to 3052 * do a partial remove of entries that were found. 3053 */ 3054 static enum ice_status 3055 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 3056 struct ice_sw_recipe *recp_list) 3057 { 3058 struct ice_fltr_list_entry *list_itr, *tmp; 3059 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3060 3061 if (!m_list) 3062 return ICE_ERR_PARAM; 3063 3064 rule_lock = &recp_list->filt_rule_lock; 3065 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry, 3066 list_entry) { 3067 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 3068 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; 3069 u16 vsi_handle; 3070 3071 if (l_type != ICE_SW_LKUP_MAC) 3072 return ICE_ERR_PARAM; 3073 3074 vsi_handle = list_itr->fltr_info.vsi_handle; 3075 if (!ice_is_vsi_valid(hw, vsi_handle)) 3076 return ICE_ERR_PARAM; 3077 3078 list_itr->fltr_info.fwd_id.hw_vsi_id = 3079 ice_get_hw_vsi_num(hw, vsi_handle); 3080 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) { 3081 /* Don't remove the unicast address that belongs to 3082 * another VSI on the switch, since it is not being 3083 * shared... 3084 */ 3085 ice_acquire_lock(rule_lock); 3086 if (!ice_find_ucast_rule_entry(&recp_list->filt_rules, 3087 &list_itr->fltr_info)) { 3088 ice_release_lock(rule_lock); 3089 return ICE_ERR_DOES_NOT_EXIST; 3090 } 3091 ice_release_lock(rule_lock); 3092 } 3093 list_itr->status = ice_remove_rule_internal(hw, recp_list, 3094 list_itr); 3095 if (list_itr->status) 3096 return list_itr->status; 3097 } 3098 return ICE_SUCCESS; 3099 } 3100 3101 /** 3102 * ice_remove_mac - remove a MAC address based filter rule 3103 * @hw: pointer to the hardware structure 3104 * @m_list: list of MAC addresses and forwarding information 3105 * 3106 */ 3107 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 3108 { 3109 struct ice_sw_recipe *recp_list; 3110 3111 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 3112 return ice_remove_mac_rule(hw, m_list, recp_list); 3113 } 3114 3115 /** 3116 * ice_remove_vlan_rule - Remove VLAN based filter rule 3117 * @hw: pointer to the hardware structure 3118 * @v_list: list of VLAN entries and forwarding information 3119 * @recp_list: list from which function remove VLAN 3120 */ 3121 static enum ice_status 3122 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 3123 struct ice_sw_recipe *recp_list) 3124 { 3125 struct ice_fltr_list_entry *v_list_itr, *tmp; 3126 3127 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3128 list_entry) { 3129 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 3130 3131 if (l_type != ICE_SW_LKUP_VLAN) 3132 return ICE_ERR_PARAM; 3133 v_list_itr->status = ice_remove_rule_internal(hw, recp_list, 3134 v_list_itr); 3135 if (v_list_itr->status) 3136 return v_list_itr->status; 3137 } 3138 return ICE_SUCCESS; 3139 } 3140 3141 /** 3142 * ice_remove_vlan - remove a VLAN address based filter rule 3143 * @hw: pointer to the hardware structure 3144 * @v_list: list of VLAN and forwarding information 3145 * 3146 */ 3147 enum ice_status 3148 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 3149 { 3150 struct ice_sw_recipe *recp_list; 3151 3152 if (!v_list || !hw) 3153 return ICE_ERR_PARAM; 3154 3155 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN]; 3156 return ice_remove_vlan_rule(hw, v_list, recp_list); 3157 } 3158 3159 /** 3160 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 3161 * @fm_entry: filter entry to inspect 3162 * @vsi_handle: VSI handle to compare with filter info 3163 */ 3164 static bool 3165 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 3166 { 3167 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 3168 fm_entry->fltr_info.vsi_handle == vsi_handle) || 3169 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 3170 fm_entry->vsi_list_info && 3171 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map, 3172 vsi_handle)))); 3173 } 3174 3175 /** 3176 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 3177 * @hw: pointer to the hardware structure 3178 * @vsi_handle: VSI handle to remove filters from 3179 * @vsi_list_head: pointer to the list to add entry to 3180 * @fi: pointer to fltr_info of filter entry to copy & add 3181 * 3182 * Helper function, used when creating a list of filters to remove from 3183 * a specific VSI. The entry added to vsi_list_head is a COPY of the 3184 * original filter entry, with the exception of fltr_info.fltr_act and 3185 * fltr_info.fwd_id fields. These are set such that later logic can 3186 * extract which VSI to remove the fltr from, and pass on that information. 3187 */ 3188 static enum ice_status 3189 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3190 struct LIST_HEAD_TYPE *vsi_list_head, 3191 struct ice_fltr_info *fi) 3192 { 3193 struct ice_fltr_list_entry *tmp; 3194 3195 /* this memory is freed up in the caller function 3196 * once filters for this VSI are removed 3197 */ 3198 tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp)); 3199 if (!tmp) 3200 return ICE_ERR_NO_MEMORY; 3201 3202 tmp->fltr_info = *fi; 3203 3204 /* Overwrite these fields to indicate which VSI to remove filter from, 3205 * so find and remove logic can extract the information from the 3206 * list entries. Note that original entries will still have proper 3207 * values. 3208 */ 3209 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 3210 tmp->fltr_info.vsi_handle = vsi_handle; 3211 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3212 3213 LIST_ADD(&tmp->list_entry, vsi_list_head); 3214 3215 return ICE_SUCCESS; 3216 } 3217 3218 /** 3219 * ice_add_to_vsi_fltr_list - Add VSI filters to the list 3220 * @hw: pointer to the hardware structure 3221 * @vsi_handle: VSI handle to remove filters from 3222 * @lkup_list_head: pointer to the list that has certain lookup type filters 3223 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 3224 * 3225 * Locates all filters in lkup_list_head that are used by the given VSI, 3226 * and adds COPIES of those entries to vsi_list_head (intended to be used 3227 * to remove the listed filters). 3228 * Note that this means all entries in vsi_list_head must be explicitly 3229 * deallocated by the caller when done with list. 3230 */ 3231 static enum ice_status 3232 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3233 struct LIST_HEAD_TYPE *lkup_list_head, 3234 struct LIST_HEAD_TYPE *vsi_list_head) 3235 { 3236 struct ice_fltr_mgmt_list_entry *fm_entry; 3237 enum ice_status status = ICE_SUCCESS; 3238 3239 /* check to make sure VSI ID is valid and within boundary */ 3240 if (!ice_is_vsi_valid(hw, vsi_handle)) 3241 return ICE_ERR_PARAM; 3242 3243 LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head, 3244 ice_fltr_mgmt_list_entry, list_entry) { 3245 if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) 3246 continue; 3247 3248 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3249 vsi_list_head, 3250 &fm_entry->fltr_info); 3251 if (status) 3252 return status; 3253 } 3254 return status; 3255 } 3256 3257 /** 3258 * ice_determine_promisc_mask 3259 * @fi: filter info to parse 3260 * @promisc_mask: pointer to mask to be filled in 3261 * 3262 * Helper function to determine which ICE_PROMISC_ mask corresponds 3263 * to given filter into. 3264 */ 3265 static void ice_determine_promisc_mask(struct ice_fltr_info *fi, 3266 ice_bitmap_t *promisc_mask) 3267 { 3268 u16 vid = fi->l_data.mac_vlan.vlan_id; 3269 u8 *macaddr = fi->l_data.mac.mac_addr; 3270 bool is_rx_lb_fltr = false; 3271 bool is_tx_fltr = false; 3272 3273 ice_zero_bitmap(promisc_mask, ICE_PROMISC_MAX); 3274 3275 if (fi->flag == ICE_FLTR_TX) 3276 is_tx_fltr = true; 3277 if (fi->flag == ICE_FLTR_RX_LB) 3278 is_rx_lb_fltr = true; 3279 3280 if (IS_BROADCAST_ETHER_ADDR(macaddr)) { 3281 ice_set_bit(is_tx_fltr ? ICE_PROMISC_BCAST_TX 3282 : ICE_PROMISC_BCAST_RX, promisc_mask); 3283 } else if (IS_MULTICAST_ETHER_ADDR(macaddr)) { 3284 ice_set_bit(is_tx_fltr ? ICE_PROMISC_MCAST_TX 3285 : ICE_PROMISC_MCAST_RX, promisc_mask); 3286 } else if (IS_UNICAST_ETHER_ADDR(macaddr)) { 3287 if (is_tx_fltr) 3288 ice_set_bit(ICE_PROMISC_UCAST_TX, promisc_mask); 3289 else if (is_rx_lb_fltr) 3290 ice_set_bit(ICE_PROMISC_UCAST_RX_LB, promisc_mask); 3291 else 3292 ice_set_bit(ICE_PROMISC_UCAST_RX, promisc_mask); 3293 } 3294 3295 if (vid) { 3296 ice_set_bit(is_tx_fltr ? ICE_PROMISC_VLAN_TX 3297 : ICE_PROMISC_VLAN_RX, promisc_mask); 3298 } 3299 } 3300 3301 /** 3302 * _ice_get_vsi_promisc - get promiscuous mode of given VSI 3303 * @hw: pointer to the hardware structure 3304 * @vsi_handle: VSI handle to retrieve info from 3305 * @promisc_mask: pointer to mask to be filled in 3306 * @vid: VLAN ID of promisc VLAN VSI 3307 * @sw: pointer to switch info struct for which function add rule 3308 * @lkup: switch rule filter lookup type 3309 */ 3310 static enum ice_status 3311 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3312 ice_bitmap_t *promisc_mask, u16 *vid, 3313 struct ice_switch_info *sw, enum ice_sw_lkup_type lkup) 3314 { 3315 ice_declare_bitmap(fltr_promisc_mask, ICE_PROMISC_MAX); 3316 struct ice_fltr_mgmt_list_entry *itr; 3317 struct LIST_HEAD_TYPE *rule_head; 3318 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3319 3320 if (!ice_is_vsi_valid(hw, vsi_handle) || 3321 (lkup != ICE_SW_LKUP_PROMISC && lkup != ICE_SW_LKUP_PROMISC_VLAN)) 3322 return ICE_ERR_PARAM; 3323 3324 *vid = 0; 3325 rule_head = &sw->recp_list[lkup].filt_rules; 3326 rule_lock = &sw->recp_list[lkup].filt_rule_lock; 3327 3328 ice_zero_bitmap(promisc_mask, ICE_PROMISC_MAX); 3329 3330 ice_acquire_lock(rule_lock); 3331 LIST_FOR_EACH_ENTRY(itr, rule_head, 3332 ice_fltr_mgmt_list_entry, list_entry) { 3333 /* Continue if this filter doesn't apply to this VSI or the 3334 * VSI ID is not in the VSI map for this filter 3335 */ 3336 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3337 continue; 3338 3339 ice_determine_promisc_mask(&itr->fltr_info, fltr_promisc_mask); 3340 ice_or_bitmap(promisc_mask, promisc_mask, fltr_promisc_mask, 3341 ICE_PROMISC_MAX); 3342 3343 } 3344 ice_release_lock(rule_lock); 3345 3346 return ICE_SUCCESS; 3347 } 3348 3349 /** 3350 * ice_get_vsi_promisc - get promiscuous mode of given VSI 3351 * @hw: pointer to the hardware structure 3352 * @vsi_handle: VSI handle to retrieve info from 3353 * @promisc_mask: pointer to mask to be filled in 3354 * @vid: VLAN ID of promisc VLAN VSI 3355 */ 3356 enum ice_status 3357 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3358 ice_bitmap_t *promisc_mask, u16 *vid) 3359 { 3360 if (!vid || !promisc_mask || !hw) 3361 return ICE_ERR_PARAM; 3362 3363 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask, 3364 vid, hw->switch_info, ICE_SW_LKUP_PROMISC); 3365 } 3366 3367 /** 3368 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI 3369 * @hw: pointer to the hardware structure 3370 * @vsi_handle: VSI handle to retrieve info from 3371 * @promisc_mask: pointer to mask to be filled in 3372 * @vid: VLAN ID of promisc VLAN VSI 3373 */ 3374 enum ice_status 3375 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, 3376 ice_bitmap_t *promisc_mask, u16 *vid) 3377 { 3378 if (!hw || !promisc_mask || !vid) 3379 return ICE_ERR_PARAM; 3380 3381 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask, 3382 vid, hw->switch_info, 3383 ICE_SW_LKUP_PROMISC_VLAN); 3384 } 3385 3386 /** 3387 * ice_remove_promisc - Remove promisc based filter rules 3388 * @hw: pointer to the hardware structure 3389 * @recp_id: recipe ID for which the rule needs to removed 3390 * @v_list: list of promisc entries 3391 */ 3392 static enum ice_status 3393 ice_remove_promisc(struct ice_hw *hw, u8 recp_id, 3394 struct LIST_HEAD_TYPE *v_list) 3395 { 3396 struct ice_fltr_list_entry *v_list_itr, *tmp; 3397 struct ice_sw_recipe *recp_list; 3398 3399 recp_list = &hw->switch_info->recp_list[recp_id]; 3400 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3401 list_entry) { 3402 v_list_itr->status = 3403 ice_remove_rule_internal(hw, recp_list, v_list_itr); 3404 if (v_list_itr->status) 3405 return v_list_itr->status; 3406 } 3407 return ICE_SUCCESS; 3408 } 3409 3410 /** 3411 * _ice_clear_vsi_promisc - clear specified promiscuous mode(s) 3412 * @hw: pointer to the hardware structure 3413 * @vsi_handle: VSI handle to clear mode 3414 * @promisc_mask: pointer to mask of promiscuous config bits to clear 3415 * @vid: VLAN ID to clear VLAN promiscuous 3416 * @sw: pointer to switch info struct for which function add rule 3417 */ 3418 static enum ice_status 3419 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3420 ice_bitmap_t *promisc_mask, u16 vid, 3421 struct ice_switch_info *sw) 3422 { 3423 ice_declare_bitmap(compl_promisc_mask, ICE_PROMISC_MAX); 3424 ice_declare_bitmap(fltr_promisc_mask, ICE_PROMISC_MAX); 3425 struct ice_fltr_list_entry *fm_entry, *tmp; 3426 struct LIST_HEAD_TYPE remove_list_head; 3427 struct ice_fltr_mgmt_list_entry *itr; 3428 struct LIST_HEAD_TYPE *rule_head; 3429 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3430 enum ice_status status = ICE_SUCCESS; 3431 u8 recipe_id; 3432 3433 if (!ice_is_vsi_valid(hw, vsi_handle)) 3434 return ICE_ERR_PARAM; 3435 3436 if (ice_is_bit_set(promisc_mask, ICE_PROMISC_VLAN_RX) && 3437 ice_is_bit_set(promisc_mask, ICE_PROMISC_VLAN_TX)) 3438 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3439 else 3440 recipe_id = ICE_SW_LKUP_PROMISC; 3441 3442 rule_head = &sw->recp_list[recipe_id].filt_rules; 3443 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 3444 3445 INIT_LIST_HEAD(&remove_list_head); 3446 3447 ice_acquire_lock(rule_lock); 3448 LIST_FOR_EACH_ENTRY(itr, rule_head, 3449 ice_fltr_mgmt_list_entry, list_entry) { 3450 struct ice_fltr_info *fltr_info; 3451 ice_zero_bitmap(compl_promisc_mask, ICE_PROMISC_MAX); 3452 3453 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3454 continue; 3455 fltr_info = &itr->fltr_info; 3456 3457 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN && 3458 vid != fltr_info->l_data.mac_vlan.vlan_id) 3459 continue; 3460 3461 ice_determine_promisc_mask(fltr_info, fltr_promisc_mask); 3462 ice_andnot_bitmap(compl_promisc_mask, fltr_promisc_mask, 3463 promisc_mask, ICE_PROMISC_MAX); 3464 3465 /* Skip if filter is not completely specified by given mask */ 3466 if (ice_is_any_bit_set(compl_promisc_mask, ICE_PROMISC_MAX)) 3467 continue; 3468 3469 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3470 &remove_list_head, 3471 fltr_info); 3472 if (status) { 3473 ice_release_lock(rule_lock); 3474 goto free_fltr_list; 3475 } 3476 } 3477 ice_release_lock(rule_lock); 3478 3479 status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 3480 3481 free_fltr_list: 3482 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 3483 ice_fltr_list_entry, list_entry) { 3484 LIST_DEL(&fm_entry->list_entry); 3485 ice_free(hw, fm_entry); 3486 } 3487 3488 return status; 3489 } 3490 3491 /** 3492 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 3493 * @hw: pointer to the hardware structure 3494 * @vsi_handle: VSI handle to clear mode 3495 * @promisc_mask: pointer to mask of promiscuous config bits to clear 3496 * @vid: VLAN ID to clear VLAN promiscuous 3497 */ 3498 enum ice_status 3499 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3500 ice_bitmap_t *promisc_mask, u16 vid) 3501 { 3502 if (!hw || !promisc_mask) 3503 return ICE_ERR_PARAM; 3504 3505 return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, 3506 vid, hw->switch_info); 3507 } 3508 3509 /** 3510 * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 3511 * @hw: pointer to the hardware structure 3512 * @vsi_handle: VSI handle to configure 3513 * @promisc_mask: pointer to mask of promiscuous config bits 3514 * @vid: VLAN ID to set VLAN promiscuous 3515 * @lport: logical port number to configure promisc mode 3516 * @sw: pointer to switch info struct for which function add rule 3517 */ 3518 static enum ice_status 3519 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3520 ice_bitmap_t *promisc_mask, u16 vid, u8 lport, 3521 struct ice_switch_info *sw) 3522 { 3523 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 3524 ice_declare_bitmap(p_mask, ICE_PROMISC_MAX); 3525 struct ice_fltr_list_entry f_list_entry; 3526 struct ice_fltr_info new_fltr; 3527 enum ice_status status = ICE_SUCCESS; 3528 bool is_tx_fltr, is_rx_lb_fltr; 3529 u16 hw_vsi_id; 3530 int pkt_type; 3531 u8 recipe_id; 3532 3533 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3534 3535 if (!ice_is_vsi_valid(hw, vsi_handle)) 3536 return ICE_ERR_PARAM; 3537 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3538 3539 ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM); 3540 3541 /* Do not modify original bitmap */ 3542 ice_cp_bitmap(p_mask, promisc_mask, ICE_PROMISC_MAX); 3543 3544 if (ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_RX) && 3545 ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_TX)) { 3546 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 3547 new_fltr.l_data.mac_vlan.vlan_id = vid; 3548 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3549 } else { 3550 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 3551 recipe_id = ICE_SW_LKUP_PROMISC; 3552 } 3553 3554 /* Separate filters must be set for each direction/packet type 3555 * combination, so we will loop over the mask value, store the 3556 * individual type, and clear it out in the input mask as it 3557 * is found. 3558 */ 3559 while (ice_is_any_bit_set(p_mask, ICE_PROMISC_MAX)) { 3560 struct ice_sw_recipe *recp_list; 3561 u8 *mac_addr; 3562 3563 pkt_type = 0; 3564 is_tx_fltr = false; 3565 is_rx_lb_fltr = false; 3566 3567 if (ice_test_and_clear_bit(ICE_PROMISC_UCAST_RX, 3568 p_mask)) { 3569 pkt_type = UCAST_FLTR; 3570 } else if (ice_test_and_clear_bit(ICE_PROMISC_UCAST_TX, 3571 p_mask)) { 3572 pkt_type = UCAST_FLTR; 3573 is_tx_fltr = true; 3574 } else if (ice_test_and_clear_bit(ICE_PROMISC_MCAST_RX, 3575 p_mask)) { 3576 pkt_type = MCAST_FLTR; 3577 } else if (ice_test_and_clear_bit(ICE_PROMISC_MCAST_TX, 3578 p_mask)) { 3579 pkt_type = MCAST_FLTR; 3580 is_tx_fltr = true; 3581 } else if (ice_test_and_clear_bit(ICE_PROMISC_BCAST_RX, 3582 p_mask)) { 3583 pkt_type = BCAST_FLTR; 3584 } else if (ice_test_and_clear_bit(ICE_PROMISC_BCAST_TX, 3585 p_mask)) { 3586 pkt_type = BCAST_FLTR; 3587 is_tx_fltr = true; 3588 } else if (ice_test_and_clear_bit(ICE_PROMISC_UCAST_RX_LB, 3589 p_mask)) { 3590 pkt_type = UCAST_FLTR; 3591 is_rx_lb_fltr = true; 3592 } 3593 3594 /* Check for VLAN promiscuous flag */ 3595 if (ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_RX)) { 3596 ice_clear_bit(ICE_PROMISC_VLAN_RX, p_mask); 3597 } else if (ice_test_and_clear_bit(ICE_PROMISC_VLAN_TX, 3598 p_mask)) { 3599 is_tx_fltr = true; 3600 } 3601 /* Set filter DA based on packet type */ 3602 mac_addr = new_fltr.l_data.mac.mac_addr; 3603 if (pkt_type == BCAST_FLTR) { 3604 ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM); 3605 } else if (pkt_type == MCAST_FLTR || 3606 pkt_type == UCAST_FLTR) { 3607 /* Use the dummy ether header DA */ 3608 ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN, 3609 ICE_NONDMA_TO_NONDMA); 3610 if (pkt_type == MCAST_FLTR) 3611 mac_addr[0] |= 0x1; /* Set multicast bit */ 3612 } 3613 3614 /* Need to reset this to zero for all iterations */ 3615 new_fltr.flag = 0; 3616 if (is_tx_fltr) { 3617 new_fltr.flag |= ICE_FLTR_TX; 3618 new_fltr.src = hw_vsi_id; 3619 } else if (is_rx_lb_fltr) { 3620 new_fltr.flag |= ICE_FLTR_RX_LB; 3621 new_fltr.src = hw_vsi_id; 3622 } else { 3623 new_fltr.flag |= ICE_FLTR_RX; 3624 new_fltr.src = lport; 3625 } 3626 3627 new_fltr.fltr_act = ICE_FWD_TO_VSI; 3628 new_fltr.vsi_handle = vsi_handle; 3629 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 3630 f_list_entry.fltr_info = new_fltr; 3631 recp_list = &sw->recp_list[recipe_id]; 3632 3633 status = ice_add_rule_internal(hw, recp_list, lport, 3634 &f_list_entry); 3635 if (status != ICE_SUCCESS) 3636 goto set_promisc_exit; 3637 } 3638 3639 set_promisc_exit: 3640 return status; 3641 } 3642 3643 /** 3644 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 3645 * @hw: pointer to the hardware structure 3646 * @vsi_handle: VSI handle to configure 3647 * @promisc_mask: pointer to mask of promiscuous config bits 3648 * @vid: VLAN ID to set VLAN promiscuous 3649 */ 3650 enum ice_status 3651 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3652 ice_bitmap_t *promisc_mask, u16 vid) 3653 { 3654 if (!hw || !promisc_mask) 3655 return ICE_ERR_PARAM; 3656 3657 return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid, 3658 hw->port_info->lport, 3659 hw->switch_info); 3660 } 3661 3662 /** 3663 * _ice_set_vlan_vsi_promisc 3664 * @hw: pointer to the hardware structure 3665 * @vsi_handle: VSI handle to configure 3666 * @promisc_mask: pointer to mask of promiscuous config bits 3667 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 3668 * @lport: logical port number to configure promisc mode 3669 * @sw: pointer to switch info struct for which function add rule 3670 * 3671 * Configure VSI with all associated VLANs to given promiscuous mode(s) 3672 */ 3673 static enum ice_status 3674 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3675 ice_bitmap_t *promisc_mask, bool rm_vlan_promisc, 3676 u8 lport, struct ice_switch_info *sw) 3677 { 3678 struct ice_fltr_list_entry *list_itr, *tmp; 3679 struct LIST_HEAD_TYPE vsi_list_head; 3680 struct LIST_HEAD_TYPE *vlan_head; 3681 struct ice_lock *vlan_lock; /* Lock to protect filter rule list */ 3682 enum ice_status status; 3683 u16 vlan_id; 3684 3685 INIT_LIST_HEAD(&vsi_list_head); 3686 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 3687 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 3688 ice_acquire_lock(vlan_lock); 3689 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 3690 &vsi_list_head); 3691 ice_release_lock(vlan_lock); 3692 if (status) 3693 goto free_fltr_list; 3694 3695 LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry, 3696 list_entry) { 3697 /* Avoid enabling or disabling vlan zero twice when in double 3698 * vlan mode 3699 */ 3700 if (ice_is_dvm_ena(hw) && 3701 list_itr->fltr_info.l_data.vlan.tpid == 0) 3702 continue; 3703 3704 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 3705 if (rm_vlan_promisc) 3706 status = _ice_clear_vsi_promisc(hw, vsi_handle, 3707 promisc_mask, 3708 vlan_id, sw); 3709 else 3710 status = _ice_set_vsi_promisc(hw, vsi_handle, 3711 promisc_mask, vlan_id, 3712 lport, sw); 3713 if (status && status != ICE_ERR_ALREADY_EXISTS) 3714 break; 3715 } 3716 3717 free_fltr_list: 3718 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head, 3719 ice_fltr_list_entry, list_entry) { 3720 LIST_DEL(&list_itr->list_entry); 3721 ice_free(hw, list_itr); 3722 } 3723 return status; 3724 } 3725 3726 /** 3727 * ice_set_vlan_vsi_promisc 3728 * @hw: pointer to the hardware structure 3729 * @vsi_handle: VSI handle to configure 3730 * @promisc_mask: mask of promiscuous config bits 3731 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 3732 * 3733 * Configure VSI with all associated VLANs to given promiscuous mode(s) 3734 */ 3735 enum ice_status 3736 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3737 ice_bitmap_t *promisc_mask, bool rm_vlan_promisc) 3738 { 3739 if (!hw || !promisc_mask) 3740 return ICE_ERR_PARAM; 3741 3742 return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask, 3743 rm_vlan_promisc, hw->port_info->lport, 3744 hw->switch_info); 3745 } 3746 3747 /** 3748 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 3749 * @hw: pointer to the hardware structure 3750 * @vsi_handle: VSI handle to remove filters from 3751 * @recp_list: recipe list from which function remove fltr 3752 * @lkup: switch rule filter lookup type 3753 */ 3754 static void 3755 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 3756 struct ice_sw_recipe *recp_list, 3757 enum ice_sw_lkup_type lkup) 3758 { 3759 struct ice_fltr_list_entry *fm_entry; 3760 struct LIST_HEAD_TYPE remove_list_head; 3761 struct LIST_HEAD_TYPE *rule_head; 3762 struct ice_fltr_list_entry *tmp; 3763 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3764 enum ice_status status; 3765 3766 INIT_LIST_HEAD(&remove_list_head); 3767 rule_lock = &recp_list[lkup].filt_rule_lock; 3768 rule_head = &recp_list[lkup].filt_rules; 3769 ice_acquire_lock(rule_lock); 3770 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 3771 &remove_list_head); 3772 ice_release_lock(rule_lock); 3773 if (status) 3774 goto free_fltr_list; 3775 3776 switch (lkup) { 3777 case ICE_SW_LKUP_MAC: 3778 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]); 3779 break; 3780 case ICE_SW_LKUP_VLAN: 3781 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]); 3782 break; 3783 case ICE_SW_LKUP_PROMISC: 3784 case ICE_SW_LKUP_PROMISC_VLAN: 3785 ice_remove_promisc(hw, (u8)lkup, &remove_list_head); 3786 break; 3787 case ICE_SW_LKUP_MAC_VLAN: 3788 ice_debug(hw, ICE_DBG_SW, "MAC VLAN look up is not supported yet\n"); 3789 break; 3790 case ICE_SW_LKUP_ETHERTYPE: 3791 case ICE_SW_LKUP_ETHERTYPE_MAC: 3792 ice_remove_eth_mac(hw, &remove_list_head); 3793 break; 3794 case ICE_SW_LKUP_DFLT: 3795 ice_debug(hw, ICE_DBG_SW, "Remove filters for this lookup type hasn't been implemented yet\n"); 3796 break; 3797 case ICE_SW_LKUP_LAST: 3798 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n"); 3799 break; 3800 } 3801 3802 free_fltr_list: 3803 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 3804 ice_fltr_list_entry, list_entry) { 3805 LIST_DEL(&fm_entry->list_entry); 3806 ice_free(hw, fm_entry); 3807 } 3808 } 3809 3810 /** 3811 * ice_remove_vsi_fltr_rule - Remove all filters for a VSI 3812 * @hw: pointer to the hardware structure 3813 * @vsi_handle: VSI handle to remove filters from 3814 * @sw: pointer to switch info struct 3815 */ 3816 static void 3817 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle, 3818 struct ice_switch_info *sw) 3819 { 3820 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3821 3822 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3823 sw->recp_list, ICE_SW_LKUP_MAC); 3824 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3825 sw->recp_list, ICE_SW_LKUP_MAC_VLAN); 3826 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3827 sw->recp_list, ICE_SW_LKUP_PROMISC); 3828 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3829 sw->recp_list, ICE_SW_LKUP_VLAN); 3830 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3831 sw->recp_list, ICE_SW_LKUP_DFLT); 3832 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3833 sw->recp_list, ICE_SW_LKUP_ETHERTYPE); 3834 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3835 sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC); 3836 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3837 sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN); 3838 } 3839 3840 /** 3841 * ice_remove_vsi_fltr - Remove all filters for a VSI 3842 * @hw: pointer to the hardware structure 3843 * @vsi_handle: VSI handle to remove filters from 3844 */ 3845 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 3846 { 3847 ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info); 3848 } 3849 3850 /** 3851 * ice_alloc_res_cntr - allocating resource counter 3852 * @hw: pointer to the hardware structure 3853 * @type: type of resource 3854 * @alloc_shared: if set it is shared else dedicated 3855 * @num_items: number of entries requested for FD resource type 3856 * @counter_id: counter index returned by AQ call 3857 */ 3858 static enum ice_status 3859 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 3860 u16 *counter_id) 3861 { 3862 struct ice_aqc_alloc_free_res_elem *buf; 3863 enum ice_status status; 3864 u16 buf_len; 3865 3866 /* Allocate resource */ 3867 buf_len = ice_struct_size(buf, elem, 1); 3868 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 3869 if (!buf) 3870 return ICE_ERR_NO_MEMORY; 3871 3872 buf->num_elems = CPU_TO_LE16(num_items); 3873 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 3874 ICE_AQC_RES_TYPE_M) | alloc_shared); 3875 3876 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 3877 ice_aqc_opc_alloc_res, NULL); 3878 if (status) 3879 goto exit; 3880 3881 *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp); 3882 3883 exit: 3884 ice_free(hw, buf); 3885 return status; 3886 } 3887 3888 /** 3889 * ice_free_res_cntr - free resource counter 3890 * @hw: pointer to the hardware structure 3891 * @type: type of resource 3892 * @alloc_shared: if set it is shared else dedicated 3893 * @num_items: number of entries to be freed for FD resource type 3894 * @counter_id: counter ID resource which needs to be freed 3895 */ 3896 static enum ice_status 3897 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 3898 u16 counter_id) 3899 { 3900 struct ice_aqc_alloc_free_res_elem *buf; 3901 enum ice_status status; 3902 u16 buf_len; 3903 3904 /* Free resource */ 3905 buf_len = ice_struct_size(buf, elem, 1); 3906 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 3907 if (!buf) 3908 return ICE_ERR_NO_MEMORY; 3909 3910 buf->num_elems = CPU_TO_LE16(num_items); 3911 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 3912 ICE_AQC_RES_TYPE_M) | alloc_shared); 3913 buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 3914 3915 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 3916 ice_aqc_opc_free_res, NULL); 3917 if (status) 3918 ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n"); 3919 3920 ice_free(hw, buf); 3921 return status; 3922 } 3923 3924 /** 3925 * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type 3926 * @hw: pointer to the hardware structure 3927 * @counter_id: returns counter index 3928 */ 3929 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id) 3930 { 3931 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 3932 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 3933 counter_id); 3934 } 3935 3936 /** 3937 * ice_free_vlan_res_counter - Free counter resource for VLAN type 3938 * @hw: pointer to the hardware structure 3939 * @counter_id: counter index to be freed 3940 */ 3941 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id) 3942 { 3943 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 3944 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 3945 counter_id); 3946 } 3947 3948 /** 3949 * ice_add_mac_with_sw_marker - add filter with sw marker 3950 * @hw: pointer to the hardware structure 3951 * @f_info: filter info structure containing the MAC filter information 3952 * @sw_marker: sw marker to tag the Rx descriptor with 3953 */ 3954 enum ice_status 3955 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info, 3956 u16 sw_marker) 3957 { 3958 struct ice_fltr_mgmt_list_entry *m_entry; 3959 struct ice_fltr_list_entry fl_info; 3960 struct ice_sw_recipe *recp_list; 3961 struct LIST_HEAD_TYPE l_head; 3962 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3963 enum ice_status ret; 3964 bool entry_exists; 3965 u16 lg_act_id; 3966 3967 if (f_info->fltr_act != ICE_FWD_TO_VSI) 3968 return ICE_ERR_PARAM; 3969 3970 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 3971 return ICE_ERR_PARAM; 3972 3973 if (sw_marker == ICE_INVAL_SW_MARKER_ID) 3974 return ICE_ERR_PARAM; 3975 3976 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 3977 return ICE_ERR_PARAM; 3978 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 3979 3980 /* Add filter if it doesn't exist so then the adding of large 3981 * action always results in update 3982 */ 3983 3984 INIT_LIST_HEAD(&l_head); 3985 fl_info.fltr_info = *f_info; 3986 LIST_ADD(&fl_info.list_entry, &l_head); 3987 3988 entry_exists = false; 3989 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 3990 hw->port_info->lport); 3991 if (ret == ICE_ERR_ALREADY_EXISTS) 3992 entry_exists = true; 3993 else if (ret) 3994 return ret; 3995 3996 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 3997 rule_lock = &recp_list->filt_rule_lock; 3998 ice_acquire_lock(rule_lock); 3999 /* Get the book keeping entry for the filter */ 4000 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 4001 if (!m_entry) 4002 goto exit_error; 4003 4004 /* If counter action was enabled for this rule then don't enable 4005 * sw marker large action 4006 */ 4007 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 4008 ret = ICE_ERR_PARAM; 4009 goto exit_error; 4010 } 4011 4012 /* if same marker was added before */ 4013 if (m_entry->sw_marker_id == sw_marker) { 4014 ret = ICE_ERR_ALREADY_EXISTS; 4015 goto exit_error; 4016 } 4017 4018 /* Allocate a hardware table entry to hold large act. Three actions 4019 * for marker based large action 4020 */ 4021 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3); 4022 if (ret) 4023 goto exit_error; 4024 4025 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4026 goto exit_error; 4027 4028 /* Update the switch rule to add the marker action */ 4029 ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id); 4030 if (!ret) { 4031 ice_release_lock(rule_lock); 4032 return ret; 4033 } 4034 4035 exit_error: 4036 ice_release_lock(rule_lock); 4037 /* only remove entry if it did not exist previously */ 4038 if (!entry_exists) 4039 ret = ice_remove_mac(hw, &l_head); 4040 4041 return ret; 4042 } 4043 4044 /** 4045 * ice_add_mac_with_counter - add filter with counter enabled 4046 * @hw: pointer to the hardware structure 4047 * @f_info: pointer to filter info structure containing the MAC filter 4048 * information 4049 */ 4050 enum ice_status 4051 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info) 4052 { 4053 struct ice_fltr_mgmt_list_entry *m_entry; 4054 struct ice_fltr_list_entry fl_info; 4055 struct ice_sw_recipe *recp_list; 4056 struct LIST_HEAD_TYPE l_head; 4057 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4058 enum ice_status ret; 4059 bool entry_exist; 4060 u16 counter_id; 4061 u16 lg_act_id; 4062 4063 if (f_info->fltr_act != ICE_FWD_TO_VSI) 4064 return ICE_ERR_PARAM; 4065 4066 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 4067 return ICE_ERR_PARAM; 4068 4069 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 4070 return ICE_ERR_PARAM; 4071 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 4072 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 4073 4074 entry_exist = false; 4075 4076 rule_lock = &recp_list->filt_rule_lock; 4077 4078 /* Add filter if it doesn't exist so then the adding of large 4079 * action always results in update 4080 */ 4081 INIT_LIST_HEAD(&l_head); 4082 4083 fl_info.fltr_info = *f_info; 4084 LIST_ADD(&fl_info.list_entry, &l_head); 4085 4086 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 4087 hw->port_info->lport); 4088 if (ret == ICE_ERR_ALREADY_EXISTS) 4089 entry_exist = true; 4090 else if (ret) 4091 return ret; 4092 4093 ice_acquire_lock(rule_lock); 4094 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 4095 if (!m_entry) { 4096 ret = ICE_ERR_BAD_PTR; 4097 goto exit_error; 4098 } 4099 4100 /* Don't enable counter for a filter for which sw marker was enabled */ 4101 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) { 4102 ret = ICE_ERR_PARAM; 4103 goto exit_error; 4104 } 4105 4106 /* If a counter was already enabled then don't need to add again */ 4107 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 4108 ret = ICE_ERR_ALREADY_EXISTS; 4109 goto exit_error; 4110 } 4111 4112 /* Allocate a hardware table entry to VLAN counter */ 4113 ret = ice_alloc_vlan_res_counter(hw, &counter_id); 4114 if (ret) 4115 goto exit_error; 4116 4117 /* Allocate a hardware table entry to hold large act. Two actions for 4118 * counter based large action 4119 */ 4120 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2); 4121 if (ret) 4122 goto exit_error; 4123 4124 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4125 goto exit_error; 4126 4127 /* Update the switch rule to add the counter action */ 4128 ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id); 4129 if (!ret) { 4130 ice_release_lock(rule_lock); 4131 return ret; 4132 } 4133 4134 exit_error: 4135 ice_release_lock(rule_lock); 4136 /* only remove entry if it did not exist previously */ 4137 if (!entry_exist) 4138 ret = ice_remove_mac(hw, &l_head); 4139 4140 return ret; 4141 } 4142 4143 /** 4144 * ice_replay_fltr - Replay all the filters stored by a specific list head 4145 * @hw: pointer to the hardware structure 4146 * @list_head: list for which filters needs to be replayed 4147 * @recp_id: Recipe ID for which rules need to be replayed 4148 */ 4149 static enum ice_status 4150 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head) 4151 { 4152 struct ice_fltr_mgmt_list_entry *itr; 4153 enum ice_status status = ICE_SUCCESS; 4154 struct ice_sw_recipe *recp_list; 4155 u8 lport = hw->port_info->lport; 4156 struct LIST_HEAD_TYPE l_head; 4157 4158 if (LIST_EMPTY(list_head)) 4159 return status; 4160 4161 recp_list = &hw->switch_info->recp_list[recp_id]; 4162 /* Move entries from the given list_head to a temporary l_head so that 4163 * they can be replayed. Otherwise when trying to re-add the same 4164 * filter, the function will return already exists 4165 */ 4166 LIST_REPLACE_INIT(list_head, &l_head); 4167 4168 /* Mark the given list_head empty by reinitializing it so filters 4169 * could be added again by *handler 4170 */ 4171 LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry, 4172 list_entry) { 4173 struct ice_fltr_list_entry f_entry; 4174 u16 vsi_handle; 4175 4176 f_entry.fltr_info = itr->fltr_info; 4177 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) { 4178 status = ice_add_rule_internal(hw, recp_list, lport, 4179 &f_entry); 4180 if (status != ICE_SUCCESS) 4181 goto end; 4182 continue; 4183 } 4184 4185 /* Add a filter per VSI separately */ 4186 ice_for_each_set_bit(vsi_handle, itr->vsi_list_info->vsi_map, 4187 ICE_MAX_VSI) { 4188 if (!ice_is_vsi_valid(hw, vsi_handle)) 4189 break; 4190 4191 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 4192 f_entry.fltr_info.vsi_handle = vsi_handle; 4193 f_entry.fltr_info.fwd_id.hw_vsi_id = 4194 ice_get_hw_vsi_num(hw, vsi_handle); 4195 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 4196 if (recp_id == ICE_SW_LKUP_VLAN) 4197 status = ice_add_vlan_internal(hw, recp_list, 4198 &f_entry); 4199 else 4200 status = ice_add_rule_internal(hw, recp_list, 4201 lport, 4202 &f_entry); 4203 if (status != ICE_SUCCESS) 4204 goto end; 4205 } 4206 } 4207 end: 4208 /* Clear the filter management list */ 4209 ice_rem_sw_rule_info(hw, &l_head); 4210 return status; 4211 } 4212 4213 /** 4214 * ice_replay_all_fltr - replay all filters stored in bookkeeping lists 4215 * @hw: pointer to the hardware structure 4216 * 4217 * NOTE: This function does not clean up partially added filters on error. 4218 * It is up to caller of the function to issue a reset or fail early. 4219 */ 4220 enum ice_status ice_replay_all_fltr(struct ice_hw *hw) 4221 { 4222 struct ice_switch_info *sw = hw->switch_info; 4223 enum ice_status status = ICE_SUCCESS; 4224 u8 i; 4225 4226 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4227 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules; 4228 4229 status = ice_replay_fltr(hw, i, head); 4230 if (status != ICE_SUCCESS) 4231 return status; 4232 } 4233 return status; 4234 } 4235 4236 /** 4237 * ice_replay_vsi_fltr - Replay filters for requested VSI 4238 * @hw: pointer to the hardware structure 4239 * @pi: pointer to port information structure 4240 * @sw: pointer to switch info struct for which function replays filters 4241 * @vsi_handle: driver VSI handle 4242 * @recp_id: Recipe ID for which rules need to be replayed 4243 * @list_head: list for which filters need to be replayed 4244 * 4245 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 4246 * It is required to pass valid VSI handle. 4247 */ 4248 static enum ice_status 4249 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi, 4250 struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id, 4251 struct LIST_HEAD_TYPE *list_head) 4252 { 4253 struct ice_fltr_mgmt_list_entry *itr; 4254 enum ice_status status = ICE_SUCCESS; 4255 struct ice_sw_recipe *recp_list; 4256 u16 hw_vsi_id; 4257 4258 if (LIST_EMPTY(list_head)) 4259 return status; 4260 recp_list = &sw->recp_list[recp_id]; 4261 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 4262 4263 LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry, 4264 list_entry) { 4265 struct ice_fltr_list_entry f_entry; 4266 4267 f_entry.fltr_info = itr->fltr_info; 4268 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 4269 itr->fltr_info.vsi_handle == vsi_handle) { 4270 /* update the src in case it is VSI num */ 4271 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 4272 f_entry.fltr_info.src = hw_vsi_id; 4273 status = ice_add_rule_internal(hw, recp_list, 4274 pi->lport, 4275 &f_entry); 4276 if (status != ICE_SUCCESS) 4277 goto end; 4278 continue; 4279 } 4280 if (!itr->vsi_list_info || 4281 !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle)) 4282 continue; 4283 /* Clearing it so that the logic can add it back */ 4284 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 4285 f_entry.fltr_info.vsi_handle = vsi_handle; 4286 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 4287 /* update the src in case it is VSI num */ 4288 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 4289 f_entry.fltr_info.src = hw_vsi_id; 4290 if (recp_id == ICE_SW_LKUP_VLAN) 4291 status = ice_add_vlan_internal(hw, recp_list, &f_entry); 4292 else 4293 status = ice_add_rule_internal(hw, recp_list, 4294 pi->lport, 4295 &f_entry); 4296 if (status != ICE_SUCCESS) 4297 goto end; 4298 } 4299 end: 4300 return status; 4301 } 4302 4303 /** 4304 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 4305 * @hw: pointer to the hardware structure 4306 * @pi: pointer to port information structure 4307 * @vsi_handle: driver VSI handle 4308 * 4309 * Replays filters for requested VSI via vsi_handle. 4310 */ 4311 enum ice_status 4312 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi, 4313 u16 vsi_handle) 4314 { 4315 struct ice_switch_info *sw = NULL; 4316 enum ice_status status = ICE_SUCCESS; 4317 u8 i; 4318 4319 sw = hw->switch_info; 4320 4321 /* Update the recipes that were created */ 4322 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4323 struct LIST_HEAD_TYPE *head; 4324 4325 head = &sw->recp_list[i].filt_replay_rules; 4326 if (!sw->recp_list[i].adv_rule) 4327 status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i, 4328 head); 4329 if (status != ICE_SUCCESS) 4330 return status; 4331 } 4332 4333 return ICE_SUCCESS; 4334 } 4335 4336 /** 4337 * ice_rm_sw_replay_rule_info - helper function to delete filter replay rules 4338 * @hw: pointer to the HW struct 4339 * @sw: pointer to switch info struct for which function removes filters 4340 * 4341 * Deletes the filter replay rules for given switch 4342 */ 4343 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw) 4344 { 4345 u8 i; 4346 4347 if (!sw) 4348 return; 4349 4350 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4351 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) { 4352 struct LIST_HEAD_TYPE *l_head; 4353 4354 l_head = &sw->recp_list[i].filt_replay_rules; 4355 if (!sw->recp_list[i].adv_rule) 4356 ice_rem_sw_rule_info(hw, l_head); 4357 } 4358 } 4359 } 4360 4361 /** 4362 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 4363 * @hw: pointer to the HW struct 4364 * 4365 * Deletes the filter replay rules. 4366 */ 4367 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 4368 { 4369 ice_rm_sw_replay_rule_info(hw, hw->switch_info); 4370 } 4371 4372