Commit b6c9ebde 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-queue

Tony Nguyen says:

====================
igc: Fix corner cases for TSN offload

Florian Kauer says:

The igc driver supports several different offloading capabilities
relevant in the TSN context. Recent patches in this area introduced
regressions for certain corner cases that are fixed in this series.

Each of the patches (except the first one) addresses a different
regression that can be separately reproduced. Still, they have
overlapping code changes so they should not be separately applied.

Especially #4 and #6 address the same observation,
but both need to be applied to avoid TX hang occurrences in
the scenario described in the patches.
====================
Signed-off-by: default avatarFlorian Kauer <florian.kauer@linutronix.de>
Reviewed-by: Kurt Kanzenbach's avatarKurt Kanzenbach <kurt@linutronix.de>
Acked-by: default avatarVinicius Costa Gomes <vinicius.gomes@intel.com>
Reviewed-by: default avatarMuhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e522c1bd 0bcc6285
...@@ -191,7 +191,7 @@ struct igc_adapter { ...@@ -191,7 +191,7 @@ struct igc_adapter {
int tc_setup_type; int tc_setup_type;
ktime_t base_time; ktime_t base_time;
ktime_t cycle_time; ktime_t cycle_time;
bool qbv_enable; bool taprio_offload_enable;
u32 qbv_config_change_errors; u32 qbv_config_change_errors;
bool qbv_transition; bool qbv_transition;
unsigned int qbv_count; unsigned int qbv_count;
......
...@@ -1016,7 +1016,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ...@@ -1016,7 +1016,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
ktime_t base_time = adapter->base_time; ktime_t base_time = adapter->base_time;
ktime_t now = ktime_get_clocktai(); ktime_t now = ktime_get_clocktai();
ktime_t baset_est, end_of_cycle; ktime_t baset_est, end_of_cycle;
u32 launchtime; s32 launchtime;
s64 n; s64 n;
n = div64_s64(ktime_sub_ns(now, base_time), cycle_time); n = div64_s64(ktime_sub_ns(now, base_time), cycle_time);
...@@ -1029,7 +1029,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ...@@ -1029,7 +1029,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
*first_flag = true; *first_flag = true;
ring->last_ff_cycle = baset_est; ring->last_ff_cycle = baset_est;
if (ktime_compare(txtime, ring->last_tx_cycle) > 0) if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0)
*insert_empty = true; *insert_empty = true;
} }
} }
...@@ -6097,6 +6097,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) ...@@ -6097,6 +6097,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
adapter->base_time = 0; adapter->base_time = 0;
adapter->cycle_time = NSEC_PER_SEC; adapter->cycle_time = NSEC_PER_SEC;
adapter->taprio_offload_enable = false;
adapter->qbv_config_change_errors = 0; adapter->qbv_config_change_errors = 0;
adapter->qbv_transition = false; adapter->qbv_transition = false;
adapter->qbv_count = 0; adapter->qbv_count = 0;
...@@ -6124,24 +6125,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -6124,24 +6125,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
size_t n; size_t n;
int i; int i;
switch (qopt->cmd) { if (qopt->cmd == TAPRIO_CMD_DESTROY)
case TAPRIO_CMD_REPLACE:
adapter->qbv_enable = true;
break;
case TAPRIO_CMD_DESTROY:
adapter->qbv_enable = false;
break;
default:
return -EOPNOTSUPP;
}
if (!adapter->qbv_enable)
return igc_tsn_clear_schedule(adapter); return igc_tsn_clear_schedule(adapter);
if (qopt->cmd != TAPRIO_CMD_REPLACE)
return -EOPNOTSUPP;
if (qopt->base_time < 0) if (qopt->base_time < 0)
return -ERANGE; return -ERANGE;
if (igc_is_device_id_i225(hw) && adapter->base_time) if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable)
return -EALREADY; return -EALREADY;
if (!validate_schedule(adapter, qopt)) if (!validate_schedule(adapter, qopt))
...@@ -6149,6 +6142,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -6149,6 +6142,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
adapter->cycle_time = qopt->cycle_time; adapter->cycle_time = qopt->cycle_time;
adapter->base_time = qopt->base_time; adapter->base_time = qopt->base_time;
adapter->taprio_offload_enable = true;
igc_ptp_read(adapter, &now); igc_ptp_read(adapter, &now);
......
...@@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) ...@@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
{ {
unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED; unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
if (adapter->qbv_enable) if (adapter->taprio_offload_enable)
new_flags |= IGC_FLAG_TSN_QBV_ENABLED; new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_any_launchtime(adapter)) if (is_any_launchtime(adapter))
...@@ -132,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) ...@@ -132,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_STQT(i), ring->start_time); wr32(IGC_STQT(i), ring->start_time);
wr32(IGC_ENDQT(i), ring->end_time); wr32(IGC_ENDQT(i), ring->end_time);
txqctl |= IGC_TXQCTL_STRICT_CYCLE | if (adapter->taprio_offload_enable) {
IGC_TXQCTL_STRICT_END; /* If taprio_offload_enable is set we are in "taprio"
* mode and we need to be strict about the
* cycles: only transmit a packet if it can be
* completed during that cycle.
*
* If taprio_offload_enable is NOT true when
* enabling TSN offload, the cycle should have
* no external effects, but is only used internally
* to adapt the base time register after a second
* has passed.
*
* Enabling strict mode in this case would
* unnecessarily prevent the transmission of
* certain packets (i.e. at the boundary of a
* second) and thus interfere with the launchtime
* feature that promises transmission at a
* certain point in time.
*/
txqctl |= IGC_TXQCTL_STRICT_CYCLE |
IGC_TXQCTL_STRICT_END;
}
if (ring->launchtime_enable) if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
......
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