mirror of
https://github.com/torvalds/linux.git
synced 2026-10-08 19:46:02 +02:00
net: stmmac: selftests: Validate EEE based on the actual LPI timer value
The EEE selftest is a 2-step test :
- It validates that we enter in LPI mode with the
irq_tx_path_in_lpi_mode_n counter
- It then validates that we exit LPI when sending a frame, with the
irq_tx_path_exit_lpi_mode_n counter.
The current state of the test lacks 2 main things :
- We don't know exactly when was the previous frame sent (it's from the
previous selftest)
- The timeout is hardcoded, while the LPI is entered after a
user-configurable delay. On top of that, the timeout loop uses a
pre-decrement iterator (--retries) that actually only iterate nine
times, so 900ms while the default LPI value is 1 second.
Let's therefore make it more deterministic :
- Send a frame at the beginning of the test
- Wait for more than the lpi timer value, we timeout after about twice
the value,
- Then send another frame, and verify that we do go out of LPI, also
with a timeout.
As LPI timer can get pretty high, bail out if LPI timer is over 5
seconds.
Note that the test's goal isn't to validate the LPI timer value itself,
only that we enter/leave LPI mode.
Fixes: 091810dbde ("net: stmmac: Introduce selftests support")
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260917215339.2022523-3-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
d68acbf935
commit
c8c1795aa8
|
|
@ -30,6 +30,7 @@ struct stmmachdr {
|
|||
sizeof(struct stmmachdr))
|
||||
#define STMMAC_TEST_PKT_MAGIC 0xdeadcafecafedeadULL
|
||||
#define STMMAC_LB_TIMEOUT msecs_to_jiffies(200)
|
||||
#define STMMAC_SFT_MAX_LPI (5 * USEC_PER_SEC)
|
||||
|
||||
struct stmmac_packet_attrs {
|
||||
int vlan;
|
||||
|
|
@ -462,12 +463,16 @@ static int stmmac_test_mmc(struct stmmac_priv *priv)
|
|||
static int stmmac_test_eee(struct stmmac_priv *priv)
|
||||
{
|
||||
struct stmmac_extra_stats *initial, *final;
|
||||
int retries = 10;
|
||||
unsigned long timeout, max_duration;
|
||||
int ret;
|
||||
|
||||
if (!priv->dma_cap.eee || !priv->eee_active)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Bail out if the configured LPI timer is too long */
|
||||
if (priv->tx_lpi_timer > STMMAC_SFT_MAX_LPI)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
initial = kzalloc_obj(*initial);
|
||||
if (!initial)
|
||||
return -ENOMEM;
|
||||
|
|
@ -478,14 +483,21 @@ static int stmmac_test_eee(struct stmmac_priv *priv)
|
|||
goto out_free_initial;
|
||||
}
|
||||
|
||||
/* Snapshot stats, we want to count the in_lpi events. We may enter
|
||||
* LPI just after the packet was sent.
|
||||
*/
|
||||
memcpy(initial, &priv->xstats, sizeof(*initial));
|
||||
|
||||
/* Send a frame, then wait to enter LPI */
|
||||
ret = stmmac_test_mac_loopback(priv);
|
||||
if (ret)
|
||||
goto out_free_final;
|
||||
|
||||
max_duration = usecs_to_jiffies(2 * priv->tx_lpi_timer);
|
||||
|
||||
/* We have no traffic in the line so, sooner or later it will go LPI */
|
||||
while (--retries) {
|
||||
timeout = jiffies + max_duration;
|
||||
while (!time_after(jiffies, timeout)) {
|
||||
memcpy(final, &priv->xstats, sizeof(*final));
|
||||
|
||||
if (final->irq_tx_path_in_lpi_mode_n >
|
||||
|
|
@ -494,20 +506,38 @@ static int stmmac_test_eee(struct stmmac_priv *priv)
|
|||
msleep(100);
|
||||
}
|
||||
|
||||
if (!retries) {
|
||||
memcpy(final, &priv->xstats, sizeof(*final));
|
||||
if (final->irq_tx_path_in_lpi_mode_n <=
|
||||
initial->irq_tx_path_in_lpi_mode_n) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out_free_final;
|
||||
}
|
||||
|
||||
if (final->irq_tx_path_in_lpi_mode_n <=
|
||||
initial->irq_tx_path_in_lpi_mode_n) {
|
||||
ret = -EINVAL;
|
||||
/* Re-snapshot, as we want to measure exit_lpi events. We should be
|
||||
* in LPI right now.
|
||||
*/
|
||||
memcpy(initial, &priv->xstats, sizeof(*initial));
|
||||
|
||||
/* TX something so we go out of LPI */
|
||||
ret = stmmac_test_mac_loopback(priv);
|
||||
if (ret)
|
||||
goto out_free_final;
|
||||
|
||||
/* Wait for the exit LPI interrupt */
|
||||
timeout = jiffies + max_duration;
|
||||
while (!time_after(jiffies, timeout)) {
|
||||
memcpy(final, &priv->xstats, sizeof(*final));
|
||||
|
||||
if (final->irq_tx_path_exit_lpi_mode_n >
|
||||
initial->irq_tx_path_exit_lpi_mode_n)
|
||||
break;
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
memcpy(final, &priv->xstats, sizeof(*final));
|
||||
if (final->irq_tx_path_exit_lpi_mode_n <=
|
||||
initial->irq_tx_path_exit_lpi_mode_n) {
|
||||
ret = -EINVAL;
|
||||
ret = -ETIMEDOUT;
|
||||
goto out_free_final;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user