[2/2] net/i40e: fix incorrect FDIR flex pit

Message ID 20201104082959.63800-3-chenxux.di@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Qi Zhang
Headers
Series net/i40e: fix incorrect FDIR flex configuration |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK
ci/travis-robot success Travis build: passed

Commit Message

Chenxu Di Nov. 4, 2020, 8:29 a.m. UTC
  The register of FDIR flex pit should not be set during flow validate.
It should be set when flow create.

Fixes: 6ced3dd72f5f ("net/i40e: support flexible payload parsing for FDIR")
Cc: stable@dpdk.org

Signed-off-by: Chenxu Di <chenxux.di@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h |  21 ++++---
 drivers/net/i40e/i40e_fdir.c   | 100 +++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_flow.c   |  98 +++-----------------------------
 3 files changed, 119 insertions(+), 100 deletions(-)
  

Comments

Guo, Jia Nov. 4, 2020, 9:18 a.m. UTC | #1
Hi, chenxu

> -----Original Message-----
> From: Chenxu Di <chenxux.di@intel.com>
> Sent: Wednesday, November 4, 2020 4:30 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Guo, Jia <jia.guo@intel.com>; Wang,
> Haiyue <haiyue.wang@intel.com>; Di, ChenxuX <chenxux.di@intel.com>;
> stable@dpdk.org
> Subject: [PATCH 2/2] net/i40e: fix incorrect FDIR flex pit
> 
> The register of FDIR flex pit should not be set during flow validate.
> It should be set when flow create.
> 
> Fixes: 6ced3dd72f5f ("net/i40e: support flexible payload parsing for FDIR")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Chenxu Di <chenxux.di@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.h |  21 ++++---
>  drivers/net/i40e/i40e_fdir.c   | 100
> +++++++++++++++++++++++++++++++++
>  drivers/net/i40e/i40e_flow.c   |  98 +++-----------------------------
>  3 files changed, 119 insertions(+), 100 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.h
> b/drivers/net/i40e/i40e_ethdev.h index 6be929f65..e00133c88 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -599,12 +599,22 @@ enum i40e_fdir_ip_type {
>  	I40E_FDIR_IPTYPE_IPV6,
>  };
> 
> +/*
> + * Structure to store flex pit for flow diretor.
> + */
> +struct i40e_fdir_flex_pit {
> +	uint8_t src_offset; /* offset in words from the beginning of payload
> */
> +	uint8_t size;       /* size in words */
> +	uint8_t dst_offset; /* offset in words of flexible payload */ };
> +
>  /* A structure used to contain extend input of flow */  struct
> i40e_fdir_flow_ext {
>  	uint16_t vlan_tci;
>  	uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
>  	/* It is filled by the flexible payload to match. */
>  	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
> +	uint8_t raw_id;
>  	uint8_t is_vf;   /* 1 for VF, 0 for port dev */
>  	uint16_t dst_id; /* VF ID, available when is_vf is 1*/
>  	bool inner_ip;   /* If there is inner ip */
> @@ -613,6 +623,8 @@ struct i40e_fdir_flow_ext {
>  	bool customized_pctype; /* If customized pctype is used */
>  	bool pkt_template; /* If raw packet template is used */
>  	bool is_udp; /* ipv4|ipv6 udp flow */
> +	enum i40e_flxpld_layer_idx layer_idx;
> +	struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_LAYER *
> +I40E_MAX_FLXPLD_FIED];
>  };
> 
>  /* A structure used to define the input for a flow director filter entry */ @@
> -664,15 +676,6 @@ struct i40e_fdir_filter_conf {
>  	struct i40e_fdir_action action;  /* Action taken when match */  };
> 
> -/*
> - * Structure to store flex pit for flow diretor.
> - */
> -struct i40e_fdir_flex_pit {
> -	uint8_t src_offset;    /* offset in words from the beginning of payload
> */
> -	uint8_t size;          /* size in words */
> -	uint8_t dst_offset;    /* offset in words of flexible payload */
> -};
> -
>  struct i40e_fdir_flex_mask {
>  	uint8_t word_mask;  /**< Bit i enables word i of flexible payload */
>  	uint8_t nb_bitmask;
> diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index
> e31464eb7..e64cb2fd0 100644
> --- a/drivers/net/i40e/i40e_fdir.c
> +++ b/drivers/net/i40e/i40e_fdir.c
> @@ -1765,6 +1765,81 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
>  	return ret;
>  }
> 
> +static int
> +i40e_flow_store_flex_pit(struct i40e_pf *pf,
> +			 struct i40e_fdir_flex_pit *flex_pit,
> +			 enum i40e_flxpld_layer_idx layer_idx,
> +			 uint8_t raw_id)
> +{
> +	uint8_t field_idx;
> +
> +	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
> +	/* Check if the configuration is conflicted */
> +	if (pf->fdir.flex_pit_flag[layer_idx] &&
> +	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
> +	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
> +	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
> +		return -1;
> +
> +	/* Check if the configuration exists. */
> +	if (pf->fdir.flex_pit_flag[layer_idx] &&
> +	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
> +	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
> +	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
> +		return 1;
> +
> +	pf->fdir.flex_set[field_idx].src_offset =
> +		flex_pit->src_offset;
> +	pf->fdir.flex_set[field_idx].size =
> +		flex_pit->size;
> +	pf->fdir.flex_set[field_idx].dst_offset =
> +		flex_pit->dst_offset;
> +
> +	return 0;
> +}
> +
> +static void
> +i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
> +			    enum i40e_flxpld_layer_idx layer_idx,
> +			    uint8_t raw_id)
> +{
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	uint32_t flx_pit, flx_ort;
> +	uint8_t field_idx;
> +	uint16_t min_next_off = 0;  /* in words */
> +	uint8_t i;
> +
> +	if (raw_id) {
> +		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
> +			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
> +			  (layer_idx * I40E_MAX_FLXPLD_FIED);
> +		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx),
> flx_ort);
> +	}
> +
> +	/* Set flex pit */
> +	for (i = 0; i < raw_id; i++) {
> +		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
> +		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
> +				     pf->fdir.flex_set[field_idx].size,
> +				     pf->fdir.flex_set[field_idx].dst_offset);
> +
> +		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx),
> flx_pit);
> +		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
> +			pf->fdir.flex_set[field_idx].size;
> +	}
> +
> +	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
> +		/* set the non-used register obeying register's constrain */
> +		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
> +		flx_pit = MK_FLX_PIT(min_next_off,
> NONUSE_FLX_PIT_FSIZE,
> +				     NONUSE_FLX_PIT_DEST_OFF);
> +		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx),
> flx_pit);
> +		min_next_off++;
> +	}
> +
> +	pf->fdir.flex_pit_flag[layer_idx] = 1; }
> +
>  static int
>  i40e_flow_store_flex_mask(struct i40e_pf *pf,
>  			  enum i40e_filter_pctype pctype,
> @@ -1889,13 +1964,17 @@ i40e_flow_add_del_fdir_filter(struct
> rte_eth_dev *dev,  {
>  	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
>  	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> +	enum i40e_flxpld_layer_idx layer_idx = I40E_FLXPLD_L2_IDX;
>  	unsigned char *pkt = NULL;
>  	enum i40e_filter_pctype pctype;
>  	struct i40e_fdir_info *fdir_info = &pf->fdir;
>  	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
>  	struct i40e_fdir_filter *node;
>  	struct i40e_fdir_filter check_filter; /* Check if the filter exists */
> +	struct i40e_fdir_flex_pit flex_pit;
> +	bool cfg_flex_pit = true;
>  	bool wait_status = true;
> +	uint8_t field_idx;
>  	int ret = 0;
>  	int i;
> 
> @@ -1931,6 +2010,27 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev
> *dev,
> 
>  	if (add) {
>  		if (!filter->input.flow_ext.customized_pctype) {
> +			for (i = 0; i < filter->input.flow_ext.raw_id; i++) {
> +				layer_idx = filter->input.flow_ext.layer_idx;
> +				field_idx = layer_idx *
> I40E_MAX_FLXPLD_FIED + i;
> +				flex_pit = filter-
> >input.flow_ext.flex_pit[field_idx];
> +
> +				/* Store flex pit to SW */
> +				ret = i40e_flow_store_flex_pit(pf, &flex_pit,
> +							       layer_idx, i);
> +				if (ret < 0) {
> +					PMD_DRV_LOG(ERR, "Conflict with
> the"
> +						    " first flexible rule.");
> +					return -EINVAL;
> +				} else if (ret > 0) {
> +					cfg_flex_pit = false;
> +				}
> +			}
> +
> +			if (cfg_flex_pit)
> +				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
> +						filter-
> >input.flow_ext.raw_id);
> +
>  			/* Store flex mask to SW */
>  			for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++)
>  				flex_mask[i] =
> diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
> index 4f916494e..098ae13ab 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -2240,81 +2240,6 @@ i40e_flow_check_raw_item(const struct
> rte_flow_item *item,
>  	return 0;
>  }
> 
> -static int
> -i40e_flow_store_flex_pit(struct i40e_pf *pf,
> -			 struct i40e_fdir_flex_pit *flex_pit,
> -			 enum i40e_flxpld_layer_idx layer_idx,
> -			 uint8_t raw_id)
> -{
> -	uint8_t field_idx;
> -
> -	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
> -	/* Check if the configuration is conflicted */
> -	if (pf->fdir.flex_pit_flag[layer_idx] &&
> -	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
> -	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
> -	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
> -		return -1;
> -
> -	/* Check if the configuration exists. */
> -	if (pf->fdir.flex_pit_flag[layer_idx] &&
> -	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
> -	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
> -	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
> -		return 1;
> -
> -	pf->fdir.flex_set[field_idx].src_offset =
> -		flex_pit->src_offset;
> -	pf->fdir.flex_set[field_idx].size =
> -		flex_pit->size;
> -	pf->fdir.flex_set[field_idx].dst_offset =
> -		flex_pit->dst_offset;
> -
> -	return 0;
> -}
> -
> -static void
> -i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
> -			    enum i40e_flxpld_layer_idx layer_idx,
> -			    uint8_t raw_id)
> -{
> -	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> -	uint32_t flx_pit, flx_ort;
> -	uint8_t field_idx;
> -	uint16_t min_next_off = 0;  /* in words */
> -	uint8_t i;
> -
> -	if (raw_id) {
> -		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
> -			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
> -			  (layer_idx * I40E_MAX_FLXPLD_FIED);
> -		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx),
> flx_ort);
> -	}
> -
> -	/* Set flex pit */
> -	for (i = 0; i < raw_id; i++) {
> -		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
> -		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
> -				     pf->fdir.flex_set[field_idx].size,
> -				     pf->fdir.flex_set[field_idx].dst_offset);
> -
> -		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx),
> flx_pit);
> -		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
> -			pf->fdir.flex_set[field_idx].size;
> -	}
> -
> -	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
> -		/* set the non-used register obeying register's constrain */
> -		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
> -		flx_pit = MK_FLX_PIT(min_next_off,
> NONUSE_FLX_PIT_FSIZE,
> -				     NONUSE_FLX_PIT_DEST_OFF);
> -		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx),
> flx_pit);
> -		min_next_off++;
> -	}
> -
> -	pf->fdir.flex_pit_flag[layer_idx] = 1;
> -}
> -
>  static int
>  i40e_flow_set_fdir_inset(struct i40e_pf *pf,
>  			 enum i40e_filter_pctype pctype,
> @@ -2534,10 +2459,10 @@ i40e_flow_parse_fdir_pattern(struct
> rte_eth_dev *dev,
>  	struct i40e_fdir_flex_pit flex_pit;
>  	uint8_t next_dst_off = 0;
>  	uint16_t flex_size;
> -	bool cfg_flex_pit = true;
>  	uint16_t ether_type;
>  	uint32_t vtc_flow_cpu;
>  	bool outer_ip = true;
> +	uint8_t field_idx;
>  	int ret;
> 
>  	memset(off_arr, 0, sizeof(off_arr));
> @@ -3089,6 +3014,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev
> *dev,
> 
>  			flex_size = 0;
>  			memset(&flex_pit, 0, sizeof(struct
> i40e_fdir_flex_pit));
> +			field_idx = layer_idx * I40E_MAX_FLXPLD_FIED +
> raw_id;
>  			flex_pit.size =
>  				raw_spec->length / sizeof(uint16_t);
>  			flex_pit.dst_offset =
> @@ -3115,18 +3041,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev
> *dev,
>  				return -rte_errno;
>  			}
> 
> -			/* Store flex pit to SW */
> -			ret = i40e_flow_store_flex_pit(pf, &flex_pit,
> -						       layer_idx, raw_id);
> -			if (ret < 0) {
> -				rte_flow_error_set(error, EINVAL,
> -				   RTE_FLOW_ERROR_TYPE_ITEM,
> -				   item,
> -				   "Conflict with the first flexible rule.");
> -				return -rte_errno;
> -			} else if (ret > 0)
> -				cfg_flex_pit = false;
> -
>  			for (i = 0; i < raw_spec->length; i++) {
>  				j = i + next_dst_off;
>  				filter->input.flow_ext.flexbytes[j] = @@ -
> 3137,6 +3051,11 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> 
>  			next_dst_off += raw_spec->length;
>  			raw_id++;
> +
> +			memcpy(&filter->input.flow_ext.flex_pit[field_idx],
> +			       &flex_pit, sizeof(struct i40e_fdir_flex_pit));
> +			filter->input.flow_ext.layer_idx = layer_idx;
> +			filter->input.flow_ext.raw_id = raw_id;
>  			break;
>  		case RTE_FLOW_ITEM_TYPE_VF:
>  			vf_spec = item->spec;
> @@ -3222,9 +3141,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev
> *dev,
>  					   "Invalid pattern mask.");
>  			return -rte_errno;
>  		}
> -
> -		if (cfg_flex_pit)
> -			i40e_flow_set_fdir_flex_pit(pf, layer_idx, raw_id);

