net/i40e: add dynamic mapping of SW flow types to HW pctypes
[dpdk.git] / drivers / net / i40e / i40e_fdir.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/queue.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <stdarg.h>
41
42 #include <rte_ether.h>
43 #include <rte_ethdev.h>
44 #include <rte_log.h>
45 #include <rte_memzone.h>
46 #include <rte_malloc.h>
47 #include <rte_arp.h>
48 #include <rte_ip.h>
49 #include <rte_udp.h>
50 #include <rte_tcp.h>
51 #include <rte_sctp.h>
52
53 #include "i40e_logs.h"
54 #include "base/i40e_type.h"
55 #include "base/i40e_prototype.h"
56 #include "i40e_ethdev.h"
57 #include "i40e_rxtx.h"
58
59 #define I40E_FDIR_MZ_NAME          "FDIR_MEMZONE"
60 #ifndef IPV6_ADDR_LEN
61 #define IPV6_ADDR_LEN              16
62 #endif
63
64 #define I40E_FDIR_PKT_LEN                   512
65 #define I40E_FDIR_IP_DEFAULT_LEN            420
66 #define I40E_FDIR_IP_DEFAULT_TTL            0x40
67 #define I40E_FDIR_IP_DEFAULT_VERSION_IHL    0x45
68 #define I40E_FDIR_TCP_DEFAULT_DATAOFF       0x50
69 #define I40E_FDIR_IPv6_DEFAULT_VTC_FLOW     0x60000000
70
71 #define I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS   0xFF
72 #define I40E_FDIR_IPv6_PAYLOAD_LEN          380
73 #define I40E_FDIR_UDP_DEFAULT_LEN           400
74
75 /* Wait time for fdir filter programming */
76 #define I40E_FDIR_MAX_WAIT_US 10000
77
78 /* Wait count and interval for fdir filter flush */
79 #define I40E_FDIR_FLUSH_RETRY       50
80 #define I40E_FDIR_FLUSH_INTERVAL_MS 5
81
82 #define I40E_COUNTER_PF           2
83 /* Statistic counter index for one pf */
84 #define I40E_COUNTER_INDEX_FDIR(pf_id)   (0 + (pf_id) * I40E_COUNTER_PF)
85
86 #define I40E_FDIR_FLOWS ( \
87         (1 << RTE_ETH_FLOW_FRAG_IPV4) | \
88         (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \
89         (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \
90         (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \
91         (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \
92         (1 << RTE_ETH_FLOW_FRAG_IPV6) | \
93         (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \
94         (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \
95         (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \
96         (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \
97         (1 << RTE_ETH_FLOW_L2_PAYLOAD))
98
99 static int i40e_fdir_filter_programming(struct i40e_pf *pf,
100                         enum i40e_filter_pctype pctype,
101                         const struct rte_eth_fdir_filter *filter,
102                         bool add);
103 static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
104                          struct i40e_fdir_filter *filter);
105 static struct i40e_fdir_filter *
106 i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
107                         const struct rte_eth_fdir_input *input);
108 static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf,
109                                    struct i40e_fdir_filter *filter);
110
111 static int
112 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
113 {
114         struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi);
115         struct i40e_hmc_obj_rxq rx_ctx;
116         int err = I40E_SUCCESS;
117
118         memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
119         /* Init the RX queue in hardware */
120         rx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT;
121         rx_ctx.hbuff = 0;
122         rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT;
123         rx_ctx.qlen = rxq->nb_rx_desc;
124 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
125         rx_ctx.dsize = 1;
126 #endif
127         rx_ctx.dtype = i40e_header_split_none;
128         rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
129         rx_ctx.rxmax = ETHER_MAX_LEN;
130         rx_ctx.tphrdesc_ena = 1;
131         rx_ctx.tphwdesc_ena = 1;
132         rx_ctx.tphdata_ena = 1;
133         rx_ctx.tphhead_ena = 1;
134         rx_ctx.lrxqthresh = 2;
135         rx_ctx.crcstrip = 0;
136         rx_ctx.l2tsel = 1;
137         rx_ctx.showiv = 0;
138         rx_ctx.prefena = 1;
139
140         err = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx);
141         if (err != I40E_SUCCESS) {
142                 PMD_DRV_LOG(ERR, "Failed to clear FDIR RX queue context.");
143                 return err;
144         }
145         err = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx);
146         if (err != I40E_SUCCESS) {
147                 PMD_DRV_LOG(ERR, "Failed to set FDIR RX queue context.");
148                 return err;
149         }
150         rxq->qrx_tail = hw->hw_addr +
151                 I40E_QRX_TAIL(rxq->vsi->base_queue);
152
153         rte_wmb();
154         /* Init the RX tail regieter. */
155         I40E_PCI_REG_WRITE(rxq->qrx_tail, 0);
156         I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
157
158         return err;
159 }
160
161 /*
162  * i40e_fdir_setup - reserve and initialize the Flow Director resources
163  * @pf: board private structure
164  */
165 int
166 i40e_fdir_setup(struct i40e_pf *pf)
167 {
168         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
169         struct i40e_vsi *vsi;
170         int err = I40E_SUCCESS;
171         char z_name[RTE_MEMZONE_NAMESIZE];
172         const struct rte_memzone *mz = NULL;
173         struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
174
175         if ((pf->flags & I40E_FLAG_FDIR) == 0) {
176                 PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
177                 return I40E_NOT_SUPPORTED;
178         }
179
180         PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u,"
181                         " num_filters_best_effort = %u.",
182                         hw->func_caps.fd_filters_guaranteed,
183                         hw->func_caps.fd_filters_best_effort);
184
185         vsi = pf->fdir.fdir_vsi;
186         if (vsi) {
187                 PMD_DRV_LOG(INFO, "FDIR initialization has been done.");
188                 return I40E_SUCCESS;
189         }
190         /* make new FDIR VSI */
191         vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);
192         if (!vsi) {
193                 PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI.");
194                 return I40E_ERR_NO_AVAILABLE_VSI;
195         }
196         pf->fdir.fdir_vsi = vsi;
197
198         /*Fdir tx queue setup*/
199         err = i40e_fdir_setup_tx_resources(pf);
200         if (err) {
201                 PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources.");
202                 goto fail_setup_tx;
203         }
204
205         /*Fdir rx queue setup*/
206         err = i40e_fdir_setup_rx_resources(pf);
207         if (err) {
208                 PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources.");
209                 goto fail_setup_rx;
210         }
211
212         err = i40e_tx_queue_init(pf->fdir.txq);
213         if (err) {
214                 PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization.");
215                 goto fail_mem;
216         }
217
218         /* need switch on before dev start*/
219         err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE);
220         if (err) {
221                 PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on.");
222                 goto fail_mem;
223         }
224
225         /* Init the rx queue in hardware */
226         err = i40e_fdir_rx_queue_init(pf->fdir.rxq);
227         if (err) {
228                 PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization.");
229                 goto fail_mem;
230         }
231
232         /* switch on rx queue */
233         err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE);
234         if (err) {
235                 PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on.");
236                 goto fail_mem;
237         }
238
239         /* reserve memory for the fdir programming packet */
240         snprintf(z_name, sizeof(z_name), "%s_%s_%d",
241                         eth_dev->device->driver->name,
242                         I40E_FDIR_MZ_NAME,
243                         eth_dev->data->port_id);
244         mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
245         if (!mz) {
246                 PMD_DRV_LOG(ERR, "Cannot init memzone for "
247                                  "flow director program packet.");
248                 err = I40E_ERR_NO_MEMORY;
249                 goto fail_mem;
250         }
251         pf->fdir.prg_pkt = mz->addr;
252         pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
253
254         pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
255         PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
256                     vsi->base_queue);
257         return I40E_SUCCESS;
258
259 fail_mem:
260         i40e_dev_rx_queue_release(pf->fdir.rxq);
261         pf->fdir.rxq = NULL;
262 fail_setup_rx:
263         i40e_dev_tx_queue_release(pf->fdir.txq);
264         pf->fdir.txq = NULL;
265 fail_setup_tx:
266         i40e_vsi_release(vsi);
267         pf->fdir.fdir_vsi = NULL;
268         return err;
269 }
270
271 /*
272  * i40e_fdir_teardown - release the Flow Director resources
273  * @pf: board private structure
274  */
275 void
276 i40e_fdir_teardown(struct i40e_pf *pf)
277 {
278         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
279         struct i40e_vsi *vsi;
280
281         vsi = pf->fdir.fdir_vsi;
282         if (!vsi)
283                 return;
284         int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
285         if (err)
286                 PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
287         err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
288         if (err)
289                 PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
290         i40e_dev_rx_queue_release(pf->fdir.rxq);
291         pf->fdir.rxq = NULL;
292         i40e_dev_tx_queue_release(pf->fdir.txq);
293         pf->fdir.txq = NULL;
294         i40e_vsi_release(vsi);
295         pf->fdir.fdir_vsi = NULL;
296 }
297
298 /* check whether the flow director table in empty */
299 static inline int
300 i40e_fdir_empty(struct i40e_hw *hw)
301 {
302         uint32_t guarant_cnt, best_cnt;
303
304         guarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
305                                  I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
306                                  I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
307         best_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
308                               I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
309                               I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
310         if (best_cnt + guarant_cnt > 0)
311                 return -1;
312
313         return 0;
314 }
315
316 /*
317  * Initialize the configuration about bytes stream extracted as flexible payload
318  * and mask setting
319  */
320 static inline void
321 i40e_init_flx_pld(struct i40e_pf *pf)
322 {
323         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
324         uint8_t pctype;
325         int i, index;
326         uint16_t flow_type;
327
328         /*
329          * Define the bytes stream extracted as flexible payload in
330          * field vector. By default, select 8 words from the beginning
331          * of payload as flexible payload.
332          */
333         for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) {
334                 index = i * I40E_MAX_FLXPLD_FIED;
335                 pf->fdir.flex_set[index].src_offset = 0;
336                 pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM;
337                 pf->fdir.flex_set[index].dst_offset = 0;
338                 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900);
339                 I40E_WRITE_REG(hw,
340                         I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/
341                 I40E_WRITE_REG(hw,
342                         I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/
343         }
344
345         /* initialize the masks */
346         for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
347              pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
348                 flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype);
349
350                 if (flow_type == RTE_ETH_FLOW_UNKNOWN)
351                         continue;
352                 pf->fdir.flex_mask[pctype].word_mask = 0;
353                 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0);
354                 for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) {
355                         pf->fdir.flex_mask[pctype].bitmask[i].offset = 0;
356                         pf->fdir.flex_mask[pctype].bitmask[i].mask = 0;
357                         i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), 0);
358                 }
359         }
360 }
361
362 #define I40E_VALIDATE_FLEX_PIT(flex_pit1, flex_pit2) do { \
363         if ((flex_pit2).src_offset < \
364                 (flex_pit1).src_offset + (flex_pit1).size) { \
365                 PMD_DRV_LOG(ERR, "src_offset should be not" \
366                         " less than than previous offset" \
367                         " + previous FSIZE."); \
368                 return -EINVAL; \
369         } \
370 } while (0)
371
372 /*
373  * i40e_srcoff_to_flx_pit - transform the src_offset into flex_pit structure,
374  * and the flex_pit will be sorted by it's src_offset value
375  */
376 static inline uint16_t
377 i40e_srcoff_to_flx_pit(const uint16_t *src_offset,
378                         struct i40e_fdir_flex_pit *flex_pit)
379 {
380         uint16_t src_tmp, size, num = 0;
381         uint16_t i, k, j = 0;
382
383         while (j < I40E_FDIR_MAX_FLEX_LEN) {
384                 size = 1;
385                 for (; j < I40E_FDIR_MAX_FLEX_LEN - 1; j++) {
386                         if (src_offset[j + 1] == src_offset[j] + 1)
387                                 size++;
388                         else
389                                 break;
390                 }
391                 src_tmp = src_offset[j] + 1 - size;
392                 /* the flex_pit need to be sort by src_offset */
393                 for (i = 0; i < num; i++) {
394                         if (src_tmp < flex_pit[i].src_offset)
395                                 break;
396                 }
397                 /* if insert required, move backward */
398                 for (k = num; k > i; k--)
399                         flex_pit[k] = flex_pit[k - 1];
400                 /* insert */
401                 flex_pit[i].dst_offset = j + 1 - size;
402                 flex_pit[i].src_offset = src_tmp;
403                 flex_pit[i].size = size;
404                 j++;
405                 num++;
406         }
407         return num;
408 }
409
410 /* i40e_check_fdir_flex_payload -check flex payload configuration arguments */
411 static inline int
412 i40e_check_fdir_flex_payload(const struct rte_eth_flex_payload_cfg *flex_cfg)
413 {
414         struct i40e_fdir_flex_pit flex_pit[I40E_FDIR_MAX_FLEX_LEN];
415         uint16_t num, i;
416
417         for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++) {
418                 if (flex_cfg->src_offset[i] >= I40E_MAX_FLX_SOURCE_OFF) {
419                         PMD_DRV_LOG(ERR, "exceeds maxmial payload limit.");
420                         return -EINVAL;
421                 }
422         }
423
424         memset(flex_pit, 0, sizeof(flex_pit));
425         num = i40e_srcoff_to_flx_pit(flex_cfg->src_offset, flex_pit);
426         if (num > I40E_MAX_FLXPLD_FIED) {
427                 PMD_DRV_LOG(ERR, "exceeds maxmial number of flex fields.");
428                 return -EINVAL;
429         }
430         for (i = 0; i < num; i++) {
431                 if (flex_pit[i].size & 0x01 || flex_pit[i].dst_offset & 0x01 ||
432                         flex_pit[i].src_offset & 0x01) {
433                         PMD_DRV_LOG(ERR, "flexpayload should be measured"
434                                 " in word");
435                         return -EINVAL;
436                 }
437                 if (i != num - 1)
438                         I40E_VALIDATE_FLEX_PIT(flex_pit[i], flex_pit[i + 1]);
439         }
440         return 0;
441 }
442
443 /*
444  * i40e_check_fdir_flex_conf -check if the flex payload and mask configuration
445  * arguments are valid
446  */
447 static int
448 i40e_check_fdir_flex_conf(const struct i40e_adapter *adapter,
449                           const struct rte_eth_fdir_flex_conf *conf)
450 {
451         const struct rte_eth_flex_payload_cfg *flex_cfg;
452         const struct rte_eth_fdir_flex_mask *flex_mask;
453         uint16_t mask_tmp;
454         uint8_t nb_bitmask;
455         uint16_t i, j;
456         int ret = 0;
457         enum i40e_filter_pctype pctype;
458
459         if (conf == NULL) {
460                 PMD_DRV_LOG(INFO, "NULL pointer.");
461                 return -EINVAL;
462         }
463         /* check flexible payload setting configuration */
464         if (conf->nb_payloads > RTE_ETH_L4_PAYLOAD) {
465                 PMD_DRV_LOG(ERR, "invalid number of payload setting.");
466                 return -EINVAL;
467         }
468         for (i = 0; i < conf->nb_payloads; i++) {
469                 flex_cfg = &conf->flex_set[i];
470                 if (flex_cfg->type > RTE_ETH_L4_PAYLOAD) {
471                         PMD_DRV_LOG(ERR, "invalid payload type.");
472                         return -EINVAL;
473                 }
474                 ret = i40e_check_fdir_flex_payload(flex_cfg);
475                 if (ret < 0) {
476                         PMD_DRV_LOG(ERR, "invalid flex payload arguments.");
477                         return -EINVAL;
478                 }
479         }
480
481         /* check flex mask setting configuration */
482         if (conf->nb_flexmasks >= RTE_ETH_FLOW_MAX) {
483                 PMD_DRV_LOG(ERR, "invalid number of flex masks.");
484                 return -EINVAL;
485         }
486         for (i = 0; i < conf->nb_flexmasks; i++) {
487                 flex_mask = &conf->flex_mask[i];
488                 pctype = i40e_flowtype_to_pctype(adapter, flex_mask->flow_type);
489                 if (pctype == I40E_FILTER_PCTYPE_INVALID) {
490                         PMD_DRV_LOG(WARNING, "invalid flow type.");
491                         return -EINVAL;
492                 }
493                 nb_bitmask = 0;
494                 for (j = 0; j < I40E_FDIR_MAX_FLEX_LEN; j += sizeof(uint16_t)) {
495                         mask_tmp = I40E_WORD(flex_mask->mask[j],
496                                              flex_mask->mask[j + 1]);
497                         if (mask_tmp != 0x0 && mask_tmp != UINT16_MAX) {
498                                 nb_bitmask++;
499                                 if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD) {
500                                         PMD_DRV_LOG(ERR, " exceed maximal"
501                                                 " number of bitmasks.");
502                                         return -EINVAL;
503                                 }
504                         }
505                 }
506         }
507         return 0;
508 }
509
510 /*
511  * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload
512  * @pf: board private structure
513  * @cfg: the rule how bytes stream is extracted as flexible payload
514  */
515 static void
516 i40e_set_flx_pld_cfg(struct i40e_pf *pf,
517                          const struct rte_eth_flex_payload_cfg *cfg)
518 {
519         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
520         struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED];
521         uint32_t flx_pit;
522         uint16_t num, min_next_off;  /* in words */
523         uint8_t field_idx = 0;
524         uint8_t layer_idx = 0;
525         uint16_t i;
526
527         if (cfg->type == RTE_ETH_L2_PAYLOAD)
528                 layer_idx = I40E_FLXPLD_L2_IDX;
529         else if (cfg->type == RTE_ETH_L3_PAYLOAD)
530                 layer_idx = I40E_FLXPLD_L3_IDX;
531         else if (cfg->type == RTE_ETH_L4_PAYLOAD)
532                 layer_idx = I40E_FLXPLD_L4_IDX;
533
534         memset(flex_pit, 0, sizeof(flex_pit));
535         num = i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit);
536
537         for (i = 0; i < RTE_MIN(num, RTE_DIM(flex_pit)); i++) {
538                 field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
539                 /* record the info in fdir structure */
540                 pf->fdir.flex_set[field_idx].src_offset =
541                         flex_pit[i].src_offset / sizeof(uint16_t);
542                 pf->fdir.flex_set[field_idx].size =
543                         flex_pit[i].size / sizeof(uint16_t);
544                 pf->fdir.flex_set[field_idx].dst_offset =
545                         flex_pit[i].dst_offset / sizeof(uint16_t);
546                 flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
547                                 pf->fdir.flex_set[field_idx].size,
548                                 pf->fdir.flex_set[field_idx].dst_offset);
549
550                 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
551         }
552         min_next_off = pf->fdir.flex_set[field_idx].src_offset +
553                                 pf->fdir.flex_set[field_idx].size;
554
555         for (; i < I40E_MAX_FLXPLD_FIED; i++) {
556                 /* set the non-used register obeying register's constrain */
557                 flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
558                            NONUSE_FLX_PIT_DEST_OFF);
559                 I40E_WRITE_REG(hw,
560                         I40E_PRTQF_FLX_PIT(layer_idx * I40E_MAX_FLXPLD_FIED + i),
561                         flx_pit);
562                 min_next_off++;
563         }
564 }
565
566 /*
567  * i40e_set_flex_mask_on_pctype - configure the mask on flexible payload
568  * @pf: board private structure
569  * @pctype: packet classify type
570  * @flex_masks: mask for flexible payload
571  */
572 static void
573 i40e_set_flex_mask_on_pctype(struct i40e_pf *pf,
574                 enum i40e_filter_pctype pctype,
575                 const struct rte_eth_fdir_flex_mask *mask_cfg)
576 {
577         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
578         struct i40e_fdir_flex_mask *flex_mask;
579         uint32_t flxinset, fd_mask;
580         uint16_t mask_tmp;
581         uint8_t i, nb_bitmask = 0;
582
583         flex_mask = &pf->fdir.flex_mask[pctype];
584         memset(flex_mask, 0, sizeof(struct i40e_fdir_flex_mask));
585         for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) {
586                 mask_tmp = I40E_WORD(mask_cfg->mask[i], mask_cfg->mask[i + 1]);
587                 if (mask_tmp != 0x0) {
588                         flex_mask->word_mask |=
589                                 I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
590                         if (mask_tmp != UINT16_MAX) {
591                                 /* set bit mask */
592                                 flex_mask->bitmask[nb_bitmask].mask = ~mask_tmp;
593                                 flex_mask->bitmask[nb_bitmask].offset =
594                                         i / sizeof(uint16_t);
595                                 nb_bitmask++;
596                         }
597                 }
598         }
599         /* write mask to hw */
600         flxinset = (flex_mask->word_mask <<
601                 I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
602                 I40E_PRTQF_FD_FLXINSET_INSET_MASK;
603         i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);
604
605         for (i = 0; i < nb_bitmask; i++) {
606                 fd_mask = (flex_mask->bitmask[i].mask <<
607                         I40E_PRTQF_FD_MSK_MASK_SHIFT) &
608                         I40E_PRTQF_FD_MSK_MASK_MASK;
609                 fd_mask |= ((flex_mask->bitmask[i].offset +
610                         I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
611                         I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
612                         I40E_PRTQF_FD_MSK_OFFSET_MASK;
613                 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask);
614         }
615 }
616
617 /*
618  * Configure flow director related setting
619  */
620 int
621 i40e_fdir_configure(struct rte_eth_dev *dev)
622 {
623         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
624         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
625         struct rte_eth_fdir_flex_conf *conf;
626         enum i40e_filter_pctype pctype;
627         uint32_t val;
628         uint8_t i;
629         int ret = 0;
630
631         /*
632         * configuration need to be done before
633         * flow director filters are added
634         * If filters exist, flush them.
635         */
636         if (i40e_fdir_empty(hw) < 0) {
637                 ret = i40e_fdir_flush(dev);
638                 if (ret) {
639                         PMD_DRV_LOG(ERR, "failed to flush fdir table.");
640                         return ret;
641                 }
642         }
643
644         /* enable FDIR filter */
645         val = i40e_read_rx_ctl(hw, I40E_PFQF_CTL_0);
646         val |= I40E_PFQF_CTL_0_FD_ENA_MASK;
647         i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, val);
648
649         i40e_init_flx_pld(pf); /* set flex config to default value */
650
651         conf = &dev->data->dev_conf.fdir_conf.flex_conf;
652         ret = i40e_check_fdir_flex_conf(pf->adapter, conf);
653         if (ret < 0) {
654                 PMD_DRV_LOG(ERR, " invalid configuration arguments.");
655                 return -EINVAL;
656         }
657         /* configure flex payload */
658         for (i = 0; i < conf->nb_payloads; i++)
659                 i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]);
660         /* configure flex mask*/
661         for (i = 0; i < conf->nb_flexmasks; i++) {
662                 if (hw->mac.type == I40E_MAC_X722) {
663                         /* get translated pctype value in fd pctype register */
664                         pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
665                                 hw, I40E_GLQF_FD_PCTYPES(
666                                 (int)i40e_flowtype_to_pctype(pf->adapter,
667                                 conf->flex_mask[i].flow_type)));
668                 } else
669                         pctype = i40e_flowtype_to_pctype(pf->adapter,
670                                                 conf->flex_mask[i].flow_type);
671
672                 i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]);
673         }
674
675         return ret;
676 }
677
678 static inline int
679 i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
680                            unsigned char *raw_pkt,
681                            bool vlan)
682 {
683         static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
684         uint16_t *ether_type;
685         uint8_t len = 2 * sizeof(struct ether_addr);
686         struct ipv4_hdr *ip;
687         struct ipv6_hdr *ip6;
688         static const uint8_t next_proto[] = {
689                 [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP,
690                 [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP,
691                 [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP,
692                 [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP,
693                 [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP,
694                 [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE,
695                 [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP,
696                 [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP,
697                 [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP,
698                 [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE,
699         };
700
701         raw_pkt += 2 * sizeof(struct ether_addr);
702         if (vlan && fdir_input->flow_ext.vlan_tci) {
703                 rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
704                 rte_memcpy(raw_pkt + sizeof(uint16_t),
705                            &fdir_input->flow_ext.vlan_tci,
706                            sizeof(uint16_t));
707                 raw_pkt += sizeof(vlan_frame);
708                 len += sizeof(vlan_frame);
709         }
710         ether_type = (uint16_t *)raw_pkt;
711         raw_pkt += sizeof(uint16_t);
712         len += sizeof(uint16_t);
713
714         switch (fdir_input->flow_type) {
715         case RTE_ETH_FLOW_L2_PAYLOAD:
716                 *ether_type = fdir_input->flow.l2_flow.ether_type;
717                 break;
718         case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
719         case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
720         case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
721         case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
722         case RTE_ETH_FLOW_FRAG_IPV4:
723                 ip = (struct ipv4_hdr *)raw_pkt;
724
725                 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
726                 ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
727                 /* set len to by default */
728                 ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
729                 ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
730                                         fdir_input->flow.ip4_flow.proto :
731                                         next_proto[fdir_input->flow_type];
732                 ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
733                                         fdir_input->flow.ip4_flow.ttl :
734                                         I40E_FDIR_IP_DEFAULT_TTL;
735                 ip->type_of_service = fdir_input->flow.ip4_flow.tos;
736                 /*
737                  * The source and destination fields in the transmitted packet
738                  * need to be presented in a reversed order with respect
739                  * to the expected received packets.
740                  */
741                 ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
742                 ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
743                 len += sizeof(struct ipv4_hdr);
744                 break;
745         case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
746         case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
747         case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
748         case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
749         case RTE_ETH_FLOW_FRAG_IPV6:
750                 ip6 = (struct ipv6_hdr *)raw_pkt;
751
752                 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
753                 ip6->vtc_flow =
754                         rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
755                                          (fdir_input->flow.ipv6_flow.tc <<
756                                           I40E_FDIR_IPv6_TC_OFFSET));
757                 ip6->payload_len =
758                         rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
759                 ip6->proto = fdir_input->flow.ipv6_flow.proto ?
760                                         fdir_input->flow.ipv6_flow.proto :
761                                         next_proto[fdir_input->flow_type];
762                 ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
763                                         fdir_input->flow.ipv6_flow.hop_limits :
764                                         I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
765                 /*
766                  * The source and destination fields in the transmitted packet
767                  * need to be presented in a reversed order with respect
768                  * to the expected received packets.
769                  */
770                 rte_memcpy(&(ip6->src_addr),
771                            &(fdir_input->flow.ipv6_flow.dst_ip),
772                            IPV6_ADDR_LEN);
773                 rte_memcpy(&(ip6->dst_addr),
774                            &(fdir_input->flow.ipv6_flow.src_ip),
775                            IPV6_ADDR_LEN);
776                 len += sizeof(struct ipv6_hdr);
777                 break;
778         default:
779                 PMD_DRV_LOG(ERR, "unknown flow type %u.",
780                             fdir_input->flow_type);
781                 return -1;
782         }
783         return len;
784 }
785
786
787 /*
788  * i40e_fdir_construct_pkt - construct packet based on fields in input
789  * @pf: board private structure
790  * @fdir_input: input set of the flow director entry
791  * @raw_pkt: a packet to be constructed
792  */
793 static int
794 i40e_fdir_construct_pkt(struct i40e_pf *pf,
795                              const struct rte_eth_fdir_input *fdir_input,
796                              unsigned char *raw_pkt)
797 {
798         unsigned char *payload, *ptr;
799         struct udp_hdr *udp;
800         struct tcp_hdr *tcp;
801         struct sctp_hdr *sctp;
802         uint8_t size, dst = 0;
803         uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
804         int len;
805
806         /* fill the ethernet and IP head */
807         len = i40e_fdir_fill_eth_ip_head(fdir_input, raw_pkt,
808                                          !!fdir_input->flow_ext.vlan_tci);
809         if (len < 0)
810                 return -EINVAL;
811
812         /* fill the L4 head */
813         switch (fdir_input->flow_type) {
814         case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
815                 udp = (struct udp_hdr *)(raw_pkt + len);
816                 payload = (unsigned char *)udp + sizeof(struct udp_hdr);
817                 /*
818                  * The source and destination fields in the transmitted packet
819                  * need to be presented in a reversed order with respect
820                  * to the expected received packets.
821                  */
822                 udp->src_port = fdir_input->flow.udp4_flow.dst_port;
823                 udp->dst_port = fdir_input->flow.udp4_flow.src_port;
824                 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
825                 break;
826
827         case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
828                 tcp = (struct tcp_hdr *)(raw_pkt + len);
829                 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
830                 /*
831                  * The source and destination fields in the transmitted packet
832                  * need to be presented in a reversed order with respect
833                  * to the expected received packets.
834                  */
835                 tcp->src_port = fdir_input->flow.tcp4_flow.dst_port;
836                 tcp->dst_port = fdir_input->flow.tcp4_flow.src_port;
837                 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
838                 break;
839
840         case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
841                 sctp = (struct sctp_hdr *)(raw_pkt + len);
842                 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
843                 /*
844                  * The source and destination fields in the transmitted packet
845                  * need to be presented in a reversed order with respect
846                  * to the expected received packets.
847                  */
848                 sctp->src_port = fdir_input->flow.sctp4_flow.dst_port;
849                 sctp->dst_port = fdir_input->flow.sctp4_flow.src_port;
850                 sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
851                 break;
852
853         case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
854         case RTE_ETH_FLOW_FRAG_IPV4:
855                 payload = raw_pkt + len;
856                 set_idx = I40E_FLXPLD_L3_IDX;
857                 break;
858
859         case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
860                 udp = (struct udp_hdr *)(raw_pkt + len);
861                 payload = (unsigned char *)udp + sizeof(struct udp_hdr);
862                 /*
863                  * The source and destination fields in the transmitted packet
864                  * need to be presented in a reversed order with respect
865                  * to the expected received packets.
866                  */
867                 udp->src_port = fdir_input->flow.udp6_flow.dst_port;
868                 udp->dst_port = fdir_input->flow.udp6_flow.src_port;
869                 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
870                 break;
871
872         case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
873                 tcp = (struct tcp_hdr *)(raw_pkt + len);
874                 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
875                 /*
876                  * The source and destination fields in the transmitted packet
877                  * need to be presented in a reversed order with respect
878                  * to the expected received packets.
879                  */
880                 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
881                 tcp->src_port = fdir_input->flow.udp6_flow.dst_port;
882                 tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
883                 break;
884
885         case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
886                 sctp = (struct sctp_hdr *)(raw_pkt + len);
887                 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
888                 /*
889                  * The source and destination fields in the transmitted packet
890                  * need to be presented in a reversed order with respect
891                  * to the expected received packets.
892                  */
893                 sctp->src_port = fdir_input->flow.sctp6_flow.dst_port;
894                 sctp->dst_port = fdir_input->flow.sctp6_flow.src_port;
895                 sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
896                 break;
897
898         case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
899         case RTE_ETH_FLOW_FRAG_IPV6:
900                 payload = raw_pkt + len;
901                 set_idx = I40E_FLXPLD_L3_IDX;
902                 break;
903         case RTE_ETH_FLOW_L2_PAYLOAD:
904                 payload = raw_pkt + len;
905                 /*
906                  * ARP packet is a special case on which the payload
907                  * starts after the whole ARP header
908                  */
909                 if (fdir_input->flow.l2_flow.ether_type ==
910                                 rte_cpu_to_be_16(ETHER_TYPE_ARP))
911                         payload += sizeof(struct arp_hdr);
912                 set_idx = I40E_FLXPLD_L2_IDX;
913                 break;
914         default:
915                 PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type);
916                 return -EINVAL;
917         }
918
919         /* fill the flexbytes to payload */
920         for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
921                 pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i;
922                 size = pf->fdir.flex_set[pit_idx].size;
923                 if (size == 0)
924                         continue;
925                 dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t);
926                 ptr = payload +
927                         pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t);
928                 rte_memcpy(ptr,
929                                  &fdir_input->flow_ext.flexbytes[dst],
930                                  size * sizeof(uint16_t));
931         }
932
933         return 0;
934 }
935
936 /* Construct the tx flags */
937 static inline uint64_t
938 i40e_build_ctob(uint32_t td_cmd,
939                 uint32_t td_offset,
940                 unsigned int size,
941                 uint32_t td_tag)
942 {
943         return rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DATA |
944                         ((uint64_t)td_cmd  << I40E_TXD_QW1_CMD_SHIFT) |
945                         ((uint64_t)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) |
946                         ((uint64_t)size  << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
947                         ((uint64_t)td_tag  << I40E_TXD_QW1_L2TAG1_SHIFT));
948 }
949
950 /*
951  * check the programming status descriptor in rx queue.
952  * done after Programming Flow Director is programmed on
953  * tx queue
954  */
955 static inline int
956 i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq)
957 {
958         volatile union i40e_rx_desc *rxdp;
959         uint64_t qword1;
960         uint32_t rx_status;
961         uint32_t len, id;
962         uint32_t error;
963         int ret = 0;
964
965         rxdp = &rxq->rx_ring[rxq->rx_tail];
966         qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len);
967         rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK)
968                         >> I40E_RXD_QW1_STATUS_SHIFT;
969
970         if (rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) {
971                 len = qword1 >> I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT;
972                 id = (qword1 & I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK) >>
973                             I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT;
974
975                 if (len  == I40E_RX_PROG_STATUS_DESC_LENGTH &&
976                     id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS) {
977                         error = (qword1 &
978                                 I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
979                                 I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
980                         if (error == (0x1 <<
981                                 I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) {
982                                 PMD_DRV_LOG(ERR, "Failed to add FDIR filter"
983                                             " (FD_ID %u): programming status"
984                                             " reported.",
985                                             rxdp->wb.qword0.hi_dword.fd_id);
986                                 ret = -1;
987                         } else if (error == (0x1 <<
988                                 I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
989                                 PMD_DRV_LOG(ERR, "Failed to delete FDIR filter"
990                                             " (FD_ID %u): programming status"
991                                             " reported.",
992                                             rxdp->wb.qword0.hi_dword.fd_id);
993                                 ret = -1;
994                         } else
995                                 PMD_DRV_LOG(ERR, "invalid programming status"
996                                             " reported, error = %u.", error);
997                 } else
998                         PMD_DRV_LOG(ERR, "unknown programming status"
999                                     " reported, len = %d, id = %u.", len, id);
1000                 rxdp->wb.qword1.status_error_len = 0;
1001                 rxq->rx_tail++;
1002                 if (unlikely(rxq->rx_tail == rxq->nb_rx_desc))
1003                         rxq->rx_tail = 0;
1004         }
1005         return ret;
1006 }
1007
1008 static int
1009 i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
1010                          struct i40e_fdir_filter *filter)
1011 {
1012         rte_memcpy(&filter->fdir, input, sizeof(struct rte_eth_fdir_filter));
1013         return 0;
1014 }
1015
1016 /* Check if there exists the flow director filter */
1017 static struct i40e_fdir_filter *
1018 i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
1019                         const struct rte_eth_fdir_input *input)
1020 {
1021         int ret;
1022
1023         ret = rte_hash_lookup(fdir_info->hash_table, (const void *)input);
1024         if (ret < 0)
1025                 return NULL;
1026
1027         return fdir_info->hash_map[ret];
1028 }
1029
1030 /* Add a flow director filter into the SW list */
1031 static int
1032 i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)
1033 {
1034         struct i40e_fdir_info *fdir_info = &pf->fdir;
1035         int ret;
1036
1037         ret = rte_hash_add_key(fdir_info->hash_table,
1038                                &filter->fdir.input);
1039         if (ret < 0) {
1040                 PMD_DRV_LOG(ERR,
1041                             "Failed to insert fdir filter to hash table %d!",
1042                             ret);
1043                 return ret;
1044         }
1045         fdir_info->hash_map[ret] = filter;
1046
1047         TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules);
1048
1049         return 0;
1050 }
1051
1052 /* Delete a flow director filter from the SW list */
1053 int
1054 i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
1055 {
1056         struct i40e_fdir_info *fdir_info = &pf->fdir;
1057         struct i40e_fdir_filter *filter;
1058         int ret;
1059
1060         ret = rte_hash_del_key(fdir_info->hash_table, input);
1061         if (ret < 0) {
1062                 PMD_DRV_LOG(ERR,
1063                             "Failed to delete fdir filter to hash table %d!",
1064                             ret);
1065                 return ret;
1066         }
1067         filter = fdir_info->hash_map[ret];
1068         fdir_info->hash_map[ret] = NULL;
1069
1070         TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules);
1071         rte_free(filter);
1072
1073         return 0;
1074 }
1075
1076 /*
1077  * i40e_add_del_fdir_filter - add or remove a flow director filter.
1078  * @pf: board private structure
1079  * @filter: fdir filter entry
1080  * @add: 0 - delete, 1 - add
1081  */
1082 int
1083 i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
1084                             const struct rte_eth_fdir_filter *filter,
1085                             bool add)
1086 {
1087         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1088         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1089         unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
1090         enum i40e_filter_pctype pctype;
1091         struct i40e_fdir_info *fdir_info = &pf->fdir;
1092         struct i40e_fdir_filter *fdir_filter, *node;
1093         struct i40e_fdir_filter check_filter; /* Check if the filter exists */
1094         int ret = 0;
1095
1096         if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
1097                 PMD_DRV_LOG(ERR, "FDIR is not enabled, please"
1098                         " check the mode in fdir_conf.");
1099                 return -ENOTSUP;
1100         }
1101
1102         pctype = i40e_flowtype_to_pctype(pf->adapter, filter->input.flow_type);
1103         if (pctype == I40E_FILTER_PCTYPE_INVALID) {
1104                 PMD_DRV_LOG(ERR, "invalid flow_type input.");
1105                 return -EINVAL;
1106         }
1107         if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
1108                 PMD_DRV_LOG(ERR, "Invalid queue ID");
1109                 return -EINVAL;
1110         }
1111         if (filter->input.flow_ext.is_vf &&
1112                 filter->input.flow_ext.dst_id >= pf->vf_num) {
1113                 PMD_DRV_LOG(ERR, "Invalid VF ID");
1114                 return -EINVAL;
1115         }
1116
1117         /* Check if there is the filter in SW list */
1118         memset(&check_filter, 0, sizeof(check_filter));
1119         i40e_fdir_filter_convert(filter, &check_filter);
1120         node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input);
1121         if (add && node) {
1122                 PMD_DRV_LOG(ERR,
1123                             "Conflict with existing flow director rules!");
1124                 return -EINVAL;
1125         }
1126
1127         if (!add && !node) {
1128                 PMD_DRV_LOG(ERR,
1129                             "There's no corresponding flow firector filter!");
1130                 return -EINVAL;
1131         }
1132
1133         memset(pkt, 0, I40E_FDIR_PKT_LEN);
1134
1135         ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
1136         if (ret < 0) {
1137                 PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
1138                 return ret;
1139         }
1140
1141         if (hw->mac.type == I40E_MAC_X722) {
1142                 /* get translated pctype value in fd pctype register */
1143                 pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
1144                         hw, I40E_GLQF_FD_PCTYPES((int)pctype));
1145         }
1146         ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
1147         if (ret < 0) {
1148                 PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
1149                             pctype);
1150                 return ret;
1151         }
1152
1153         if (add) {
1154                 fdir_filter = rte_zmalloc("fdir_filter",
1155                                           sizeof(*fdir_filter), 0);
1156                 rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter));
1157                 ret = i40e_sw_fdir_filter_insert(pf, fdir_filter);
1158         } else {
1159                 ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
1160         }
1161
1162         return ret;
1163 }
1164
1165 /*
1166  * i40e_fdir_filter_programming - Program a flow director filter rule.
1167  * Is done by Flow Director Programming Descriptor followed by packet
1168  * structure that contains the filter fields need to match.
1169  * @pf: board private structure
1170  * @pctype: pctype
1171  * @filter: fdir filter entry
1172  * @add: 0 - delete, 1 - add
1173  */
1174 static int
1175 i40e_fdir_filter_programming(struct i40e_pf *pf,
1176                         enum i40e_filter_pctype pctype,
1177                         const struct rte_eth_fdir_filter *filter,
1178                         bool add)
1179 {
1180         struct i40e_tx_queue *txq = pf->fdir.txq;
1181         struct i40e_rx_queue *rxq = pf->fdir.rxq;
1182         const struct rte_eth_fdir_action *fdir_action = &filter->action;
1183         volatile struct i40e_tx_desc *txdp;
1184         volatile struct i40e_filter_program_desc *fdirdp;
1185         uint32_t td_cmd;
1186         uint16_t vsi_id, i;
1187         uint8_t dest;
1188
1189         PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
1190         fdirdp = (volatile struct i40e_filter_program_desc *)
1191                         (&(txq->tx_ring[txq->tx_tail]));
1192
1193         fdirdp->qindex_flex_ptype_vsi =
1194                         rte_cpu_to_le_32((fdir_action->rx_queue <<
1195                                           I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
1196                                           I40E_TXD_FLTR_QW0_QINDEX_MASK);
1197
1198         fdirdp->qindex_flex_ptype_vsi |=
1199                         rte_cpu_to_le_32((fdir_action->flex_off <<
1200                                           I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
1201                                           I40E_TXD_FLTR_QW0_FLEXOFF_MASK);
1202
1203         fdirdp->qindex_flex_ptype_vsi |=
1204                         rte_cpu_to_le_32((pctype <<
1205                                           I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
1206                                           I40E_TXD_FLTR_QW0_PCTYPE_MASK);
1207
1208         if (filter->input.flow_ext.is_vf)
1209                 vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
1210         else
1211                 /* Use LAN VSI Id by default */
1212                 vsi_id = pf->main_vsi->vsi_id;
1213         fdirdp->qindex_flex_ptype_vsi |=
1214                 rte_cpu_to_le_32(((uint32_t)vsi_id <<
1215                                   I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
1216                                   I40E_TXD_FLTR_QW0_DEST_VSI_MASK);
1217
1218         fdirdp->dtype_cmd_cntindex =
1219                         rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);
1220
1221         if (add)
1222                 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1223                                 I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
1224                                 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1225         else
1226                 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1227                                 I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
1228                                 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1229
1230         if (fdir_action->behavior == RTE_ETH_FDIR_REJECT)
1231                 dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
1232         else if (fdir_action->behavior == RTE_ETH_FDIR_ACCEPT)
1233                 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
1234         else if (fdir_action->behavior == RTE_ETH_FDIR_PASSTHRU)
1235                 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
1236         else {
1237                 PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
1238                             " unsupported fdir behavior.");
1239                 return -EINVAL;
1240         }
1241
1242         fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
1243                                 I40E_TXD_FLTR_QW1_DEST_SHIFT) &
1244                                 I40E_TXD_FLTR_QW1_DEST_MASK);
1245
1246         fdirdp->dtype_cmd_cntindex |=
1247                 rte_cpu_to_le_32((fdir_action->report_status<<
1248                                 I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
1249                                 I40E_TXD_FLTR_QW1_FD_STATUS_MASK);
1250
1251         fdirdp->dtype_cmd_cntindex |=
1252                         rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
1253         fdirdp->dtype_cmd_cntindex |=
1254                         rte_cpu_to_le_32(
1255                         ((uint32_t)pf->fdir.match_counter_index <<
1256                         I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
1257                         I40E_TXD_FLTR_QW1_CNTINDEX_MASK);
1258
1259         fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);
1260
1261         PMD_DRV_LOG(INFO, "filling transmit descriptor.");
1262         txdp = &(txq->tx_ring[txq->tx_tail + 1]);
1263         txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr);
1264         td_cmd = I40E_TX_DESC_CMD_EOP |
1265                  I40E_TX_DESC_CMD_RS  |
1266                  I40E_TX_DESC_CMD_DUMMY;
1267
1268         txdp->cmd_type_offset_bsz =
1269                 i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);
1270
1271         txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */
1272         if (txq->tx_tail >= txq->nb_tx_desc)
1273                 txq->tx_tail = 0;
1274         /* Update the tx tail register */
1275         rte_wmb();
1276         I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
1277         for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
1278                 if ((txdp->cmd_type_offset_bsz &
1279                                 rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
1280                                 rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
1281                         break;
1282                 rte_delay_us(1);
1283         }
1284         if (i >= I40E_FDIR_MAX_WAIT_US) {
1285                 PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
1286                             " time out to get DD on tx queue.");
1287                 return -ETIMEDOUT;
1288         }
1289         /* totally delay 10 ms to check programming status*/
1290         for (; i < I40E_FDIR_MAX_WAIT_US; i++) {
1291                 if (i40e_check_fdir_programming_status(rxq) >= 0)
1292                         return 0;
1293                 rte_delay_us(1);
1294         }
1295         PMD_DRV_LOG(ERR,
1296                 "Failed to program FDIR filter: programming status reported.");
1297         return -ETIMEDOUT;
1298 }
1299
1300 /*
1301  * i40e_fdir_flush - clear all filters of Flow Director table
1302  * @pf: board private structure
1303  */
1304 int
1305 i40e_fdir_flush(struct rte_eth_dev *dev)
1306 {
1307         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1308         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1309         uint32_t reg;
1310         uint16_t guarant_cnt, best_cnt;
1311         uint16_t i;
1312
1313         I40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
1314         I40E_WRITE_FLUSH(hw);
1315
1316         for (i = 0; i < I40E_FDIR_FLUSH_RETRY; i++) {
1317                 rte_delay_ms(I40E_FDIR_FLUSH_INTERVAL_MS);
1318                 reg = I40E_READ_REG(hw, I40E_PFQF_CTL_1);
1319                 if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))
1320                         break;
1321         }
1322         if (i >= I40E_FDIR_FLUSH_RETRY) {
1323                 PMD_DRV_LOG(ERR, "FD table did not flush, may need more time.");
1324                 return -ETIMEDOUT;
1325         }
1326         guarant_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
1327                                 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
1328                                 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
1329         best_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
1330                                 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
1331                                 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
1332         if (guarant_cnt != 0 || best_cnt != 0) {
1333                 PMD_DRV_LOG(ERR, "Failed to flush FD table.");
1334                 return -ENOSYS;
1335         } else
1336                 PMD_DRV_LOG(INFO, "FD table Flush success.");
1337         return 0;
1338 }
1339
1340 static inline void
1341 i40e_fdir_info_get_flex_set(struct i40e_pf *pf,
1342                         struct rte_eth_flex_payload_cfg *flex_set,
1343                         uint16_t *num)
1344 {
1345         struct i40e_fdir_flex_pit *flex_pit;
1346         struct rte_eth_flex_payload_cfg *ptr = flex_set;
1347         uint16_t src, dst, size, j, k;
1348         uint8_t i, layer_idx;
1349
1350         for (layer_idx = I40E_FLXPLD_L2_IDX;
1351              layer_idx <= I40E_FLXPLD_L4_IDX;
1352              layer_idx++) {
1353                 if (layer_idx == I40E_FLXPLD_L2_IDX)
1354                         ptr->type = RTE_ETH_L2_PAYLOAD;
1355                 else if (layer_idx == I40E_FLXPLD_L3_IDX)
1356                         ptr->type = RTE_ETH_L3_PAYLOAD;
1357                 else if (layer_idx == I40E_FLXPLD_L4_IDX)
1358                         ptr->type = RTE_ETH_L4_PAYLOAD;
1359
1360                 for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
1361                         flex_pit = &pf->fdir.flex_set[layer_idx *
1362                                 I40E_MAX_FLXPLD_FIED + i];
1363                         if (flex_pit->size == 0)
1364                                 continue;
1365                         src = flex_pit->src_offset * sizeof(uint16_t);
1366                         dst = flex_pit->dst_offset * sizeof(uint16_t);
1367                         size = flex_pit->size * sizeof(uint16_t);
1368                         for (j = src, k = dst; j < src + size; j++, k++)
1369                                 ptr->src_offset[k] = j;
1370                 }
1371                 (*num)++;
1372                 ptr++;
1373         }
1374 }
1375
1376 static inline void
1377 i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
1378                         struct rte_eth_fdir_flex_mask *flex_mask,
1379                         uint16_t *num)
1380 {
1381         struct i40e_fdir_flex_mask *mask;
1382         struct rte_eth_fdir_flex_mask *ptr = flex_mask;
1383         uint16_t flow_type;
1384         uint8_t i, j;
1385         uint16_t off_bytes, mask_tmp;
1386
1387         for (i = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
1388              i <= I40E_FILTER_PCTYPE_L2_PAYLOAD;
1389              i++) {
1390                 mask =  &pf->fdir.flex_mask[i];
1391                 flow_type = i40e_pctype_to_flowtype(pf->adapter,
1392                                                     (enum i40e_filter_pctype)i);
1393                 if (flow_type == RTE_ETH_FLOW_UNKNOWN)
1394                         continue;
1395
1396                 for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) {
1397                         if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) {
1398                                 ptr->mask[j * sizeof(uint16_t)] = UINT8_MAX;
1399                                 ptr->mask[j * sizeof(uint16_t) + 1] = UINT8_MAX;
1400                         } else {
1401                                 ptr->mask[j * sizeof(uint16_t)] = 0x0;
1402                                 ptr->mask[j * sizeof(uint16_t) + 1] = 0x0;
1403                         }
1404                 }
1405                 for (j = 0; j < I40E_FDIR_BITMASK_NUM_WORD; j++) {
1406                         off_bytes = mask->bitmask[j].offset * sizeof(uint16_t);
1407                         mask_tmp = ~mask->bitmask[j].mask;
1408                         ptr->mask[off_bytes] &= I40E_HI_BYTE(mask_tmp);
1409                         ptr->mask[off_bytes + 1] &= I40E_LO_BYTE(mask_tmp);
1410                 }
1411                 ptr->flow_type = flow_type;
1412                 ptr++;
1413                 (*num)++;
1414         }
1415 }
1416
1417 /*
1418  * i40e_fdir_info_get - get information of Flow Director
1419  * @pf: ethernet device to get info from
1420  * @fdir: a pointer to a structure of type *rte_eth_fdir_info* to be filled with
1421  *    the flow director information.
1422  */
1423 static void
1424 i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir)
1425 {
1426         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1427         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1428         uint16_t num_flex_set = 0;
1429         uint16_t num_flex_mask = 0;
1430
1431         if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT)
1432                 fdir->mode = RTE_FDIR_MODE_PERFECT;
1433         else
1434                 fdir->mode = RTE_FDIR_MODE_NONE;
1435
1436         fdir->guarant_spc =
1437                 (uint32_t)hw->func_caps.fd_filters_guaranteed;
1438         fdir->best_spc =
1439                 (uint32_t)hw->func_caps.fd_filters_best_effort;
1440         fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN;
1441         fdir->flow_types_mask[0] = I40E_FDIR_FLOWS;
1442         fdir->flex_payload_unit = sizeof(uint16_t);
1443         fdir->flex_bitmask_unit = sizeof(uint16_t);
1444         fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED;
1445         fdir->flex_payload_limit = I40E_MAX_FLX_SOURCE_OFF;
1446         fdir->max_flex_bitmask_num = I40E_FDIR_BITMASK_NUM_WORD;
1447
1448         i40e_fdir_info_get_flex_set(pf,
1449                                 fdir->flex_conf.flex_set,
1450                                 &num_flex_set);
1451         i40e_fdir_info_get_flex_mask(pf,
1452                                 fdir->flex_conf.flex_mask,
1453                                 &num_flex_mask);
1454
1455         fdir->flex_conf.nb_payloads = num_flex_set;
1456         fdir->flex_conf.nb_flexmasks = num_flex_mask;
1457 }
1458
1459 /*
1460  * i40e_fdir_stat_get - get statistics of Flow Director
1461  * @pf: ethernet device to get info from
1462  * @stat: a pointer to a structure of type *rte_eth_fdir_stats* to be filled with
1463  *    the flow director statistics.
1464  */
1465 static void
1466 i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat)
1467 {
1468         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1469         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1470         uint32_t fdstat;
1471
1472         fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
1473         stat->guarant_cnt =
1474                 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
1475                             I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
1476         stat->best_cnt =
1477                 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
1478                             I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
1479 }
1480
1481 static int
1482 i40e_fdir_filter_set(struct rte_eth_dev *dev,
1483                      struct rte_eth_fdir_filter_info *info)
1484 {
1485         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1486         int ret = 0;
1487
1488         if (!info) {
1489                 PMD_DRV_LOG(ERR, "Invalid pointer");
1490                 return -EFAULT;
1491         }
1492
1493         switch (info->info_type) {
1494         case RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT:
1495                 ret = i40e_fdir_filter_inset_select(pf,
1496                                 &(info->info.input_set_conf));
1497                 break;
1498         default:
1499                 PMD_DRV_LOG(ERR, "FD filter info type (%d) not supported",
1500                             info->info_type);
1501                 return -EINVAL;
1502         }
1503
1504         return ret;
1505 }
1506
1507 /*
1508  * i40e_fdir_ctrl_func - deal with all operations on flow director.
1509  * @pf: board private structure
1510  * @filter_op:operation will be taken.
1511  * @arg: a pointer to specific structure corresponding to the filter_op
1512  */
1513 int
1514 i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
1515                        enum rte_filter_op filter_op,
1516                        void *arg)
1517 {
1518         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1519         int ret = 0;
1520
1521         if ((pf->flags & I40E_FLAG_FDIR) == 0)
1522                 return -ENOTSUP;
1523
1524         if (filter_op == RTE_ETH_FILTER_NOP)
1525                 return 0;
1526
1527         if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
1528                 return -EINVAL;
1529
1530         switch (filter_op) {
1531         case RTE_ETH_FILTER_ADD:
1532                 ret = i40e_add_del_fdir_filter(dev,
1533                         (struct rte_eth_fdir_filter *)arg,
1534                         TRUE);
1535                 break;
1536         case RTE_ETH_FILTER_DELETE:
1537                 ret = i40e_add_del_fdir_filter(dev,
1538                         (struct rte_eth_fdir_filter *)arg,
1539                         FALSE);
1540                 break;
1541         case RTE_ETH_FILTER_FLUSH:
1542                 ret = i40e_fdir_flush(dev);
1543                 break;
1544         case RTE_ETH_FILTER_INFO:
1545                 i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
1546                 break;
1547         case RTE_ETH_FILTER_SET:
1548                 ret = i40e_fdir_filter_set(dev,
1549                         (struct rte_eth_fdir_filter_info *)arg);
1550                 break;
1551         case RTE_ETH_FILTER_STATS:
1552                 i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg);
1553                 break;
1554         default:
1555                 PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op);
1556                 ret = -EINVAL;
1557                 break;
1558         }
1559         return ret;
1560 }
1561
1562 /* Restore flow director filter */
1563 void
1564 i40e_fdir_filter_restore(struct i40e_pf *pf)
1565 {
1566         struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi);
1567         struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list;
1568         struct i40e_fdir_filter *f;
1569         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1570         uint32_t fdstat;
1571         uint32_t guarant_cnt;  /**< Number of filters in guaranteed spaces. */
1572         uint32_t best_cnt;     /**< Number of filters in best effort spaces. */
1573
1574         TAILQ_FOREACH(f, fdir_list, rules)
1575                 i40e_add_del_fdir_filter(dev, &f->fdir, TRUE);
1576
1577         fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
1578         guarant_cnt =
1579                 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
1580                            I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
1581         best_cnt =
1582                 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
1583                            I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
1584
1585         PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d,  Best count: %d",
1586                     guarant_cnt, best_cnt);
1587 }