1d08e03b2ff016e242391778a4f25af4536a3f58
[dpdk.git] / drivers / net / bnxt / bnxt_filter.c
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
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
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
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                         filter = temp_filter;
103                 }
104                 STAILQ_INIT(&vnic->filter);
105         }
106
107 }
108
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
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
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
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 }