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_sw_rule_* 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_sw_rule_lkup_rx_tx *s_rule, 1211 enum ice_adminq_opc opc) 1212 { 1213 u16 vlan_id = ICE_MAX_VLAN_ID + 1; 1214 u16 vlan_tpid = ICE_ETH_P_8021Q; 1215 void *daddr = NULL; 1216 u16 eth_hdr_sz; 1217 u8 *eth_hdr; 1218 u32 act = 0; 1219 __be16 *off; 1220 u8 q_rgn; 1221 1222 if (opc == ice_aqc_opc_remove_sw_rules) { 1223 s_rule->act = 0; 1224 s_rule->index = CPU_TO_LE16(f_info->fltr_rule_id); 1225 s_rule->hdr_len = 0; 1226 return; 1227 } 1228 1229 eth_hdr_sz = sizeof(dummy_eth_header); 1230 eth_hdr = s_rule->hdr_data; 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->hdr.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->recipe_id = CPU_TO_LE16(f_info->lkup_type); 1321 s_rule->src = CPU_TO_LE16(f_info->src); 1322 s_rule->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->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_sw_rule_lkup_rx_tx *rx_tx; 1355 struct ice_sw_rule_lg_act *lg_act; 1356 /* For software marker we need 3 large actions 1357 * 1. FWD action: FWD TO VSI or VSI LIST 1358 * 2. GENERIC VALUE action to hold the profile ID 1359 * 3. GENERIC VALUE action to hold the software marker ID 1360 */ 1361 const u16 num_lg_acts = 3; 1362 enum ice_status status; 1363 u16 lg_act_size; 1364 u16 rules_size; 1365 u32 act; 1366 u16 id; 1367 1368 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC) 1369 return ICE_ERR_PARAM; 1370 1371 /* Create two back-to-back switch rules and submit them to the HW using 1372 * one memory buffer: 1373 * 1. Large Action 1374 * 2. Look up Tx Rx 1375 */ 1376 lg_act_size = (u16)ice_struct_size(lg_act, act, num_lg_acts); 1377 rules_size = lg_act_size + 1378 ice_struct_size(rx_tx, hdr_data, DUMMY_ETH_HDR_LEN); 1379 lg_act = (struct ice_sw_rule_lg_act *)ice_malloc(hw, rules_size); 1380 if (!lg_act) 1381 return ICE_ERR_NO_MEMORY; 1382 1383 rx_tx = (struct ice_sw_rule_lkup_rx_tx *)((u8 *)lg_act + lg_act_size); 1384 1385 /* Fill in the first switch rule i.e. large action */ 1386 lg_act->hdr.type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1387 lg_act->index = CPU_TO_LE16(l_id); 1388 lg_act->size = CPU_TO_LE16(num_lg_acts); 1389 1390 /* First action VSI forwarding or VSI list forwarding depending on how 1391 * many VSIs 1392 */ 1393 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1394 m_ent->fltr_info.fwd_id.hw_vsi_id; 1395 1396 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1397 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M; 1398 if (m_ent->vsi_count > 1) 1399 act |= ICE_LG_ACT_VSI_LIST; 1400 lg_act->act[0] = CPU_TO_LE32(act); 1401 1402 /* Second action descriptor type */ 1403 act = ICE_LG_ACT_GENERIC; 1404 1405 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; 1406 lg_act->act[1] = CPU_TO_LE32(act); 1407 1408 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << 1409 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; 1410 1411 /* Third action Marker value */ 1412 act |= ICE_LG_ACT_GENERIC; 1413 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & 1414 ICE_LG_ACT_GENERIC_VALUE_M; 1415 1416 lg_act->act[2] = CPU_TO_LE32(act); 1417 1418 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1419 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1420 ice_aqc_opc_update_sw_rules); 1421 1422 /* Update the action to point to the large action ID */ 1423 rx_tx->act = CPU_TO_LE32(ICE_SINGLE_ACT_PTR | 1424 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) & 1425 ICE_SINGLE_ACT_PTR_VAL_M)); 1426 1427 /* Use the filter rule ID of the previously created rule with single 1428 * act. Once the update happens, hardware will treat this as large 1429 * action 1430 */ 1431 rx_tx->index = 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_sw_rule_lkup_rx_tx *rx_tx; 1456 struct ice_sw_rule_lg_act *lg_act; 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_struct_size(lg_act, act, num_acts); 1475 rules_size = lg_act_size + 1476 ice_struct_size(rx_tx, hdr_data, DUMMY_ETH_HDR_LEN); 1477 lg_act = (struct ice_sw_rule_lg_act *)ice_malloc(hw, rules_size); 1478 if (!lg_act) 1479 return ICE_ERR_NO_MEMORY; 1480 1481 rx_tx = (struct ice_sw_rule_lkup_rx_tx *)((u8 *)lg_act + 1482 lg_act_size); 1483 1484 /* Fill in the first switch rule i.e. large action */ 1485 lg_act->hdr.type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT); 1486 lg_act->index = CPU_TO_LE16(l_id); 1487 lg_act->size = CPU_TO_LE16(num_acts); 1488 1489 /* First action VSI forwarding or VSI list forwarding depending on how 1490 * many VSIs 1491 */ 1492 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id : 1493 m_ent->fltr_info.fwd_id.hw_vsi_id; 1494 1495 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; 1496 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & 1497 ICE_LG_ACT_VSI_LIST_ID_M; 1498 if (m_ent->vsi_count > 1) 1499 act |= ICE_LG_ACT_VSI_LIST; 1500 lg_act->act[0] = CPU_TO_LE32(act); 1501 1502 /* Second action counter ID */ 1503 act = ICE_LG_ACT_STAT_COUNT; 1504 act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) & 1505 ICE_LG_ACT_STAT_COUNT_M; 1506 lg_act->act[1] = CPU_TO_LE32(act); 1507 1508 /* call the fill switch rule to fill the lookup Tx Rx structure */ 1509 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx, 1510 ice_aqc_opc_update_sw_rules); 1511 1512 act = ICE_SINGLE_ACT_PTR; 1513 act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M; 1514 rx_tx->act = CPU_TO_LE32(act); 1515 1516 /* Use the filter rule ID of the previously created rule with single 1517 * act. Once the update happens, hardware will treat this as large 1518 * action 1519 */ 1520 f_rule_id = m_ent->fltr_info.fltr_rule_id; 1521 rx_tx->index = CPU_TO_LE16(f_rule_id); 1522 1523 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2, 1524 ice_aqc_opc_update_sw_rules, NULL); 1525 if (!status) { 1526 m_ent->lg_act_idx = l_id; 1527 m_ent->counter_index = (u8)counter_id; 1528 } 1529 1530 ice_free(hw, lg_act); 1531 return status; 1532 } 1533 1534 /** 1535 * ice_create_vsi_list_map 1536 * @hw: pointer to the hardware structure 1537 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping 1538 * @num_vsi: number of VSI handles in the array 1539 * @vsi_list_id: VSI list ID generated as part of allocate resource 1540 * 1541 * Helper function to create a new entry of VSI list ID to VSI mapping 1542 * using the given VSI list ID 1543 */ 1544 static struct ice_vsi_list_map_info * 1545 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1546 u16 vsi_list_id) 1547 { 1548 struct ice_switch_info *sw = hw->switch_info; 1549 struct ice_vsi_list_map_info *v_map; 1550 int i; 1551 1552 v_map = (struct ice_vsi_list_map_info *)ice_malloc(hw, sizeof(*v_map)); 1553 if (!v_map) 1554 return NULL; 1555 1556 v_map->vsi_list_id = vsi_list_id; 1557 v_map->ref_cnt = 1; 1558 for (i = 0; i < num_vsi; i++) 1559 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map); 1560 1561 LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head); 1562 return v_map; 1563 } 1564 1565 /** 1566 * ice_update_vsi_list_rule 1567 * @hw: pointer to the hardware structure 1568 * @vsi_handle_arr: array of VSI handles to form a VSI list 1569 * @num_vsi: number of VSI handles in the array 1570 * @vsi_list_id: VSI list ID generated as part of allocate resource 1571 * @remove: Boolean value to indicate if this is a remove action 1572 * @opc: switch rules population command type - pass in the command opcode 1573 * @lkup_type: lookup type of the filter 1574 * 1575 * Call AQ command to add a new switch rule or update existing switch rule 1576 * using the given VSI list ID 1577 */ 1578 static enum ice_status 1579 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1580 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc, 1581 enum ice_sw_lkup_type lkup_type) 1582 { 1583 struct ice_sw_rule_vsi_list *s_rule; 1584 enum ice_status status; 1585 u16 s_rule_size; 1586 u16 rule_type; 1587 int i; 1588 1589 if (!num_vsi) 1590 return ICE_ERR_PARAM; 1591 1592 if (lkup_type == ICE_SW_LKUP_MAC || 1593 lkup_type == ICE_SW_LKUP_MAC_VLAN || 1594 lkup_type == ICE_SW_LKUP_ETHERTYPE || 1595 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC || 1596 lkup_type == ICE_SW_LKUP_PROMISC || 1597 lkup_type == ICE_SW_LKUP_PROMISC_VLAN || 1598 lkup_type == ICE_SW_LKUP_DFLT || 1599 lkup_type == ICE_SW_LKUP_LAST) 1600 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR : 1601 ICE_AQC_SW_RULES_T_VSI_LIST_SET; 1602 else if (lkup_type == ICE_SW_LKUP_VLAN) 1603 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR : 1604 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET; 1605 else 1606 return ICE_ERR_PARAM; 1607 1608 s_rule_size = (u16)ice_struct_size(s_rule, vsi, num_vsi); 1609 s_rule = (struct ice_sw_rule_vsi_list *)ice_malloc(hw, s_rule_size); 1610 if (!s_rule) 1611 return ICE_ERR_NO_MEMORY; 1612 for (i = 0; i < num_vsi; i++) { 1613 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) { 1614 status = ICE_ERR_PARAM; 1615 goto exit; 1616 } 1617 /* AQ call requires hw_vsi_id(s) */ 1618 s_rule->vsi[i] = 1619 CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i])); 1620 } 1621 1622 s_rule->hdr.type = CPU_TO_LE16(rule_type); 1623 s_rule->number_vsi = CPU_TO_LE16(num_vsi); 1624 s_rule->index = CPU_TO_LE16(vsi_list_id); 1625 1626 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL); 1627 1628 exit: 1629 ice_free(hw, s_rule); 1630 return status; 1631 } 1632 1633 /** 1634 * ice_create_vsi_list_rule - Creates and populates a VSI list rule 1635 * @hw: pointer to the HW struct 1636 * @vsi_handle_arr: array of VSI handles to form a VSI list 1637 * @num_vsi: number of VSI handles in the array 1638 * @vsi_list_id: stores the ID of the VSI list to be created 1639 * @lkup_type: switch rule filter's lookup type 1640 */ 1641 static enum ice_status 1642 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi, 1643 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type) 1644 { 1645 enum ice_status status; 1646 1647 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type, 1648 ice_aqc_opc_alloc_res); 1649 if (status) 1650 return status; 1651 1652 /* Update the newly created VSI list to include the specified VSIs */ 1653 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi, 1654 *vsi_list_id, false, 1655 ice_aqc_opc_add_sw_rules, lkup_type); 1656 } 1657 1658 /** 1659 * ice_create_pkt_fwd_rule 1660 * @hw: pointer to the hardware structure 1661 * @recp_list: corresponding filter management list 1662 * @f_entry: entry containing packet forwarding information 1663 * 1664 * Create switch rule with given filter information and add an entry 1665 * to the corresponding filter management list to track this switch rule 1666 * and VSI mapping 1667 */ 1668 static enum ice_status 1669 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 1670 struct ice_fltr_list_entry *f_entry) 1671 { 1672 struct ice_fltr_mgmt_list_entry *fm_entry; 1673 struct ice_sw_rule_lkup_rx_tx *s_rule; 1674 enum ice_status status; 1675 1676 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 1677 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 1678 DUMMY_ETH_HDR_LEN)); 1679 if (!s_rule) 1680 return ICE_ERR_NO_MEMORY; 1681 fm_entry = (struct ice_fltr_mgmt_list_entry *) 1682 ice_malloc(hw, sizeof(*fm_entry)); 1683 if (!fm_entry) { 1684 status = ICE_ERR_NO_MEMORY; 1685 goto ice_create_pkt_fwd_rule_exit; 1686 } 1687 1688 fm_entry->fltr_info = f_entry->fltr_info; 1689 1690 /* Initialize all the fields for the management entry */ 1691 fm_entry->vsi_count = 1; 1692 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX; 1693 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID; 1694 fm_entry->counter_index = ICE_INVAL_COUNTER_ID; 1695 1696 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule, 1697 ice_aqc_opc_add_sw_rules); 1698 1699 status = ice_aq_sw_rules(hw, s_rule, 1700 ice_struct_size(s_rule, hdr_data, 1701 DUMMY_ETH_HDR_LEN), 1702 1, ice_aqc_opc_add_sw_rules, NULL); 1703 if (status) { 1704 ice_free(hw, fm_entry); 1705 goto ice_create_pkt_fwd_rule_exit; 1706 } 1707 1708 f_entry->fltr_info.fltr_rule_id = LE16_TO_CPU(s_rule->index); 1709 fm_entry->fltr_info.fltr_rule_id = LE16_TO_CPU(s_rule->index); 1710 1711 /* The book keeping entries will get removed when base driver 1712 * calls remove filter AQ command 1713 */ 1714 LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules); 1715 1716 ice_create_pkt_fwd_rule_exit: 1717 ice_free(hw, s_rule); 1718 return status; 1719 } 1720 1721 /** 1722 * ice_update_pkt_fwd_rule 1723 * @hw: pointer to the hardware structure 1724 * @f_info: filter information for switch rule 1725 * 1726 * Call AQ command to update a previously created switch rule with a 1727 * VSI list ID 1728 */ 1729 static enum ice_status 1730 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info) 1731 { 1732 struct ice_sw_rule_lkup_rx_tx *s_rule; 1733 enum ice_status status; 1734 1735 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 1736 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 1737 DUMMY_ETH_HDR_LEN)); 1738 if (!s_rule) 1739 return ICE_ERR_NO_MEMORY; 1740 1741 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules); 1742 1743 s_rule->index = CPU_TO_LE16(f_info->fltr_rule_id); 1744 1745 /* Update switch rule with new rule set to forward VSI list */ 1746 status = ice_aq_sw_rules(hw, s_rule, 1747 ice_struct_size(s_rule, hdr_data, 1748 DUMMY_ETH_HDR_LEN), 1749 1, ice_aqc_opc_update_sw_rules, NULL); 1750 1751 ice_free(hw, s_rule); 1752 return status; 1753 } 1754 1755 /** 1756 * ice_update_sw_rule_bridge_mode 1757 * @hw: pointer to the HW struct 1758 * 1759 * Updates unicast switch filter rules based on VEB/VEPA mode 1760 */ 1761 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw) 1762 { 1763 struct ice_fltr_mgmt_list_entry *fm_entry; 1764 enum ice_status status = ICE_SUCCESS; 1765 struct ice_switch_info *sw = NULL; 1766 struct LIST_HEAD_TYPE *rule_head; 1767 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 1768 sw = hw->switch_info; 1769 1770 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock; 1771 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules; 1772 1773 ice_acquire_lock(rule_lock); 1774 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry, 1775 list_entry) { 1776 struct ice_fltr_info *fi = &fm_entry->fltr_info; 1777 u8 *addr = fi->l_data.mac.mac_addr; 1778 1779 /* Update unicast Tx rules to reflect the selected 1780 * VEB/VEPA mode 1781 */ 1782 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) && 1783 (fi->fltr_act == ICE_FWD_TO_VSI || 1784 fi->fltr_act == ICE_FWD_TO_VSI_LIST || 1785 fi->fltr_act == ICE_FWD_TO_Q || 1786 fi->fltr_act == ICE_FWD_TO_QGRP)) { 1787 status = ice_update_pkt_fwd_rule(hw, fi); 1788 if (status) 1789 break; 1790 } 1791 } 1792 1793 ice_release_lock(rule_lock); 1794 1795 return status; 1796 } 1797 1798 /** 1799 * ice_add_update_vsi_list 1800 * @hw: pointer to the hardware structure 1801 * @m_entry: pointer to current filter management list entry 1802 * @cur_fltr: filter information from the book keeping entry 1803 * @new_fltr: filter information with the new VSI to be added 1804 * 1805 * Call AQ command to add or update previously created VSI list with new VSI. 1806 * 1807 * Helper function to do book keeping associated with adding filter information 1808 * The algorithm to do the book keeping is described below : 1809 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.) 1810 * if only one VSI has been added till now 1811 * Allocate a new VSI list and add two VSIs 1812 * to this list using switch rule command 1813 * Update the previously created switch rule with the 1814 * newly created VSI list ID 1815 * if a VSI list was previously created 1816 * Add the new VSI to the previously created VSI list set 1817 * using the update switch rule command 1818 */ 1819 static enum ice_status 1820 ice_add_update_vsi_list(struct ice_hw *hw, 1821 struct ice_fltr_mgmt_list_entry *m_entry, 1822 struct ice_fltr_info *cur_fltr, 1823 struct ice_fltr_info *new_fltr) 1824 { 1825 enum ice_status status = ICE_SUCCESS; 1826 u16 vsi_list_id = 0; 1827 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q || 1828 cur_fltr->fltr_act == ICE_FWD_TO_QGRP)) 1829 return ICE_ERR_NOT_IMPL; 1830 1831 if ((new_fltr->fltr_act == ICE_FWD_TO_Q || 1832 new_fltr->fltr_act == ICE_FWD_TO_QGRP) && 1833 (cur_fltr->fltr_act == ICE_FWD_TO_VSI || 1834 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST)) 1835 return ICE_ERR_NOT_IMPL; 1836 1837 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) { 1838 /* Only one entry existed in the mapping and it was not already 1839 * a part of a VSI list. So, create a VSI list with the old and 1840 * new VSIs. 1841 */ 1842 struct ice_fltr_info tmp_fltr; 1843 u16 vsi_handle_arr[2]; 1844 1845 /* A rule already exists with the new VSI being added */ 1846 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id) 1847 return ICE_ERR_ALREADY_EXISTS; 1848 1849 vsi_handle_arr[0] = cur_fltr->vsi_handle; 1850 vsi_handle_arr[1] = new_fltr->vsi_handle; 1851 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 1852 &vsi_list_id, 1853 new_fltr->lkup_type); 1854 if (status) 1855 return status; 1856 1857 tmp_fltr = *new_fltr; 1858 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id; 1859 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 1860 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 1861 /* Update the previous switch rule of "MAC forward to VSI" to 1862 * "MAC fwd to VSI list" 1863 */ 1864 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 1865 if (status) 1866 return status; 1867 1868 cur_fltr->fwd_id.vsi_list_id = vsi_list_id; 1869 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 1870 m_entry->vsi_list_info = 1871 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 1872 vsi_list_id); 1873 1874 if (!m_entry->vsi_list_info) 1875 return ICE_ERR_NO_MEMORY; 1876 1877 /* If this entry was large action then the large action needs 1878 * to be updated to point to FWD to VSI list 1879 */ 1880 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) 1881 status = 1882 ice_add_marker_act(hw, m_entry, 1883 m_entry->sw_marker_id, 1884 m_entry->lg_act_idx); 1885 } else { 1886 u16 vsi_handle = new_fltr->vsi_handle; 1887 enum ice_adminq_opc opcode; 1888 1889 if (!m_entry->vsi_list_info) 1890 return ICE_ERR_CFG; 1891 1892 /* A rule already exists with the new VSI being added */ 1893 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle)) 1894 return ICE_SUCCESS; 1895 1896 /* Update the previously created VSI list set with 1897 * the new VSI ID passed in 1898 */ 1899 vsi_list_id = cur_fltr->fwd_id.vsi_list_id; 1900 opcode = ice_aqc_opc_update_sw_rules; 1901 1902 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, 1903 vsi_list_id, false, opcode, 1904 new_fltr->lkup_type); 1905 /* update VSI list mapping info with new VSI ID */ 1906 if (!status) 1907 ice_set_bit(vsi_handle, 1908 m_entry->vsi_list_info->vsi_map); 1909 } 1910 if (!status) 1911 m_entry->vsi_count++; 1912 return status; 1913 } 1914 1915 /** 1916 * ice_find_rule_entry - Search a rule entry 1917 * @list_head: head of rule list 1918 * @f_info: rule information 1919 * 1920 * Helper function to search for a given rule entry 1921 * Returns pointer to entry storing the rule if found 1922 */ 1923 static struct ice_fltr_mgmt_list_entry * 1924 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head, 1925 struct ice_fltr_info *f_info) 1926 { 1927 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL; 1928 1929 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 1930 list_entry) { 1931 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 1932 sizeof(f_info->l_data)) && 1933 f_info->flag == list_itr->fltr_info.flag) { 1934 ret = list_itr; 1935 break; 1936 } 1937 } 1938 return ret; 1939 } 1940 1941 /** 1942 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1 1943 * @recp_list: VSI lists needs to be searched 1944 * @vsi_handle: VSI handle to be found in VSI list 1945 * @vsi_list_id: VSI list ID found containing vsi_handle 1946 * 1947 * Helper function to search a VSI list with single entry containing given VSI 1948 * handle element. This can be extended further to search VSI list with more 1949 * than 1 vsi_count. Returns pointer to VSI list entry if found. 1950 */ 1951 struct ice_vsi_list_map_info * 1952 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle, 1953 u16 *vsi_list_id) 1954 { 1955 struct ice_vsi_list_map_info *map_info = NULL; 1956 struct LIST_HEAD_TYPE *list_head; 1957 1958 list_head = &recp_list->filt_rules; 1959 if (recp_list->adv_rule) { 1960 struct ice_adv_fltr_mgmt_list_entry *list_itr; 1961 1962 LIST_FOR_EACH_ENTRY(list_itr, list_head, 1963 ice_adv_fltr_mgmt_list_entry, 1964 list_entry) { 1965 if (list_itr->vsi_list_info) { 1966 map_info = list_itr->vsi_list_info; 1967 if (ice_is_bit_set(map_info->vsi_map, 1968 vsi_handle)) { 1969 *vsi_list_id = map_info->vsi_list_id; 1970 return map_info; 1971 } 1972 } 1973 } 1974 } else { 1975 struct ice_fltr_mgmt_list_entry *list_itr; 1976 1977 LIST_FOR_EACH_ENTRY(list_itr, list_head, 1978 ice_fltr_mgmt_list_entry, 1979 list_entry) { 1980 if (list_itr->vsi_count == 1 && 1981 list_itr->vsi_list_info) { 1982 map_info = list_itr->vsi_list_info; 1983 if (ice_is_bit_set(map_info->vsi_map, 1984 vsi_handle)) { 1985 *vsi_list_id = map_info->vsi_list_id; 1986 return map_info; 1987 } 1988 } 1989 } 1990 } 1991 return NULL; 1992 } 1993 1994 /** 1995 * ice_add_rule_internal - add rule for a given lookup type 1996 * @hw: pointer to the hardware structure 1997 * @recp_list: recipe list for which rule has to be added 1998 * @lport: logic port number on which function add rule 1999 * @f_entry: structure containing MAC forwarding information 2000 * 2001 * Adds or updates the rule lists for a given recipe 2002 */ 2003 static enum ice_status 2004 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2005 u8 lport, struct ice_fltr_list_entry *f_entry) 2006 { 2007 struct ice_fltr_info *new_fltr, *cur_fltr; 2008 struct ice_fltr_mgmt_list_entry *m_entry; 2009 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2010 enum ice_status status = ICE_SUCCESS; 2011 2012 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2013 return ICE_ERR_PARAM; 2014 2015 /* Load the hw_vsi_id only if the fwd action is fwd to VSI */ 2016 if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI) 2017 f_entry->fltr_info.fwd_id.hw_vsi_id = 2018 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2019 2020 rule_lock = &recp_list->filt_rule_lock; 2021 2022 ice_acquire_lock(rule_lock); 2023 new_fltr = &f_entry->fltr_info; 2024 if (new_fltr->flag & ICE_FLTR_RX) 2025 new_fltr->src = lport; 2026 else if (new_fltr->flag & ICE_FLTR_TX) 2027 new_fltr->src = 2028 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2029 2030 m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 2031 if (!m_entry) { 2032 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 2033 goto exit_add_rule_internal; 2034 } 2035 2036 cur_fltr = &m_entry->fltr_info; 2037 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr); 2038 2039 exit_add_rule_internal: 2040 ice_release_lock(rule_lock); 2041 return status; 2042 } 2043 2044 /** 2045 * ice_remove_vsi_list_rule 2046 * @hw: pointer to the hardware structure 2047 * @vsi_list_id: VSI list ID generated as part of allocate resource 2048 * @lkup_type: switch rule filter lookup type 2049 * 2050 * The VSI list should be emptied before this function is called to remove the 2051 * VSI list. 2052 */ 2053 static enum ice_status 2054 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id, 2055 enum ice_sw_lkup_type lkup_type) 2056 { 2057 /* Free the vsi_list resource that we allocated. It is assumed that the 2058 * list is empty at this point. 2059 */ 2060 return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type, 2061 ice_aqc_opc_free_res); 2062 } 2063 2064 /** 2065 * ice_rem_update_vsi_list 2066 * @hw: pointer to the hardware structure 2067 * @vsi_handle: VSI handle of the VSI to remove 2068 * @fm_list: filter management entry for which the VSI list management needs to 2069 * be done 2070 */ 2071 static enum ice_status 2072 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle, 2073 struct ice_fltr_mgmt_list_entry *fm_list) 2074 { 2075 enum ice_sw_lkup_type lkup_type; 2076 enum ice_status status = ICE_SUCCESS; 2077 u16 vsi_list_id; 2078 2079 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST || 2080 fm_list->vsi_count == 0) 2081 return ICE_ERR_PARAM; 2082 2083 /* A rule with the VSI being removed does not exist */ 2084 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle)) 2085 return ICE_ERR_DOES_NOT_EXIST; 2086 2087 lkup_type = fm_list->fltr_info.lkup_type; 2088 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id; 2089 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true, 2090 ice_aqc_opc_update_sw_rules, 2091 lkup_type); 2092 if (status) 2093 return status; 2094 2095 fm_list->vsi_count--; 2096 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map); 2097 2098 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) { 2099 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info; 2100 struct ice_vsi_list_map_info *vsi_list_info = 2101 fm_list->vsi_list_info; 2102 u16 rem_vsi_handle; 2103 2104 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map, 2105 ICE_MAX_VSI); 2106 if (!ice_is_vsi_valid(hw, rem_vsi_handle)) 2107 return ICE_ERR_OUT_OF_RANGE; 2108 2109 /* Make sure VSI list is empty before removing it below */ 2110 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1, 2111 vsi_list_id, true, 2112 ice_aqc_opc_update_sw_rules, 2113 lkup_type); 2114 if (status) 2115 return status; 2116 2117 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI; 2118 tmp_fltr_info.fwd_id.hw_vsi_id = 2119 ice_get_hw_vsi_num(hw, rem_vsi_handle); 2120 tmp_fltr_info.vsi_handle = rem_vsi_handle; 2121 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info); 2122 if (status) { 2123 ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n", 2124 tmp_fltr_info.fwd_id.hw_vsi_id, status); 2125 return status; 2126 } 2127 2128 fm_list->fltr_info = tmp_fltr_info; 2129 } 2130 2131 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) || 2132 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) { 2133 struct ice_vsi_list_map_info *vsi_list_info = 2134 fm_list->vsi_list_info; 2135 2136 /* Remove the VSI list since it is no longer used */ 2137 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type); 2138 if (status) { 2139 ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n", 2140 vsi_list_id, status); 2141 return status; 2142 } 2143 2144 LIST_DEL(&vsi_list_info->list_entry); 2145 ice_free(hw, vsi_list_info); 2146 fm_list->vsi_list_info = NULL; 2147 } 2148 2149 return status; 2150 } 2151 2152 /** 2153 * ice_remove_rule_internal - Remove a filter rule of a given type 2154 * @hw: pointer to the hardware structure 2155 * @recp_list: recipe list for which the rule needs to removed 2156 * @f_entry: rule entry containing filter information 2157 */ 2158 static enum ice_status 2159 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2160 struct ice_fltr_list_entry *f_entry) 2161 { 2162 struct ice_fltr_mgmt_list_entry *list_elem; 2163 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2164 enum ice_status status = ICE_SUCCESS; 2165 bool remove_rule = false; 2166 u16 vsi_handle; 2167 2168 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2169 return ICE_ERR_PARAM; 2170 f_entry->fltr_info.fwd_id.hw_vsi_id = 2171 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2172 2173 rule_lock = &recp_list->filt_rule_lock; 2174 ice_acquire_lock(rule_lock); 2175 list_elem = ice_find_rule_entry(&recp_list->filt_rules, 2176 &f_entry->fltr_info); 2177 if (!list_elem) { 2178 status = ICE_ERR_DOES_NOT_EXIST; 2179 goto exit; 2180 } 2181 2182 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) { 2183 remove_rule = true; 2184 } else if (!list_elem->vsi_list_info) { 2185 status = ICE_ERR_DOES_NOT_EXIST; 2186 goto exit; 2187 } else if (list_elem->vsi_list_info->ref_cnt > 1) { 2188 /* a ref_cnt > 1 indicates that the vsi_list is being 2189 * shared by multiple rules. Decrement the ref_cnt and 2190 * remove this rule, but do not modify the list, as it 2191 * is in-use by other rules. 2192 */ 2193 list_elem->vsi_list_info->ref_cnt--; 2194 remove_rule = true; 2195 } else { 2196 /* a ref_cnt of 1 indicates the vsi_list is only used 2197 * by one rule. However, the original removal request is only 2198 * for a single VSI. Update the vsi_list first, and only 2199 * remove the rule if there are no further VSIs in this list. 2200 */ 2201 vsi_handle = f_entry->fltr_info.vsi_handle; 2202 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 2203 if (status) 2204 goto exit; 2205 /* if VSI count goes to zero after updating the VSI list */ 2206 if (list_elem->vsi_count == 0) 2207 remove_rule = true; 2208 } 2209 2210 if (remove_rule) { 2211 /* Remove the lookup rule */ 2212 struct ice_sw_rule_lkup_rx_tx *s_rule; 2213 2214 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 2215 ice_malloc(hw, ice_struct_size(s_rule, hdr_data, 0)); 2216 if (!s_rule) { 2217 status = ICE_ERR_NO_MEMORY; 2218 goto exit; 2219 } 2220 2221 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule, 2222 ice_aqc_opc_remove_sw_rules); 2223 2224 status = ice_aq_sw_rules(hw, s_rule, 2225 ice_struct_size(s_rule, hdr_data, 0), 2226 1, ice_aqc_opc_remove_sw_rules, NULL); 2227 2228 /* Remove a book keeping from the list */ 2229 ice_free(hw, s_rule); 2230 2231 if (status) 2232 goto exit; 2233 2234 LIST_DEL(&list_elem->list_entry); 2235 ice_free(hw, list_elem); 2236 } 2237 exit: 2238 ice_release_lock(rule_lock); 2239 return status; 2240 } 2241 2242 /** 2243 * ice_aq_get_res_alloc - get allocated resources 2244 * @hw: pointer to the HW struct 2245 * @num_entries: pointer to u16 to store the number of resource entries returned 2246 * @buf: pointer to buffer 2247 * @buf_size: size of buf 2248 * @cd: pointer to command details structure or NULL 2249 * 2250 * The caller-supplied buffer must be large enough to store the resource 2251 * information for all resource types. Each resource type is an 2252 * ice_aqc_get_res_resp_elem structure. 2253 */ 2254 enum ice_status 2255 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, 2256 struct ice_aqc_get_res_resp_elem *buf, u16 buf_size, 2257 struct ice_sq_cd *cd) 2258 { 2259 struct ice_aqc_get_res_alloc *resp; 2260 enum ice_status status; 2261 struct ice_aq_desc desc; 2262 2263 if (!buf) 2264 return ICE_ERR_BAD_PTR; 2265 2266 if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN) 2267 return ICE_ERR_INVAL_SIZE; 2268 2269 resp = &desc.params.get_res; 2270 2271 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc); 2272 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2273 2274 if (!status && num_entries) 2275 *num_entries = LE16_TO_CPU(resp->resp_elem_num); 2276 2277 return status; 2278 } 2279 2280 /** 2281 * ice_aq_get_res_descs - get allocated resource descriptors 2282 * @hw: pointer to the hardware structure 2283 * @num_entries: number of resource entries in buffer 2284 * @buf: structure to hold response data buffer 2285 * @buf_size: size of buffer 2286 * @res_type: resource type 2287 * @res_shared: is resource shared 2288 * @desc_id: input - first desc ID to start; output - next desc ID 2289 * @cd: pointer to command details structure or NULL 2290 */ 2291 enum ice_status 2292 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries, 2293 struct ice_aqc_res_elem *buf, u16 buf_size, u16 res_type, 2294 bool res_shared, u16 *desc_id, struct ice_sq_cd *cd) 2295 { 2296 struct ice_aqc_get_allocd_res_desc *cmd; 2297 struct ice_aq_desc desc; 2298 enum ice_status status; 2299 2300 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 2301 2302 cmd = &desc.params.get_res_desc; 2303 2304 if (!buf) 2305 return ICE_ERR_PARAM; 2306 2307 if (buf_size != (num_entries * sizeof(*buf))) 2308 return ICE_ERR_PARAM; 2309 2310 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc); 2311 2312 cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) & 2313 ICE_AQC_RES_TYPE_M) | (res_shared ? 2314 ICE_AQC_RES_TYPE_FLAG_SHARED : 0)); 2315 cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id); 2316 2317 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 2318 if (!status) 2319 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc); 2320 2321 return status; 2322 } 2323 2324 /** 2325 * ice_add_mac_rule - Add a MAC address based filter rule 2326 * @hw: pointer to the hardware structure 2327 * @m_list: list of MAC addresses and forwarding information 2328 * @sw: pointer to switch info struct for which function add rule 2329 * @lport: logic port number on which function add rule 2330 * 2331 * IMPORTANT: When the umac_shared flag is set to false and m_list has 2332 * multiple unicast addresses, the function assumes that all the 2333 * addresses are unique in a given add_mac call. It doesn't 2334 * check for duplicates in this case, removing duplicates from a given 2335 * list should be taken care of in the caller of this function. 2336 */ 2337 static enum ice_status 2338 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 2339 struct ice_switch_info *sw, u8 lport) 2340 { 2341 struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC]; 2342 struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter; 2343 struct ice_fltr_list_entry *m_list_itr; 2344 struct LIST_HEAD_TYPE *rule_head; 2345 u16 total_elem_left, s_rule_size; 2346 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2347 enum ice_status status = ICE_SUCCESS; 2348 u16 num_unicast = 0; 2349 u8 elem_sent; 2350 2351 s_rule = NULL; 2352 rule_lock = &recp_list->filt_rule_lock; 2353 rule_head = &recp_list->filt_rules; 2354 2355 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2356 list_entry) { 2357 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0]; 2358 u16 vsi_handle; 2359 u16 hw_vsi_id; 2360 2361 m_list_itr->fltr_info.flag = ICE_FLTR_TX; 2362 vsi_handle = m_list_itr->fltr_info.vsi_handle; 2363 if (!ice_is_vsi_valid(hw, vsi_handle)) 2364 return ICE_ERR_PARAM; 2365 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2366 if (m_list_itr->fltr_info.fltr_act == ICE_FWD_TO_VSI) 2367 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id; 2368 /* update the src in case it is VSI num */ 2369 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI) 2370 return ICE_ERR_PARAM; 2371 m_list_itr->fltr_info.src = hw_vsi_id; 2372 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC || 2373 IS_ZERO_ETHER_ADDR(add)) 2374 return ICE_ERR_PARAM; 2375 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) { 2376 /* Don't overwrite the unicast address */ 2377 ice_acquire_lock(rule_lock); 2378 if (ice_find_rule_entry(rule_head, 2379 &m_list_itr->fltr_info)) { 2380 ice_release_lock(rule_lock); 2381 continue; 2382 } 2383 ice_release_lock(rule_lock); 2384 num_unicast++; 2385 } else if (IS_MULTICAST_ETHER_ADDR(add) || 2386 (IS_UNICAST_ETHER_ADDR(add) && hw->umac_shared)) { 2387 m_list_itr->status = 2388 ice_add_rule_internal(hw, recp_list, lport, 2389 m_list_itr); 2390 if (m_list_itr->status) 2391 return m_list_itr->status; 2392 } 2393 } 2394 2395 ice_acquire_lock(rule_lock); 2396 /* Exit if no suitable entries were found for adding bulk switch rule */ 2397 if (!num_unicast) { 2398 status = ICE_SUCCESS; 2399 goto ice_add_mac_exit; 2400 } 2401 2402 /* Allocate switch rule buffer for the bulk update for unicast */ 2403 s_rule_size = ice_struct_size(s_rule, hdr_data, DUMMY_ETH_HDR_LEN); 2404 s_rule = (struct ice_sw_rule_lkup_rx_tx *) 2405 ice_calloc(hw, num_unicast, s_rule_size); 2406 if (!s_rule) { 2407 status = ICE_ERR_NO_MEMORY; 2408 goto ice_add_mac_exit; 2409 } 2410 2411 r_iter = s_rule; 2412 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2413 list_entry) { 2414 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2415 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2416 2417 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2418 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter, 2419 ice_aqc_opc_add_sw_rules); 2420 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2421 ((u8 *)r_iter + s_rule_size); 2422 } 2423 } 2424 2425 /* Call AQ bulk switch rule update for all unicast addresses */ 2426 r_iter = s_rule; 2427 /* Call AQ switch rule in AQ_MAX chunk */ 2428 for (total_elem_left = num_unicast; total_elem_left > 0; 2429 total_elem_left -= elem_sent) { 2430 struct ice_sw_rule_lkup_rx_tx *entry = r_iter; 2431 2432 elem_sent = MIN_T(u8, total_elem_left, 2433 (ICE_AQ_MAX_BUF_LEN / s_rule_size)); 2434 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, 2435 elem_sent, ice_aqc_opc_add_sw_rules, 2436 NULL); 2437 if (status) 2438 goto ice_add_mac_exit; 2439 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2440 ((u8 *)r_iter + (elem_sent * s_rule_size)); 2441 } 2442 2443 /* Fill up rule ID based on the value returned from FW */ 2444 r_iter = s_rule; 2445 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry, 2446 list_entry) { 2447 struct ice_fltr_info *f_info = &m_list_itr->fltr_info; 2448 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0]; 2449 struct ice_fltr_mgmt_list_entry *fm_entry; 2450 2451 if (IS_UNICAST_ETHER_ADDR(mac_addr)) { 2452 f_info->fltr_rule_id = 2453 LE16_TO_CPU(r_iter->index); 2454 f_info->fltr_act = ICE_FWD_TO_VSI; 2455 /* Create an entry to track this MAC address */ 2456 fm_entry = (struct ice_fltr_mgmt_list_entry *) 2457 ice_malloc(hw, sizeof(*fm_entry)); 2458 if (!fm_entry) { 2459 status = ICE_ERR_NO_MEMORY; 2460 goto ice_add_mac_exit; 2461 } 2462 fm_entry->fltr_info = *f_info; 2463 fm_entry->vsi_count = 1; 2464 /* The book keeping entries will get removed when 2465 * base driver calls remove filter AQ command 2466 */ 2467 2468 LIST_ADD(&fm_entry->list_entry, rule_head); 2469 r_iter = (struct ice_sw_rule_lkup_rx_tx *) 2470 ((u8 *)r_iter + s_rule_size); 2471 } 2472 } 2473 2474 ice_add_mac_exit: 2475 ice_release_lock(rule_lock); 2476 if (s_rule) 2477 ice_free(hw, s_rule); 2478 return status; 2479 } 2480 2481 /** 2482 * ice_add_mac - Add a MAC address based filter rule 2483 * @hw: pointer to the hardware structure 2484 * @m_list: list of MAC addresses and forwarding information 2485 * 2486 * Function add MAC rule for logical port from HW struct 2487 */ 2488 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 2489 { 2490 if (!m_list || !hw) 2491 return ICE_ERR_PARAM; 2492 2493 return ice_add_mac_rule(hw, m_list, hw->switch_info, 2494 hw->port_info->lport); 2495 } 2496 2497 /** 2498 * ice_add_vlan_internal - Add one VLAN based filter rule 2499 * @hw: pointer to the hardware structure 2500 * @recp_list: recipe list for which rule has to be added 2501 * @f_entry: filter entry containing one VLAN information 2502 */ 2503 static enum ice_status 2504 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list, 2505 struct ice_fltr_list_entry *f_entry) 2506 { 2507 struct ice_fltr_mgmt_list_entry *v_list_itr; 2508 struct ice_fltr_info *new_fltr, *cur_fltr; 2509 enum ice_sw_lkup_type lkup_type; 2510 u16 vsi_list_id = 0, vsi_handle; 2511 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 2512 enum ice_status status = ICE_SUCCESS; 2513 2514 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle)) 2515 return ICE_ERR_PARAM; 2516 2517 f_entry->fltr_info.fwd_id.hw_vsi_id = 2518 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle); 2519 new_fltr = &f_entry->fltr_info; 2520 2521 /* VLAN ID should only be 12 bits */ 2522 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID) 2523 return ICE_ERR_PARAM; 2524 2525 if (new_fltr->src_id != ICE_SRC_ID_VSI) 2526 return ICE_ERR_PARAM; 2527 2528 new_fltr->src = new_fltr->fwd_id.hw_vsi_id; 2529 lkup_type = new_fltr->lkup_type; 2530 vsi_handle = new_fltr->vsi_handle; 2531 rule_lock = &recp_list->filt_rule_lock; 2532 ice_acquire_lock(rule_lock); 2533 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr); 2534 if (!v_list_itr) { 2535 struct ice_vsi_list_map_info *map_info = NULL; 2536 2537 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) { 2538 /* All VLAN pruning rules use a VSI list. Check if 2539 * there is already a VSI list containing VSI that we 2540 * want to add. If found, use the same vsi_list_id for 2541 * this new VLAN rule or else create a new list. 2542 */ 2543 map_info = ice_find_vsi_list_entry(recp_list, 2544 vsi_handle, 2545 &vsi_list_id); 2546 if (!map_info) { 2547 status = ice_create_vsi_list_rule(hw, 2548 &vsi_handle, 2549 1, 2550 &vsi_list_id, 2551 lkup_type); 2552 if (status) 2553 goto exit; 2554 } 2555 /* Convert the action to forwarding to a VSI list. */ 2556 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST; 2557 new_fltr->fwd_id.vsi_list_id = vsi_list_id; 2558 } 2559 2560 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry); 2561 if (!status) { 2562 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, 2563 new_fltr); 2564 if (!v_list_itr) { 2565 status = ICE_ERR_DOES_NOT_EXIST; 2566 goto exit; 2567 } 2568 /* reuse VSI list for new rule and increment ref_cnt */ 2569 if (map_info) { 2570 v_list_itr->vsi_list_info = map_info; 2571 map_info->ref_cnt++; 2572 } else { 2573 v_list_itr->vsi_list_info = 2574 ice_create_vsi_list_map(hw, &vsi_handle, 2575 1, vsi_list_id); 2576 } 2577 } 2578 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) { 2579 /* Update existing VSI list to add new VSI ID only if it used 2580 * by one VLAN rule. 2581 */ 2582 cur_fltr = &v_list_itr->fltr_info; 2583 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr, 2584 new_fltr); 2585 } else { 2586 /* If VLAN rule exists and VSI list being used by this rule is 2587 * referenced by more than 1 VLAN rule. Then create a new VSI 2588 * list appending previous VSI with new VSI and update existing 2589 * VLAN rule to point to new VSI list ID 2590 */ 2591 struct ice_fltr_info tmp_fltr; 2592 u16 vsi_handle_arr[2]; 2593 u16 cur_handle; 2594 2595 /* Current implementation only supports reusing VSI list with 2596 * one VSI count. We should never hit below condition 2597 */ 2598 if (v_list_itr->vsi_count > 1 && 2599 v_list_itr->vsi_list_info->ref_cnt > 1) { 2600 ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n"); 2601 status = ICE_ERR_CFG; 2602 goto exit; 2603 } 2604 2605 cur_handle = 2606 ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map, 2607 ICE_MAX_VSI); 2608 2609 /* A rule already exists with the new VSI being added */ 2610 if (cur_handle == vsi_handle) { 2611 status = ICE_ERR_ALREADY_EXISTS; 2612 goto exit; 2613 } 2614 2615 vsi_handle_arr[0] = cur_handle; 2616 vsi_handle_arr[1] = vsi_handle; 2617 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2, 2618 &vsi_list_id, lkup_type); 2619 if (status) 2620 goto exit; 2621 2622 tmp_fltr = v_list_itr->fltr_info; 2623 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id; 2624 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id; 2625 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST; 2626 /* Update the previous switch rule to a new VSI list which 2627 * includes current VSI that is requested 2628 */ 2629 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr); 2630 if (status) 2631 goto exit; 2632 2633 /* before overriding VSI list map info. decrement ref_cnt of 2634 * previous VSI list 2635 */ 2636 v_list_itr->vsi_list_info->ref_cnt--; 2637 2638 /* now update to newly created list */ 2639 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id; 2640 v_list_itr->vsi_list_info = 2641 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, 2642 vsi_list_id); 2643 v_list_itr->vsi_count++; 2644 } 2645 2646 exit: 2647 ice_release_lock(rule_lock); 2648 return status; 2649 } 2650 2651 /** 2652 * ice_add_vlan_rule - Add VLAN based filter rule 2653 * @hw: pointer to the hardware structure 2654 * @v_list: list of VLAN entries and forwarding information 2655 * @sw: pointer to switch info struct for which function add rule 2656 */ 2657 static enum ice_status 2658 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 2659 struct ice_switch_info *sw) 2660 { 2661 struct ice_fltr_list_entry *v_list_itr; 2662 struct ice_sw_recipe *recp_list; 2663 2664 recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN]; 2665 LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry, 2666 list_entry) { 2667 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN) 2668 return ICE_ERR_PARAM; 2669 v_list_itr->fltr_info.flag = ICE_FLTR_TX; 2670 v_list_itr->status = ice_add_vlan_internal(hw, recp_list, 2671 v_list_itr); 2672 if (v_list_itr->status) 2673 return v_list_itr->status; 2674 } 2675 return ICE_SUCCESS; 2676 } 2677 2678 /** 2679 * ice_add_vlan - Add a VLAN based filter rule 2680 * @hw: pointer to the hardware structure 2681 * @v_list: list of VLAN and forwarding information 2682 * 2683 * Function add VLAN rule for logical port from HW struct 2684 */ 2685 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 2686 { 2687 if (!v_list || !hw) 2688 return ICE_ERR_PARAM; 2689 2690 return ice_add_vlan_rule(hw, v_list, hw->switch_info); 2691 } 2692 2693 /** 2694 * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule 2695 * @hw: pointer to the hardware structure 2696 * @em_list: list of ether type MAC filter, MAC is optional 2697 * @sw: pointer to switch info struct for which function add rule 2698 * @lport: logic port number on which function add rule 2699 * 2700 * This function requires the caller to populate the entries in 2701 * the filter list with the necessary fields (including flags to 2702 * indicate Tx or Rx rules). 2703 */ 2704 static enum ice_status 2705 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 2706 struct ice_switch_info *sw, u8 lport) 2707 { 2708 struct ice_fltr_list_entry *em_list_itr; 2709 2710 LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry, 2711 list_entry) { 2712 struct ice_sw_recipe *recp_list; 2713 enum ice_sw_lkup_type l_type; 2714 2715 l_type = em_list_itr->fltr_info.lkup_type; 2716 recp_list = &sw->recp_list[l_type]; 2717 2718 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 2719 l_type != ICE_SW_LKUP_ETHERTYPE) 2720 return ICE_ERR_PARAM; 2721 2722 em_list_itr->status = ice_add_rule_internal(hw, recp_list, 2723 lport, 2724 em_list_itr); 2725 if (em_list_itr->status) 2726 return em_list_itr->status; 2727 } 2728 return ICE_SUCCESS; 2729 } 2730 2731 /** 2732 * ice_add_eth_mac - Add a ethertype based filter rule 2733 * @hw: pointer to the hardware structure 2734 * @em_list: list of ethertype and forwarding information 2735 * 2736 * Function add ethertype rule for logical port from HW struct 2737 */ 2738 enum ice_status 2739 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 2740 { 2741 if (!em_list || !hw) 2742 return ICE_ERR_PARAM; 2743 2744 return ice_add_eth_mac_rule(hw, em_list, hw->switch_info, 2745 hw->port_info->lport); 2746 } 2747 2748 /** 2749 * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule 2750 * @hw: pointer to the hardware structure 2751 * @em_list: list of ethertype or ethertype MAC entries 2752 * @sw: pointer to switch info struct for which function add rule 2753 */ 2754 static enum ice_status 2755 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list, 2756 struct ice_switch_info *sw) 2757 { 2758 struct ice_fltr_list_entry *em_list_itr, *tmp; 2759 2760 LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry, 2761 list_entry) { 2762 struct ice_sw_recipe *recp_list; 2763 enum ice_sw_lkup_type l_type; 2764 2765 l_type = em_list_itr->fltr_info.lkup_type; 2766 2767 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && 2768 l_type != ICE_SW_LKUP_ETHERTYPE) 2769 return ICE_ERR_PARAM; 2770 2771 recp_list = &sw->recp_list[l_type]; 2772 em_list_itr->status = ice_remove_rule_internal(hw, recp_list, 2773 em_list_itr); 2774 if (em_list_itr->status) 2775 return em_list_itr->status; 2776 } 2777 return ICE_SUCCESS; 2778 } 2779 2780 /** 2781 * ice_remove_eth_mac - remove a ethertype based filter rule 2782 * @hw: pointer to the hardware structure 2783 * @em_list: list of ethertype and forwarding information 2784 * 2785 */ 2786 enum ice_status 2787 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) 2788 { 2789 if (!em_list || !hw) 2790 return ICE_ERR_PARAM; 2791 2792 return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info); 2793 } 2794 2795 /** 2796 * ice_get_lg_act_aqc_res_type - get resource type for a large action 2797 * @res_type: resource type to be filled in case of function success 2798 * @num_acts: number of actions to hold with a large action entry 2799 * 2800 * Get resource type for a large action depending on the number 2801 * of single actions that it contains. 2802 */ 2803 static enum ice_status 2804 ice_get_lg_act_aqc_res_type(u16 *res_type, int num_acts) 2805 { 2806 if (!res_type) 2807 return ICE_ERR_BAD_PTR; 2808 2809 /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1. 2810 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3. 2811 * If num_acts is greater than 2, then use 2812 * ICE_AQC_RES_TYPE_WIDE_TABLE_4. 2813 * The num_acts cannot be equal to 0 or greater than 4. 2814 */ 2815 switch (num_acts) { 2816 case 1: 2817 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_1; 2818 break; 2819 case 2: 2820 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_2; 2821 break; 2822 case 3: 2823 case 4: 2824 *res_type = ICE_AQC_RES_TYPE_WIDE_TABLE_4; 2825 break; 2826 default: 2827 return ICE_ERR_PARAM; 2828 } 2829 2830 return ICE_SUCCESS; 2831 } 2832 2833 /** 2834 * ice_alloc_res_lg_act - add large action resource 2835 * @hw: pointer to the hardware structure 2836 * @l_id: large action ID to fill it in 2837 * @num_acts: number of actions to hold with a large action entry 2838 */ 2839 static enum ice_status 2840 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts) 2841 { 2842 struct ice_aqc_alloc_free_res_elem *sw_buf; 2843 enum ice_status status; 2844 u16 buf_len, res_type; 2845 2846 if (!l_id) 2847 return ICE_ERR_BAD_PTR; 2848 2849 status = ice_get_lg_act_aqc_res_type(&res_type, num_acts); 2850 if (status) 2851 return status; 2852 2853 /* Allocate resource for large action */ 2854 buf_len = ice_struct_size(sw_buf, elem, 1); 2855 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 2856 if (!sw_buf) 2857 return ICE_ERR_NO_MEMORY; 2858 2859 sw_buf->res_type = CPU_TO_LE16(res_type); 2860 sw_buf->num_elems = CPU_TO_LE16(1); 2861 2862 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, 2863 ice_aqc_opc_alloc_res, NULL); 2864 if (!status) 2865 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp); 2866 2867 ice_free(hw, sw_buf); 2868 2869 return status; 2870 } 2871 2872 /** 2873 * ice_rem_sw_rule_info 2874 * @hw: pointer to the hardware structure 2875 * @rule_head: pointer to the switch list structure that we want to delete 2876 */ 2877 static void 2878 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head) 2879 { 2880 if (!LIST_EMPTY(rule_head)) { 2881 struct ice_fltr_mgmt_list_entry *entry; 2882 struct ice_fltr_mgmt_list_entry *tmp; 2883 2884 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head, 2885 ice_fltr_mgmt_list_entry, list_entry) { 2886 LIST_DEL(&entry->list_entry); 2887 ice_free(hw, entry); 2888 } 2889 } 2890 } 2891 2892 /** 2893 * ice_rem_all_sw_rules_info 2894 * @hw: pointer to the hardware structure 2895 */ 2896 void ice_rem_all_sw_rules_info(struct ice_hw *hw) 2897 { 2898 struct ice_switch_info *sw = hw->switch_info; 2899 u8 i; 2900 2901 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 2902 struct LIST_HEAD_TYPE *rule_head; 2903 2904 rule_head = &sw->recp_list[i].filt_rules; 2905 if (!sw->recp_list[i].adv_rule) 2906 ice_rem_sw_rule_info(hw, rule_head); 2907 } 2908 } 2909 2910 /** 2911 * ice_cfg_dflt_vsi - change state of VSI to set/clear default 2912 * @pi: pointer to the port_info structure 2913 * @vsi_handle: VSI handle to set as default 2914 * @set: true to add the above mentioned switch rule, false to remove it 2915 * @direction: ICE_FLTR_RX or ICE_FLTR_TX 2916 * 2917 * add filter rule to set/unset given VSI as default VSI for the switch 2918 * (represented by swid) 2919 */ 2920 enum ice_status 2921 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set, 2922 u8 direction) 2923 { 2924 struct ice_fltr_list_entry f_list_entry; 2925 struct ice_sw_recipe *recp_list = NULL; 2926 struct ice_fltr_info f_info; 2927 struct ice_hw *hw = pi->hw; 2928 enum ice_status status; 2929 u8 lport = pi->lport; 2930 u16 hw_vsi_id; 2931 recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT]; 2932 2933 if (!ice_is_vsi_valid(hw, vsi_handle)) 2934 return ICE_ERR_PARAM; 2935 2936 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 2937 2938 ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM); 2939 2940 f_info.lkup_type = ICE_SW_LKUP_DFLT; 2941 f_info.flag = direction; 2942 f_info.fltr_act = ICE_FWD_TO_VSI; 2943 f_info.fwd_id.hw_vsi_id = hw_vsi_id; 2944 f_info.vsi_handle = vsi_handle; 2945 2946 if (f_info.flag & ICE_FLTR_RX) { 2947 f_info.src = pi->lport; 2948 f_info.src_id = ICE_SRC_ID_LPORT; 2949 } else if (f_info.flag & ICE_FLTR_TX) { 2950 f_info.src_id = ICE_SRC_ID_VSI; 2951 f_info.src = hw_vsi_id; 2952 } 2953 f_list_entry.fltr_info = f_info; 2954 2955 if (set) 2956 status = ice_add_rule_internal(hw, recp_list, lport, 2957 &f_list_entry); 2958 else 2959 status = ice_remove_rule_internal(hw, recp_list, 2960 &f_list_entry); 2961 2962 return status; 2963 } 2964 2965 /** 2966 * ice_check_if_dflt_vsi - check if VSI is default VSI 2967 * @pi: pointer to the port_info structure 2968 * @vsi_handle: vsi handle to check for in filter list 2969 * @rule_exists: indicates if there are any VSI's in the rule list 2970 * 2971 * checks if the VSI is in a default VSI list, and also indicates 2972 * if the default VSI list is empty 2973 */ 2974 bool ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, 2975 bool *rule_exists) 2976 { 2977 struct ice_fltr_mgmt_list_entry *fm_entry; 2978 struct LIST_HEAD_TYPE *rule_head; 2979 struct ice_sw_recipe *recp_list; 2980 struct ice_lock *rule_lock; 2981 bool ret = false; 2982 recp_list = &pi->hw->switch_info->recp_list[ICE_SW_LKUP_DFLT]; 2983 rule_lock = &recp_list->filt_rule_lock; 2984 rule_head = &recp_list->filt_rules; 2985 2986 ice_acquire_lock(rule_lock); 2987 2988 if (rule_exists && !LIST_EMPTY(rule_head)) 2989 *rule_exists = true; 2990 2991 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, 2992 ice_fltr_mgmt_list_entry, list_entry) { 2993 if (ice_vsi_uses_fltr(fm_entry, vsi_handle)) { 2994 ret = true; 2995 break; 2996 } 2997 } 2998 2999 ice_release_lock(rule_lock); 3000 return ret; 3001 } 3002 3003 /** 3004 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry 3005 * @list_head: head of rule list 3006 * @f_info: rule information 3007 * 3008 * Helper function to search for a unicast rule entry - this is to be used 3009 * to remove unicast MAC filter that is not shared with other VSIs on the 3010 * PF switch. 3011 * 3012 * Returns pointer to entry storing the rule if found 3013 */ 3014 static struct ice_fltr_mgmt_list_entry * 3015 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head, 3016 struct ice_fltr_info *f_info) 3017 { 3018 struct ice_fltr_mgmt_list_entry *list_itr; 3019 3020 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry, 3021 list_entry) { 3022 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data, 3023 sizeof(f_info->l_data)) && 3024 f_info->fwd_id.hw_vsi_id == 3025 list_itr->fltr_info.fwd_id.hw_vsi_id && 3026 f_info->flag == list_itr->fltr_info.flag) 3027 return list_itr; 3028 } 3029 return NULL; 3030 } 3031 3032 /** 3033 * ice_remove_mac_rule - remove a MAC based filter rule 3034 * @hw: pointer to the hardware structure 3035 * @m_list: list of MAC addresses and forwarding information 3036 * @recp_list: list from which function remove MAC address 3037 * 3038 * This function removes either a MAC filter rule or a specific VSI from a 3039 * VSI list for a multicast MAC address. 3040 * 3041 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by 3042 * ice_add_mac. Caller should be aware that this call will only work if all 3043 * the entries passed into m_list were added previously. It will not attempt to 3044 * do a partial remove of entries that were found. 3045 */ 3046 static enum ice_status 3047 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list, 3048 struct ice_sw_recipe *recp_list) 3049 { 3050 struct ice_fltr_list_entry *list_itr, *tmp; 3051 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3052 3053 if (!m_list) 3054 return ICE_ERR_PARAM; 3055 3056 rule_lock = &recp_list->filt_rule_lock; 3057 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry, 3058 list_entry) { 3059 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type; 3060 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0]; 3061 u16 vsi_handle; 3062 3063 if (l_type != ICE_SW_LKUP_MAC) 3064 return ICE_ERR_PARAM; 3065 3066 vsi_handle = list_itr->fltr_info.vsi_handle; 3067 if (!ice_is_vsi_valid(hw, vsi_handle)) 3068 return ICE_ERR_PARAM; 3069 3070 list_itr->fltr_info.fwd_id.hw_vsi_id = 3071 ice_get_hw_vsi_num(hw, vsi_handle); 3072 if (IS_UNICAST_ETHER_ADDR(add) && !hw->umac_shared) { 3073 /* Don't remove the unicast address that belongs to 3074 * another VSI on the switch, since it is not being 3075 * shared... 3076 */ 3077 ice_acquire_lock(rule_lock); 3078 if (!ice_find_ucast_rule_entry(&recp_list->filt_rules, 3079 &list_itr->fltr_info)) { 3080 ice_release_lock(rule_lock); 3081 return ICE_ERR_DOES_NOT_EXIST; 3082 } 3083 ice_release_lock(rule_lock); 3084 } 3085 list_itr->status = ice_remove_rule_internal(hw, recp_list, 3086 list_itr); 3087 if (list_itr->status) 3088 return list_itr->status; 3089 } 3090 return ICE_SUCCESS; 3091 } 3092 3093 /** 3094 * ice_remove_mac - remove a MAC address based filter rule 3095 * @hw: pointer to the hardware structure 3096 * @m_list: list of MAC addresses and forwarding information 3097 * 3098 */ 3099 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list) 3100 { 3101 struct ice_sw_recipe *recp_list; 3102 3103 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 3104 return ice_remove_mac_rule(hw, m_list, recp_list); 3105 } 3106 3107 /** 3108 * ice_remove_vlan_rule - Remove VLAN based filter rule 3109 * @hw: pointer to the hardware structure 3110 * @v_list: list of VLAN entries and forwarding information 3111 * @recp_list: list from which function remove VLAN 3112 */ 3113 static enum ice_status 3114 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list, 3115 struct ice_sw_recipe *recp_list) 3116 { 3117 struct ice_fltr_list_entry *v_list_itr, *tmp; 3118 3119 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3120 list_entry) { 3121 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type; 3122 3123 if (l_type != ICE_SW_LKUP_VLAN) 3124 return ICE_ERR_PARAM; 3125 v_list_itr->status = ice_remove_rule_internal(hw, recp_list, 3126 v_list_itr); 3127 if (v_list_itr->status) 3128 return v_list_itr->status; 3129 } 3130 return ICE_SUCCESS; 3131 } 3132 3133 /** 3134 * ice_remove_vlan - remove a VLAN address based filter rule 3135 * @hw: pointer to the hardware structure 3136 * @v_list: list of VLAN and forwarding information 3137 * 3138 */ 3139 enum ice_status 3140 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list) 3141 { 3142 struct ice_sw_recipe *recp_list; 3143 3144 if (!v_list || !hw) 3145 return ICE_ERR_PARAM; 3146 3147 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN]; 3148 return ice_remove_vlan_rule(hw, v_list, recp_list); 3149 } 3150 3151 /** 3152 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter 3153 * @fm_entry: filter entry to inspect 3154 * @vsi_handle: VSI handle to compare with filter info 3155 */ 3156 static bool 3157 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) 3158 { 3159 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && 3160 fm_entry->fltr_info.vsi_handle == vsi_handle) || 3161 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && 3162 fm_entry->vsi_list_info && 3163 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map, 3164 vsi_handle)))); 3165 } 3166 3167 /** 3168 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list 3169 * @hw: pointer to the hardware structure 3170 * @vsi_handle: VSI handle to remove filters from 3171 * @vsi_list_head: pointer to the list to add entry to 3172 * @fi: pointer to fltr_info of filter entry to copy & add 3173 * 3174 * Helper function, used when creating a list of filters to remove from 3175 * a specific VSI. The entry added to vsi_list_head is a COPY of the 3176 * original filter entry, with the exception of fltr_info.fltr_act and 3177 * fltr_info.fwd_id fields. These are set such that later logic can 3178 * extract which VSI to remove the fltr from, and pass on that information. 3179 */ 3180 static enum ice_status 3181 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3182 struct LIST_HEAD_TYPE *vsi_list_head, 3183 struct ice_fltr_info *fi) 3184 { 3185 struct ice_fltr_list_entry *tmp; 3186 3187 /* this memory is freed up in the caller function 3188 * once filters for this VSI are removed 3189 */ 3190 tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp)); 3191 if (!tmp) 3192 return ICE_ERR_NO_MEMORY; 3193 3194 tmp->fltr_info = *fi; 3195 3196 /* Overwrite these fields to indicate which VSI to remove filter from, 3197 * so find and remove logic can extract the information from the 3198 * list entries. Note that original entries will still have proper 3199 * values. 3200 */ 3201 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 3202 tmp->fltr_info.vsi_handle = vsi_handle; 3203 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3204 3205 LIST_ADD(&tmp->list_entry, vsi_list_head); 3206 3207 return ICE_SUCCESS; 3208 } 3209 3210 /** 3211 * ice_add_to_vsi_fltr_list - Add VSI filters to the list 3212 * @hw: pointer to the hardware structure 3213 * @vsi_handle: VSI handle to remove filters from 3214 * @lkup_list_head: pointer to the list that has certain lookup type filters 3215 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle 3216 * 3217 * Locates all filters in lkup_list_head that are used by the given VSI, 3218 * and adds COPIES of those entries to vsi_list_head (intended to be used 3219 * to remove the listed filters). 3220 * Note that this means all entries in vsi_list_head must be explicitly 3221 * deallocated by the caller when done with list. 3222 */ 3223 static enum ice_status 3224 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, 3225 struct LIST_HEAD_TYPE *lkup_list_head, 3226 struct LIST_HEAD_TYPE *vsi_list_head) 3227 { 3228 struct ice_fltr_mgmt_list_entry *fm_entry; 3229 enum ice_status status = ICE_SUCCESS; 3230 3231 /* check to make sure VSI ID is valid and within boundary */ 3232 if (!ice_is_vsi_valid(hw, vsi_handle)) 3233 return ICE_ERR_PARAM; 3234 3235 LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head, 3236 ice_fltr_mgmt_list_entry, list_entry) { 3237 if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) 3238 continue; 3239 3240 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3241 vsi_list_head, 3242 &fm_entry->fltr_info); 3243 if (status) 3244 return status; 3245 } 3246 return status; 3247 } 3248 3249 /** 3250 * ice_determine_promisc_mask 3251 * @fi: filter info to parse 3252 * @promisc_mask: pointer to mask to be filled in 3253 * 3254 * Helper function to determine which ICE_PROMISC_ mask corresponds 3255 * to given filter into. 3256 */ 3257 static void ice_determine_promisc_mask(struct ice_fltr_info *fi, 3258 ice_bitmap_t *promisc_mask) 3259 { 3260 u16 vid = fi->l_data.mac_vlan.vlan_id; 3261 u8 *macaddr = fi->l_data.mac.mac_addr; 3262 bool is_tx_fltr = false; 3263 3264 ice_zero_bitmap(promisc_mask, ICE_PROMISC_MAX); 3265 3266 if (fi->flag == ICE_FLTR_TX) 3267 is_tx_fltr = true; 3268 3269 if (IS_BROADCAST_ETHER_ADDR(macaddr)) { 3270 ice_set_bit(is_tx_fltr ? ICE_PROMISC_BCAST_TX 3271 : ICE_PROMISC_BCAST_RX, promisc_mask); 3272 } else if (IS_MULTICAST_ETHER_ADDR(macaddr)) { 3273 ice_set_bit(is_tx_fltr ? ICE_PROMISC_MCAST_TX 3274 : ICE_PROMISC_MCAST_RX, promisc_mask); 3275 } else if (IS_UNICAST_ETHER_ADDR(macaddr)) { 3276 ice_set_bit(is_tx_fltr ? ICE_PROMISC_UCAST_TX 3277 : ICE_PROMISC_UCAST_RX, promisc_mask); 3278 } 3279 3280 if (vid) { 3281 ice_set_bit(is_tx_fltr ? ICE_PROMISC_VLAN_TX 3282 : ICE_PROMISC_VLAN_RX, promisc_mask); 3283 } 3284 } 3285 3286 /** 3287 * _ice_get_vsi_promisc - get promiscuous mode of given VSI 3288 * @hw: pointer to the hardware structure 3289 * @vsi_handle: VSI handle to retrieve info from 3290 * @promisc_mask: pointer to mask to be filled in 3291 * @vid: VLAN ID of promisc VLAN VSI 3292 * @sw: pointer to switch info struct for which function add rule 3293 * @lkup: switch rule filter lookup type 3294 */ 3295 static enum ice_status 3296 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3297 ice_bitmap_t *promisc_mask, u16 *vid, 3298 struct ice_switch_info *sw, enum ice_sw_lkup_type lkup) 3299 { 3300 ice_declare_bitmap(fltr_promisc_mask, ICE_PROMISC_MAX); 3301 struct ice_fltr_mgmt_list_entry *itr; 3302 struct LIST_HEAD_TYPE *rule_head; 3303 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3304 3305 if (!ice_is_vsi_valid(hw, vsi_handle) || 3306 (lkup != ICE_SW_LKUP_PROMISC && lkup != ICE_SW_LKUP_PROMISC_VLAN)) 3307 return ICE_ERR_PARAM; 3308 3309 *vid = 0; 3310 rule_head = &sw->recp_list[lkup].filt_rules; 3311 rule_lock = &sw->recp_list[lkup].filt_rule_lock; 3312 3313 ice_zero_bitmap(promisc_mask, ICE_PROMISC_MAX); 3314 3315 ice_acquire_lock(rule_lock); 3316 LIST_FOR_EACH_ENTRY(itr, rule_head, 3317 ice_fltr_mgmt_list_entry, list_entry) { 3318 /* Continue if this filter doesn't apply to this VSI or the 3319 * VSI ID is not in the VSI map for this filter 3320 */ 3321 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3322 continue; 3323 3324 ice_determine_promisc_mask(&itr->fltr_info, fltr_promisc_mask); 3325 ice_or_bitmap(promisc_mask, promisc_mask, fltr_promisc_mask, 3326 ICE_PROMISC_MAX); 3327 3328 } 3329 ice_release_lock(rule_lock); 3330 3331 return ICE_SUCCESS; 3332 } 3333 3334 /** 3335 * ice_get_vsi_promisc - get promiscuous mode of given VSI 3336 * @hw: pointer to the hardware structure 3337 * @vsi_handle: VSI handle to retrieve info from 3338 * @promisc_mask: pointer to mask to be filled in 3339 * @vid: VLAN ID of promisc VLAN VSI 3340 */ 3341 enum ice_status 3342 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3343 ice_bitmap_t *promisc_mask, u16 *vid) 3344 { 3345 if (!vid || !promisc_mask || !hw) 3346 return ICE_ERR_PARAM; 3347 3348 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask, 3349 vid, hw->switch_info, ICE_SW_LKUP_PROMISC); 3350 } 3351 3352 /** 3353 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI 3354 * @hw: pointer to the hardware structure 3355 * @vsi_handle: VSI handle to retrieve info from 3356 * @promisc_mask: pointer to mask to be filled in 3357 * @vid: VLAN ID of promisc VLAN VSI 3358 */ 3359 enum ice_status 3360 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, 3361 ice_bitmap_t *promisc_mask, u16 *vid) 3362 { 3363 if (!hw || !promisc_mask || !vid) 3364 return ICE_ERR_PARAM; 3365 3366 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask, 3367 vid, hw->switch_info, 3368 ICE_SW_LKUP_PROMISC_VLAN); 3369 } 3370 3371 /** 3372 * ice_remove_promisc - Remove promisc based filter rules 3373 * @hw: pointer to the hardware structure 3374 * @recp_id: recipe ID for which the rule needs to removed 3375 * @v_list: list of promisc entries 3376 */ 3377 static enum ice_status 3378 ice_remove_promisc(struct ice_hw *hw, u8 recp_id, 3379 struct LIST_HEAD_TYPE *v_list) 3380 { 3381 struct ice_fltr_list_entry *v_list_itr, *tmp; 3382 struct ice_sw_recipe *recp_list; 3383 3384 recp_list = &hw->switch_info->recp_list[recp_id]; 3385 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry, 3386 list_entry) { 3387 v_list_itr->status = 3388 ice_remove_rule_internal(hw, recp_list, v_list_itr); 3389 if (v_list_itr->status) 3390 return v_list_itr->status; 3391 } 3392 return ICE_SUCCESS; 3393 } 3394 3395 /** 3396 * _ice_clear_vsi_promisc - clear specified promiscuous mode(s) 3397 * @hw: pointer to the hardware structure 3398 * @vsi_handle: VSI handle to clear mode 3399 * @promisc_mask: pointer to mask of promiscuous config bits to clear 3400 * @vid: VLAN ID to clear VLAN promiscuous 3401 * @sw: pointer to switch info struct for which function add rule 3402 */ 3403 static enum ice_status 3404 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3405 ice_bitmap_t *promisc_mask, u16 vid, 3406 struct ice_switch_info *sw) 3407 { 3408 ice_declare_bitmap(compl_promisc_mask, ICE_PROMISC_MAX); 3409 ice_declare_bitmap(fltr_promisc_mask, ICE_PROMISC_MAX); 3410 struct ice_fltr_list_entry *fm_entry, *tmp; 3411 struct LIST_HEAD_TYPE remove_list_head; 3412 struct ice_fltr_mgmt_list_entry *itr; 3413 struct LIST_HEAD_TYPE *rule_head; 3414 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3415 enum ice_status status = ICE_SUCCESS; 3416 u8 recipe_id; 3417 3418 if (!ice_is_vsi_valid(hw, vsi_handle)) 3419 return ICE_ERR_PARAM; 3420 3421 if (ice_is_bit_set(promisc_mask, ICE_PROMISC_VLAN_RX) && 3422 ice_is_bit_set(promisc_mask, ICE_PROMISC_VLAN_TX)) 3423 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3424 else 3425 recipe_id = ICE_SW_LKUP_PROMISC; 3426 3427 rule_head = &sw->recp_list[recipe_id].filt_rules; 3428 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock; 3429 3430 INIT_LIST_HEAD(&remove_list_head); 3431 3432 ice_acquire_lock(rule_lock); 3433 LIST_FOR_EACH_ENTRY(itr, rule_head, 3434 ice_fltr_mgmt_list_entry, list_entry) { 3435 struct ice_fltr_info *fltr_info; 3436 ice_zero_bitmap(compl_promisc_mask, ICE_PROMISC_MAX); 3437 3438 if (!ice_vsi_uses_fltr(itr, vsi_handle)) 3439 continue; 3440 fltr_info = &itr->fltr_info; 3441 3442 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN && 3443 vid != fltr_info->l_data.mac_vlan.vlan_id) 3444 continue; 3445 3446 ice_determine_promisc_mask(fltr_info, fltr_promisc_mask); 3447 ice_andnot_bitmap(compl_promisc_mask, fltr_promisc_mask, 3448 promisc_mask, ICE_PROMISC_MAX); 3449 3450 /* Skip if filter is not completely specified by given mask */ 3451 if (ice_is_any_bit_set(compl_promisc_mask, ICE_PROMISC_MAX)) 3452 continue; 3453 3454 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, 3455 &remove_list_head, 3456 fltr_info); 3457 if (status) { 3458 ice_release_lock(rule_lock); 3459 goto free_fltr_list; 3460 } 3461 } 3462 ice_release_lock(rule_lock); 3463 3464 status = ice_remove_promisc(hw, recipe_id, &remove_list_head); 3465 3466 free_fltr_list: 3467 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 3468 ice_fltr_list_entry, list_entry) { 3469 LIST_DEL(&fm_entry->list_entry); 3470 ice_free(hw, fm_entry); 3471 } 3472 3473 return status; 3474 } 3475 3476 /** 3477 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI 3478 * @hw: pointer to the hardware structure 3479 * @vsi_handle: VSI handle to clear mode 3480 * @promisc_mask: pointer to mask of promiscuous config bits to clear 3481 * @vid: VLAN ID to clear VLAN promiscuous 3482 */ 3483 enum ice_status 3484 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3485 ice_bitmap_t *promisc_mask, u16 vid) 3486 { 3487 if (!hw || !promisc_mask) 3488 return ICE_ERR_PARAM; 3489 3490 return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, 3491 vid, hw->switch_info); 3492 } 3493 3494 /** 3495 * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 3496 * @hw: pointer to the hardware structure 3497 * @vsi_handle: VSI handle to configure 3498 * @promisc_mask: pointer to mask of promiscuous config bits 3499 * @vid: VLAN ID to set VLAN promiscuous 3500 * @lport: logical port number to configure promisc mode 3501 * @sw: pointer to switch info struct for which function add rule 3502 */ 3503 static enum ice_status 3504 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3505 ice_bitmap_t *promisc_mask, u16 vid, u8 lport, 3506 struct ice_switch_info *sw) 3507 { 3508 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR }; 3509 ice_declare_bitmap(p_mask, ICE_PROMISC_MAX); 3510 struct ice_fltr_list_entry f_list_entry; 3511 struct ice_fltr_info new_fltr; 3512 enum ice_status status = ICE_SUCCESS; 3513 bool is_tx_fltr; 3514 u16 hw_vsi_id; 3515 int pkt_type; 3516 u8 recipe_id; 3517 3518 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3519 3520 if (!ice_is_vsi_valid(hw, vsi_handle)) 3521 return ICE_ERR_PARAM; 3522 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 3523 3524 ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM); 3525 3526 /* Do not modify original bitmap */ 3527 ice_cp_bitmap(p_mask, promisc_mask, ICE_PROMISC_MAX); 3528 3529 if (ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_RX) && 3530 ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_TX)) { 3531 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN; 3532 new_fltr.l_data.mac_vlan.vlan_id = vid; 3533 recipe_id = ICE_SW_LKUP_PROMISC_VLAN; 3534 } else { 3535 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC; 3536 recipe_id = ICE_SW_LKUP_PROMISC; 3537 } 3538 3539 /* Separate filters must be set for each direction/packet type 3540 * combination, so we will loop over the mask value, store the 3541 * individual type, and clear it out in the input mask as it 3542 * is found. 3543 */ 3544 while (ice_is_any_bit_set(p_mask, ICE_PROMISC_MAX)) { 3545 struct ice_sw_recipe *recp_list; 3546 u8 *mac_addr; 3547 3548 pkt_type = 0; 3549 is_tx_fltr = false; 3550 3551 if (ice_test_and_clear_bit(ICE_PROMISC_UCAST_RX, 3552 p_mask)) { 3553 pkt_type = UCAST_FLTR; 3554 } else if (ice_test_and_clear_bit(ICE_PROMISC_UCAST_TX, 3555 p_mask)) { 3556 pkt_type = UCAST_FLTR; 3557 is_tx_fltr = true; 3558 } else if (ice_test_and_clear_bit(ICE_PROMISC_MCAST_RX, 3559 p_mask)) { 3560 pkt_type = MCAST_FLTR; 3561 } else if (ice_test_and_clear_bit(ICE_PROMISC_MCAST_TX, 3562 p_mask)) { 3563 pkt_type = MCAST_FLTR; 3564 is_tx_fltr = true; 3565 } else if (ice_test_and_clear_bit(ICE_PROMISC_BCAST_RX, 3566 p_mask)) { 3567 pkt_type = BCAST_FLTR; 3568 } else if (ice_test_and_clear_bit(ICE_PROMISC_BCAST_TX, 3569 p_mask)) { 3570 pkt_type = BCAST_FLTR; 3571 is_tx_fltr = true; 3572 } 3573 3574 /* Check for VLAN promiscuous flag */ 3575 if (ice_is_bit_set(p_mask, ICE_PROMISC_VLAN_RX)) { 3576 ice_clear_bit(ICE_PROMISC_VLAN_RX, p_mask); 3577 } else if (ice_test_and_clear_bit(ICE_PROMISC_VLAN_TX, 3578 p_mask)) { 3579 is_tx_fltr = true; 3580 } 3581 /* Set filter DA based on packet type */ 3582 mac_addr = new_fltr.l_data.mac.mac_addr; 3583 if (pkt_type == BCAST_FLTR) { 3584 ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM); 3585 } else if (pkt_type == MCAST_FLTR || 3586 pkt_type == UCAST_FLTR) { 3587 /* Use the dummy ether header DA */ 3588 ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN, 3589 ICE_NONDMA_TO_NONDMA); 3590 if (pkt_type == MCAST_FLTR) 3591 mac_addr[0] |= 0x1; /* Set multicast bit */ 3592 } 3593 3594 /* Need to reset this to zero for all iterations */ 3595 new_fltr.flag = 0; 3596 if (is_tx_fltr) { 3597 new_fltr.flag |= ICE_FLTR_TX; 3598 new_fltr.src = hw_vsi_id; 3599 } else { 3600 new_fltr.flag |= ICE_FLTR_RX; 3601 new_fltr.src = lport; 3602 } 3603 3604 new_fltr.fltr_act = ICE_FWD_TO_VSI; 3605 new_fltr.vsi_handle = vsi_handle; 3606 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id; 3607 f_list_entry.fltr_info = new_fltr; 3608 recp_list = &sw->recp_list[recipe_id]; 3609 3610 status = ice_add_rule_internal(hw, recp_list, lport, 3611 &f_list_entry); 3612 if (status != ICE_SUCCESS) 3613 goto set_promisc_exit; 3614 } 3615 3616 set_promisc_exit: 3617 return status; 3618 } 3619 3620 /** 3621 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s) 3622 * @hw: pointer to the hardware structure 3623 * @vsi_handle: VSI handle to configure 3624 * @promisc_mask: pointer to mask of promiscuous config bits 3625 * @vid: VLAN ID to set VLAN promiscuous 3626 */ 3627 enum ice_status 3628 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3629 ice_bitmap_t *promisc_mask, u16 vid) 3630 { 3631 if (!hw || !promisc_mask) 3632 return ICE_ERR_PARAM; 3633 3634 return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid, 3635 hw->port_info->lport, 3636 hw->switch_info); 3637 } 3638 3639 /** 3640 * _ice_set_vlan_vsi_promisc 3641 * @hw: pointer to the hardware structure 3642 * @vsi_handle: VSI handle to configure 3643 * @promisc_mask: pointer to mask of promiscuous config bits 3644 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 3645 * @lport: logical port number to configure promisc mode 3646 * @sw: pointer to switch info struct for which function add rule 3647 * 3648 * Configure VSI with all associated VLANs to given promiscuous mode(s) 3649 */ 3650 static enum ice_status 3651 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3652 ice_bitmap_t *promisc_mask, bool rm_vlan_promisc, 3653 u8 lport, struct ice_switch_info *sw) 3654 { 3655 struct ice_fltr_list_entry *list_itr, *tmp; 3656 struct LIST_HEAD_TYPE vsi_list_head; 3657 struct LIST_HEAD_TYPE *vlan_head; 3658 struct ice_lock *vlan_lock; /* Lock to protect filter rule list */ 3659 enum ice_status status; 3660 u16 vlan_id; 3661 3662 INIT_LIST_HEAD(&vsi_list_head); 3663 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock; 3664 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules; 3665 ice_acquire_lock(vlan_lock); 3666 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head, 3667 &vsi_list_head); 3668 ice_release_lock(vlan_lock); 3669 if (status) 3670 goto free_fltr_list; 3671 3672 LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry, 3673 list_entry) { 3674 /* Avoid enabling or disabling vlan zero twice when in double 3675 * vlan mode 3676 */ 3677 if (ice_is_dvm_ena(hw) && 3678 list_itr->fltr_info.l_data.vlan.tpid == 0) 3679 continue; 3680 3681 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id; 3682 if (rm_vlan_promisc) 3683 status = _ice_clear_vsi_promisc(hw, vsi_handle, 3684 promisc_mask, 3685 vlan_id, sw); 3686 else 3687 status = _ice_set_vsi_promisc(hw, vsi_handle, 3688 promisc_mask, vlan_id, 3689 lport, sw); 3690 if (status && status != ICE_ERR_ALREADY_EXISTS) 3691 break; 3692 } 3693 3694 free_fltr_list: 3695 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head, 3696 ice_fltr_list_entry, list_entry) { 3697 LIST_DEL(&list_itr->list_entry); 3698 ice_free(hw, list_itr); 3699 } 3700 return status; 3701 } 3702 3703 /** 3704 * ice_set_vlan_vsi_promisc 3705 * @hw: pointer to the hardware structure 3706 * @vsi_handle: VSI handle to configure 3707 * @promisc_mask: mask of promiscuous config bits 3708 * @rm_vlan_promisc: Clear VLANs VSI promisc mode 3709 * 3710 * Configure VSI with all associated VLANs to given promiscuous mode(s) 3711 */ 3712 enum ice_status 3713 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, 3714 ice_bitmap_t *promisc_mask, bool rm_vlan_promisc) 3715 { 3716 if (!hw || !promisc_mask) 3717 return ICE_ERR_PARAM; 3718 3719 return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask, 3720 rm_vlan_promisc, hw->port_info->lport, 3721 hw->switch_info); 3722 } 3723 3724 /** 3725 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 3726 * @hw: pointer to the hardware structure 3727 * @vsi_handle: VSI handle to remove filters from 3728 * @recp_list: recipe list from which function remove fltr 3729 * @lkup: switch rule filter lookup type 3730 */ 3731 static void 3732 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, 3733 struct ice_sw_recipe *recp_list, 3734 enum ice_sw_lkup_type lkup) 3735 { 3736 struct ice_fltr_list_entry *fm_entry; 3737 struct LIST_HEAD_TYPE remove_list_head; 3738 struct LIST_HEAD_TYPE *rule_head; 3739 struct ice_fltr_list_entry *tmp; 3740 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3741 enum ice_status status; 3742 3743 INIT_LIST_HEAD(&remove_list_head); 3744 rule_lock = &recp_list[lkup].filt_rule_lock; 3745 rule_head = &recp_list[lkup].filt_rules; 3746 ice_acquire_lock(rule_lock); 3747 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head, 3748 &remove_list_head); 3749 ice_release_lock(rule_lock); 3750 if (status) 3751 goto free_fltr_list; 3752 3753 switch (lkup) { 3754 case ICE_SW_LKUP_MAC: 3755 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]); 3756 break; 3757 case ICE_SW_LKUP_VLAN: 3758 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]); 3759 break; 3760 case ICE_SW_LKUP_PROMISC: 3761 case ICE_SW_LKUP_PROMISC_VLAN: 3762 ice_remove_promisc(hw, (u8)lkup, &remove_list_head); 3763 break; 3764 case ICE_SW_LKUP_MAC_VLAN: 3765 ice_debug(hw, ICE_DBG_SW, "MAC VLAN look up is not supported yet\n"); 3766 break; 3767 case ICE_SW_LKUP_ETHERTYPE: 3768 case ICE_SW_LKUP_ETHERTYPE_MAC: 3769 ice_remove_eth_mac(hw, &remove_list_head); 3770 break; 3771 case ICE_SW_LKUP_DFLT: 3772 ice_debug(hw, ICE_DBG_SW, "Remove filters for this lookup type hasn't been implemented yet\n"); 3773 break; 3774 case ICE_SW_LKUP_LAST: 3775 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n"); 3776 break; 3777 } 3778 3779 free_fltr_list: 3780 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head, 3781 ice_fltr_list_entry, list_entry) { 3782 LIST_DEL(&fm_entry->list_entry); 3783 ice_free(hw, fm_entry); 3784 } 3785 } 3786 3787 /** 3788 * ice_remove_vsi_fltr_rule - Remove all filters for a VSI 3789 * @hw: pointer to the hardware structure 3790 * @vsi_handle: VSI handle to remove filters from 3791 * @sw: pointer to switch info struct 3792 */ 3793 static void 3794 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle, 3795 struct ice_switch_info *sw) 3796 { 3797 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); 3798 3799 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3800 sw->recp_list, ICE_SW_LKUP_MAC); 3801 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3802 sw->recp_list, ICE_SW_LKUP_MAC_VLAN); 3803 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3804 sw->recp_list, ICE_SW_LKUP_PROMISC); 3805 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3806 sw->recp_list, ICE_SW_LKUP_VLAN); 3807 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3808 sw->recp_list, ICE_SW_LKUP_DFLT); 3809 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3810 sw->recp_list, ICE_SW_LKUP_ETHERTYPE); 3811 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3812 sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC); 3813 ice_remove_vsi_lkup_fltr(hw, vsi_handle, 3814 sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN); 3815 } 3816 3817 /** 3818 * ice_remove_vsi_fltr - Remove all filters for a VSI 3819 * @hw: pointer to the hardware structure 3820 * @vsi_handle: VSI handle to remove filters from 3821 */ 3822 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) 3823 { 3824 ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info); 3825 } 3826 3827 /** 3828 * ice_alloc_res_cntr - allocating resource counter 3829 * @hw: pointer to the hardware structure 3830 * @type: type of resource 3831 * @alloc_shared: if set it is shared else dedicated 3832 * @num_items: number of entries requested for FD resource type 3833 * @counter_id: counter index returned by AQ call 3834 */ 3835 static enum ice_status 3836 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 3837 u16 *counter_id) 3838 { 3839 struct ice_aqc_alloc_free_res_elem *buf; 3840 enum ice_status status; 3841 u16 buf_len; 3842 3843 /* Allocate resource */ 3844 buf_len = ice_struct_size(buf, elem, 1); 3845 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 3846 if (!buf) 3847 return ICE_ERR_NO_MEMORY; 3848 3849 buf->num_elems = CPU_TO_LE16(num_items); 3850 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 3851 ICE_AQC_RES_TYPE_M) | alloc_shared); 3852 3853 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 3854 ice_aqc_opc_alloc_res, NULL); 3855 if (status) 3856 goto exit; 3857 3858 *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp); 3859 3860 exit: 3861 ice_free(hw, buf); 3862 return status; 3863 } 3864 3865 /** 3866 * ice_free_res_cntr - free resource counter 3867 * @hw: pointer to the hardware structure 3868 * @type: type of resource 3869 * @alloc_shared: if set it is shared else dedicated 3870 * @num_items: number of entries to be freed for FD resource type 3871 * @counter_id: counter ID resource which needs to be freed 3872 */ 3873 static enum ice_status 3874 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, 3875 u16 counter_id) 3876 { 3877 struct ice_aqc_alloc_free_res_elem *buf; 3878 enum ice_status status; 3879 u16 buf_len; 3880 3881 /* Free resource */ 3882 buf_len = ice_struct_size(buf, elem, 1); 3883 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len); 3884 if (!buf) 3885 return ICE_ERR_NO_MEMORY; 3886 3887 buf->num_elems = CPU_TO_LE16(num_items); 3888 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) & 3889 ICE_AQC_RES_TYPE_M) | alloc_shared); 3890 buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id); 3891 3892 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 3893 ice_aqc_opc_free_res, NULL); 3894 if (status) 3895 ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n"); 3896 3897 ice_free(hw, buf); 3898 return status; 3899 } 3900 3901 /** 3902 * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type 3903 * @hw: pointer to the hardware structure 3904 * @counter_id: returns counter index 3905 */ 3906 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id) 3907 { 3908 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 3909 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 3910 counter_id); 3911 } 3912 3913 /** 3914 * ice_free_vlan_res_counter - Free counter resource for VLAN type 3915 * @hw: pointer to the hardware structure 3916 * @counter_id: counter index to be freed 3917 */ 3918 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id) 3919 { 3920 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER, 3921 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, 3922 counter_id); 3923 } 3924 3925 /** 3926 * ice_add_mac_with_sw_marker - add filter with sw marker 3927 * @hw: pointer to the hardware structure 3928 * @f_info: filter info structure containing the MAC filter information 3929 * @sw_marker: sw marker to tag the Rx descriptor with 3930 */ 3931 enum ice_status 3932 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info, 3933 u16 sw_marker) 3934 { 3935 struct ice_fltr_mgmt_list_entry *m_entry; 3936 struct ice_fltr_list_entry fl_info; 3937 struct ice_sw_recipe *recp_list; 3938 struct LIST_HEAD_TYPE l_head; 3939 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 3940 enum ice_status ret; 3941 bool entry_exists; 3942 u16 lg_act_id; 3943 3944 if (f_info->fltr_act != ICE_FWD_TO_VSI) 3945 return ICE_ERR_PARAM; 3946 3947 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 3948 return ICE_ERR_PARAM; 3949 3950 if (sw_marker == ICE_INVAL_SW_MARKER_ID) 3951 return ICE_ERR_PARAM; 3952 3953 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 3954 return ICE_ERR_PARAM; 3955 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 3956 3957 /* Add filter if it doesn't exist so then the adding of large 3958 * action always results in update 3959 */ 3960 3961 INIT_LIST_HEAD(&l_head); 3962 fl_info.fltr_info = *f_info; 3963 LIST_ADD(&fl_info.list_entry, &l_head); 3964 3965 entry_exists = false; 3966 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 3967 hw->port_info->lport); 3968 if (ret == ICE_ERR_ALREADY_EXISTS) 3969 entry_exists = true; 3970 else if (ret) 3971 return ret; 3972 3973 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 3974 rule_lock = &recp_list->filt_rule_lock; 3975 ice_acquire_lock(rule_lock); 3976 /* Get the book keeping entry for the filter */ 3977 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 3978 if (!m_entry) 3979 goto exit_error; 3980 3981 /* If counter action was enabled for this rule then don't enable 3982 * sw marker large action 3983 */ 3984 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 3985 ret = ICE_ERR_PARAM; 3986 goto exit_error; 3987 } 3988 3989 /* if same marker was added before */ 3990 if (m_entry->sw_marker_id == sw_marker) { 3991 ret = ICE_ERR_ALREADY_EXISTS; 3992 goto exit_error; 3993 } 3994 3995 /* Allocate a hardware table entry to hold large act. Three actions 3996 * for marker based large action 3997 */ 3998 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3); 3999 if (ret) 4000 goto exit_error; 4001 4002 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4003 goto exit_error; 4004 4005 /* Update the switch rule to add the marker action */ 4006 ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id); 4007 if (!ret) { 4008 ice_release_lock(rule_lock); 4009 return ret; 4010 } 4011 4012 exit_error: 4013 ice_release_lock(rule_lock); 4014 /* only remove entry if it did not exist previously */ 4015 if (!entry_exists) 4016 ret = ice_remove_mac(hw, &l_head); 4017 4018 return ret; 4019 } 4020 4021 /** 4022 * ice_add_mac_with_counter - add filter with counter enabled 4023 * @hw: pointer to the hardware structure 4024 * @f_info: pointer to filter info structure containing the MAC filter 4025 * information 4026 */ 4027 enum ice_status 4028 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info) 4029 { 4030 struct ice_fltr_mgmt_list_entry *m_entry; 4031 struct ice_fltr_list_entry fl_info; 4032 struct ice_sw_recipe *recp_list; 4033 struct LIST_HEAD_TYPE l_head; 4034 struct ice_lock *rule_lock; /* Lock to protect filter rule list */ 4035 enum ice_status ret; 4036 bool entry_exist; 4037 u16 counter_id; 4038 u16 lg_act_id; 4039 4040 if (f_info->fltr_act != ICE_FWD_TO_VSI) 4041 return ICE_ERR_PARAM; 4042 4043 if (f_info->lkup_type != ICE_SW_LKUP_MAC) 4044 return ICE_ERR_PARAM; 4045 4046 if (!ice_is_vsi_valid(hw, f_info->vsi_handle)) 4047 return ICE_ERR_PARAM; 4048 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle); 4049 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC]; 4050 4051 entry_exist = false; 4052 4053 rule_lock = &recp_list->filt_rule_lock; 4054 4055 /* Add filter if it doesn't exist so then the adding of large 4056 * action always results in update 4057 */ 4058 INIT_LIST_HEAD(&l_head); 4059 4060 fl_info.fltr_info = *f_info; 4061 LIST_ADD(&fl_info.list_entry, &l_head); 4062 4063 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info, 4064 hw->port_info->lport); 4065 if (ret == ICE_ERR_ALREADY_EXISTS) 4066 entry_exist = true; 4067 else if (ret) 4068 return ret; 4069 4070 ice_acquire_lock(rule_lock); 4071 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info); 4072 if (!m_entry) { 4073 ret = ICE_ERR_BAD_PTR; 4074 goto exit_error; 4075 } 4076 4077 /* Don't enable counter for a filter for which sw marker was enabled */ 4078 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) { 4079 ret = ICE_ERR_PARAM; 4080 goto exit_error; 4081 } 4082 4083 /* If a counter was already enabled then don't need to add again */ 4084 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) { 4085 ret = ICE_ERR_ALREADY_EXISTS; 4086 goto exit_error; 4087 } 4088 4089 /* Allocate a hardware table entry to VLAN counter */ 4090 ret = ice_alloc_vlan_res_counter(hw, &counter_id); 4091 if (ret) 4092 goto exit_error; 4093 4094 /* Allocate a hardware table entry to hold large act. Two actions for 4095 * counter based large action 4096 */ 4097 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2); 4098 if (ret) 4099 goto exit_error; 4100 4101 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX) 4102 goto exit_error; 4103 4104 /* Update the switch rule to add the counter action */ 4105 ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id); 4106 if (!ret) { 4107 ice_release_lock(rule_lock); 4108 return ret; 4109 } 4110 4111 exit_error: 4112 ice_release_lock(rule_lock); 4113 /* only remove entry if it did not exist previously */ 4114 if (!entry_exist) 4115 ret = ice_remove_mac(hw, &l_head); 4116 4117 return ret; 4118 } 4119 4120 /** 4121 * ice_replay_fltr - Replay all the filters stored by a specific list head 4122 * @hw: pointer to the hardware structure 4123 * @list_head: list for which filters needs to be replayed 4124 * @recp_id: Recipe ID for which rules need to be replayed 4125 */ 4126 static enum ice_status 4127 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head) 4128 { 4129 struct ice_fltr_mgmt_list_entry *itr; 4130 enum ice_status status = ICE_SUCCESS; 4131 struct ice_sw_recipe *recp_list; 4132 u8 lport = hw->port_info->lport; 4133 struct LIST_HEAD_TYPE l_head; 4134 4135 if (LIST_EMPTY(list_head)) 4136 return status; 4137 4138 recp_list = &hw->switch_info->recp_list[recp_id]; 4139 /* Move entries from the given list_head to a temporary l_head so that 4140 * they can be replayed. Otherwise when trying to re-add the same 4141 * filter, the function will return already exists 4142 */ 4143 LIST_REPLACE_INIT(list_head, &l_head); 4144 4145 /* Mark the given list_head empty by reinitializing it so filters 4146 * could be added again by *handler 4147 */ 4148 LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry, 4149 list_entry) { 4150 struct ice_fltr_list_entry f_entry; 4151 u16 vsi_handle; 4152 4153 f_entry.fltr_info = itr->fltr_info; 4154 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) { 4155 status = ice_add_rule_internal(hw, recp_list, lport, 4156 &f_entry); 4157 if (status != ICE_SUCCESS) 4158 goto end; 4159 continue; 4160 } 4161 4162 /* Add a filter per VSI separately */ 4163 ice_for_each_set_bit(vsi_handle, itr->vsi_list_info->vsi_map, 4164 ICE_MAX_VSI) { 4165 if (!ice_is_vsi_valid(hw, vsi_handle)) 4166 break; 4167 4168 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 4169 f_entry.fltr_info.vsi_handle = vsi_handle; 4170 f_entry.fltr_info.fwd_id.hw_vsi_id = 4171 ice_get_hw_vsi_num(hw, vsi_handle); 4172 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 4173 if (recp_id == ICE_SW_LKUP_VLAN) 4174 status = ice_add_vlan_internal(hw, recp_list, 4175 &f_entry); 4176 else 4177 status = ice_add_rule_internal(hw, recp_list, 4178 lport, 4179 &f_entry); 4180 if (status != ICE_SUCCESS) 4181 goto end; 4182 } 4183 } 4184 end: 4185 /* Clear the filter management list */ 4186 ice_rem_sw_rule_info(hw, &l_head); 4187 return status; 4188 } 4189 4190 /** 4191 * ice_replay_all_fltr - replay all filters stored in bookkeeping lists 4192 * @hw: pointer to the hardware structure 4193 * 4194 * NOTE: This function does not clean up partially added filters on error. 4195 * It is up to caller of the function to issue a reset or fail early. 4196 */ 4197 enum ice_status ice_replay_all_fltr(struct ice_hw *hw) 4198 { 4199 struct ice_switch_info *sw = hw->switch_info; 4200 enum ice_status status = ICE_SUCCESS; 4201 u8 i; 4202 4203 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4204 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules; 4205 4206 status = ice_replay_fltr(hw, i, head); 4207 if (status != ICE_SUCCESS) 4208 return status; 4209 } 4210 return status; 4211 } 4212 4213 /** 4214 * ice_replay_vsi_fltr - Replay filters for requested VSI 4215 * @hw: pointer to the hardware structure 4216 * @pi: pointer to port information structure 4217 * @sw: pointer to switch info struct for which function replays filters 4218 * @vsi_handle: driver VSI handle 4219 * @recp_id: Recipe ID for which rules need to be replayed 4220 * @list_head: list for which filters need to be replayed 4221 * 4222 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle. 4223 * It is required to pass valid VSI handle. 4224 */ 4225 static enum ice_status 4226 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi, 4227 struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id, 4228 struct LIST_HEAD_TYPE *list_head) 4229 { 4230 struct ice_fltr_mgmt_list_entry *itr; 4231 enum ice_status status = ICE_SUCCESS; 4232 struct ice_sw_recipe *recp_list; 4233 u16 hw_vsi_id; 4234 4235 if (LIST_EMPTY(list_head)) 4236 return status; 4237 recp_list = &sw->recp_list[recp_id]; 4238 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); 4239 4240 LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry, 4241 list_entry) { 4242 struct ice_fltr_list_entry f_entry; 4243 4244 f_entry.fltr_info = itr->fltr_info; 4245 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN && 4246 itr->fltr_info.vsi_handle == vsi_handle) { 4247 /* update the src in case it is VSI num */ 4248 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 4249 f_entry.fltr_info.src = hw_vsi_id; 4250 status = ice_add_rule_internal(hw, recp_list, 4251 pi->lport, 4252 &f_entry); 4253 if (status != ICE_SUCCESS) 4254 goto end; 4255 continue; 4256 } 4257 if (!itr->vsi_list_info || 4258 !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle)) 4259 continue; 4260 /* Clearing it so that the logic can add it back */ 4261 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map); 4262 f_entry.fltr_info.vsi_handle = vsi_handle; 4263 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI; 4264 /* update the src in case it is VSI num */ 4265 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI) 4266 f_entry.fltr_info.src = hw_vsi_id; 4267 if (recp_id == ICE_SW_LKUP_VLAN) 4268 status = ice_add_vlan_internal(hw, recp_list, &f_entry); 4269 else 4270 status = ice_add_rule_internal(hw, recp_list, 4271 pi->lport, 4272 &f_entry); 4273 if (status != ICE_SUCCESS) 4274 goto end; 4275 } 4276 end: 4277 return status; 4278 } 4279 4280 /** 4281 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists 4282 * @hw: pointer to the hardware structure 4283 * @pi: pointer to port information structure 4284 * @vsi_handle: driver VSI handle 4285 * 4286 * Replays filters for requested VSI via vsi_handle. 4287 */ 4288 enum ice_status 4289 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi, 4290 u16 vsi_handle) 4291 { 4292 struct ice_switch_info *sw = NULL; 4293 enum ice_status status = ICE_SUCCESS; 4294 u8 i; 4295 4296 sw = hw->switch_info; 4297 4298 /* Update the recipes that were created */ 4299 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4300 struct LIST_HEAD_TYPE *head; 4301 4302 head = &sw->recp_list[i].filt_replay_rules; 4303 if (!sw->recp_list[i].adv_rule) 4304 status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i, 4305 head); 4306 if (status != ICE_SUCCESS) 4307 return status; 4308 } 4309 4310 return ICE_SUCCESS; 4311 } 4312 4313 /** 4314 * ice_rm_sw_replay_rule_info - helper function to delete filter replay rules 4315 * @hw: pointer to the HW struct 4316 * @sw: pointer to switch info struct for which function removes filters 4317 * 4318 * Deletes the filter replay rules for given switch 4319 */ 4320 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw) 4321 { 4322 u8 i; 4323 4324 if (!sw) 4325 return; 4326 4327 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) { 4328 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) { 4329 struct LIST_HEAD_TYPE *l_head; 4330 4331 l_head = &sw->recp_list[i].filt_replay_rules; 4332 if (!sw->recp_list[i].adv_rule) 4333 ice_rem_sw_rule_info(hw, l_head); 4334 } 4335 } 4336 } 4337 4338 /** 4339 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules 4340 * @hw: pointer to the HW struct 4341 * 4342 * Deletes the filter replay rules. 4343 */ 4344 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw) 4345 { 4346 ice_rm_sw_replay_rule_info(hw, hw->switch_info); 4347 } 4348 4349