xref: /dpdk/drivers/net/bnxt/bnxt_filter.c (revision e99981af34632ecce3bac82d05db97b08308f9b5)
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