Enabling Flow Director reduces RXPBSIZE to reserve SRAM for the
filter table. Clearing the last FDIR rule set the mode back to
none without restoring that buffer, so the next flow create ran
configure again and subtracted the same amount a second time.

Keep the FDIR mode after rules are removed, and subtract RXPBSIZE
only once until the next hardware reset.

Fixes: 301abd26b118 ("net/ixgbe: reset flow state on clear paths")
Cc: [email protected]
Signed-off-by: Zhang Tengfei <[email protected]>
---
 drivers/net/intel/ixgbe/ixgbe_ethdev.c |  7 +++++--
 drivers/net/intel/ixgbe/ixgbe_ethdev.h |  1 +
 drivers/net/intel/ixgbe/ixgbe_fdir.c   | 21 ++++++++++++++-------
 drivers/net/intel/ixgbe/ixgbe_flow.c   |  1 -
 4 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/net/intel/ixgbe/ixgbe_ethdev.c 
b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
index cbb7b4831c..ce5b4c51f5 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.c
@@ -1372,6 +1372,7 @@ static int ixgbe_fdir_filter_init(struct rte_eth_dev 
*eth_dev)
        }
        fdir_info->n_flows = 0;
        fdir_info->mask_added = FALSE;
+       fdir_info->rx_pb_reduced = false;
 
        /* drop queue is always fixed */
        IXGBE_DEV_FDIR_CONF(eth_dev)->drop_queue = IXGBE_FDIR_DROP_QUEUE;
@@ -2541,6 +2542,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
                IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
        struct ixgbe_macsec_setting *macsec_setting =
                IXGBE_DEV_PRIVATE_TO_MACSEC_SETTING(dev->data->dev_private);
+       struct ixgbe_hw_fdir_info *info =
+               IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
 
        /*
         * This function calls into the base driver, which in turn will use
@@ -2628,9 +2631,9 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        /* Configure DCB hw */
        ixgbe_configure_dcb(dev);
 
+       /* reset_hw restored RXPBSIZE; FDIR must subtract again */
+       info->rx_pb_reduced = false;
        if (fdir_conf->mode != RTE_FDIR_MODE_NONE) {
-               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 ba826b6d8d..495a6ddd22 100644
--- a/drivers/net/intel/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/intel/ixgbe/ixgbe_ethdev.h
@@ -200,6 +200,7 @@ struct ixgbe_hw_fdir_info {
        struct rte_hash *hash_handle; /* cuckoo hash handler */
        uint32_t n_flows;
        bool mask_added; /* If already got mask from consistent filter */
+       bool rx_pb_reduced; /* RXPBSIZE already reduced for FDIR */
 };
 
 struct ixgbe_rte_flow_rss_conf {
diff --git a/drivers/net/intel/ixgbe/ixgbe_fdir.c 
b/drivers/net/intel/ixgbe/ixgbe_fdir.c
index b32dc54287..ca96ea85d7 100644
--- a/drivers/net/intel/ixgbe/ixgbe_fdir.c
+++ b/drivers/net/intel/ixgbe/ixgbe_fdir.c
@@ -560,8 +560,10 @@ ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
                const struct ixgbe_hw_fdir_mask *fdir_mask)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(adapter);
+       struct ixgbe_hw_fdir_info *info =
+                       IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
        int err;
-       uint32_t fdirctrl, pbsize;
+       uint32_t fdirctrl;
        int i;
        enum rte_fdir_mode mode = fdir_conf->mode;
 
@@ -591,11 +593,18 @@ ixgbe_fdir_configure(struct ixgbe_adapter *adapter,
        /*
         * Before enabling Flow Director, the Rx Packet Buffer size
         * must be reduced.  The new value is the current size minus
-        * flow director memory usage size.
+        * flow director memory usage size.  Do this only once; a later
+        * re-configure (e.g. after a failed filter program) must not
+        * subtract again.
         */
-       pbsize = (1 << (PBALLOC_SIZE_SHIFT + (fdirctrl & 
FDIRCTRL_PBALLOC_MASK)));
-       IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
-           (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+       if (!info->rx_pb_reduced) {
+               uint32_t pbsize = (1 << (PBALLOC_SIZE_SHIFT +
+                                       (fdirctrl & FDIRCTRL_PBALLOC_MASK)));
+
+               IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
+                   (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+               info->rx_pb_reduced = true;
+       }
 
        /*
         * The defaults in the HW for RX PB 1-7 are not zero and so should be
@@ -1359,7 +1368,6 @@ ixgbe_fdir_filter_restore(struct rte_eth_dev *dev)
 int
 ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)
 {
-       struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
        struct ixgbe_hw_fdir_info *fdir_info =
                IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private);
        struct ixgbe_fdir_filter *fdir_filter;
@@ -1384,7 +1392,6 @@ ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev)
        fdir_info->mask = (struct ixgbe_hw_fdir_mask){0};
        fdir_info->flex_bytes_offset = 0;
        fdir_info->mask_added = FALSE;
-       fdir_conf->mode = RTE_FDIR_MODE_NONE;
 
        if (had_flows)
                ret = ixgbe_fdir_flush(dev);
diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c 
b/drivers/net/intel/ixgbe/ixgbe_flow.c
index 6868893d46..1e79ef8b28 100644
--- a/drivers/net/intel/ixgbe/ixgbe_flow.c
+++ b/drivers/net/intel/ixgbe/ixgbe_flow.c
@@ -3164,7 +3164,6 @@ ixgbe_flow_destroy(struct rte_eth_dev *dev,
                                fdir_info->mask_added = false;
                                fdir_info->mask = (struct 
ixgbe_hw_fdir_mask){0};
                                fdir_info->flex_bytes_offset = 0;
-                               fdir_conf->mode = RTE_FDIR_MODE_NONE;
                        }
                }
                break;
-- 
2.53.0

Reply via email to