Commit 484caf20 authored by David S. Miller's avatar David S. Miller

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

ueue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2024-08-07 (igc)

This series contains updates to igc driver only.

Faizal adjusts the size of the MAC internal buffer on i226 devices to
resolve an errata for leaking packet transmits. He also corrects a
condition in which qbv_config_change_errors are incorrectly counted.
Lastly, he adjusts the conditions for resetting the adapter when
changing TSN Tx mode and corrects the conditions in which gtxoffset
register is set.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9a039eeb 6c3fc0b1
......@@ -404,6 +404,12 @@
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
/* Retry Buffer Control */
#define IGC_RETX_CTL 0x041C
#define IGC_RETX_CTL_WATERMARK_MASK 0xF
#define IGC_RETX_CTL_QBVFULLTH_SHIFT 8 /* QBV Retry Buffer Full Threshold */
#define IGC_RETX_CTL_QBVFULLEN 0x1000 /* Enable QBV Retry Buffer Full Threshold */
/* Transmit Scheduling Latency */
/* Latency between transmission scheduling (LaunchTime) and the time
* the packet is transmitted to the network in nanosecond.
......
......@@ -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];
......
......@@ -49,12 +49,19 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
return new_flags;
}
static bool igc_tsn_is_tx_mode_in_tsn(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
return !!(rd32(IGC_TQAVCTRL) & IGC_TQAVCTRL_TRANSMIT_MODE_TSN);
}
void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u16 txoffset;
if (!is_any_launchtime(adapter))
if (!igc_tsn_is_tx_mode_in_tsn(adapter))
return;
switch (adapter->link_speed) {
......@@ -78,6 +85,23 @@ void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
wr32(IGC_GTXOFFSET, txoffset);
}
static void igc_tsn_restore_retx_default(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 retxctl;
retxctl = rd32(IGC_RETX_CTL) & IGC_RETX_CTL_WATERMARK_MASK;
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.
*/
......@@ -91,6 +115,9 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
if (igc_is_device_id_i226(hw))
igc_tsn_restore_retx_default(adapter);
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
......@@ -111,6 +138,25 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
return 0;
}
/* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes
* to 88 Bytes by setting RETX_CTL register using the recommendation from:
* a) Ethernet Controller I225/I226 Specification Update Rev 2.1
* Item 9: TSN: Packet Transmission Might Cross the Qbv Window
* b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control
*/
static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 retxctl, watermark;
retxctl = rd32(IGC_RETX_CTL);
watermark = retxctl & IGC_RETX_CTL_WATERMARK_MASK;
/* Set QBVFULLTH value using watermark and set QBVFULLEN */
retxctl |= (watermark << IGC_RETX_CTL_QBVFULLTH_SHIFT) |
IGC_RETX_CTL_QBVFULLEN;
wr32(IGC_RETX_CTL, retxctl);
}
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
......@@ -123,6 +169,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
if (igc_is_device_id_i226(hw))
igc_tsn_set_retx_qbvfullthreshold(adapter);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
u32 txqctl = 0;
......@@ -262,14 +311,6 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
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;
......@@ -331,15 +372,22 @@ int igc_tsn_reset(struct igc_adapter *adapter)
return err;
}
int igc_tsn_offload_apply(struct igc_adapter *adapter)
static bool igc_tsn_will_tx_mode_change(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
bool any_tsn_enabled = !!(igc_tsn_new_flags(adapter) &
IGC_FLAG_TSN_ANY_ENABLED);
/* Per I225/6 HW Design Section 7.5.2.1, transmit mode
* cannot be changed dynamically. Require reset the adapter.
return (any_tsn_enabled && !igc_tsn_is_tx_mode_in_tsn(adapter)) ||
(!any_tsn_enabled && igc_tsn_is_tx_mode_in_tsn(adapter));
}
int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
/* Per I225/6 HW Design Section 7.5.2.1 guideline, if tx mode change
* from legacy->tsn or tsn->legacy, then reset adapter is needed.
*/
if (netif_running(adapter->netdev) &&
(igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
igc_tsn_will_tx_mode_change(adapter)) {
schedule_work(&adapter->reset_task);
return 0;
}
......
......@@ -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 */
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