Seems that multiple switch case set the layer_idx not only the place you delete, please double check if these case all need to handle.

>  	}
> 
>  	filter->input.pctype = pctype;
> --
> 2.17.1
  

Patch

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 6be929f65..e00133c88 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -599,12 +599,22 @@  enum i40e_fdir_ip_type {
 	I40E_FDIR_IPTYPE_IPV6,
 };
 
+/*
+ * Structure to store flex pit for flow diretor.
+ */
+struct i40e_fdir_flex_pit {
+	uint8_t src_offset; /* offset in words from the beginning of payload */
+	uint8_t size;       /* size in words */
+	uint8_t dst_offset; /* offset in words of flexible payload */
+};
+
 /* A structure used to contain extend input of flow */
 struct i40e_fdir_flow_ext {
 	uint16_t vlan_tci;
 	uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
 	/* It is filled by the flexible payload to match. */
 	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
+	uint8_t raw_id;
 	uint8_t is_vf;   /* 1 for VF, 0 for port dev */
 	uint16_t dst_id; /* VF ID, available when is_vf is 1*/
 	bool inner_ip;   /* If there is inner ip */
@@ -613,6 +623,8 @@  struct i40e_fdir_flow_ext {
 	bool customized_pctype; /* If customized pctype is used */
 	bool pkt_template; /* If raw packet template is used */
 	bool is_udp; /* ipv4|ipv6 udp flow */
+	enum i40e_flxpld_layer_idx layer_idx;
+	struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_LAYER * I40E_MAX_FLXPLD_FIED];
 };
 
 /* A structure used to define the input for a flow director filter entry */
