Commit 1f47510e authored by David S. Miller's avatar David S. Miller

Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2023-01-03 (igc)

Muhammad Husaini Zulkifli says:

Improvements to the Time-Sensitive Networking (TSN) Qbv Scheduling
capabilities were included in this patch series for I226 SKU.

An overview of each patch series is given below:

Patch 1: To enable basetime scheduling in the future, remove the existing
restriction for i226 stepping while maintain the restriction for i225.
Patch 2: Remove the restriction which require a controller reset when
setting the basetime register for new i226 steps and enable the second
GCL configuration.
Patch 3: Remove the power reset adapter during disabling the tsn config.
---
Patches remaining from initial PR:
https://lore.kernel.org/netdev/20221205212414.3197525-1-anthony.l.nguyen@intel.com/

after sending net patches:
https://lore.kernel.org/netdev/20221215230758.3595578-1-anthony.l.nguyen@intel.com/

Note: patch 3 is an additional patch from the initial PR.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c183e6c3 1d1b4c63
...@@ -396,6 +396,35 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw) ...@@ -396,6 +396,35 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw)
rd32(IGC_MPC); 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 = { static struct igc_mac_operations igc_mac_ops_base = {
.init_hw = igc_init_hw_base, .init_hw = igc_init_hw_base,
.check_for_link = igc_check_for_copper_link, .check_for_link = igc_check_for_copper_link,
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
/* forward declaration */ /* forward declaration */
void igc_rx_fifo_flush_base(struct igc_hw *hw); void igc_rx_fifo_flush_base(struct igc_hw *hw);
void igc_power_down_phy_copper_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 */ /* Transmit Descriptor - Advanced */
union igc_adv_tx_desc { union igc_adv_tx_desc {
......
...@@ -522,6 +522,7 @@ ...@@ -522,6 +522,7 @@
/* Transmit Scheduling */ /* Transmit Scheduling */
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001 #define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008 #define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
#define IGC_TQAVCTRL_FUTSCDDIS 0x00000080
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001 #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002 #define IGC_TXQCTL_STRICT_CYCLE 0x00000002
......
...@@ -5958,6 +5958,7 @@ static bool validate_schedule(struct igc_adapter *adapter, ...@@ -5958,6 +5958,7 @@ static bool validate_schedule(struct igc_adapter *adapter,
const struct tc_taprio_qopt_offload *qopt) const struct tc_taprio_qopt_offload *qopt)
{ {
int queue_uses[IGC_MAX_TX_QUEUES] = { }; int queue_uses[IGC_MAX_TX_QUEUES] = { };
struct igc_hw *hw = &adapter->hw;
struct timespec64 now; struct timespec64 now;
size_t n; size_t n;
...@@ -5970,8 +5971,10 @@ static bool validate_schedule(struct igc_adapter *adapter, ...@@ -5970,8 +5971,10 @@ static bool validate_schedule(struct igc_adapter *adapter,
* in the future, it will hold all the packets until that * in the future, it will hold all the packets until that
* time, causing a lot of TX Hangs, so to avoid that, we * time, causing a lot of TX Hangs, so to avoid that, we
* reject schedules that would start in the future. * 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; return false;
for (n = 0; n < qopt->num_entries; n++) { for (n = 0; n < qopt->num_entries; n++) {
...@@ -6041,6 +6044,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -6041,6 +6044,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
struct tc_taprio_qopt_offload *qopt) struct tc_taprio_qopt_offload *qopt)
{ {
bool queue_configured[IGC_MAX_TX_QUEUES] = { }; bool queue_configured[IGC_MAX_TX_QUEUES] = { };
struct igc_hw *hw = &adapter->hw;
u32 start_time = 0, end_time = 0; u32 start_time = 0, end_time = 0;
size_t n; size_t n;
int i; int i;
...@@ -6053,7 +6057,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -6053,7 +6057,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
if (qopt->base_time < 0) if (qopt->base_time < 0)
return -ERANGE; return -ERANGE;
if (adapter->base_time) if (igc_is_device_id_i225(hw) && adapter->base_time)
return -EALREADY; return -EALREADY;
if (!validate_schedule(adapter, qopt)) if (!validate_schedule(adapter, qopt))
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2019 Intel Corporation */ /* Copyright (c) 2019 Intel Corporation */
#include "igc.h" #include "igc.h"
#include "igc_hw.h"
#include "igc_tsn.h" #include "igc_tsn.h"
static bool is_any_launchtime(struct igc_adapter *adapter) static bool is_any_launchtime(struct igc_adapter *adapter)
...@@ -92,7 +93,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) ...@@ -92,7 +93,8 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
tqavctrl = rd32(IGC_TQAVCTRL); tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
IGC_TQAVCTRL_ENHANCED_QAV); IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
wr32(IGC_TQAVCTRL, tqavctrl); wr32(IGC_TQAVCTRL, tqavctrl);
for (i = 0; i < adapter->num_tx_queues; i++) { for (i = 0; i < adapter->num_tx_queues; i++) {
...@@ -117,20 +119,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) ...@@ -117,20 +119,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
ktime_t base_time, systim; ktime_t base_time, systim;
int i; int i;
cycle = adapter->cycle_time;
base_time = adapter->base_time;
wr32(IGC_TSAUXC, 0); wr32(IGC_TSAUXC, 0);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
wr32(IGC_TXPBS, IGC_TXPBSIZE_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++) { for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i]; struct igc_ring *ring = adapter->tx_ring[i];
u32 txqctl = 0; u32 txqctl = 0;
...@@ -233,21 +225,46 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) ...@@ -233,21 +225,46 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_TXQCTL(i), txqctl); wr32(IGC_TXQCTL(i), txqctl);
} }
tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
cycle = adapter->cycle_time;
base_time = adapter->base_time;
nsec = rd32(IGC_SYSTIML); nsec = rd32(IGC_SYSTIML);
sec = rd32(IGC_SYSTIMH); sec = rd32(IGC_SYSTIMH);
systim = ktime_set(sec, nsec); systim = ktime_set(sec, nsec);
if (ktime_compare(systim, base_time) > 0) { 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); 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.
* 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) &&
!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
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); 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); wr32(IGC_BASET_L, baset_l);
return 0; return 0;
...@@ -274,17 +291,14 @@ int igc_tsn_reset(struct igc_adapter *adapter) ...@@ -274,17 +291,14 @@ int igc_tsn_reset(struct igc_adapter *adapter)
int igc_tsn_offload_apply(struct igc_adapter *adapter) int igc_tsn_offload_apply(struct igc_adapter *adapter)
{ {
int err; struct igc_hw *hw = &adapter->hw;
if (netif_running(adapter->netdev)) { if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
schedule_work(&adapter->reset_task); schedule_work(&adapter->reset_task);
return 0; return 0;
} }
err = igc_tsn_enable_offload(adapter); igc_tsn_reset(adapter);
if (err < 0)
return err;
adapter->flags = igc_tsn_new_flags(adapter);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment