Merge branch 'introduce-and-use-netif_xmit_timeout_ms-helper'

Tariq Toukan says:

====================
Introduce and use netif_xmit_timeout_ms() helper

This is V2, find V1 here:
https://lore.kernel.org/all/1764054776-1308696-1-git-send-email-tariqt@nvidia.com/

This series by Shahar introduces a new helper function
netif_xmit_timeout_ms() to check if a TX queue has timed out and report
the timeout duration.
It also encapsulates the check for whether the TX queue is stopped.

Replace duplicated open-coded timeout check in hns3 driver with the new
helper.

For mlx5e, refine the TX timeout recovery flow to act only on SQs whose
transmit timestamp indicates an actual timeout, as determined by the
helper. This prevents unnecessary channel reopen events caused by
attempting recovery on queues that are merely stopped but not truly
timed out.
====================

Link: https://patch.msgid.link/1768209383-1546791-1-git-send-email-tariqt@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2026-01-15 11:55:09 +01:00
commit 8138fc46d9
3 changed files with 17 additions and 8 deletions

View File

@ -25,6 +25,7 @@
#include <net/tcp.h>
#include <net/vxlan.h>
#include <net/geneve.h>
#include <net/netdev_queues.h>
#include "hnae3.h"
#include "hns3_enet.h"
@ -2807,14 +2808,12 @@ static int hns3_get_timeout_queue(struct net_device *ndev)
/* Find the stopped queue the same way the stack does */
for (i = 0; i < ndev->num_tx_queues; i++) {
unsigned int timedout_ms;
struct netdev_queue *q;
unsigned long trans_start;
q = netdev_get_tx_queue(ndev, i);
trans_start = READ_ONCE(q->trans_start);
if (netif_xmit_stopped(q) &&
time_after(jiffies,
(trans_start + ndev->watchdog_timeo))) {
timedout_ms = netif_xmit_timeout_ms(q);
if (timedout_ms) {
#ifdef CONFIG_BQL
struct dql *dql = &q->dql;
@ -2823,8 +2822,7 @@ static int hns3_get_timeout_queue(struct net_device *ndev)
dql->adj_limit, dql->num_completed);
#endif
netdev_info(ndev, "queue state: 0x%lx, delta msecs: %u\n",
q->state,
jiffies_to_msecs(jiffies - trans_start));
q->state, timedout_ms);
break;
}
}

View File

@ -5137,7 +5137,7 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
netdev_get_tx_queue(netdev, i);
struct mlx5e_txqsq *sq = priv->txq2sq[i];
if (!netif_xmit_stopped(dev_queue))
if (!netif_xmit_timeout_ms(dev_queue))
continue;
if (mlx5e_reporter_tx_timeout(sq))

View File

@ -310,6 +310,17 @@ static inline void netif_subqueue_sent(const struct net_device *dev,
netdev_tx_sent_queue(txq, bytes);
}
static inline unsigned int netif_xmit_timeout_ms(struct netdev_queue *txq)
{
unsigned long trans_start = READ_ONCE(txq->trans_start);
if (netif_xmit_stopped(txq) &&
time_after(jiffies, trans_start + txq->dev->watchdog_timeo))
return jiffies_to_msecs(jiffies - trans_start);
return 0;
}
#define netif_subqueue_maybe_stop(dev, idx, get_desc, stop_thrs, start_thrs) \
({ \
struct netdev_queue *_txq; \