@@ -664,15 +676,6 @@  struct i40e_fdir_filter_conf {
 	struct i40e_fdir_action action;  /* Action taken when match */
 };
 
-/*
- * Structure to store flex pit for flow diretor.
- */
-struct i40e_fdir_flex_pit {
-	uint8_t src_offset;    /* offset in words from the beginning of payload */
-	uint8_t size;          /* size in words */
-	uint8_t dst_offset;    /* offset in words of flexible payload */
-};
-
 struct i40e_fdir_flex_mask {
 	uint8_t word_mask;  /**< Bit i enables word i of flexible payload */
 	uint8_t nb_bitmask;
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index e31464eb7..e64cb2fd0 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1765,6 +1765,81 @@  i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+i40e_flow_store_flex_pit(struct i40e_pf *pf,
+			 struct i40e_fdir_flex_pit *flex_pit,
+			 enum i40e_flxpld_layer_idx layer_idx,
+			 uint8_t raw_id)
+{
+	uint8_t field_idx;
+
+	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
+	/* Check if the configuration is conflicted */
+	if (pf->fdir.flex_pit_flag[layer_idx] &&
+	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
+	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
+	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
+		return -1;
+
+	/* Check if the configuration exists. */
+	if (pf->fdir.flex_pit_flag[layer_idx] &&
+	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
+	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
+	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
+		return 1;
+
+	pf->fdir.flex_set[field_idx].src_offset =
+		flex_pit->src_offset;
+	pf->fdir.flex_set[field_idx].size =
+		flex_pit->size;
+	pf->fdir.flex_set[field_idx].dst_offset =
+		flex_pit->dst_offset;
+
+	return 0;
+}
+
+static void
+i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
+			    enum i40e_flxpld_layer_idx layer_idx,
+			    uint8_t raw_id)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint32_t flx_pit, flx_ort;
+	uint8_t field_idx;
+	uint16_t min_next_off = 0;  /* in words */
+	uint8_t i;
+
+	if (raw_id) {
+		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
+			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
+			  (layer_idx * I40E_MAX_FLXPLD_FIED);
+		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
+	}
+
+	/* Set flex pit */
+	for (i = 0; i < raw_id; i++) {
+		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
+				     pf->fdir.flex_set[field_idx].size,
+				     pf->fdir.flex_set[field_idx].dst_offset);
+
+		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
+		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
+			pf->fdir.flex_set[field_idx].size;
+	}
+
+	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
+		/* set the non-used register obeying register's constrain */
+		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+		flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
+				     NONUSE_FLX_PIT_DEST_OFF);
+		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
+		min_next_off++;
+	}
+
+	pf->fdir.flex_pit_flag[layer_idx] = 1;
+}
+
 static int
 i40e_flow_store_flex_mask(struct i40e_pf *pf,
 			  enum i40e_filter_pctype pctype,
@@ -1889,13 +1964,17 @@  i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 {
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	enum i40e_flxpld_layer_idx layer_idx = I40E_FLXPLD_L2_IDX;
 	unsigned char *pkt = NULL;
 	enum i40e_filter_pctype pctype;
 	struct i40e_fdir_info *fdir_info = &pf->fdir;
 	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
 	struct i40e_fdir_filter *node;
 	struct i40e_fdir_filter check_filter; /* Check if the filter exists */
+	struct i40e_fdir_flex_pit flex_pit;
+	bool cfg_flex_pit = true;
 	bool wait_status = true;
+	uint8_t field_idx;
 	int ret = 0;
 	int i;
 
@@ -1931,6 +2010,27 @@  i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 
 	if (add) {
 		if (!filter->input.flow_ext.customized_pctype) {
+			for (i = 0; i < filter->input.flow_ext.raw_id; i++) {
+				layer_idx = filter->input.flow_ext.layer_idx;
+				field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+				flex_pit = filter->input.flow_ext.flex_pit[field_idx];
+
+				/* Store flex pit to SW */
+				ret = i40e_flow_store_flex_pit(pf, &flex_pit,
+							       layer_idx, i);
+				if (ret < 0) {
+					PMD_DRV_LOG(ERR, "Conflict with the"
+						    " first flexible rule.");
+					return -EINVAL;
+				} else if (ret > 0) {
+					cfg_flex_pit = false;
+				}
+			}
+
+			if (cfg_flex_pit)
+				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
+						filter->input.flow_ext.raw_id);
+
 			/* Store flex mask to SW */
 			for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++)
 				flex_mask[i] =
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 4f916494e..098ae13ab 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2240,81 +2240,6 @@  i40e_flow_check_raw_item(const struct rte_flow_item *item,
 	return 0;
 }
 
-static int
-i40e_flow_store_flex_pit(struct i40e_pf *pf,
-			 struct i40e_fdir_flex_pit *flex_pit,
-			 enum i40e_flxpld_layer_idx layer_idx,
-			 uint8_t raw_id)
-{
-	uint8_t field_idx;
-
-	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
-	/* Check if the configuration is conflicted */
-	if (pf->fdir.flex_pit_flag[layer_idx] &&
-	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
-	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
-	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
-		return -1;
-
-	/* Check if the configuration exists. */
-	if (pf->fdir.flex_pit_flag[layer_idx] &&
-	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
-	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
-	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
-		return 1;
-
-	pf->fdir.flex_set[field_idx].src_offset =
-		flex_pit->src_offset;
-	pf->fdir.flex_set[field_idx].size =
-		flex_pit->size;
-	pf->fdir.flex_set[field_idx].dst_offset =
-		flex_pit->dst_offset;
-
-	return 0;
-}
-
-static void
-i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
-			    enum i40e_flxpld_layer_idx layer_idx,
-			    uint8_t raw_id)
-{
-	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
-	uint32_t flx_pit, flx_ort;
-	uint8_t field_idx;
-	uint16_t min_next_off = 0;  /* in words */
-	uint8_t i;
-
-	if (raw_id) {
-		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
-			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
-			  (layer_idx * I40E_MAX_FLXPLD_FIED);
-		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
-	}
-
-	/* Set flex pit */
-	for (i = 0; i < raw_id; i++) {
-		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
-		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
-				     pf->fdir.flex_set[field_idx].size,
-				     pf->fdir.flex_set[field_idx].dst_offset);
-
-		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
-		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
-			pf->fdir.flex_set[field_idx].size;
-	}
-
-	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
-		/* set the non-used register obeying register's constrain */
-		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
-		flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
-				     NONUSE_FLX_PIT_DEST_OFF);
-		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
-		min_next_off++;
-	}
-
-	pf->fdir.flex_pit_flag[layer_idx] = 1;
-}
-
 static int
 i40e_flow_set_fdir_inset(struct i40e_pf *pf,
 			 enum i40e_filter_pctype pctype,
@@ -2534,10 +2459,10 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 	struct i40e_fdir_flex_pit flex_pit;
 	uint8_t next_dst_off = 0;
 	uint16_t flex_size;
-	bool cfg_flex_pit = true;
 	uint16_t ether_type;
 	uint32_t vtc_flow_cpu;
 	bool outer_ip = true;
+	uint8_t field_idx;
 	int ret;
 
 	memset(off_arr, 0, sizeof(off_arr));
@@ -3089,6 +3014,7 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
 			flex_size = 0;
 			memset(&flex_pit, 0, sizeof(struct i40e_fdir_flex_pit));
+			field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
 			flex_pit.size =
 				raw_spec->length / sizeof(uint16_t);
 			flex_pit.dst_offset =
@@ -3115,18 +3041,6 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 				return -rte_errno;
 			}
 
