FDIR setup helpers were implicitly reading and updating global state.
This made behavior depend on cached values and tightly coupled call
ordering to hidden side effects.

Update `ixgbe_fdir_configure()`, `ixgbe_fdir_set_input_mask()`, and
`ixgbe_fdir_filter_program()` to take explicit inputs (`fdir_conf`,
`mask`, `mode`) and make the internal mask helpers use those arguments
instead of reading globals.

Also remove implicit cached-state behavior from
`ixgbe_fdir_set_flexbytes_offset()`: it no longer short-circuits on
cached offset and no longer updates cached offset internally.

Adjust all current callers to match the new semantics:
- pass local config/mask/mode values into setup APIs,
- write global mode/mask/flex cached state in caller code only after
  successful programming.

Signed-off-by: Anatoly Burakov <[email protected]>
---
 drivers/net/intel/ixgbe/ixgbe_ethdev.c |   4 +-
 drivers/net/intel/ixgbe/ixgbe_ethdev.h |  13 +++-
 drivers/net/intel/ixgbe/ixgbe_fdir.c   | 104 +++++++++++--------------
 drivers/net/intel/ixgbe/ixgbe_flow.c   |  32 +++++---
 4 files changed, 79 insertions(+), 74 deletions(-)

diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.c 
b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
index 62edada379..d4122107ac 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
@@ -2724,7 +2724,9 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        ixgbe_configure_dcb(dev);
 
        if (fdir_conf->mode != RTE_FDIR_MODE_NONE) {
-               err = ixgbe_fdir_configure(adapter);
+               struct ixgbe_hw_fdir_info *info =
+                       IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
+               err = ixgbe_fdir_configure(adapter, fdir_conf, &info->mask);
                if (err)
                        goto error;
        }
diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.h 
b/drivers/net/intel/ixgbe/ixgbe_ethdev.h
index 65e71e7689..165bd93379 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.h
@@ -705,13 +705,18 @@ void ixgbe_filterlist_flush(struct rte_eth_dev *dev);
 /*
  * Flow director function prototypes
  */
-int ixgbe_fdir_configure(struct ixgbe_adapter *adapter);
-int ixgbe_fdir_set_input_mask(struct ixgbe_adapter *adapter);
+int ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
+                        const struct rte_eth_fdir_conf *fdir_conf,
+                        const struct ixgbe_hw_fdir_mask *fdir_mask);
+int ixgbe_fdir_set_input_mask(struct ixgbe_adapter *adapter,
+                             const struct ixgbe_hw_fdir_mask *mask,
+                             enum rte_fdir_mode mode);
 int ixgbe_fdir_set_flexbytes_offset(struct ixgbe_adapter *adapter,
                                    uint16_t offset);
 int ixgbe_fdir_filter_program(struct ixgbe_adapter *adapter,
-                             struct ixgbe_fdir_rule *rule,
-                             bool del, bool update);
+               struct rte_eth_fdir_conf *fdir_conf,
+               struct ixgbe_fdir_rule *rule,
+               bool del, bool update);
 void ixgbe_fdir_info_get(struct rte_eth_dev *dev,
                         struct rte_eth_fdir_info *fdir_info);
 void ixgbe_fdir_stats_get(struct rte_eth_dev *dev,
diff --git a/drivers/net/intel/ixgbe/ixgbe_fdir.c 
b/drivers/net/intel/ixgbe/ixgbe_fdir.c
index e7a380da31..c2828df1f9 100644
--- a/drivers/net/intel/ixgbe/ixgbe_fdir.c
+++ b/drivers/net/intel/ixgbe/ixgbe_fdir.c
@@ -79,8 +79,12 @@
 #define IXGBE_FDIRIP6M_INNER_MAC_SHIFT 4
 
 static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash);
