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