igc: Fix qbv_config_change_errors logics
authorFaizal Rahim <faizal.abdul.rahim@linux.intel.com>
Sun, 7 Jul 2024 12:53:16 +0000 (08:53 -0400)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Wed, 7 Aug 2024 20:30:23 +0000 (13:30 -0700)
When user issues these cmds:
1. Either a) or b)
   a) mqprio with hardware offload disabled
   b) taprio with txtime-assist feature enabled
2. etf
3. tc qdisc delete
4. taprio with base time in the past

At step 4, qbv_config_change_errors wrongly increased by 1.

Excerpt from IEEE 802.1Q-2018 8.6.9.3.1:
"If AdminBaseTime specifies a time in the past, and the current schedule
is running, then: Increment ConfigChangeError counter"

qbv_config_change_errors should only increase if base time is in the past
and no taprio is active. In user perspective, taprio was not active when
first triggered at step 4. However, i225/6 reuses qbv for etf, so qbv is
enabled with a dummy schedule at step 2 where it enters
igc_tsn_enable_offload() and qbv_count got incremented to 1. At step 4, it
enters igc_tsn_enable_offload() again, qbv_count is incremented to 2.
Because taprio is running, tc_setup_type is TC_SETUP_QDISC_ETF and
qbv_count > 1, qbv_config_change_errors value got incremented.

This issue happens due to reliance on qbv_count field where a non-zero
value indicates that taprio is running. But qbv_count increases
regardless if taprio is triggered by user or by other tsn feature. It does
not align with qbv_config_change_errors expectation where it is only
concerned with taprio triggered by user.

Fixing this by relocating the qbv_config_change_errors logic to
igc_save_qbv_schedule(), eliminating reliance on qbv_count and its
inaccuracies from i225/6's multiple uses of qbv feature for other TSN
features.

The new function created: igc_tsn_is_taprio_activated_by_user() uses
taprio_offload_enable field to indicate that the current running taprio
was triggered by user, instead of triggered by non-qbv feature like etf.

Fixes: ae4fe4698300 ("igc: Add qbv_config_change_errors counter")
Signed-off-by: Faizal Rahim <faizal.abdul.rahim@linux.intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Tested-by: Mor Bar-Gabay <morx.bar.gabay@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/igc/igc_tsn.c
drivers/net/ethernet/intel/igc/igc_tsn.h

index 8daf938afc36c2881d9e55a42ac08d4838ab80c9..dfd6c00b4205d4ab251bbd994ceccd4ae1cd0f69 100644 (file)
@@ -6315,12 +6315,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
        if (!validate_schedule(adapter, qopt))
                return -EINVAL;
 
+       igc_ptp_read(adapter, &now);
+
+       if (igc_tsn_is_taprio_activated_by_user(adapter) &&
+           is_base_time_past(qopt->base_time, &now))
+               adapter->qbv_config_change_errors++;
+
        adapter->cycle_time = qopt->cycle_time;
        adapter->base_time = qopt->base_time;
        adapter->taprio_offload_enable = true;
 
-       igc_ptp_read(adapter, &now);
-
        for (n = 0; n < qopt->num_entries; n++) {
                struct tc_taprio_sched_entry *e = &qopt->entries[n];
 
index 46d4c3275bbb565ff47a12ca7650e4551b20a2d3..8ed7b965484da7aad91dcc49ddf4c259c4981948 100644 (file)
@@ -87,6 +87,14 @@ static void igc_tsn_restore_retx_default(struct igc_adapter *adapter)
        wr32(IGC_RETX_CTL, retxctl);
 }
 
+bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter)
+{
+       struct igc_hw *hw = &adapter->hw;
+
+       return (rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
+               adapter->taprio_offload_enable;
+}
+
 /* Returns the TSN specific registers to their default values after
  * the adapter is reset.
  */
@@ -296,14 +304,6 @@ skip_cbs:
                s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
 
                base_time = ktime_add_ns(base_time, (n + 1) * cycle);
-
-               /* Increase the counter if scheduling into the past while
-                * Gate Control List (GCL) is running.
-                */
-               if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
-                   (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
-                   (adapter->qbv_count > 1))
-                       adapter->qbv_config_change_errors++;
        } else {
                if (igc_is_device_id_i226(hw)) {
                        ktime_t adjust_time, expires_time;
index b53e6af560b73857829d0361356f83aee9bbd57f..98ec845a86bf00935089bd7c5c7a3a7422facf05 100644 (file)
@@ -7,5 +7,6 @@
 int igc_tsn_offload_apply(struct igc_adapter *adapter);
 int igc_tsn_reset(struct igc_adapter *adapter);
 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter);
+bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter);
 
 #endif /* _IGC_BASE_H */