-static int fdir_set_input_mask_82599(struct ixgbe_adapter *adapter);
-static int fdir_set_input_mask_x550(struct ixgbe_adapter *adapter);
+static int fdir_set_input_mask_82599(struct ixgbe_adapter *adapter,
+               const struct ixgbe_hw_fdir_mask *mask,
+               enum rte_fdir_mode mode);
+static int fdir_set_input_mask_x550(struct ixgbe_adapter *adapter,
+               const struct ixgbe_hw_fdir_mask *mask,
+               enum rte_fdir_mode mode);
 static int ixgbe_set_fdir_flex_conf(struct ixgbe_adapter *adapter,
                const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl);
 static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl);
@@ -248,13 +252,11 @@ reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t 
lo_dword)
  * but makes use of the rte_fdir_masks structure to see which bits to set.
  */
 static int
-fdir_set_input_mask_82599(struct ixgbe_adapter *adapter)
+fdir_set_input_mask_82599(struct ixgbe_adapter *adapter,
+               const struct ixgbe_hw_fdir_mask *mask,
+               enum rte_fdir_mode mode)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
-       struct rte_eth_fdir_conf *fdir_conf =
-               IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
-       struct ixgbe_hw_fdir_info *info =
-                       IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
        /*
         * mask VM pool and DIPv6 since there are currently not supported
         * mask FLEX byte, it will be set in flex_conf
@@ -266,34 +268,34 @@ fdir_set_input_mask_82599(struct ixgbe_adapter *adapter)
 
        PMD_INIT_FUNC_TRACE();
 
-       if (!info->mask.l4_proto_match)
+       if (!mask->l4_proto_match)
                /* set L4P to ignore L4 protocol for IP traffic */
                fdirm |= IXGBE_FDIRM_L4P;
 
-       if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0x0FFF))
+       if (mask->vlan_tci_mask == rte_cpu_to_be_16(0x0FFF))
                /* mask VLAN Priority */
                fdirm |= IXGBE_FDIRM_VLANP;
-       else if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0xE000))
+       else if (mask->vlan_tci_mask == rte_cpu_to_be_16(0xE000))
                /* mask VLAN ID */
                fdirm |= IXGBE_FDIRM_VLANID;
-       else if (info->mask.vlan_tci_mask == 0)
+       else if (mask->vlan_tci_mask == 0)
                /* mask VLAN ID and Priority */
                fdirm |= IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP;
-       else if (info->mask.vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) {
+       else if (mask->vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) {
                PMD_INIT_LOG(ERR, "invalid vlan_tci_mask");
                return -EINVAL;
        }
 
        /* flex byte mask */
-       if (info->mask.flex_bytes_mask == 0)
+       if (mask->flex_bytes_mask == 0)
                fdirm |= IXGBE_FDIRM_FLEX;
 
        IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
 
        /* store the TCP/UDP port masks, bit reversed from port layout */
        fdirtcpm = reverse_fdir_bitmasks(
-                       rte_be_to_cpu_16(info->mask.dst_port_mask),
-                       rte_be_to_cpu_16(info->mask.src_port_mask));
+                       rte_be_to_cpu_16(mask->dst_port_mask),
+                       rte_be_to_cpu_16(mask->src_port_mask));
 
        /* write all the same so that UDP, TCP and SCTP use the same mask
         * (little-endian)
@@ -311,16 +313,16 @@ fdir_set_input_mask_82599(struct ixgbe_adapter *adapter)
         * can not use IXGBE_WRITE_REG.
         */
        reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRSIP4M);
-       *reg = ~(info->mask.src_ipv4_mask);
+       *reg = ~(mask->src_ipv4_mask);
        reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRDIP4M);
-       *reg = ~(info->mask.dst_ipv4_mask);
+       *reg = ~(mask->dst_ipv4_mask);
 
-       if (fdir_conf->mode == RTE_FDIR_MODE_SIGNATURE) {
+       if (mode == RTE_FDIR_MODE_SIGNATURE) {
                /*
                 * Store source and destination IPv6 masks (bit reversed)
                 */
-               fdiripv6m = (info->mask.dst_ipv6_mask << 16) |
-                           info->mask.src_ipv6_mask;
+               fdiripv6m = (mask->dst_ipv6_mask << 16) |
+                               mask->src_ipv6_mask;
 
                IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, ~fdiripv6m);
        }
