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