From: Greg Kroah-Hartman Date: Fri, 20 Oct 2023 16:15:27 +0000 (+0200) Subject: 6.1-stable patches X-Git-Tag: v4.14.328~114 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=afdecf141145ffb865318df40822bf4b5ce8bb51;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches 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 --- 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 index 00000000000..e649aea9b13 --- /dev/null +++ b/queue-6.1/igc-add-condition-for-qbv_config_change_errors-counter.patch @@ -0,0 +1,57 @@ +From ed89b74d2dc920cb61d3094e0e97ec8775b13086 Mon Sep 17 00:00:00 2001 +From: Muhammad Husaini Zulkifli +Date: Mon, 15 May 2023 14:03:36 +0800 +Subject: igc: Add condition for qbv_config_change_errors counter + +From: Muhammad Husaini Zulkifli + +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 +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..c8da8adbaff --- /dev/null +++ b/queue-6.1/igc-add-qbv_config_change_errors-counter.patch @@ -0,0 +1,94 @@ +From ae4fe46983007bc46d87dcb284a5e5851c3e1c84 Mon Sep 17 00:00:00 2001 +From: Muhammad Husaini Zulkifli +Date: Thu, 16 Feb 2023 10:07:31 +0800 +Subject: igc: Add qbv_config_change_errors counter + +From: Muhammad Husaini Zulkifli + +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 | grep qbv_config_change_errors" +command to check the counter values. + +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..da99ec9c3bb --- /dev/null +++ b/queue-6.1/igc-enable-qbv-configuration-for-2nd-gcl.patch @@ -0,0 +1,123 @@ +From 5ac1231ac14d1b8a1098048e51cad45f11b85c0a Mon Sep 17 00:00:00 2001 +From: Tan Tee Min +Date: Thu, 15 Dec 2022 00:29:08 +0800 +Subject: igc: enable Qbv configuration for 2nd GCL + +From: Tan Tee Min + +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 +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..99eb9636100 --- /dev/null +++ b/queue-6.1/igc-fix-race-condition-in-ptp-tx-code.patch @@ -0,0 +1,228 @@ +From 9c50e2b150c8ee0eee5f8154e2ad168cdd748877 Mon Sep 17 00:00:00 2001 +From: Vinicius Costa Gomes +Date: Wed, 7 Jun 2023 14:32:29 -0700 +Subject: igc: Fix race condition in PTP tx code + +From: Vinicius Costa Gomes + +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 +Signed-off-by: Vinicius Costa Gomes +Reviewed-by: Kurt Kanzenbach +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..443dc941c2c --- /dev/null +++ b/queue-6.1/igc-remove-i226-qbv-basetime-restriction.patch @@ -0,0 +1,207 @@ +From b8897dc54e3bc9d25281bbb42a7d730782ff4588 Mon Sep 17 00:00:00 2001 +From: Muhammad Husaini Zulkifli +Date: Thu, 15 Dec 2022 00:29:07 +0800 +Subject: igc: remove I226 Qbv BaseTime restriction + +From: Muhammad Husaini Zulkifli + +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 +Signed-off-by: Tan Tee Min +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ec4c3328673 --- /dev/null +++ b/queue-6.1/igc-remove-reset-adapter-task-for-i226-during-disable-tsn-config.patch @@ -0,0 +1,110 @@ +From 1d1b4c63ba739c6ca695cb2ea13fefa9dfbff60d Mon Sep 17 00:00:00 2001 +From: Muhammad Husaini Zulkifli +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 + +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 +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + 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 */ diff --git a/queue-6.1/series b/queue-6.1/series index 3b34f9c4342..68d3796d551 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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