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