common/mlx5: fix user mode register access command
[dpdk.git] / drivers / net / igc / igc_filter.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2020 Intel Corporation
3  */
4
5 #include "rte_malloc.h"
6 #include "igc_logs.h"
7 #include "igc_txrx.h"
8 #include "igc_filter.h"
9 #include "igc_flow.h"
10
11 /*
12  * igc_ethertype_filter_lookup - lookup ether-type filter
13  *
14  * @igc, IGC filter pointer
15  * @ethertype, ethernet type
16  * @empty, a place to store the index of empty entry if the item not found
17  *  it's not smaller than 0 if valid, otherwise -1 for no empty entry.
18  *  empty parameter is only valid if the return value of the function is -1
19  *
20  * Return value
21  * >= 0, item index of the ether-type filter
22  * -1, the item not been found
23  */
24 static inline int
25 igc_ethertype_filter_lookup(const struct igc_adapter *igc,
26                         uint16_t ethertype, int *empty)
27 {
28         int i = 0;
29
30         if (empty) {
31                 /* set to invalid valid */
32                 *empty = -1;
33
34                 /* search the filters array */
35                 for (; i < IGC_MAX_ETQF_FILTERS; i++) {
36                         if (igc->ethertype_filters[i].ether_type == ethertype)
37                                 return i;
38                         if (igc->ethertype_filters[i].ether_type == 0) {
39                                 /* get empty entry */
40                                 *empty = i;
41                                 i++;
42                                 break;
43                         }
44                 }
45         }
46
47         /* search the rest of filters */
48         for (; i < IGC_MAX_ETQF_FILTERS; i++) {
49                 if (igc->ethertype_filters[i].ether_type == ethertype)
50                         return i;       /* filter be found, return index */
51         }
52
53         return -1;
54 }
55
56 int
57 igc_del_ethertype_filter(struct rte_eth_dev *dev,
58                         const struct igc_ethertype_filter *filter)
59 {
60         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
61         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
62         int ret;
63
64         if (filter->ether_type == 0) {
65                 PMD_DRV_LOG(ERR, "Ethertype 0 is not been supported");
66                 return -EINVAL;
67         }
68
69         ret = igc_ethertype_filter_lookup(igc, filter->ether_type, NULL);
70         if (ret < 0) {
71                 /* not found */
72                 PMD_DRV_LOG(ERR,
73                         "Ethertype (0x%04x) filter doesn't exist",
74                         filter->ether_type);
75                 return -ENOENT;
76         }
77
78         igc->ethertype_filters[ret].ether_type = 0;
79
80         IGC_WRITE_REG(hw, IGC_ETQF(ret), 0);
81         IGC_WRITE_FLUSH(hw);
82         return 0;
83 }
84
85 int
86 igc_add_ethertype_filter(struct rte_eth_dev *dev,
87                         const struct igc_ethertype_filter *filter)
88 {
89         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
90         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
91         uint32_t etqf;
92         int ret, empty;
93
94         if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
95                 filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
96                 filter->ether_type == 0) {
97                 PMD_DRV_LOG(ERR,
98                         "Unsupported ether_type(0x%04x) in ethertype filter",
99                         filter->ether_type);
100                 return -EINVAL;
101         }
102
103         ret = igc_ethertype_filter_lookup(igc, filter->ether_type, &empty);
104         if (ret >= 0) {
105                 PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.",
106                                 filter->ether_type);
107                 return -EEXIST;
108         }
109
110         if (empty < 0) {
111                 PMD_DRV_LOG(ERR, "no ethertype filter entry.");
112                 return -ENOSPC;
113         }
114         ret = empty;
115
116         etqf = filter->ether_type;
117         etqf |= IGC_ETQF_FILTER_ENABLE | IGC_ETQF_QUEUE_ENABLE;
118         etqf |= (uint32_t)filter->queue << IGC_ETQF_QUEUE_SHIFT;
119
120         memcpy(&igc->ethertype_filters[ret], filter, sizeof(*filter));
121
122         IGC_WRITE_REG(hw, IGC_ETQF(ret), etqf);
123         IGC_WRITE_FLUSH(hw);
124         return 0;
125 }
126
127 /* clear all the ether type filters */
128 static void
129 igc_clear_all_ethertype_filter(struct rte_eth_dev *dev)
130 {
131         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
132         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
133         int i;
134
135         for (i = 0; i < IGC_MAX_ETQF_FILTERS; i++)
136                 IGC_WRITE_REG(hw, IGC_ETQF(i), 0);
137         IGC_WRITE_FLUSH(hw);
138
139         memset(&igc->ethertype_filters, 0, sizeof(igc->ethertype_filters));
140 }
141
142 /*
143  * igc_tuple_filter_lookup - lookup n-tuple filter
144  *
145  * @igc, igc filter pointer
146  * @ntuple, n-tuple filter pointer
147  * @empty, a place to store the index of empty entry if the item not found
148  *  it's not smaller than 0 if valid, otherwise -1 for no empty entry.
149  *  The value of empty is uncertain if the return value of the function is
150  *  not -1.
151  *
152  * Return value
153  * >= 0, item index of the filter
154  * -1, the item not been found
155  */
156 static int
157 igc_tuple_filter_lookup(const struct igc_adapter *igc,
158                         const struct igc_ntuple_filter *ntuple,
159                         int *empty)
160 {
161         int i = 0;
162
163         if (empty) {
164                 /* set initial value */
165                 *empty = -1;
166
167                 /* search the filter array */
168                 for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
169                         if (igc->ntuple_filters[i].hash_val) {
170                                 /* compare the hase value */
171                                 if (ntuple->hash_val ==
172                                         igc->ntuple_filters[i].hash_val)
173                                         /* filter be found, return index */
174                                         return i;
175                         } else {
176                                 /* get the empty entry */
177                                 *empty = i;
178                                 i++;
179                                 break;
180                         }
181                 }
182         }
183
184         /* search the rest of filters */
185         for (; i < IGC_MAX_NTUPLE_FILTERS; i++) {
186                 if (ntuple->hash_val == igc->ntuple_filters[i].hash_val)
187                         /* filter be found, return index */
188                         return i;
189         }
190
191         return -1;
192 }
193
194 /* Set hardware register values */
195 static void
196 igc_enable_tuple_filter(struct rte_eth_dev *dev,
197                         const struct igc_adapter *igc, uint8_t index)
198 {
199         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
200         const struct igc_ntuple_filter *filter = &igc->ntuple_filters[index];
201         const struct igc_ntuple_info *info = &filter->tuple_info;
202         uint32_t ttqf, imir, imir_ext = IGC_IMIREXT_SIZE_BP;
203
204         imir = info->dst_port;
205         imir |= (uint32_t)info->priority << IGC_IMIR_PRIORITY_SHIFT;
206
207         /* 0b means not compare. */
208         if (info->dst_port_mask == 0)
209                 imir |= IGC_IMIR_PORT_BP;
210
211         ttqf = IGC_TTQF_DISABLE_MASK | IGC_TTQF_QUEUE_ENABLE;
212         ttqf |= (uint32_t)filter->queue << IGC_TTQF_QUEUE_SHIFT;
213         ttqf |= info->proto;
214
215         if (info->proto_mask)
216                 ttqf &= ~IGC_TTQF_MASK_ENABLE;
217
218         /* TCP flags bits setting. */
219         if (info->tcp_flags & RTE_NTUPLE_TCP_FLAGS_MASK) {
220                 if (info->tcp_flags & RTE_TCP_URG_FLAG)
221                         imir_ext |= IGC_IMIREXT_CTRL_URG;
222                 if (info->tcp_flags & RTE_TCP_ACK_FLAG)
223                         imir_ext |= IGC_IMIREXT_CTRL_ACK;
224                 if (info->tcp_flags & RTE_TCP_PSH_FLAG)
225                         imir_ext |= IGC_IMIREXT_CTRL_PSH;
226                 if (info->tcp_flags & RTE_TCP_RST_FLAG)
227                         imir_ext |= IGC_IMIREXT_CTRL_RST;
228                 if (info->tcp_flags & RTE_TCP_SYN_FLAG)
229                         imir_ext |= IGC_IMIREXT_CTRL_SYN;
230                 if (info->tcp_flags & RTE_TCP_FIN_FLAG)
231                         imir_ext |= IGC_IMIREXT_CTRL_FIN;
232         } else {
233                 imir_ext |= IGC_IMIREXT_CTRL_BP;
234         }
235
236         IGC_WRITE_REG(hw, IGC_IMIR(index), imir);
237         IGC_WRITE_REG(hw, IGC_TTQF(index), ttqf);
238         IGC_WRITE_REG(hw, IGC_IMIREXT(index), imir_ext);
239         IGC_WRITE_FLUSH(hw);
240 }
241
242 /* Reset hardware register values */
243 static void
244 igc_disable_tuple_filter(struct rte_eth_dev *dev, uint8_t index)
245 {
246         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
247
248         IGC_WRITE_REG(hw, IGC_TTQF(index), IGC_TTQF_DISABLE_MASK);
249         IGC_WRITE_REG(hw, IGC_IMIR(index), 0);
250         IGC_WRITE_REG(hw, IGC_IMIREXT(index), 0);
251         IGC_WRITE_FLUSH(hw);
252 }
253
254 int
255 igc_add_ntuple_filter(struct rte_eth_dev *dev,
256                 const struct igc_ntuple_filter *ntuple)
257 {
258         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
259         int ret, empty;
260
261         ret = igc_tuple_filter_lookup(igc, ntuple, &empty);
262         if (ret >= 0) {
263                 PMD_DRV_LOG(ERR, "filter exists.");
264                 return -EEXIST;
265         }
266
267         if (empty < 0) {
268                 PMD_DRV_LOG(ERR, "filter no entry.");
269                 return -ENOSPC;
270         }
271
272         ret = empty;
273         memcpy(&igc->ntuple_filters[ret], ntuple, sizeof(*ntuple));
274         igc_enable_tuple_filter(dev, igc, (uint8_t)ret);
275         return 0;
276 }
277
278 int
279 igc_del_ntuple_filter(struct rte_eth_dev *dev,
280                 const struct igc_ntuple_filter *ntuple)
281 {
282         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
283         int ret;
284
285         ret = igc_tuple_filter_lookup(igc, ntuple, NULL);
286         if (ret < 0) {
287                 PMD_DRV_LOG(ERR, "filter not exists.");
288                 return -ENOENT;
289         }
290
291         memset(&igc->ntuple_filters[ret], 0, sizeof(*ntuple));
292         igc_disable_tuple_filter(dev, (uint8_t)ret);
293         return 0;
294 }
295
296 /* Clear all the n-tuple filters */
297 static void
298 igc_clear_all_ntuple_filter(struct rte_eth_dev *dev)
299 {
300         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
301         int i;
302
303         for (i = 0; i < IGC_MAX_NTUPLE_FILTERS; i++)
304                 igc_disable_tuple_filter(dev, i);
305
306         memset(&igc->ntuple_filters, 0, sizeof(igc->ntuple_filters));
307 }
308
309 int
310 igc_set_syn_filter(struct rte_eth_dev *dev,
311                 const struct igc_syn_filter *filter)
312 {
313         struct igc_hw *hw;
314         struct igc_adapter *igc;
315         uint32_t synqf, rfctl;
316
317         if (filter->queue >= IGC_QUEUE_PAIRS_NUM) {
318                 PMD_DRV_LOG(ERR, "out of range queue %u(max is %u)",
319                         filter->queue, IGC_QUEUE_PAIRS_NUM);
320                 return -EINVAL;
321         }
322
323         igc = IGC_DEV_PRIVATE(dev);
324
325         if (igc->syn_filter.enable) {
326                 PMD_DRV_LOG(ERR, "SYN filter has been enabled before!");
327                 return -EEXIST;
328         }
329
330         hw = IGC_DEV_PRIVATE_HW(dev);
331         synqf = (uint32_t)filter->queue << IGC_SYN_FILTER_QUEUE_SHIFT;
332         synqf |= IGC_SYN_FILTER_ENABLE;
333
334         rfctl = IGC_READ_REG(hw, IGC_RFCTL);
335         if (filter->hig_pri)
336                 rfctl |= IGC_RFCTL_SYNQFP;
337         else
338                 rfctl &= ~IGC_RFCTL_SYNQFP;
339
340         memcpy(&igc->syn_filter, filter, sizeof(igc->syn_filter));
341         igc->syn_filter.enable = 1;
342
343         IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
344         IGC_WRITE_REG(hw, IGC_SYNQF(0), synqf);
345         IGC_WRITE_FLUSH(hw);
346         return 0;
347 }
348
349 /* clear the SYN filter */
350 void
351 igc_clear_syn_filter(struct rte_eth_dev *dev)
352 {
353         struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
354         struct igc_adapter *igc = IGC_DEV_PRIVATE(dev);
355
356         IGC_WRITE_REG(hw, IGC_SYNQF(0), 0);
357         IGC_WRITE_FLUSH(hw);
358
359         memset(&igc->syn_filter, 0, sizeof(igc->syn_filter));
360 }
361
362 void
363 igc_clear_all_filter(struct rte_eth_dev *dev)
364 {
365         igc_clear_all_ethertype_filter(dev);
366         igc_clear_all_ntuple_filter(dev);
367         igc_clear_syn_filter(dev);
368         igc_clear_rss_filter(dev);
369 }
370
371 int
372 eth_igc_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
373                 enum rte_filter_op filter_op, void *arg)
374 {
375         int ret = 0;
376
377         RTE_SET_USED(dev);
378
379         switch (filter_type) {
380         case RTE_ETH_FILTER_GENERIC:
381                 if (filter_op != RTE_ETH_FILTER_GET)
382                         return -EINVAL;
383                 *(const void **)arg = &igc_flow_ops;
384                 break;
385         default:
386                 PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
387                                                         filter_type);
388                 ret = -EINVAL;
389         }
390
391         return ret;
392 }