igc: remove I226 Qbv BaseTime restriction
authorMuhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
Wed, 14 Dec 2022 16:29:07 +0000 (00:29 +0800)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 3 Jan 2023 17:35:37 +0000 (09:35 -0800)
Remove the Qbv BaseTime restriction for I226 so that the BaseTime can be
scheduled to the future time. A new register bit of Tx Qav Control
(Bit-7: FutScdDis) was introduced to allow I226 scheduling future time as
Qbv BaseTime and not having the Tx hang timeout issue.

Besides, according to datasheet section 7.5.2.9.3.3, FutScdDis bit has to
be configured first before the cycle time and base time.

Indeed the FutScdDis bit is only active on re-configuration, thus we have
to set the BASET_L to zero and then only set it to the desired value.

Please also note that the Qbv configuration flow is moved around based on
the Qbv programming guideline that is documented in the latest datasheet.

Co-developed-by: Tan Tee Min <tee.min.tan@linux.intel.com>
Signed-off-by: Tan Tee Min <tee.min.tan@linux.intel.com>
Signed-off-by: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
Tested-by: Naama Meir <naamax.meir@linux.intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/igc/igc_base.c
drivers/net/ethernet/intel/igc/igc_base.h
drivers/net/ethernet/intel/igc/igc_defines.h
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/igc/igc_tsn.c

index a15927e..a1d815a 100644 (file)
@@ -396,6 +396,35 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw)
        rd32(IGC_MPC);
 }
 
+bool igc_is_device_id_i225(struct igc_hw *hw)
+{
+       switch (hw->device_id) {
+       case IGC_DEV_ID_I225_LM:
+       case IGC_DEV_ID_I225_V:
+       case IGC_DEV_ID_I225_I:
+       case IGC_DEV_ID_I225_K:
+       case IGC_DEV_ID_I225_K2:
+       case IGC_DEV_ID_I225_LMVP:
+       case IGC_DEV_ID_I225_IT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+bool igc_is_device_id_i226(struct igc_hw *hw)
+{
+       switch (hw->device_id) {
+       case IGC_DEV_ID_I226_LM:
+       case IGC_DEV_ID_I226_V:
+       case IGC_DEV_ID_I226_K:
+       case IGC_DEV_ID_I226_IT:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static struct igc_mac_operations igc_mac_ops_base = {
        .init_hw                = igc_init_hw_base,
        .check_for_link         = igc_check_for_copper_link,
index ce530f5..7a992be 100644 (file)
@@ -7,6 +7,8 @@
 /* forward declaration */
 void igc_rx_fifo_flush_base(struct igc_hw *hw);
 void igc_power_down_phy_copper_base(struct igc_hw *hw);
+bool igc_is_device_id_i225(struct igc_hw *hw);
+bool igc_is_device_id_i226(struct igc_hw *hw);
 
 /* Transmit Descriptor - Advanced */
 union igc_adv_tx_desc {
index a7b2263..0e23f62 100644 (file)
 /* Transmit Scheduling */
 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
 #define IGC_TQAVCTRL_ENHANCED_QAV      0x00000008
+#define IGC_TQAVCTRL_FUTSCDDIS         0x00000080
 
 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT  0x00000001
 #define IGC_TXQCTL_STRICT_CYCLE                0x00000002
index 44b1740..988131d 100644 (file)
@@ -5958,6 +5958,7 @@ static bool validate_schedule(struct igc_adapter *adapter,
                              const struct tc_taprio_qopt_offload *qopt)
 {
        int queue_uses[IGC_MAX_TX_QUEUES] = { };
+       struct igc_hw *hw = &adapter->hw;
        struct timespec64 now;
        size_t n;
 
@@ -5970,8 +5971,10 @@ static bool validate_schedule(struct igc_adapter *adapter,
         * in the future, it will hold all the packets until that
         * time, causing a lot of TX Hangs, so to avoid that, we
         * reject schedules that would start in the future.
+        * Note: Limitation above is no longer in i226.
         */
-       if (!is_base_time_past(qopt->base_time, &now))
+       if (!is_base_time_past(qopt->base_time, &now) &&
+           igc_is_device_id_i225(hw))
                return false;
 
        for (n = 0; n < qopt->num_entries; n++) {
index bb10d7b..28325dc 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c)  2019 Intel Corporation */
 
 #include "igc.h"
+#include "igc_hw.h"
 #include "igc_tsn.h"
 
 static bool is_any_launchtime(struct igc_adapter *adapter)
@@ -92,7 +93,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 
        tqavctrl = rd32(IGC_TQAVCTRL);
        tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
-                     IGC_TQAVCTRL_ENHANCED_QAV);
+                     IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
+
        wr32(IGC_TQAVCTRL, tqavctrl);
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -117,20 +119,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
        ktime_t base_time, systim;
        int i;
 
-       cycle = adapter->cycle_time;
-       base_time = adapter->base_time;
-
        wr32(IGC_TSAUXC, 0);
        wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
        wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
 
-       tqavctrl = rd32(IGC_TQAVCTRL);
-       tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
-       wr32(IGC_TQAVCTRL, tqavctrl);
-
-       wr32(IGC_QBVCYCLET_S, cycle);
-       wr32(IGC_QBVCYCLET, cycle);
-
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igc_ring *ring = adapter->tx_ring[i];
                u32 txqctl = 0;
@@ -233,21 +225,43 @@ skip_cbs:
                wr32(IGC_TXQCTL(i), txqctl);
        }
 
+       tqavctrl = rd32(IGC_TQAVCTRL);
+       tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
+
+       cycle = adapter->cycle_time;
+       base_time = adapter->base_time;
+
        nsec = rd32(IGC_SYSTIML);
        sec = rd32(IGC_SYSTIMH);
 
        systim = ktime_set(sec, nsec);
-
        if (ktime_compare(systim, base_time) > 0) {
-               s64 n;
+               s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
 
-               n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
                base_time = ktime_add_ns(base_time, (n + 1) * cycle);
+       } else {
+               /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+                * has to be configured before the cycle time and base time.
+                */
+               if (igc_is_device_id_i226(hw))
+                       tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
        }
 
-       baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
+       wr32(IGC_TQAVCTRL, tqavctrl);
+
+       wr32(IGC_QBVCYCLET_S, cycle);
+       wr32(IGC_QBVCYCLET, cycle);
 
+       baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
        wr32(IGC_BASET_H, baset_h);
+
+       /* In i226, Future base time is only supported when FutScdDis bit
+        * is enabled and only active for re-configuration.
+        * In this case, initialize the base time with zero to create
+        * "re-configuration" scenario then only set the desired base time.
+        */
+       if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
+               wr32(IGC_BASET_L, 0);
        wr32(IGC_BASET_L, baset_l);
 
        return 0;