xref: /f-stack/dpdk/drivers/net/bnxt/bnxt_filter.c (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2018 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 
bnxt_alloc_filter(struct bnxt * bp)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(ERR, "No more free filter resources\n");
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 
bnxt_alloc_vf_filter(struct bnxt * bp,uint16_t vf)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(ERR, "Failed to alloc memory for VF %hu filters\n",
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 
bnxt_init_filters(struct bnxt * bp)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 
bnxt_free_all_filters(struct bnxt * bp)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 			filter = temp_filter;
103 		}
104 		STAILQ_INIT(&vnic->filter);
105 	}
106 
107 }
108 
bnxt_free_filter_mem(struct bnxt * bp)109 void bnxt_free_filter_mem(struct bnxt *bp)
110 {
111 	struct bnxt_filter_info *filter;
112 	uint16_t max_filters, i;
113 	int rc = 0;
114 
115 	if (bp->filter_info == NULL)
116 		return;
117 
118 	/* Ensure that all filters are freed */
119 	max_filters = bp->max_l2_ctx;
120 	for (i = 0; i < max_filters; i++) {
121 		filter = &bp->filter_info[i];
122 		if (filter->fw_ntuple_filter_id != ((uint64_t)-1) &&
123 		    filter->filter_type == HWRM_CFA_NTUPLE_FILTER) {
124 			/* Call HWRM to try to free filter again */
125 			rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
126 			if (rc)
127 				PMD_DRV_LOG(ERR,
128 					    "Cannot free ntuple filter: %d\n",
129 					    rc);
130 		}
131 		filter->fw_ntuple_filter_id = UINT64_MAX;
132 
133 		if (filter->fw_l2_filter_id != ((uint64_t)-1) &&
134 		    filter->filter_type == HWRM_CFA_L2_FILTER) {
135 			PMD_DRV_LOG(DEBUG, "L2 filter is not free\n");
136 			/* Call HWRM to try to free filter again */
137 			rc = bnxt_hwrm_clear_l2_filter(bp, filter);
138 			if (rc)
139 				PMD_DRV_LOG(ERR,
140 					    "Cannot free L2 filter: %d\n",
141 					    rc);
142 		}
143 		filter->fw_l2_filter_id = UINT64_MAX;
144 
145 	}
146 	STAILQ_INIT(&bp->free_filter_list);
147 
148 	rte_free(bp->filter_info);
149 	bp->filter_info = NULL;
150 
151 	for (i = 0; i < bp->pf->max_vfs; i++) {
152 		STAILQ_FOREACH(filter, &bp->pf->vf_info[i].filter, next) {
153 			rte_free(filter);
154 			STAILQ_REMOVE(&bp->pf->vf_info[i].filter, filter,
155 				      bnxt_filter_info, next);
156 		}
157 	}
158 }
159 
bnxt_alloc_filter_mem(struct bnxt * bp)160 int bnxt_alloc_filter_mem(struct bnxt *bp)
161 {
162 	struct bnxt_filter_info *filter_mem;
163 	uint16_t max_filters;
164 
165 	max_filters = bp->max_l2_ctx;
166 	/* Allocate memory for VNIC pool and filter pool */
167 	filter_mem = rte_zmalloc("bnxt_filter_info",
168 				 max_filters * sizeof(struct bnxt_filter_info),
169 				 0);
170 	if (filter_mem == NULL) {
171 		PMD_DRV_LOG(ERR, "Failed to alloc memory for %d filters",
172 			max_filters);
173 		return -ENOMEM;
174 	}
175 	bp->filter_info = filter_mem;
176 	bnxt_init_filters(bp);
177 	return 0;
178 }
179 
bnxt_get_unused_filter(struct bnxt * bp)180 struct bnxt_filter_info *bnxt_get_unused_filter(struct bnxt *bp)
181 {
182 	struct bnxt_filter_info *filter;
183 
184 	/* Find the 1st unused filter from the free_filter_list pool*/
185 	filter = STAILQ_FIRST(&bp->free_filter_list);
186 	if (!filter) {
187 		PMD_DRV_LOG(ERR, "No more free filter resources\n");
188 		return NULL;
189 	}
190 	STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
191 
192 	return filter;
193 }
194 
bnxt_free_filter(struct bnxt * bp,struct bnxt_filter_info * filter)195 void bnxt_free_filter(struct bnxt *bp, struct bnxt_filter_info *filter)
196 {
197 	memset(filter, 0, sizeof(*filter));
198 	filter->mac_index = INVALID_MAC_INDEX;
199 	filter->fw_l2_filter_id = UINT64_MAX;
200 	filter->fw_ntuple_filter_id = UINT64_MAX;
201 	filter->fw_em_filter_id = UINT64_MAX;
202 	STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next);
203 }
204