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