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