net/i40e: fix flow director config after flow validate
[dpdk.git] / drivers / net / i40e / i40e_fdir.c
index c572d00..da089ba 100644 (file)
@@ -1588,6 +1588,83 @@ i40e_flow_set_fdir_flex_msk(struct i40e_pf *pf,
        pf->fdir.flex_mask_flag[pctype] = 1;
 }
 
+static int
+i40e_flow_set_fdir_inset(struct i40e_pf *pf,
+                        enum i40e_filter_pctype pctype,
+                        uint64_t input_set)
+{
+       uint32_t mask_reg[I40E_INSET_MASK_NUM_REG] = {0};
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       uint64_t inset_reg = 0;
+       int i, num;
+
+       /* Check if the input set is valid */
+       if (i40e_validate_input_set(pctype, RTE_ETH_FILTER_FDIR,
+                                   input_set) != 0) {
+               PMD_DRV_LOG(ERR, "Invalid input set");
+               return -EINVAL;
+       }
+
+       /* Check if the configuration is conflicted */
+       if (pf->fdir.inset_flag[pctype] &&
+           memcmp(&pf->fdir.input_set[pctype], &input_set, sizeof(uint64_t)))
+               return -1;
+
+       if (pf->fdir.inset_flag[pctype] &&
+           !memcmp(&pf->fdir.input_set[pctype], &input_set, sizeof(uint64_t)))
+               return 0;
+
+       num = i40e_generate_inset_mask_reg(hw, input_set, mask_reg,
+                                                I40E_INSET_MASK_NUM_REG);
+       if (num < 0)
+               return -EINVAL;
+
+       if (pf->support_multi_driver) {
+               for (i = 0; i < num; i++)
+                       if (i40e_read_rx_ctl(hw,
+                                       I40E_GLQF_FD_MSK(i, pctype)) !=
+                                       mask_reg[i]) {
+                               PMD_DRV_LOG(ERR, "Input set setting is not"
+                                               " supported with"
+                                               " `support-multi-driver`"
+                                               " enabled!");
+                               return -EPERM;
+                       }
+               for (i = num; i < I40E_INSET_MASK_NUM_REG; i++)
+                       if (i40e_read_rx_ctl(hw,
+                                       I40E_GLQF_FD_MSK(i, pctype)) != 0) {
+                               PMD_DRV_LOG(ERR, "Input set setting is not"
+                                               " supported with"
+                                               " `support-multi-driver`"
+                                               " enabled!");
+                               return -EPERM;
+                       }
+
+       } else {
+               for (i = 0; i < num; i++)
+                       i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype),
+                               mask_reg[i]);
+               /*clear unused mask registers of the pctype */
+               for (i = num; i < I40E_INSET_MASK_NUM_REG; i++)
+                       i40e_check_write_reg(hw,
+                                       I40E_GLQF_FD_MSK(i, pctype), 0);
+       }
+
+       inset_reg |= i40e_translate_input_set_reg(hw->mac.type, input_set);
+
+       i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
+                            (uint32_t)(inset_reg & UINT32_MAX));
+       i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1),
+                            (uint32_t)((inset_reg >>
+                                        I40E_32_BIT_WIDTH) & UINT32_MAX));
+
+       I40E_WRITE_FLUSH(hw);
+
+       pf->fdir.input_set[pctype] = input_set;
+       pf->fdir.inset_flag[pctype] = 1;
+       return 0;
+}
+
 static inline unsigned char *
 i40e_find_available_buffer(struct rte_eth_dev *dev)
 {
@@ -1686,6 +1763,17 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 
        if (add) {
                if (filter->input.flow_ext.is_flex_flow) {
+                       ret = i40e_flow_set_fdir_inset(pf, pctype,
+                                       filter->input.flow_ext.input_set);
+                       if (ret == -1) {
+                               PMD_DRV_LOG(ERR, "Conflict with the"
+                                           " first rule's input set.");
+                               return -EINVAL;
+                       } else if (ret == -EINVAL) {
+                               PMD_DRV_LOG(ERR, "Invalid pattern mask.");
+                               return -EINVAL;
+                       }
+
                        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;