net: docs: update the sample code in driver.rst
authorJakub Kicinski <kuba@kernel.org>
Wed, 12 Apr 2023 01:50:36 +0000 (18:50 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 13 Apr 2023 11:30:21 +0000 (13:30 +0200)
The sample code talks about single-queue devices and uses locks.
Update it to something resembling more modern code.
Make sure we mention use of READ_ONCE() / WRITE_ONCE().

Change the comment which talked about consumer on the xmit side.
AFAIU xmit is the producer and completions are a consumer.

Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Documentation/networking/driver.rst

index 4071f2c..4f5dfa9 100644 (file)
@@ -47,30 +47,43 @@ for a driver implementing scatter-gather this means:
 
 .. code-block:: c
 
+       static u32 drv_tx_avail(struct drv_ring *dr)
+       {
+               u32 used = READ_ONCE(dr->prod) - READ_ONCE(dr->cons);
+
+               return dr->tx_ring_size - (used & bp->tx_ring_mask);
+       }
+
        static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb,
                                               struct net_device *dev)
        {
                struct drv *dp = netdev_priv(dev);
+               struct netdev_queue *txq;
+               struct drv_ring *dr;
+               int idx;
+
+               idx = skb_get_queue_mapping(skb);
+               dr = dp->tx_rings[idx];
+               txq = netdev_get_tx_queue(dev, idx);
 
-               lock_tx(dp);
                //...
-               /* This is a hard error log it. */
-               if (TX_BUFFS_AVAIL(dp) <= (skb_shinfo(skb)->nr_frags + 1)) {
+               /* This should be a very rare race - log it. */
+               if (drv_tx_avail(dr) <= skb_shinfo(skb)->nr_frags + 1) {
                        netif_stop_queue(dev);
-                       unlock_tx(dp);
-                       printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-                              dev->name);
+                       netdev_warn(dev, "Tx Ring full when queue awake!\n");
                        return NETDEV_TX_BUSY;
                }
 
                //... queue packet to card ...
-               //... update tx consumer index ...
 
-               if (TX_BUFFS_AVAIL(dp) <= (MAX_SKB_FRAGS + 1))
-                       netif_stop_queue(dev);
+               netdev_tx_sent_queue(txq, skb->len);
+
+               //... update tx producer index using WRITE_ONCE() ...
+
+               if (!netif_txq_maybe_stop(txq, drv_tx_avail(dr),
+                                         MAX_SKB_FRAGS + 1, 2 * MAX_SKB_FRAGS))
+                       dr->stats.stopped++;
 
-               //...
-               unlock_tx(dp);
                //...
                return NETDEV_TX_OK;
        }
@@ -79,30 +92,10 @@ And then at the end of your TX reclamation event handling:
 
 .. code-block:: c
 
-       if (netif_queue_stopped(dp->dev) &&
-           TX_BUFFS_AVAIL(dp) > (MAX_SKB_FRAGS + 1))
-               netif_wake_queue(dp->dev);
-
-For a non-scatter-gather supporting card, the three tests simply become:
-
-.. code-block:: c
-
-               /* This is a hard error log it. */
-               if (TX_BUFFS_AVAIL(dp) <= 0)
-
-and:
-
-.. code-block:: c
-
-               if (TX_BUFFS_AVAIL(dp) == 0)
-
-and:
-
-.. code-block:: c
+       //... update tx consumer index using WRITE_ONCE() ...
 
-       if (netif_queue_stopped(dp->dev) &&
-           TX_BUFFS_AVAIL(dp) > 0)
-               netif_wake_queue(dp->dev);
+       netif_txq_completed_wake(txq, cmpl_pkts, cmpl_bytes,
+                                drv_tx_avail(dr), 2 * MAX_SKB_FRAGS);
 
 Lockless queue stop / wake helper macros
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~