Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | ===================== |
| 4 | Softnet Driver Issues |
| 5 | ===================== |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6 | |
| 7 | Transmit path guidelines: |
| 8 | |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 9 | 1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under |
| 10 | any normal circumstances. It is considered a hard error unless |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11 | there is no way your device can tell ahead of time when it's |
| 12 | transmit function will become busy. |
| 13 | |
| 14 | Instead it must maintain the queue properly. For example, |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 15 | for a driver implementing scatter-gather this means:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 16 | |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 17 | static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb, |
| 18 | struct net_device *dev) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 19 | { |
Wang Chen | b74ca3a | 2008-12-08 01:14:16 -0800 | [diff] [blame] | 20 | struct drv *dp = netdev_priv(dev); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | |
| 22 | lock_tx(dp); |
| 23 | ... |
| 24 | /* This is a hard error log it. */ |
| 25 | if (TX_BUFFS_AVAIL(dp) <= (skb_shinfo(skb)->nr_frags + 1)) { |
| 26 | netif_stop_queue(dev); |
| 27 | unlock_tx(dp); |
| 28 | printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", |
| 29 | dev->name); |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 30 | return NETDEV_TX_BUSY; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 | } |
| 32 | |
| 33 | ... queue packet to card ... |
| 34 | ... update tx consumer index ... |
| 35 | |
| 36 | if (TX_BUFFS_AVAIL(dp) <= (MAX_SKB_FRAGS + 1)) |
| 37 | netif_stop_queue(dev); |
| 38 | |
| 39 | ... |
| 40 | unlock_tx(dp); |
| 41 | ... |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 42 | return NETDEV_TX_OK; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 | } |
| 44 | |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 45 | And then at the end of your TX reclamation event handling:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | |
| 47 | if (netif_queue_stopped(dp->dev) && |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 48 | TX_BUFFS_AVAIL(dp) > (MAX_SKB_FRAGS + 1)) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 | netif_wake_queue(dp->dev); |
| 50 | |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 51 | For a non-scatter-gather supporting card, the three tests simply become:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 52 | |
| 53 | /* This is a hard error log it. */ |
| 54 | if (TX_BUFFS_AVAIL(dp) <= 0) |
| 55 | |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 56 | and:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 57 | |
| 58 | if (TX_BUFFS_AVAIL(dp) == 0) |
| 59 | |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 60 | and:: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 | |
| 62 | if (netif_queue_stopped(dp->dev) && |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 63 | TX_BUFFS_AVAIL(dp) > 0) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 64 | netif_wake_queue(dp->dev); |
| 65 | |
Ben Hutchings | de7aca1 | 2012-04-05 14:40:06 +0000 | [diff] [blame] | 66 | 2) An ndo_start_xmit method must not modify the shared parts of a |
Matti Linnanvuori | ce3ba13 | 2008-01-15 06:25:27 -0800 | [diff] [blame] | 67 | cloned SKB. |
| 68 | |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 69 | 3) Do not forget that once you return NETDEV_TX_OK from your |
| 70 | ndo_start_xmit method, it is your driver's responsibility to free |
| 71 | up the SKB and in some finite amount of time. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 72 | |
| 73 | For example, this means that it is not allowed for your TX |
| 74 | mitigation scheme to let TX packets "hang out" in the TX |
| 75 | ring unreclaimed forever if no new TX packets are sent. |
| 76 | This error can deadlock sockets waiting for send buffer room |
| 77 | to be freed up. |
| 78 | |
Ben Hutchings | e34fac1 | 2012-04-05 14:40:25 +0000 | [diff] [blame] | 79 | If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you |
| 80 | must not keep any reference to that SKB and you must not attempt |
| 81 | to free it up. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 82 | |
| 83 | Probing guidelines: |
| 84 | |
| 85 | 1) Any hardware layer address you obtain for your device should |
| 86 | be verified. For example, for ethernet check it with |
| 87 | linux/etherdevice.h:is_valid_ether_addr() |
| 88 | |
| 89 | Close/stop guidelines: |
| 90 | |
Ben Hutchings | b3cf654 | 2012-04-05 14:39:47 +0000 | [diff] [blame] | 91 | 1) After the ndo_stop routine has been called, the hardware must |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 92 | not receive or transmit any data. All in flight packets must |
Mauro Carvalho Chehab | 28d2331 | 2020-04-28 00:01:33 +0200 | [diff] [blame] | 93 | be aborted. If necessary, poll or wait for completion of |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 | any reset commands. |
| 95 | |
Ben Hutchings | b3cf654 | 2012-04-05 14:39:47 +0000 | [diff] [blame] | 96 | 2) The ndo_stop routine will be called by unregister_netdevice |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 97 | if device is still UP. |