|
|
|
@@ -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 @@ 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)) &&
|
|
|
|
|
(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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool igc_tsn_will_tx_mode_change(struct igc_adapter *adapter)
|
|
|
|
|
{
|
|
|
|
|
bool any_tsn_enabled = !!(igc_tsn_new_flags(adapter) &
|
|
|
|
|
IGC_FLAG_TSN_ANY_ENABLED);
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
struct igc_hw *hw = &adapter->hw;
|
|
|
|
|
|
|
|
|
|
/* Per I225/6 HW Design Section 7.5.2.1, transmit mode
|
|
|
|
|
* cannot be changed dynamically. Require reset the 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;
|
|
|
|
|
}
|
|
|
|
|