@@ -333,20 +335,17 @@ fdir_set_input_mask_82599(struct ixgbe_adapter *adapter)
  * but makes use of the rte_fdir_masks structure to see which bits to set.
  */
 static int
-fdir_set_input_mask_x550(struct ixgbe_adapter *adapter)
+fdir_set_input_mask_x550(struct ixgbe_adapter *adapter,
+               const struct ixgbe_hw_fdir_mask *mask,
+               enum rte_fdir_mode mode)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
-       struct rte_eth_fdir_conf *fdir_conf =
-               IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
-       struct ixgbe_hw_fdir_info *info =
-                       IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
        /* mask VM pool and DIPv6 since there are currently not supported
         * mask FLEX byte, it will be set in flex_conf
         */
        uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6 |
                         IXGBE_FDIRM_FLEX;
        uint32_t fdiripv6m;
-       enum rte_fdir_mode mode = fdir_conf->mode;
        uint16_t mac_mask;
 
        PMD_INIT_FUNC_TRACE();
@@ -358,16 +357,16 @@ fdir_set_input_mask_x550(struct ixgbe_adapter *adapter)
        /* some bits must be set for mac vlan or tunnel mode */
        fdirm |= IXGBE_FDIRM_L4P | IXGBE_FDIRM_L3P;
 
-       if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0x0FFF))
+       if (mask->vlan_tci_mask == rte_cpu_to_be_16(0x0FFF))
                /* mask VLAN Priority */
                fdirm |= IXGBE_FDIRM_VLANP;
-       else if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0xE000))
+       else if (mask->vlan_tci_mask == rte_cpu_to_be_16(0xE000))
                /* mask VLAN ID */
                fdirm |= IXGBE_FDIRM_VLANID;
-       else if (info->mask.vlan_tci_mask == 0)
+       else if (mask->vlan_tci_mask == 0)
                /* mask VLAN ID and Priority */
                fdirm |= IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP;