-			/* Store flex pit to SW */
-			ret = i40e_flow_store_flex_pit(pf, &flex_pit,
-						       layer_idx, raw_id);
-			if (ret < 0) {
-				rte_flow_error_set(error, EINVAL,
-				   RTE_FLOW_ERROR_TYPE_ITEM,
-				   item,
-				   "Conflict with the first flexible rule.");
-				return -rte_errno;
-			} else if (ret > 0)
-				cfg_flex_pit = false;
-
 			for (i = 0; i < raw_spec->length; i++) {
 				j = i + next_dst_off;
 				filter->input.flow_ext.flexbytes[j] =
@@ -3137,6 +3051,11 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
 			next_dst_off += raw_spec->length;
 			raw_id++;
+
+			memcpy(&filter->input.flow_ext.flex_pit[field_idx],
+			       &flex_pit, sizeof(struct i40e_fdir_flex_pit));
+			filter->input.flow_ext.layer_idx = layer_idx;
+			filter->input.flow_ext.raw_id = raw_id;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VF:
 			vf_spec = item->spec;
@@ -3222,9 +3141,6 @@  i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 					   "Invalid pattern mask.");
 			return -rte_errno;
 		}
-
-		if (cfg_flex_pit)
-			i40e_flow_set_fdir_flex_pit(pf, layer_idx, raw_id);
 	}
 
 	filter->input.pctype = pctype;