net/ice: enable flow director engine
[dpdk.git] / drivers / net / ice / ice_fdir_filter.c
1 #include <stdio.h>
2 #include <rte_flow.h>
3 #include "base/ice_fdir.h"
4 #include "base/ice_flow.h"
5 #include "base/ice_type.h"
6 #include "ice_ethdev.h"
7 #include "ice_rxtx.h"
8 #include "ice_generic_flow.h"
9
10 static const struct rte_memzone *
11 ice_memzone_reserve(const char *name, uint32_t len, int socket_id)
12 {
13         return rte_memzone_reserve_aligned(name, len, socket_id,
14                                            RTE_MEMZONE_IOVA_CONTIG,
15                                            ICE_RING_BASE_ALIGN);
16 }
17
18 #define ICE_FDIR_MZ_NAME        "FDIR_MEMZONE"
19
20 static int
21 ice_fdir_prof_alloc(struct ice_hw *hw)
22 {
23         enum ice_fltr_ptype ptype, fltr_ptype;
24
25         if (!hw->fdir_prof) {
26                 hw->fdir_prof = (struct ice_fd_hw_prof **)
27                         ice_malloc(hw, ICE_FLTR_PTYPE_MAX *
28                                    sizeof(*hw->fdir_prof));
29                 if (!hw->fdir_prof)
30                         return -ENOMEM;
31         }
32         for (ptype = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
33              ptype < ICE_FLTR_PTYPE_MAX;
34              ptype++) {
35                 if (!hw->fdir_prof[ptype]) {
36                         hw->fdir_prof[ptype] = (struct ice_fd_hw_prof *)
37                                 ice_malloc(hw, sizeof(**hw->fdir_prof));
38                         if (!hw->fdir_prof[ptype])
39                                 goto fail_mem;
40                 }
41         }
42         return 0;
43
44 fail_mem:
45         for (fltr_ptype = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
46              fltr_ptype < ptype;
47              fltr_ptype++)
48                 rte_free(hw->fdir_prof[fltr_ptype]);
49         rte_free(hw->fdir_prof);
50         return -ENOMEM;
51 }
52
53 /*
54  * ice_fdir_setup - reserve and initialize the Flow Director resources
55  * @pf: board private structure
56  */
57 static int
58 ice_fdir_setup(struct ice_pf *pf)
59 {
60         struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
61         struct ice_hw *hw = ICE_PF_TO_HW(pf);
62         const struct rte_memzone *mz = NULL;
63         char z_name[RTE_MEMZONE_NAMESIZE];
64         struct ice_vsi *vsi;
65         int err = ICE_SUCCESS;
66
67         if ((pf->flags & ICE_FLAG_FDIR) == 0) {
68                 PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
69                 return -ENOTSUP;
70         }
71
72         PMD_DRV_LOG(INFO, "FDIR HW Capabilities: fd_fltr_guar = %u,"
73                     " fd_fltr_best_effort = %u.",
74                     hw->func_caps.fd_fltr_guar,
75                     hw->func_caps.fd_fltr_best_effort);
76
77         if (pf->fdir.fdir_vsi) {
78                 PMD_DRV_LOG(INFO, "FDIR initialization has been done.");
79                 return ICE_SUCCESS;
80         }
81
82         /* make new FDIR VSI */
83         vsi = ice_setup_vsi(pf, ICE_VSI_CTRL);
84         if (!vsi) {
85                 PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI.");
86                 return -EINVAL;
87         }
88         pf->fdir.fdir_vsi = vsi;
89
90         /*Fdir tx queue setup*/
91         err = ice_fdir_setup_tx_resources(pf);
92         if (err) {
93                 PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources.");
94                 goto fail_setup_tx;
95         }
96
97         /*Fdir rx queue setup*/
98         err = ice_fdir_setup_rx_resources(pf);
99         if (err) {
100                 PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources.");
101                 goto fail_setup_rx;
102         }
103
104         err = ice_fdir_tx_queue_start(eth_dev, pf->fdir.txq->queue_id);
105         if (err) {
106                 PMD_DRV_LOG(ERR, "Failed to start FDIR TX queue.");
107                 goto fail_mem;
108         }
109
110         err = ice_fdir_rx_queue_start(eth_dev, pf->fdir.rxq->queue_id);
111         if (err) {
112                 PMD_DRV_LOG(ERR, "Failed to start FDIR RX queue.");
113                 goto fail_mem;
114         }
115
116         /* reserve memory for the fdir programming packet */
117         snprintf(z_name, sizeof(z_name), "ICE_%s_%d",
118                  ICE_FDIR_MZ_NAME,
119                  eth_dev->data->port_id);
120         mz = ice_memzone_reserve(z_name, ICE_FDIR_PKT_LEN, SOCKET_ID_ANY);
121         if (!mz) {
122                 PMD_DRV_LOG(ERR, "Cannot init memzone for "
123                             "flow director program packet.");
124                 err = -ENOMEM;
125                 goto fail_mem;
126         }
127         pf->fdir.prg_pkt = mz->addr;
128         pf->fdir.dma_addr = mz->iova;
129
130         err = ice_fdir_prof_alloc(hw);
131         if (err) {
132                 PMD_DRV_LOG(ERR, "Cannot allocate memory for "
133                             "flow director profile.");
134                 err = -ENOMEM;
135                 goto fail_mem;
136         }
137
138         PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
139                     vsi->base_queue);
140         return ICE_SUCCESS;
141
142 fail_mem:
143         ice_rx_queue_release(pf->fdir.rxq);
144         pf->fdir.rxq = NULL;
145 fail_setup_rx:
146         ice_tx_queue_release(pf->fdir.txq);
147         pf->fdir.txq = NULL;
148 fail_setup_tx:
149         ice_release_vsi(vsi);
150         pf->fdir.fdir_vsi = NULL;
151         return err;
152 }
153
154 static void
155 ice_fdir_prof_free(struct ice_hw *hw)
156 {
157         enum ice_fltr_ptype ptype;
158
159         for (ptype = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
160              ptype < ICE_FLTR_PTYPE_MAX;
161              ptype++)
162                 rte_free(hw->fdir_prof[ptype]);
163
164         rte_free(hw->fdir_prof);
165 }
166
167 /*
168  * ice_fdir_teardown - release the Flow Director resources
169  * @pf: board private structure
170  */
171 static void
172 ice_fdir_teardown(struct ice_pf *pf)
173 {
174         struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
175         struct ice_hw *hw = ICE_PF_TO_HW(pf);
176         struct ice_vsi *vsi;
177         int err;
178
179         vsi = pf->fdir.fdir_vsi;
180         if (!vsi)
181                 return;
182
183         err = ice_fdir_tx_queue_stop(eth_dev, pf->fdir.txq->queue_id);
184         if (err)
185                 PMD_DRV_LOG(ERR, "Failed to stop TX queue.");
186
187         err = ice_fdir_rx_queue_stop(eth_dev, pf->fdir.rxq->queue_id);
188         if (err)
189                 PMD_DRV_LOG(ERR, "Failed to stop RX queue.");
190
191         ice_tx_queue_release(pf->fdir.txq);
192         pf->fdir.txq = NULL;
193         ice_rx_queue_release(pf->fdir.rxq);
194         pf->fdir.rxq = NULL;
195         ice_release_vsi(vsi);
196         pf->fdir.fdir_vsi = NULL;
197         ice_fdir_prof_free(hw);
198 }
199
200 static int
201 ice_fdir_init(struct ice_adapter *ad)
202 {
203         struct ice_pf *pf = &ad->pf;
204
205         return ice_fdir_setup(pf);
206 }
207
208 static void
209 ice_fdir_uninit(struct ice_adapter *ad)
210 {
211         struct ice_pf *pf = &ad->pf;
212
213         ice_fdir_teardown(pf);
214 }
215
216 static struct ice_flow_engine ice_fdir_engine = {
217         .init = ice_fdir_init,
218         .uninit = ice_fdir_uninit,
219         .type = ICE_FLOW_ENGINE_FDIR,
220 };
221
222 RTE_INIT(ice_fdir_engine_register)
223 {
224         ice_register_flow_engine(&ice_fdir_engine);
225 }