1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <sys/queue.h> 7 8 #include <rte_byteorder.h> 9 #include <rte_log.h> 10 #include <rte_malloc.h> 11 #include <rte_flow.h> 12 #include <rte_flow_driver.h> 13 #include <rte_tailq.h> 14 15 #include "bnxt.h" 16 #include "bnxt_filter.h" 17 #include "bnxt_hwrm.h" 18 #include "bnxt_vnic.h" 19 #include "hsi_struct_def_dpdk.h" 20 21 /* 22 * Filter Functions 23 */ 24 25 struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp) 26 { 27 struct bnxt_filter_info *filter; 28 29 filter = bnxt_get_unused_filter(bp); 30 if (!filter) { 31 PMD_DRV_LOG_LINE(ERR, "No more free filter resources"); 32 return NULL; 33 } 34 35 filter->mac_index = INVALID_MAC_INDEX; 36 /* Default to L2 MAC Addr filter */ 37 filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; 38 filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | 39 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK; 40 memcpy(filter->l2_addr, bp->mac_addr, RTE_ETHER_ADDR_LEN); 41 memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN); 42 43 return filter; 44 } 45 46 struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf) 47 { 48 struct bnxt_filter_info *filter; 49 50 filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0); 51 if (!filter) { 52 PMD_DRV_LOG_LINE(ERR, "Failed to alloc memory for VF %hu filters", 53 vf); 54 return NULL; 55 } 56 57 filter->fw_l2_filter_id = UINT64_MAX; 58 STAILQ_INSERT_TAIL(&bp->pf->vf_info[vf].filter, filter, next); 59 return filter; 60 } 61 62 static void bnxt_init_filters(struct bnxt *bp) 63 { 64 struct bnxt_filter_info *filter; 65 int i, max_filters; 66 67 max_filters = bp->max_l2_ctx; 68 STAILQ_INIT(&bp->free_filter_list); 69 for (i = 0; i < max_filters; i++) { 70 filter = &bp->filter_info[i]; 71 filter->fw_l2_filter_id = UINT64_MAX; 72 filter->fw_em_filter_id = UINT64_MAX; 73 filter->fw_ntuple_filter_id = UINT64_MAX; 74 STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); 75 } 76 } 77 78 void bnxt_free_all_filters(struct bnxt *bp) 79 { 80 struct bnxt_vnic_info *vnic; 81 struct bnxt_filter_info *filter, *temp_filter; 82 unsigned int i; 83 84 for (i = 0; i < bp->pf->max_vfs; i++) { 85 STAILQ_FOREACH(filter, &bp->pf->vf_info[i].filter, next) { 86 bnxt_hwrm_clear_l2_filter(bp, filter); 87 } 88 } 89 90 if (bp->vnic_info == NULL) 91 return; 92 93 for (i = 0; i < bp->nr_vnics; i++) { 94 vnic = &bp->vnic_info[i]; 95 filter = STAILQ_FIRST(&vnic->filter); 96 while (filter) { 97 temp_filter = STAILQ_NEXT(filter, next); 98 STAILQ_REMOVE(&vnic->filter, filter, 99 bnxt_filter_info, next); 100 STAILQ_INSERT_TAIL(&bp->free_filter_list, 101 filter, next); 102 if (filter->vnic) 103 filter->vnic = NULL; 104 filter = temp_filter; 105 } 106 STAILQ_INIT(&vnic->filter); 107 } 108 109 } 110 111 void bnxt_free_filter_mem(struct bnxt *bp) 112 { 113 struct bnxt_filter_info *filter; 114 uint16_t max_filters, i; 115 int rc = 0; 116 117 if (bp->filter_info == NULL) 118 return; 119 120 /* Ensure that all filters are freed */ 121 max_filters = bp->max_l2_ctx; 122 for (i = 0; i < max_filters; i++) { 123 filter = &bp->filter_info[i]; 124 if (filter->fw_ntuple_filter_id != ((uint64_t)-1) && 125 filter->filter_type == HWRM_CFA_NTUPLE_FILTER) { 126 /* Call HWRM to try to free filter again */ 127 rc = bnxt_hwrm_clear_ntuple_filter(bp, filter); 128 if (rc) 129 PMD_DRV_LOG_LINE(ERR, 130 "Cannot free ntuple filter: %d", 131 rc); 132 } 133 filter->fw_ntuple_filter_id = UINT64_MAX; 134 135 if (filter->fw_l2_filter_id != ((uint64_t)-1) && 136 filter->filter_type == HWRM_CFA_L2_FILTER) { 137 PMD_DRV_LOG_LINE(DEBUG, "L2 filter is not free"); 138 /* Call HWRM to try to free filter again */ 139 rc = bnxt_hwrm_clear_l2_filter(bp, filter); 140 if (rc) 141 PMD_DRV_LOG_LINE(ERR, 142 "Cannot free L2 filter: %d", 143 rc); 144 } 145 filter->fw_l2_filter_id = UINT64_MAX; 146 147 } 148 STAILQ_INIT(&bp->free_filter_list); 149 150 rte_free(bp->filter_info); 151 bp->filter_info = NULL; 152 153 for (i = 0; i < bp->pf->max_vfs; i++) { 154 STAILQ_FOREACH(filter, &bp->pf->vf_info[i].filter, next) { 155 rte_free(filter); 156 STAILQ_REMOVE(&bp->pf->vf_info[i].filter, filter, 157 bnxt_filter_info, next); 158 } 159 } 160 } 161 162 int bnxt_alloc_filter_mem(struct bnxt *bp) 163 { 164 struct bnxt_filter_info *filter_mem; 165 uint16_t max_filters; 166 167 max_filters = bp->max_l2_ctx; 168 /* Allocate memory for VNIC pool and filter pool */ 169 filter_mem = rte_zmalloc("bnxt_filter_info", 170 max_filters * sizeof(struct bnxt_filter_info), 171 0); 172 if (filter_mem == NULL) { 173 PMD_DRV_LOG_LINE(ERR, "Failed to alloc memory for %d filters", 174 max_filters); 175 return -ENOMEM; 176 } 177 bp->filter_info = filter_mem; 178 bnxt_init_filters(bp); 179 return 0; 180 } 181 182 struct bnxt_filter_info *bnxt_get_unused_filter(struct bnxt *bp) 183 { 184 struct bnxt_filter_info *filter; 185 186 /* Find the 1st unused filter from the free_filter_list pool*/ 187 filter = STAILQ_FIRST(&bp->free_filter_list); 188 if (!filter) { 189 PMD_DRV_LOG_LINE(ERR, "No more free filter resources"); 190 return NULL; 191 } 192 STAILQ_REMOVE_HEAD(&bp->free_filter_list, next); 193 194 return filter; 195 } 196 197 void bnxt_free_filter(struct bnxt *bp, struct bnxt_filter_info *filter) 198 { 199 memset(filter, 0, sizeof(*filter)); 200 filter->mac_index = INVALID_MAC_INDEX; 201 filter->fw_l2_filter_id = UINT64_MAX; 202 filter->fw_ntuple_filter_id = UINT64_MAX; 203 filter->fw_em_filter_id = UINT64_MAX; 204 STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); 205 } 206