4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include <sys/queue.h>
42 #include <rte_ether.h>
43 #include <rte_ethdev.h>
45 #include <rte_memzone.h>
46 #include <rte_malloc.h>
48 #include "i40e_logs.h"
49 #include "i40e/i40e_type.h"
50 #include "i40e_ethdev.h"
51 #include "i40e_rxtx.h"
53 #define I40E_FDIR_MZ_NAME "FDIR_MEMZONE"
54 #define I40E_FDIR_PKT_LEN 512
57 /* Wait count and interval for fdir filter flush */
58 #define I40E_FDIR_FLUSH_RETRY 50
59 #define I40E_FDIR_FLUSH_INTERVAL_MS 5
61 #define I40E_COUNTER_PF 2
62 /* Statistic counter index for one pf */
63 #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF)
64 #define I40E_FLX_OFFSET_IN_FIELD_VECTOR 50
66 static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq);
67 static int i40e_fdir_flush(struct rte_eth_dev *dev);
70 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
72 struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi);
73 struct i40e_hmc_obj_rxq rx_ctx;
74 int err = I40E_SUCCESS;
76 memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
77 /* Init the RX queue in hardware */
78 rx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT;
80 rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT;
81 rx_ctx.qlen = rxq->nb_rx_desc;
82 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
85 rx_ctx.dtype = i40e_header_split_none;
86 rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
87 rx_ctx.rxmax = ETHER_MAX_LEN;
88 rx_ctx.tphrdesc_ena = 1;
89 rx_ctx.tphwdesc_ena = 1;
90 rx_ctx.tphdata_ena = 1;
91 rx_ctx.tphhead_ena = 1;
92 rx_ctx.lrxqthresh = 2;
98 err = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx);
99 if (err != I40E_SUCCESS) {
100 PMD_DRV_LOG(ERR, "Failed to clear FDIR RX queue context.");
103 err = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx);
104 if (err != I40E_SUCCESS) {
105 PMD_DRV_LOG(ERR, "Failed to set FDIR RX queue context.");
108 rxq->qrx_tail = hw->hw_addr +
109 I40E_QRX_TAIL(rxq->vsi->base_queue);
112 /* Init the RX tail regieter. */
113 I40E_PCI_REG_WRITE(rxq->qrx_tail, 0);
114 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
120 * i40e_fdir_setup - reserve and initialize the Flow Director resources
121 * @pf: board private structure
124 i40e_fdir_setup(struct i40e_pf *pf)
126 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
127 struct i40e_vsi *vsi;
128 int err = I40E_SUCCESS;
129 char z_name[RTE_MEMZONE_NAMESIZE];
130 const struct rte_memzone *mz = NULL;
131 struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
133 PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u,"
134 " num_filters_best_effort = %u.",
135 hw->func_caps.fd_filters_guaranteed,
136 hw->func_caps.fd_filters_best_effort);
138 vsi = pf->fdir.fdir_vsi;
140 PMD_DRV_LOG(ERR, "FDIR vsi pointer needs "
141 "to be null before creation.");
142 return I40E_ERR_BAD_PTR;
144 /* make new FDIR VSI */
145 vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);
147 PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI.");
148 return I40E_ERR_NO_AVAILABLE_VSI;
150 pf->fdir.fdir_vsi = vsi;
152 /*Fdir tx queue setup*/
153 err = i40e_fdir_setup_tx_resources(pf);
155 PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources.");
159 /*Fdir rx queue setup*/
160 err = i40e_fdir_setup_rx_resources(pf);
162 PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources.");
166 err = i40e_tx_queue_init(pf->fdir.txq);
168 PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization.");
172 /* need switch on before dev start*/
173 err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE);
175 PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on.");
179 /* Init the rx queue in hardware */
180 err = i40e_fdir_rx_queue_init(pf->fdir.rxq);
182 PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization.");
186 /* switch on rx queue */
187 err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE);
189 PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on.");
193 /* reserve memory for the fdir programming packet */
194 snprintf(z_name, sizeof(z_name), "%s_%s_%d",
195 eth_dev->driver->pci_drv.name,
197 eth_dev->data->port_id);
198 mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
200 PMD_DRV_LOG(ERR, "Cannot init memzone for "
201 "flow director program packet.");
202 err = I40E_ERR_NO_MEMORY;
205 pf->fdir.prg_pkt = mz->addr;
206 #ifdef RTE_LIBRTE_XEN_DOM0
207 pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);
209 pf->fdir.dma_addr = (uint64_t)mz->phys_addr;
211 pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
212 PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
217 i40e_dev_rx_queue_release(pf->fdir.rxq);
220 i40e_dev_tx_queue_release(pf->fdir.txq);
223 i40e_vsi_release(vsi);
224 pf->fdir.fdir_vsi = NULL;
229 * i40e_fdir_teardown - release the Flow Director resources
230 * @pf: board private structure
233 i40e_fdir_teardown(struct i40e_pf *pf)
235 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
236 struct i40e_vsi *vsi;
238 vsi = pf->fdir.fdir_vsi;
239 i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
240 i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
241 i40e_dev_rx_queue_release(pf->fdir.rxq);
243 i40e_dev_tx_queue_release(pf->fdir.txq);
245 i40e_vsi_release(vsi);
246 pf->fdir.fdir_vsi = NULL;
249 /* check whether the flow director table in empty */
251 i40e_fdir_empty(struct i40e_hw *hw)
253 uint32_t guarant_cnt, best_cnt;
255 guarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
256 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
257 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
258 best_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
259 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
260 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
261 if (best_cnt + guarant_cnt > 0)
268 * Initialize the configuration about bytes stream extracted as flexible payload
272 i40e_init_flx_pld(struct i40e_pf *pf)
274 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
279 * Define the bytes stream extracted as flexible payload in
280 * field vector. By default, select 8 words from the beginning
281 * of payload as flexible payload.
283 for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) {
284 index = i * I40E_MAX_FLXPLD_FIED;
285 pf->fdir.flex_set[index].src_offset = 0;
286 pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM;
287 pf->fdir.flex_set[index].dst_offset = 0;
288 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900);
290 I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/
292 I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/
295 /* initialize the masks */
296 for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
297 pctype <= I40E_FILTER_PCTYPE_FRAG_IPV6; pctype++) {
298 pf->fdir.flex_mask[pctype].word_mask = 0;
299 I40E_WRITE_REG(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0);
300 for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) {
301 pf->fdir.flex_mask[pctype].bitmask[i].offset = 0;
302 pf->fdir.flex_mask[pctype].bitmask[i].mask = 0;
303 I40E_WRITE_REG(hw, I40E_PRTQF_FD_MSK(pctype, i), 0);
309 * Configure flow director related setting
312 i40e_fdir_configure(struct rte_eth_dev *dev)
314 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
315 struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
320 * configuration need to be done before
321 * flow director filters are added
322 * If filters exist, flush them.
324 if (i40e_fdir_empty(hw) < 0) {
325 ret = i40e_fdir_flush(dev);
327 PMD_DRV_LOG(ERR, "failed to flush fdir table.");
332 val = I40E_READ_REG(hw, I40E_PFQF_CTL_0);
333 if ((pf->flags & I40E_FLAG_FDIR) &&
334 dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) {
335 /* enable FDIR filter */
336 val |= I40E_PFQF_CTL_0_FD_ENA_MASK;
337 I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);
339 i40e_init_flx_pld(pf); /* set flex config to default value */
341 /* disable FDIR filter */
342 val &= ~I40E_PFQF_CTL_0_FD_ENA_MASK;
343 I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val);
344 pf->flags &= ~I40E_FLAG_FDIR;
351 * i40e_fdir_flush - clear all filters of Flow Director table
352 * @pf: board private structure
355 i40e_fdir_flush(struct rte_eth_dev *dev)
357 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
358 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
360 uint16_t guarant_cnt, best_cnt;
363 I40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
364 I40E_WRITE_FLUSH(hw);
366 for (i = 0; i < I40E_FDIR_FLUSH_RETRY; i++) {
367 rte_delay_ms(I40E_FDIR_FLUSH_INTERVAL_MS);
368 reg = I40E_READ_REG(hw, I40E_PFQF_CTL_1);
369 if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))
372 if (i >= I40E_FDIR_FLUSH_RETRY) {
373 PMD_DRV_LOG(ERR, "FD table did not flush, may need more time.");
376 guarant_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
377 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
378 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
379 best_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
380 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
381 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
382 if (guarant_cnt != 0 || best_cnt != 0) {
383 PMD_DRV_LOG(ERR, "Failed to flush FD table.");
386 PMD_DRV_LOG(INFO, "FD table Flush success.");