From: Michal Kubiak <michal.kub...@intel.com>

netif_txq_maybe_stop() returns -1, 0, or 1, while
idpf_tx_maybe_stop_common() says it returns 0 or -EBUSY. As a result,
there sometimes are Tx queue timeout warnings despite that the queue
is empty or there is at least enough space to restart it.
Make idpf_tx_maybe_stop_common() inline and returning true or false,
handling the return of netif_txq_maybe_stop() properly. Use a correct
goto in idpf_tx_maybe_stop_splitq() to avoid stopping the queue or
incrementing the stops counter twice.

Fixes: 6818c4d5b3c2 ("idpf: add splitq start_xmit")
Fixes: a5ab9ee0df0b ("idpf: add singleq start_xmit and napi poll")
Cc: sta...@vger.kernel.org # 6.7+
Signed-off-by: Michal Kubiak <michal.kub...@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kits...@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.loba...@intel.com>
---
 drivers/net/ethernet/intel/idpf/idpf_txrx.h   |  9 ++++-
 .../ethernet/intel/idpf/idpf_singleq_txrx.c   |  4 +++
 drivers/net/ethernet/intel/idpf/idpf_txrx.c   | 35 +++++--------------
 3 files changed, 21 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h 
b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index 3a2a92e79e60..33305de06975 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -1018,7 +1018,6 @@ void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, 
struct sk_buff *skb,
                           struct idpf_tx_buf *first, u16 ring_idx);
 unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq,
                                         struct sk_buff *skb);
-int idpf_tx_maybe_stop_common(struct idpf_tx_queue *tx_q, unsigned int size);
 void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue);
 netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
                                  struct idpf_tx_queue *tx_q);
@@ -1027,4 +1026,12 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct 
idpf_rx_queue *rxq,
                                      u16 cleaned_count);
 int idpf_tso(struct sk_buff *skb, struct idpf_tx_offload_params *off);
 
+static inline bool idpf_tx_maybe_stop_common(struct idpf_tx_queue *tx_q,
+                                            u32 needed)
+{
+       return !netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx,
+                                         IDPF_DESC_UNUSED(tx_q),
+                                         needed, needed);
+}
+
 #endif /* !_IDPF_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c 
b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
index 947d3ff9677c..5ba360abbe66 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
@@ -375,6 +375,10 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb,
                                      IDPF_TX_DESCS_FOR_CTX)) {
                idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false);
 
+               u64_stats_update_begin(&tx_q->stats_sync);
+               u64_stats_inc(&tx_q->q_stats.q_busy);
+               u64_stats_update_end(&tx_q->stats_sync);
+
                return NETDEV_TX_BUSY;
        }
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c 
b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index a7f7efc61caf..05555303e097 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -2131,29 +2131,6 @@ void idpf_tx_splitq_build_flow_desc(union 
idpf_tx_flex_desc *desc,
        desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag);
 }
 
-/**
- * idpf_tx_maybe_stop_common - 1st level check for common Tx stop conditions
- * @tx_q: the queue to be checked
- * @size: number of descriptors we want to assure is available
- *
- * Returns 0 if stop is not needed
- */
-int idpf_tx_maybe_stop_common(struct idpf_tx_queue *tx_q, unsigned int size)
-{
-       struct netdev_queue *nq;
-
-       if (likely(IDPF_DESC_UNUSED(tx_q) >= size))
-               return 0;
-
-       u64_stats_update_begin(&tx_q->stats_sync);
-       u64_stats_inc(&tx_q->q_stats.q_busy);
-       u64_stats_update_end(&tx_q->stats_sync);
-
-       nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx);
-
-       return netif_txq_maybe_stop(nq, IDPF_DESC_UNUSED(tx_q), size, size);
-}
-
 /**
  * idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions
  * @tx_q: the queue to be checked
@@ -2165,7 +2142,7 @@ static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue 
*tx_q,
                                     unsigned int descs_needed)
 {
        if (idpf_tx_maybe_stop_common(tx_q, descs_needed))
-               goto splitq_stop;
+               goto out;
 
        /* If there are too many outstanding completions expected on the
         * completion queue, stop the TX queue to give the device some time to
@@ -2184,10 +2161,12 @@ static int idpf_tx_maybe_stop_splitq(struct 
idpf_tx_queue *tx_q,
        return 0;
 
 splitq_stop:
+       netif_stop_subqueue(tx_q->netdev, tx_q->idx);
+
+out:
        u64_stats_update_begin(&tx_q->stats_sync);
        u64_stats_inc(&tx_q->q_stats.q_busy);
        u64_stats_update_end(&tx_q->stats_sync);
-       netif_stop_subqueue(tx_q->netdev, tx_q->idx);
 
        return -EBUSY;
 }
@@ -2210,7 +2189,11 @@ void idpf_tx_buf_hw_update(struct idpf_tx_queue *tx_q, 
u32 val,
        nq = netdev_get_tx_queue(tx_q->netdev, tx_q->idx);
        tx_q->next_to_use = val;
 
-       idpf_tx_maybe_stop_common(tx_q, IDPF_TX_DESC_NEEDED);
+       if (idpf_tx_maybe_stop_common(tx_q, IDPF_TX_DESC_NEEDED)) {
+               u64_stats_update_begin(&tx_q->stats_sync);
+               u64_stats_inc(&tx_q->q_stats.q_busy);
+               u64_stats_update_end(&tx_q->stats_sync);
+       }
 
        /* Force memory writes to complete before letting h/w
         * know there are new descriptors to fetch.  (Only
-- 
2.46.0

Reply via email to