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