dma/dpaa2: support statistics
[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                         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(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
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
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
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 }