b31f10479edb4025b5533a3ca264f41e439c5dfc
[dpdk.git] / drivers / net / bnxt / bnxt_filter.c
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
25 struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp)
26 {
27         struct bnxt_filter_info *filter;
28
29         /* Find the 1st unused filter from the free_filter_list pool*/
30         filter = STAILQ_FIRST(&bp->free_filter_list);
31         if (!filter) {
32                 PMD_DRV_LOG(ERR, "No more free filter resources\n");
33                 return NULL;
34         }
35         STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
36
37         filter->mac_index = INVALID_MAC_INDEX;
38         /* Default to L2 MAC Addr filter */
39         filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
40         filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
41                         HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
42         memcpy(filter->l2_addr, bp->mac_addr, RTE_ETHER_ADDR_LEN);
43         memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
44         /* bump up the reference count of filter */
45         filter->l2_ref_cnt++;
46         return filter;
47 }
48
49 struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf)
50 {
51         struct bnxt_filter_info *filter;
52
53         filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0);
54         if (!filter) {
55                 PMD_DRV_LOG(ERR, "Failed to alloc memory for VF %hu filters\n",
56                         vf);
57                 return NULL;
58         }
59
60         filter->fw_l2_filter_id = UINT64_MAX;
61         STAILQ_INSERT_TAIL(&bp->pf.vf_info[vf].filter, filter, next);
62         return filter;
63 }
64
65 static void bnxt_init_filters(struct bnxt *bp)
66 {
67         struct bnxt_filter_info *filter;
68         int i, max_filters;
69
70         max_filters = bp->max_l2_ctx;
71         STAILQ_INIT(&bp->free_filter_list);
72         for (i = 0; i < max_filters; i++) {
73                 filter = &bp->filter_info[i];
74                 filter->fw_l2_filter_id = UINT64_MAX;
75                 filter->fw_em_filter_id = UINT64_MAX;
76                 filter->fw_ntuple_filter_id = UINT64_MAX;
77                 STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next);
78         }
79 }
80
81 void bnxt_free_all_filters(struct bnxt *bp)
82 {
83         struct bnxt_vnic_info *vnic;
84         struct bnxt_filter_info *filter, *temp_filter;
85         unsigned int i;
86
87         for (i = 0; i < bp->nr_vnics; i++) {
88                 vnic = &bp->vnic_info[i];
89                 filter = STAILQ_FIRST(&vnic->filter);
90                 while (filter) {
91                         temp_filter = STAILQ_NEXT(filter, next);
92                         STAILQ_REMOVE(&vnic->filter, filter,
93                                         bnxt_filter_info, next);
94                         STAILQ_INSERT_TAIL(&bp->free_filter_list,
95                                         filter, next);
96                         filter = temp_filter;
97                 }
98                 STAILQ_INIT(&vnic->filter);
99         }
100
101         for (i = 0; i < bp->pf.max_vfs; i++) {
102                 STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) {
103                         bnxt_hwrm_clear_l2_filter(bp, filter);
104                 }
105         }
106 }
107
108 void bnxt_free_filter_mem(struct bnxt *bp)
109 {
110         struct bnxt_filter_info *filter;
111         uint16_t max_filters, i;
112         int rc = 0;
113
114         if (bp->filter_info == NULL)
115                 return;
116
117         /* Ensure that all filters are freed */
118         max_filters = bp->max_l2_ctx;
119         for (i = 0; i < max_filters; i++) {
120                 filter = &bp->filter_info[i];
121                 if (filter->fw_ntuple_filter_id != ((uint64_t)-1) &&
122                     filter->filter_type == HWRM_CFA_NTUPLE_FILTER) {
123                         /* Call HWRM to try to free filter again */
124                         rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
125                         if (rc)
126                                 PMD_DRV_LOG(ERR,
127                                             "Cannot free ntuple filter: %d\n",
128                                             rc);
129                 }
130                 filter->fw_ntuple_filter_id = UINT64_MAX;
131
132                 if (filter->fw_l2_filter_id != ((uint64_t)-1) &&
133                     filter->filter_type == HWRM_CFA_L2_FILTER) {
134                         PMD_DRV_LOG(DEBUG, "L2 filter is not free\n");
135                         /* Call HWRM to try to free filter again */
136                         rc = bnxt_hwrm_clear_l2_filter(bp, filter);
137                         if (rc)
138                                 PMD_DRV_LOG(ERR,
139                                             "Cannot free L2 filter: %d\n",
140                                             rc);
141                 }
142                 filter->fw_l2_filter_id = UINT64_MAX;
143
144         }
145         STAILQ_INIT(&bp->free_filter_list);
146
147         rte_free(bp->filter_info);
148         bp->filter_info = NULL;
149
150         for (i = 0; i < bp->pf.max_vfs; i++) {
151                 STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) {
152                         rte_free(filter);
153                         STAILQ_REMOVE(&bp->pf.vf_info[i].filter, filter,
154                                       bnxt_filter_info, next);
155                 }
156         }
157 }
158
159 int bnxt_alloc_filter_mem(struct bnxt *bp)
160 {
161         struct bnxt_filter_info *filter_mem;
162         uint16_t max_filters;
163
164         max_filters = bp->max_l2_ctx;
165         /* Allocate memory for VNIC pool and filter pool */
166         filter_mem = rte_zmalloc("bnxt_filter_info",
167                                  max_filters * sizeof(struct bnxt_filter_info),
168                                  0);
169         if (filter_mem == NULL) {
170                 PMD_DRV_LOG(ERR, "Failed to alloc memory for %d filters",
171                         max_filters);
172                 return -ENOMEM;
173         }
174         bp->filter_info = filter_mem;
175         bnxt_init_filters(bp);
176         return 0;
177 }
178
179 struct bnxt_filter_info *bnxt_get_unused_filter(struct bnxt *bp)
180 {
181         struct bnxt_filter_info *filter;
182
183         /* Find the 1st unused filter from the free_filter_list pool*/
184         filter = STAILQ_FIRST(&bp->free_filter_list);
185         if (!filter) {
186                 PMD_DRV_LOG(ERR, "No more free filter resources\n");
187                 return NULL;
188         }
189         STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
190
191         return filter;
192 }
193
194 void bnxt_free_filter(struct bnxt *bp, struct bnxt_filter_info *filter)
195 {
196         memset(filter, 0, sizeof(*filter));
197         filter->mac_index = INVALID_MAC_INDEX;
198         filter->fw_l2_filter_id = UINT64_MAX;
199         filter->fw_ntuple_filter_id = UINT64_MAX;
200         filter->fw_em_filter_id = UINT64_MAX;
201         STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next);
202 }