]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Oct 2023 16:15:27 +0000 (18:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Oct 2023 16:15:27 +0000 (18:15 +0200)
added patches:
igc-add-condition-for-qbv_config_change_errors-counter.patch
igc-add-qbv_config_change_errors-counter.patch
igc-enable-qbv-configuration-for-2nd-gcl.patch
igc-fix-race-condition-in-ptp-tx-code.patch
igc-remove-i226-qbv-basetime-restriction.patch
igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch

queue-6.1/igc-add-condition-for-qbv_config_change_errors-counter.patch [new file with mode: 0644]
queue-6.1/igc-add-qbv_config_change_errors-counter.patch [new file with mode: 0644]
queue-6.1/igc-enable-qbv-configuration-for-2nd-gcl.patch [new file with mode: 0644]
queue-6.1/igc-fix-race-condition-in-ptp-tx-code.patch [new file with mode: 0644]
queue-6.1/igc-remove-i226-qbv-basetime-restriction.patch [new file with mode: 0644]
queue-6.1/igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/igc-add-condition-for-qbv_config_change_errors-counter.patch b/queue-6.1/igc-add-condition-for-qbv_config_change_errors-counter.patch
new file mode 100644 (file)
index 0000000..e649aea
--- /dev/null
@@ -0,0 +1,57 @@
+From ed89b74d2dc920cb61d3094e0e97ec8775b13086 Mon Sep 17 00:00:00 2001
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+Date: Mon, 15 May 2023 14:03:36 +0800
+Subject: igc: Add condition for qbv_config_change_errors counter
+
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+
+commit ed89b74d2dc920cb61d3094e0e97ec8775b13086 upstream.
+
+Add condition to increase the qbv counter during taprio qbv
+configuration only.
+
+There might be a case when TC already been setup then user configure
+the ETF/CBS qdisc and this counter will increase if no condition above.
+
+Fixes: ae4fe4698300 ("igc: Add qbv_config_change_errors counter")
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc.h      |    1 +
+ drivers/net/ethernet/intel/igc/igc_main.c |    2 ++
+ drivers/net/ethernet/intel/igc/igc_tsn.c  |    1 +
+ 3 files changed, 4 insertions(+)
+
+--- a/drivers/net/ethernet/intel/igc/igc.h
++++ b/drivers/net/ethernet/intel/igc/igc.h
+@@ -183,6 +183,7 @@ struct igc_adapter {
+       u32 max_frame_size;
+       u32 min_frame_size;
++      int tc_setup_type;
+       ktime_t base_time;
+       ktime_t cycle_time;
+       bool qbv_enable;
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -6288,6 +6288,8 @@ static int igc_setup_tc(struct net_devic
+ {
+       struct igc_adapter *adapter = netdev_priv(dev);
++      adapter->tc_setup_type = type;
++
+       switch (type) {
+       case TC_SETUP_QDISC_TAPRIO:
+               return igc_tsn_enable_qbv_scheduling(adapter, type_data);
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
+@@ -219,6 +219,7 @@ skip_cbs:
+                * Gate Control List (GCL) is running.
+                */
+               if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
++                  (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
+                   tsn_mode_reconfig)
+                       adapter->qbv_config_change_errors++;
+       } else {
diff --git a/queue-6.1/igc-add-qbv_config_change_errors-counter.patch b/queue-6.1/igc-add-qbv_config_change_errors-counter.patch
new file mode 100644 (file)
index 0000000..c8da8ad
--- /dev/null
@@ -0,0 +1,94 @@
+From ae4fe46983007bc46d87dcb284a5e5851c3e1c84 Mon Sep 17 00:00:00 2001
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+Date: Thu, 16 Feb 2023 10:07:31 +0800
+Subject: igc: Add qbv_config_change_errors counter
+
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+
+commit ae4fe46983007bc46d87dcb284a5e5851c3e1c84 upstream.
+
+Add ConfigChangeError(qbv_config_change_errors) when user try to set the
+AdminBaseTime to past value while the current GCL is still running.
+
+The ConfigChangeError counter should not be increased when a gate control
+list is scheduled into the future.
+
+User can use "ethtool -S <interface> | grep qbv_config_change_errors"
+command to check the counter values.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc.h         |    1 +
+ drivers/net/ethernet/intel/igc/igc_ethtool.c |    1 +
+ drivers/net/ethernet/intel/igc/igc_main.c    |    1 +
+ drivers/net/ethernet/intel/igc/igc_tsn.c     |   12 ++++++++++++
+ 4 files changed, 15 insertions(+)
+
+--- a/drivers/net/ethernet/intel/igc/igc.h
++++ b/drivers/net/ethernet/intel/igc/igc.h
+@@ -186,6 +186,7 @@ struct igc_adapter {
+       ktime_t base_time;
+       ktime_t cycle_time;
+       bool qbv_enable;
++      u32 qbv_config_change_errors;
+       /* OS defined structs */
+       struct pci_dev *pdev;
+--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
++++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
+@@ -67,6 +67,7 @@ static const struct igc_stats igc_gstrin
+       IGC_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
+       IGC_STAT("tx_lpi_counter", stats.tlpic),
+       IGC_STAT("rx_lpi_counter", stats.rlpic),
++      IGC_STAT("qbv_config_change_errors", qbv_config_change_errors),
+ };
+ #define IGC_NETDEV_STAT(_net_stat) { \
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -6106,6 +6106,7 @@ static int igc_tsn_clear_schedule(struct
+       adapter->base_time = 0;
+       adapter->cycle_time = NSEC_PER_SEC;
++      adapter->qbv_config_change_errors = 0;
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *ring = adapter->tx_ring[i];
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
+@@ -84,6 +84,7 @@ static int igc_tsn_disable_offload(struc
+ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
+ {
+       struct igc_hw *hw = &adapter->hw;
++      bool tsn_mode_reconfig = false;
+       u32 tqavctrl, baset_l, baset_h;
+       u32 sec, nsec, cycle;
+       ktime_t base_time, systim;
+@@ -196,6 +197,10 @@ skip_cbs:
+       }
+       tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
++
++      if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
++              tsn_mode_reconfig = true;
++
+       tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
+       cycle = adapter->cycle_time;
+@@ -209,6 +214,13 @@ 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)) &&
++                  tsn_mode_reconfig)
++                      adapter->qbv_config_change_errors++;
+       } else {
+               /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+                * has to be configured before the cycle time and base time.
diff --git a/queue-6.1/igc-enable-qbv-configuration-for-2nd-gcl.patch b/queue-6.1/igc-enable-qbv-configuration-for-2nd-gcl.patch
new file mode 100644 (file)
index 0000000..da99ec9
--- /dev/null
@@ -0,0 +1,123 @@
+From 5ac1231ac14d1b8a1098048e51cad45f11b85c0a Mon Sep 17 00:00:00 2001
+From: Tan Tee Min <tee.min.tan@linux.intel.com>
+Date: Thu, 15 Dec 2022 00:29:08 +0800
+Subject: igc: enable Qbv configuration for 2nd GCL
+
+From: Tan Tee Min <tee.min.tan@linux.intel.com>
+
+commit 5ac1231ac14d1b8a1098048e51cad45f11b85c0a upstream.
+
+Make reset task only executes for i225 and Qbv disabling to allow
+i226 configure for 2nd GCL without resetting the adapter.
+
+In i226, Tx won't hang if there is a GCL is already running, so in
+this case we don't need to set FutScdDis bit.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c |    9 +++++----
+ drivers/net/ethernet/intel/igc/igc_tsn.c  |   13 +++++++++----
+ drivers/net/ethernet/intel/igc/igc_tsn.h  |    2 +-
+ 3 files changed, 15 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -6097,7 +6097,7 @@ static int igc_tsn_enable_launchtime(str
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter);
++      return igc_tsn_offload_apply(adapter, qopt->enable);
+ }
+ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+@@ -6121,6 +6121,7 @@ static int igc_save_qbv_schedule(struct
+                                struct tc_taprio_qopt_offload *qopt)
+ {
+       bool queue_configured[IGC_MAX_TX_QUEUES] = { };
++      struct igc_hw *hw = &adapter->hw;
+       u32 start_time = 0, end_time = 0;
+       size_t n;
+       int i;
+@@ -6133,7 +6134,7 @@ static int igc_save_qbv_schedule(struct
+       if (qopt->base_time < 0)
+               return -ERANGE;
+-      if (adapter->base_time)
++      if (igc_is_device_id_i225(hw) && adapter->base_time)
+               return -EALREADY;
+       if (!validate_schedule(adapter, qopt))
+@@ -6210,7 +6211,7 @@ static int igc_tsn_enable_qbv_scheduling
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter);
++      return igc_tsn_offload_apply(adapter, qopt->enable);
+ }
+ static int igc_save_cbs_params(struct igc_adapter *adapter, int queue,
+@@ -6278,7 +6279,7 @@ static int igc_tsn_enable_cbs(struct igc
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter);
++      return igc_tsn_offload_apply(adapter, qopt->enable);
+ }
+ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
+@@ -195,7 +195,7 @@ skip_cbs:
+               wr32(IGC_TXQCTL(i), txqctl);
+       }
+-      tqavctrl = rd32(IGC_TQAVCTRL);
++      tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
+       tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
+       cycle = adapter->cycle_time;
+@@ -212,8 +212,11 @@ skip_cbs:
+       } else {
+               /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+                * has to be configured before the cycle time and base time.
++               * Tx won't hang if there is a GCL is already running,
++               * so in this case we don't need to set FutScdDis.
+                */
+-              if (igc_is_device_id_i226(hw))
++              if (igc_is_device_id_i226(hw) &&
++                  !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
+                       tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+       }
+@@ -256,11 +259,13 @@ int igc_tsn_reset(struct igc_adapter *ad
+       return err;
+ }
+-int igc_tsn_offload_apply(struct igc_adapter *adapter)
++int igc_tsn_offload_apply(struct igc_adapter *adapter, bool enable)
+ {
++      struct igc_hw *hw = &adapter->hw;
+       int err;
+-      if (netif_running(adapter->netdev)) {
++      if (netif_running(adapter->netdev) &&
++          (igc_is_device_id_i225(hw) || !enable)) {
+               schedule_work(&adapter->reset_task);
+               return 0;
+       }
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
+@@ -4,7 +4,7 @@
+ #ifndef _IGC_TSN_H_
+ #define _IGC_TSN_H_
+-int igc_tsn_offload_apply(struct igc_adapter *adapter);
++int igc_tsn_offload_apply(struct igc_adapter *adapter, bool enable);
+ int igc_tsn_reset(struct igc_adapter *adapter);
+ #endif /* _IGC_BASE_H */
diff --git a/queue-6.1/igc-fix-race-condition-in-ptp-tx-code.patch b/queue-6.1/igc-fix-race-condition-in-ptp-tx-code.patch
new file mode 100644 (file)
index 0000000..99eb963
--- /dev/null
@@ -0,0 +1,228 @@
+From 9c50e2b150c8ee0eee5f8154e2ad168cdd748877 Mon Sep 17 00:00:00 2001
+From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Date: Wed, 7 Jun 2023 14:32:29 -0700
+Subject: igc: Fix race condition in PTP tx code
+
+From: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+
+commit 9c50e2b150c8ee0eee5f8154e2ad168cdd748877 upstream.
+
+Currently, the igc driver supports timestamping only one tx packet at a
+time. During the transmission flow, the skb that requires hardware
+timestamping is saved in adapter->ptp_tx_skb. Once hardware has the
+timestamp, an interrupt is delivered, and adapter->ptp_tx_work is
+scheduled. In igc_ptp_tx_work(), we read the timestamp register, update
+adapter->ptp_tx_skb, and notify the network stack.
+
+While the thread executing the transmission flow (the user process
+running in kernel mode) and the thread executing ptp_tx_work don't
+access adapter->ptp_tx_skb concurrently, there are two other places
+where adapter->ptp_tx_skb is accessed: igc_ptp_tx_hang() and
+igc_ptp_suspend().
+
+igc_ptp_tx_hang() is executed by the adapter->watchdog_task worker
+thread which runs periodically so it is possible we have two threads
+accessing ptp_tx_skb at the same time. Consider the following scenario:
+right after __IGC_PTP_TX_IN_PROGRESS is set in igc_xmit_frame_ring(),
+igc_ptp_tx_hang() is executed. Since adapter->ptp_tx_start hasn't been
+written yet, this is considered a timeout and adapter->ptp_tx_skb is
+cleaned up.
+
+This patch fixes the issue described above by adding the ptp_tx_lock to
+protect access to ptp_tx_skb and ptp_tx_start fields from igc_adapter.
+Since igc_xmit_frame_ring() called in atomic context by the networking
+stack, ptp_tx_lock is defined as a spinlock, and the irq safe variants
+of lock/unlock are used.
+
+With the introduction of the ptp_tx_lock, the __IGC_PTP_TX_IN_PROGRESS
+flag doesn't provide much of a use anymore so this patch gets rid of it.
+
+Fixes: 2c344ae24501 ("igc: Add support for TX timestamping")
+Signed-off-by: Andre Guedes <andre.guedes@intel.com>
+Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de>
+Tested-by: Naama Meir <naamax.meir@linux.intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc.h      |    5 ++
+ drivers/net/ethernet/intel/igc/igc_main.c |    9 +++-
+ drivers/net/ethernet/intel/igc/igc_ptp.c  |   57 ++++++++++++++++--------------
+ 3 files changed, 41 insertions(+), 30 deletions(-)
+
+--- a/drivers/net/ethernet/intel/igc/igc.h
++++ b/drivers/net/ethernet/intel/igc/igc.h
+@@ -230,6 +230,10 @@ struct igc_adapter {
+       struct ptp_clock *ptp_clock;
+       struct ptp_clock_info ptp_caps;
+       struct work_struct ptp_tx_work;
++      /* Access to ptp_tx_skb and ptp_tx_start are protected by the
++       * ptp_tx_lock.
++       */
++      spinlock_t ptp_tx_lock;
+       struct sk_buff *ptp_tx_skb;
+       struct hwtstamp_config tstamp_config;
+       unsigned long ptp_tx_start;
+@@ -431,7 +435,6 @@ enum igc_state_t {
+       __IGC_TESTING,
+       __IGC_RESETTING,
+       __IGC_DOWN,
+-      __IGC_PTP_TX_IN_PROGRESS,
+ };
+ enum igc_tx_flags {
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -1606,9 +1606,10 @@ done:
+                * the other timer registers before skipping the
+                * timestamping request.
+                */
+-              if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
+-                  !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS,
+-                                         &adapter->state)) {
++              unsigned long flags;
++
++              spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
++              if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && !adapter->ptp_tx_skb) {
+                       skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+                       tx_flags |= IGC_TX_FLAGS_TSTAMP;
+@@ -1617,6 +1618,8 @@ done:
+               } else {
+                       adapter->tx_hwtstamp_skipped++;
+               }
++
++              spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
+       }
+       if (skb_vlan_tag_present(skb)) {
+--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
++++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
+@@ -622,6 +622,7 @@ static int igc_ptp_set_timestamp_mode(st
+       return 0;
+ }
++/* Requires adapter->ptp_tx_lock held by caller. */
+ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
+ {
+       struct igc_hw *hw = &adapter->hw;
+@@ -629,7 +630,6 @@ static void igc_ptp_tx_timeout(struct ig
+       dev_kfree_skb_any(adapter->ptp_tx_skb);
+       adapter->ptp_tx_skb = NULL;
+       adapter->tx_hwtstamp_timeouts++;
+-      clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+       /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
+       rd32(IGC_TXSTMPH);
+       netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
+@@ -637,20 +637,20 @@ static void igc_ptp_tx_timeout(struct ig
+ void igc_ptp_tx_hang(struct igc_adapter *adapter)
+ {
+-      bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
+-                                            IGC_PTP_TX_TIMEOUT);
++      unsigned long flags;
+-      if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
+-              return;
++      spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
+-      /* If we haven't received a timestamp within the timeout, it is
+-       * reasonable to assume that it will never occur, so we can unlock the
+-       * timestamp bit when this occurs.
+-       */
+-      if (timeout) {
+-              cancel_work_sync(&adapter->ptp_tx_work);
+-              igc_ptp_tx_timeout(adapter);
+-      }
++      if (!adapter->ptp_tx_skb)
++              goto unlock;
++
++      if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT))
++              goto unlock;
++
++      igc_ptp_tx_timeout(adapter);
++
++unlock:
++      spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
+ }
+ /**
+@@ -660,6 +660,8 @@ void igc_ptp_tx_hang(struct igc_adapter
+  * If we were asked to do hardware stamping and such a time stamp is
+  * available, then it must have been for this skb here because we only
+  * allow only one such packet into the queue.
++ *
++ * Context: Expects adapter->ptp_tx_lock to be held by caller.
+  */
+ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
+ {
+@@ -695,13 +697,7 @@ static void igc_ptp_tx_hwtstamp(struct i
+       shhwtstamps.hwtstamp =
+               ktime_add_ns(shhwtstamps.hwtstamp, adjust);
+-      /* Clear the lock early before calling skb_tstamp_tx so that
+-       * applications are not woken up before the lock bit is clear. We use
+-       * a copy of the skb pointer to ensure other threads can't change it
+-       * while we're notifying the stack.
+-       */
+       adapter->ptp_tx_skb = NULL;
+-      clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+       /* Notify the stack and free the skb after we've unlocked */
+       skb_tstamp_tx(skb, &shhwtstamps);
+@@ -712,24 +708,33 @@ static void igc_ptp_tx_hwtstamp(struct i
+  * igc_ptp_tx_work
+  * @work: pointer to work struct
+  *
+- * This work function polls the TSYNCTXCTL valid bit to determine when a
+- * timestamp has been taken for the current stored skb.
++ * This work function checks the TSYNCTXCTL valid bit to determine when
++ * a timestamp has been taken for the current stored skb.
+  */
+ static void igc_ptp_tx_work(struct work_struct *work)
+ {
+       struct igc_adapter *adapter = container_of(work, struct igc_adapter,
+                                                  ptp_tx_work);
+       struct igc_hw *hw = &adapter->hw;
++      unsigned long flags;
+       u32 tsynctxctl;
+-      if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
+-              return;
++      spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
++
++      if (!adapter->ptp_tx_skb)
++              goto unlock;
+       tsynctxctl = rd32(IGC_TSYNCTXCTL);
+-      if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
+-              return;
++      tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0;
++      if (!tsynctxctl) {
++              WARN_ONCE(1, "Received a TSTAMP interrupt but no TSTAMP is ready.\n");
++              goto unlock;
++      }
+       igc_ptp_tx_hwtstamp(adapter);
++
++unlock:
++      spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
+ }
+ /**
+@@ -978,6 +983,7 @@ void igc_ptp_init(struct igc_adapter *ad
+               return;
+       }
++      spin_lock_init(&adapter->ptp_tx_lock);
+       spin_lock_init(&adapter->tmreg_lock);
+       INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
+@@ -1042,7 +1048,6 @@ void igc_ptp_suspend(struct igc_adapter
+       cancel_work_sync(&adapter->ptp_tx_work);
+       dev_kfree_skb_any(adapter->ptp_tx_skb);
+       adapter->ptp_tx_skb = NULL;
+-      clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+       if (pci_device_is_present(adapter->pdev)) {
+               igc_ptp_time_save(adapter);
diff --git a/queue-6.1/igc-remove-i226-qbv-basetime-restriction.patch b/queue-6.1/igc-remove-i226-qbv-basetime-restriction.patch
new file mode 100644 (file)
index 0000000..443dc94
--- /dev/null
@@ -0,0 +1,207 @@
+From b8897dc54e3bc9d25281bbb42a7d730782ff4588 Mon Sep 17 00:00:00 2001
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+Date: Thu, 15 Dec 2022 00:29:07 +0800
+Subject: igc: remove I226 Qbv BaseTime restriction
+
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+
+commit b8897dc54e3bc9d25281bbb42a7d730782ff4588 upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc_base.c    |   29 +++++++++++++++++
+ drivers/net/ethernet/intel/igc/igc_base.h    |    2 +
+ drivers/net/ethernet/intel/igc/igc_defines.h |    1 
+ drivers/net/ethernet/intel/igc/igc_main.c    |    5 ++-
+ drivers/net/ethernet/intel/igc/igc_tsn.c     |   44 +++++++++++++++++----------
+ 5 files changed, 65 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/ethernet/intel/igc/igc_base.c
++++ b/drivers/net/ethernet/intel/igc/igc_base.c
+@@ -396,6 +396,35 @@ void igc_rx_fifo_flush_base(struct igc_h
+       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,
+--- a/drivers/net/ethernet/intel/igc/igc_base.h
++++ b/drivers/net/ethernet/intel/igc/igc_base.h
+@@ -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 {
+--- a/drivers/net/ethernet/intel/igc/igc_defines.h
++++ b/drivers/net/ethernet/intel/igc/igc_defines.h
+@@ -515,6 +515,7 @@
+ /* 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
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -6035,6 +6035,7 @@ static bool validate_schedule(struct igc
+                             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;
+@@ -6047,8 +6048,10 @@ static bool validate_schedule(struct igc
+        * 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++) {
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
+@@ -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)
+@@ -62,7 +63,8 @@ static int igc_tsn_disable_offload(struc
+       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++) {
+@@ -87,20 +89,10 @@ static int igc_tsn_enable_offload(struct
+       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;
+@@ -203,21 +195,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;
diff --git a/queue-6.1/igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch b/queue-6.1/igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch
new file mode 100644 (file)
index 0000000..ec4c332
--- /dev/null
@@ -0,0 +1,110 @@
+From 1d1b4c63ba739c6ca695cb2ea13fefa9dfbff60d Mon Sep 17 00:00:00 2001
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+Date: Thu, 15 Dec 2022 00:29:09 +0800
+Subject: igc: Remove reset adapter task for i226 during disable tsn config
+
+From: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+
+commit 1d1b4c63ba739c6ca695cb2ea13fefa9dfbff60d upstream.
+
+I225 have limitation when programming the BaseTime register which required
+a power cycle of the controller. This limitation already lifted in I226.
+This patch removes the restriction so that when user configure/remove any
+TSN mode, it would not go into power cycle reset adapter.
+
+How to test:
+
+Schedule any gate control list configuration or delete it.
+
+Example:
+
+1)
+
+BASE_TIME=$(date +%s%N)
+tc qdisc replace dev $interface_name parent root handle 100 taprio \
+    num_tc 4 \
+    map 3 1 0 2 3 3 3 3 3 3 3 3 3 3 3 3 \
+    queues 1@0 1@1 1@2 1@3 \
+    base-time $BASE_TIME \
+    sched-entry S 0F 1000000 \
+    flags 0x2
+
+2) tc qdisc del dev $intername_name root
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/intel/igc/igc_main.c |    6 +++---
+ drivers/net/ethernet/intel/igc/igc_tsn.c  |   11 +++--------
+ drivers/net/ethernet/intel/igc/igc_tsn.h  |    2 +-
+ 3 files changed, 7 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -6097,7 +6097,7 @@ static int igc_tsn_enable_launchtime(str
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter, qopt->enable);
++      return igc_tsn_offload_apply(adapter);
+ }
+ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+@@ -6211,7 +6211,7 @@ static int igc_tsn_enable_qbv_scheduling
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter, qopt->enable);
++      return igc_tsn_offload_apply(adapter);
+ }
+ static int igc_save_cbs_params(struct igc_adapter *adapter, int queue,
+@@ -6279,7 +6279,7 @@ static int igc_tsn_enable_cbs(struct igc
+       if (err)
+               return err;
+-      return igc_tsn_offload_apply(adapter, qopt->enable);
++      return igc_tsn_offload_apply(adapter);
+ }
+ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
+@@ -259,21 +259,16 @@ int igc_tsn_reset(struct igc_adapter *ad
+       return err;
+ }
+-int igc_tsn_offload_apply(struct igc_adapter *adapter, bool enable)
++int igc_tsn_offload_apply(struct igc_adapter *adapter)
+ {
+       struct igc_hw *hw = &adapter->hw;
+-      int err;
+-      if (netif_running(adapter->netdev) &&
+-          (igc_is_device_id_i225(hw) || !enable)) {
++      if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
+               schedule_work(&adapter->reset_task);
+               return 0;
+       }
+-      err = igc_tsn_enable_offload(adapter);
+-      if (err < 0)
+-              return err;
++      igc_tsn_reset(adapter);
+-      adapter->flags = igc_tsn_new_flags(adapter);
+       return 0;
+ }
+--- a/drivers/net/ethernet/intel/igc/igc_tsn.h
++++ b/drivers/net/ethernet/intel/igc/igc_tsn.h
+@@ -4,7 +4,7 @@
+ #ifndef _IGC_TSN_H_
+ #define _IGC_TSN_H_
+-int igc_tsn_offload_apply(struct igc_adapter *adapter, bool enable);
++int igc_tsn_offload_apply(struct igc_adapter *adapter);
+ int igc_tsn_reset(struct igc_adapter *adapter);
+ #endif /* _IGC_BASE_H */
index 3b34f9c43424eab5a8937cf4ead7160454bf859a..68d3796d551202c5640f50278d24da9977f043a8 100644 (file)
@@ -1 +1,7 @@
 lib-kconfig.debug-do-not-enable-debug_preempt-by-default.patch
+igc-remove-i226-qbv-basetime-restriction.patch
+igc-enable-qbv-configuration-for-2nd-gcl.patch
+igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch
+igc-add-qbv_config_change_errors-counter.patch
+igc-add-condition-for-qbv_config_change_errors-counter.patch
+igc-fix-race-condition-in-ptp-tx-code.patch