-       else if (info->mask.vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) {
+       else if (mask->vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) {
                PMD_INIT_LOG(ERR, "invalid vlan_tci_mask");
                return -EINVAL;
        }
@@ -382,13 +381,13 @@ fdir_set_input_mask_x550(struct ixgbe_adapter *adapter)
 
        if (mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
                fdiripv6m |= IXGBE_FDIRIP6M_INNER_MAC;
-               mac_mask = info->mask.mac_addr_byte_mask &
+               mac_mask = mask->mac_addr_byte_mask &
                        (IXGBE_FDIRIP6M_INNER_MAC >>
                        IXGBE_FDIRIP6M_INNER_MAC_SHIFT);
                fdiripv6m &= ~((mac_mask << IXGBE_FDIRIP6M_INNER_MAC_SHIFT) &
                                IXGBE_FDIRIP6M_INNER_MAC);
 
-               switch (info->mask.tunnel_type_mask) {
+               switch (mask->tunnel_type_mask) {
                case 0:
                        /* Mask tunnel type */
                        fdiripv6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE;
@@ -400,7 +399,7 @@ fdir_set_input_mask_x550(struct ixgbe_adapter *adapter)
                        return -EINVAL;
                }
 
-               switch (rte_be_to_cpu_32(info->mask.tunnel_id_mask)) {
+               switch (rte_be_to_cpu_32(mask->tunnel_id_mask)) {
                case 0x0:
                        /* Mask vxlan id */
                        fdiripv6m |= IXGBE_FDIRIP6M_TNI_VNI;
@@ -427,36 +426,28 @@ fdir_set_input_mask_x550(struct ixgbe_adapter *adapter)
 }
 
 int
-ixgbe_fdir_set_input_mask(struct ixgbe_adapter *adapter)
+ixgbe_fdir_set_input_mask(struct ixgbe_adapter *adapter,
+               const struct ixgbe_hw_fdir_mask *mask,
+               enum rte_fdir_mode mode)
 {
-       struct rte_eth_fdir_conf *fdir_conf =
-               IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
-       enum rte_fdir_mode mode = fdir_conf->mode;
-
        if (mode >= RTE_FDIR_MODE_SIGNATURE &&
            mode <= RTE_FDIR_MODE_PERFECT)
-               return fdir_set_input_mask_82599(adapter);
+               return fdir_set_input_mask_82599(adapter, mask, mode);
        else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
                 mode <= RTE_FDIR_MODE_PERFECT_TUNNEL)
-               return fdir_set_input_mask_x550(adapter);
+               return fdir_set_input_mask_x550(adapter, mask, mode);
 
        PMD_DRV_LOG(ERR, "Not supported fdir mode - %d!", mode);
        return -ENOTSUP;
 }
 
 int
-ixgbe_fdir_set_flexbytes_offset(struct ixgbe_adapter *adapter,
-                               uint16_t offset)
+ixgbe_fdir_set_flexbytes_offset(struct ixgbe_adapter *adapter, uint16_t offset)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
-       struct ixgbe_hw_fdir_info *fdir_info =
-               IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
        uint32_t fdirctrl;
        int i;
 
-       if (fdir_info->flex_bytes_offset == offset)
-               return 0;
-
        /**
         * 82599 adapters flow director init flow cannot be restarted,
         * Workaround 82599 silicon errata by performing the following steps
@@ -493,8 +484,6 @@ ixgbe_fdir_set_flexbytes_offset(struct ixgbe_adapter 
*adapter,
                return -ETIMEDOUT;
        }
 
-       fdir_info->flex_bytes_offset = offset;
-
        return 0;
 }
 
@@ -566,11 +555,11 @@ ixgbe_set_fdir_flex_conf(struct ixgbe_adapter *adapter,
 }
 
 int
-ixgbe_fdir_configure(struct ixgbe_adapter *adapter)
+ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
+               const struct rte_eth_fdir_conf *fdir_conf,
+               const struct ixgbe_hw_fdir_mask *fdir_mask)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
-       struct rte_eth_fdir_conf *fdir_conf =
-               IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
        int err;
        uint32_t fdirctrl, pbsize;
        int i;
@@ -617,7 +606,7 @@ ixgbe_fdir_configure(struct ixgbe_adapter *adapter)
        for (i = 1; i < 8; i++)
                IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
 
-       err = ixgbe_fdir_set_input_mask(adapter);
+       err = ixgbe_fdir_set_input_mask(adapter, fdir_mask, mode);
        if (err < 0) {
                PMD_INIT_LOG(ERR, " Error on setting FD mask");
                return err;
@@ -1046,13 +1035,12 @@ ixgbe_remove_fdir_filter(struct ixgbe_hw_fdir_info 
*fdir_info,
 
 int
 ixgbe_fdir_filter_program(struct ixgbe_adapter *adapter,
-                         struct ixgbe_fdir_rule *rule,
-                         bool del,
-                         bool update)
+               struct rte_eth_fdir_conf *fdir_conf,
+               struct ixgbe_fdir_rule *rule,
+               bool del,
+               bool update)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
-       struct rte_eth_fdir_conf *fdir_conf =
-               IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
        uint32_t fdircmd_flags;
        uint32_t fdirhash;
        uint8_t queue;
diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c 
b/drivers/net/intel/ixgbe/ixgbe_flow.c
index eae81462f6..cda2e95d22 100644
--- a/drivers/net/intel/ixgbe/ixgbe_flow.c
+++ b/drivers/net/intel/ixgbe/ixgbe_flow.c
@@ -2838,7 +2838,6 @@ ixgbe_parse_fdir_filter(struct rte_eth_dev *dev,
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_adapter *adapter = 
IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
-       fdir_conf->drop_queue = IXGBE_FDIR_DROP_QUEUE;
 
        if (hw->mac.type != ixgbe_mac_82599EB &&
                hw->mac.type != ixgbe_mac_X540 &&
@@ -2863,12 +2862,15 @@ ixgbe_parse_fdir_filter(struct rte_eth_dev *dev,
 step_next:
 
        if (fdir_conf->mode == RTE_FDIR_MODE_NONE) {
-               fdir_conf->mode = rule->mode;
-               ret = ixgbe_fdir_configure(adapter);
+               struct rte_eth_fdir_conf fc = *fdir_conf;
+
+               fc.mode = rule->mode;
+               ret = ixgbe_fdir_configure(adapter, &fc, &rule->mask);
                if (ret) {
                        fdir_conf->mode = RTE_FDIR_MODE_NONE;
                        return ret;
                }
+               fdir_conf->mode = rule->mode;
        } else if (fdir_conf->mode != rule->mode) {
                return -ENOTSUP;
        }
@@ -3167,19 +3169,25 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
                /* A mask cannot be deleted. */
                if (fdir_rule.b_mask) {
                        if (!fdir_info->mask_added) {
-                               /* It's the first time the mask is set. */
-                               *&fdir_info->mask = *&fdir_rule.mask;
+                               bool flex_byte_offset_changed =
+                                       fdir_info->flex_bytes_offset !=
+                                       fdir_rule.flex_bytes_offset;
 
-                               if (fdir_rule.mask.flex_bytes_mask) {
+                               if (fdir_rule.mask.flex_bytes_mask &&
+                                   flex_byte_offset_changed) {
                                        ret = 
ixgbe_fdir_set_flexbytes_offset(adapter,
                                                fdir_rule.flex_bytes_offset);
                                        if (ret)
                                                goto out;
                                }
-                               ret = ixgbe_fdir_set_input_mask(adapter);
+                               ret = ixgbe_fdir_set_input_mask(adapter,
+                                               &fdir_rule.mask, 
fdir_rule.mode);
                                if (ret)
                                        goto out;
 
+                               fdir_info->mask = fdir_rule.mask;
+                               fdir_info->flex_bytes_offset =
+                                       fdir_rule.flex_bytes_offset;
                                fdir_info->mask_added = TRUE;
                                first_mask = TRUE;
                        } else {
@@ -3201,8 +3209,10 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
                }
 
                if (fdir_rule.b_spec) {
-                       ret = ixgbe_fdir_filter_program(adapter, &fdir_rule,
-                                       FALSE, FALSE);
+                       struct rte_eth_fdir_conf *fdir_conf = 
IXGBE_DEV_FDIR_CONF(dev);
+
+                       ret = ixgbe_fdir_filter_program(adapter, fdir_conf,
+                                       &fdir_rule, FALSE, FALSE);
                        if (!ret) {
                                fdir_rule_ptr = rte_zmalloc("ixgbe_fdir_filter",
                                        sizeof(struct ixgbe_fdir_rule_ele), 0);
@@ -3374,6 +3384,7 @@ ixgbe_flow_destroy(struct rte_eth_dev *dev,
        struct ixgbe_filter_ele_base *flow_mem_base;
        struct ixgbe_hw_fdir_info *fdir_info =
                IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
+       struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
        struct ixgbe_rss_conf_ele *rss_filter_ptr;
 
        /* Validate ownership before touching HW/SW state. */
@@ -3433,9 +3444,8 @@ ixgbe_flow_destroy(struct rte_eth_dev *dev,
                rte_memcpy(&fdir_rule,
                        &fdir_rule_ptr->filter_info,
                        sizeof(struct ixgbe_fdir_rule));
-               ret = ixgbe_fdir_filter_program(adapter, &fdir_rule, TRUE, 
FALSE);
+               ret = ixgbe_fdir_filter_program(adapter, fdir_conf, &fdir_rule, 
TRUE, FALSE);
                if (!ret) {
-                       struct rte_eth_fdir_conf *fdir_conf = 
IXGBE_DEV_FDIR_CONF(dev);
                        rte_free(fdir_rule_ptr);
                        if (fdir_info->n_flows > 0 && --(fdir_info->n_flows) == 
0) {
                                fdir_info->mask_added = false;
-- 
2.47.3

Reply via email to