1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2021 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 if (filter->vnic)
103 filter->vnic = NULL;
104 filter = temp_filter;
105 }
106 STAILQ_INIT(&vnic->filter);
107 }
108
109 }
110
bnxt_free_filter_mem(struct bnxt * bp)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(ERR,
130 "Cannot free ntuple filter: %d\n",
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(DEBUG, "L2 filter is not free\n");
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(ERR,
142 "Cannot free L2 filter: %d\n",
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
bnxt_alloc_filter_mem(struct bnxt * bp)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(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
bnxt_get_unused_filter(struct bnxt * bp)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(ERR, "No more free filter resources\n");
190 return NULL;
191 }
192 STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
193
194 return filter;
195 }
196
bnxt_free_filter(struct bnxt * bp,struct bnxt_filter_info * filter)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