et131x: support arbitrary MAX_SKB_FRAGS
authorEric Dumazet <edumazet@google.com>
Tue, 8 Feb 2022 00:48:55 +0000 (16:48 -0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 9 Feb 2022 00:51:23 +0000 (16:51 -0800)
This NIC does not support TSO, it is very unlikely it would
have to send packets with many fragments.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20220208004855.1887345-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/agere/et131x.c

index 537e6a8..fbf4588 100644 (file)
@@ -2413,11 +2413,13 @@ static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
        kfree(tx_ring->tcb_ring);
 }
 
+#define MAX_TX_DESC_PER_PKT 24
+
 /* nic_send_packet - NIC specific send handler for version B silicon. */
 static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
 {
        u32 i;
-       struct tx_desc desc[24];
+       struct tx_desc desc[MAX_TX_DESC_PER_PKT];
        u32 frag = 0;
        u32 thiscopy, remainder;
        struct sk_buff *skb = tcb->skb;
@@ -2432,9 +2434,6 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
         * more than 5 fragments.
         */
 
-       /* nr_frags should be no more than 18. */
-       BUILD_BUG_ON(MAX_SKB_FRAGS + 1 > 23);
-
        memset(desc, 0, sizeof(struct tx_desc) * (nr_frags + 1));
 
        for (i = 0; i < nr_frags; i++) {
@@ -3762,6 +3761,13 @@ static netdev_tx_t et131x_tx(struct sk_buff *skb, struct net_device *netdev)
        struct et131x_adapter *adapter = netdev_priv(netdev);
        struct tx_ring *tx_ring = &adapter->tx_ring;
 
+       /* This driver does not support TSO, it is very unlikely
+        * this condition is true.
+        */
+       if (unlikely(skb_shinfo(skb)->nr_frags > MAX_TX_DESC_PER_PKT - 2)) {
+               if (skb_linearize(skb))
+                       goto drop_err;
+       }
        /* stop the queue if it's getting full */
        if (tx_ring->used >= NUM_TCB - 1 && !netif_queue_stopped(netdev))
                netif_stop_queue(netdev);