From: Mohammad Heib <[email protected]>

The ATR sample rate is currently stored per-ring and initialized when each
TX ring is configured. Since the sample rate is a global policy that
applies uniformly across all rings, it makes more sense to store it at
the PF level.

Move atr_sample_rate from struct i40e_ring to struct i40e_pf and initialize
it once during i40e_sw_init(). Update i40e_atr() to reference the PF-level
field. Change atr_count from u8 to u32 to match the sample rate type.

This also changes a user-visible behavior: previously, re-enabling ATR via
"ethtool --set-priv-flags ethX flow-director-atr on" did not resume
sampling until an ifdown/ifup or PF reset, because the per-ring sample
rate was latched at ring configuration time. With the PF-level rate always
initialized, the flag takes effect immediately.

Trigger a PF reset when re-enabling ATR so that fd_ena is re-evaluated
in the TX queue HW context.

Signed-off-by: Mohammad Heib <[email protected]>
---
 drivers/net/ethernet/intel/i40e/i40e.h         |  1 +
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 12 +++++++++++-
 drivers/net/ethernet/intel/i40e/i40e_main.c    |  9 +++------
 drivers/net/ethernet/intel/i40e/i40e_txrx.c    |  6 ++++--
 drivers/net/ethernet/intel/i40e/i40e_txrx.h    |  3 +--
 5 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e.h 
b/drivers/net/ethernet/intel/i40e/i40e.h
index a9d79bbd3ea7..528ef329a647 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -486,6 +486,7 @@ struct i40e_pf {
        u16 rss_size_max;          /* HW defined max RSS queues */
        u16 fdir_pf_filter_count;  /* num of guaranteed filters for this PF */
        u16 num_alloc_vsi;         /* num VSIs this driver supports */
+       u32 atr_sample_rate;
        bool wol_en;
 
        struct hlist_head fdir_filter_list;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c 
b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 0ae50d7f3465..9b1ecb2c4edc 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -5300,6 +5300,16 @@ static int i40e_set_priv_flags(struct net_device *dev, 
u32 flags)
            test_bit(I40E_FLAG_SOURCE_PRUNING_DIS, changed_flags))
                reset_needed = BIT(__I40E_PF_RESET_REQUESTED);
 
+       /* Re-enabling ATR requires a reset to reprogram fd_ena in the
+        * TX queue HW context. Skip when FD_SB (ntuple) is already
+        * enabled, since i40e_configure_tx_ring() sets fd_ena when
+        * either FD flag is active.
+        */
+       if (test_bit(I40E_FLAG_FD_ATR_ENA, changed_flags) &&
+           test_bit(I40E_FLAG_FD_ATR_ENA, new_flags) &&
+           !test_bit(I40E_FLAG_FD_SB_ENA, new_flags))
+               reset_needed = BIT(__I40E_PF_RESET_REQUESTED);
+
        /* Before we finalize any flag changes, we need to perform some
         * checks to ensure that the changes are supported and safe.
         */
@@ -5431,7 +5441,7 @@ static int i40e_set_priv_flags(struct net_device *dev, 
u32 flags)
                                case LIBIE_AQ_RC_EEXIST:
                                        dev_warn(&pf->pdev->dev,
                                                 "FW LLDP agent is already 
running\n");
-                                       reset_needed = 0;
+                                       reset_needed &= 
~I40E_PF_RESET_AND_REBUILD_FLAG;
                                        break;
                                case LIBIE_AQ_RC_EPERM:
                                        dev_warn(&pf->pdev->dev,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c 
b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 109ba6b20f8e..d83116596eda 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -3459,12 +3459,7 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
                ring->xsk_pool = i40e_xsk_pool(ring);
 
        /* some ATR related tx ring init */
-       if (test_bit(I40E_FLAG_FD_ATR_ENA, vsi->back->flags)) {
-               ring->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
-               ring->atr_count = 0;
-       } else {
-               ring->atr_sample_rate = 0;
-       }
+       ring->atr_count = 0;
 
        /* configure XPS */
        i40e_config_xps_tx_ring(ring);
@@ -12754,6 +12749,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
                }
        }
 
+       pf->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
+
        if ((pf->hw.func_caps.fd_filters_guaranteed > 0) ||
            (pf->hw.func_caps.fd_filters_best_effort > 0)) {
                set_bit(I40E_FLAG_FD_ATR_ENA, pf->flags);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 2032465c9b7c..acb47a9fd86f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2887,6 +2887,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct 
sk_buff *skb,
        struct tcphdr *th;
        unsigned int hlen;
        u32 flex_ptype, dtype_cmd;
+       u32 sample_rate;
        int l4_proto;
        u16 i;
 
@@ -2898,7 +2899,8 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct 
sk_buff *skb,
                return;
 
        /* if sampling is disabled do nothing */
-       if (!tx_ring->atr_sample_rate)
+       sample_rate = READ_ONCE(pf->atr_sample_rate);
+       if (!sample_rate)
                return;
 
        /* Currently only IPv4/IPv6 with TCP is supported */
@@ -2950,7 +2952,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct 
sk_buff *skb,
        if (!th->fin &&
            !th->syn &&
            !th->rst &&
-           (tx_ring->atr_count < tx_ring->atr_sample_rate))
+           (tx_ring->atr_count < sample_rate))
                return;
 
        tx_ring->atr_count = 0;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index bb741ff3e5f2..be587f804e7a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -372,8 +372,7 @@ struct i40e_ring {
        u16 next_to_clean;
        u16 xdp_tx_active;
 
-       u8 atr_sample_rate;
-       u8 atr_count;
+       u32 atr_count;
 
        bool ring_active;               /* is ring online or not */
        bool arm_wb;            /* do something to arm write back */
-- 
2.56.0

Reply via email to