Commit 50762d9a authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Paolo Abeni
Browse files

net: docs: update the sample code in driver.rst



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: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 21cdc87f
Loading
Loading
Loading
Loading
+27 −34
Original line number Diff line number Diff line
@@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~