mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-13 00:17:02 +04:00
qualcommax: qca_edma: add TSO support
A descriptor carries a segmentation enable and the preheader the MSS, so the engine cuts an oversized frame into segments and writes the headers of each. The conduit advertises NETIF_F_TSO and NETIF_F_TSO6, the stack hands over one frame per window instead of one per segment, and the checksums the engine already generates cover the segments it produced. Assisted-by: Claude:claude-opus-5 Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> Link: https://github.com/openwrt/openwrt/pull/25117 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
1 parent
ed30f802ed
commit
e1ecaf5fe6
2 files changed
+23
-5
No files matched your search
@@ -673,6 +673,20 @@ static void edma_tx_csum(struct sk_buff *skb, struct edma_tx_preheader *txph,
|
||||
txph->tx_pre6 |= EDMA_TX_PRE6_IP_CSUM_EN;
|
||||
}
|
||||
|
||||
/* Segmentation is one bit in every descriptor of the frame and the segment
|
||||
* size in the preheader. The engine writes the headers of each segment it
|
||||
* cuts, so the checksums it is already asked for cover what it produced.
|
||||
*/
|
||||
static u32 edma_tx_tso(struct sk_buff *skb, struct edma_tx_preheader *txph)
|
||||
{
|
||||
if (!skb_is_gso(skb))
|
||||
return 0;
|
||||
|
||||
txph->tx_pre6 |= skb_shinfo(skb)->gso_size & EDMA_TX_PRE6_MSS_MASK;
|
||||
|
||||
return EDMA_TXDESC_TSO_EN;
|
||||
}
|
||||
|
||||
static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *netdev,
|
||||
struct sk_buff *skb,
|
||||
struct edma_ring *txdesc_ring)
|
||||
@@ -686,7 +700,7 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
|
||||
u16 ndesc = shinfo->nr_frags + 1;
|
||||
struct edma_txdesc *txdesc;
|
||||
u16 prod, cons, dst_info;
|
||||
u32 val, idx, i, len, bytes;
|
||||
u32 val, idx, i, len, bytes, tso;
|
||||
dma_addr_t head_dma;
|
||||
bool taken = false;
|
||||
__be16 proto;
|
||||
@@ -739,6 +753,7 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
|
||||
|
||||
txph->dst_info = dst_info;
|
||||
edma_tx_csum(skb, txph, proto);
|
||||
tso = edma_tx_tso(skb, txph);
|
||||
|
||||
txdesc_ring->skb_store[idx] = skb;
|
||||
txph->opaque = idx;
|
||||
@@ -752,7 +767,7 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
|
||||
|
||||
txdesc = EDMA_TXDESC_DESC(txdesc_ring, idx);
|
||||
txdesc->buffer_addr = cpu_to_le32(head_dma);
|
||||
txdesc->word1 = (1 << EDMA_TXDESC_PREHEADER_SHIFT) |
|
||||
txdesc->word1 = tso | (1 << EDMA_TXDESC_PREHEADER_SHIFT) |
|
||||
(ndesc > 1 ? EDMA_TXDESC_MORE : 0) |
|
||||
((EDMA_TX_PREHDR_SIZE & EDMA_TXDESC_DATA_OFFSET_MASK)
|
||||
<< EDMA_TXDESC_DATA_OFFSET_SHIFT) |
|
||||
@@ -771,8 +786,8 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
|
||||
txdesc_ring->skb_store[fidx] = skb;
|
||||
txdesc = EDMA_TXDESC_DESC(txdesc_ring, fidx);
|
||||
txdesc->buffer_addr = cpu_to_le32(dma);
|
||||
txdesc->word1 = (i + 1 < shinfo->nr_frags ?
|
||||
EDMA_TXDESC_MORE : 0) |
|
||||
txdesc->word1 = tso | (i + 1 < shinfo->nr_frags ?
|
||||
EDMA_TXDESC_MORE : 0) |
|
||||
(len & EDMA_TXDESC_DATA_LENGTH_MASK);
|
||||
}
|
||||
|
||||
@@ -1493,7 +1508,8 @@ static int edma_probe(struct platform_device *pdev)
|
||||
netdev->dev.of_node = dev->of_node;
|
||||
netdev->netdev_ops = &edma_netdev_ops;
|
||||
netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
|
||||
NETIF_F_IPV6_CSUM | NETIF_F_SG;
|
||||
NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO |
|
||||
NETIF_F_TSO6;
|
||||
netdev->features = NETIF_F_GRO | netdev->hw_features;
|
||||
/* A DSA user port takes its features from the conduit's vlan_features. */
|
||||
netdev->vlan_features = netdev->hw_features;
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
|
||||
/* TX descriptor fields */
|
||||
#define EDMA_TXDESC_MORE BIT(30)
|
||||
#define EDMA_TXDESC_TSO_EN BIT(28)
|
||||
#define EDMA_TXDESC_PREHEADER_SHIFT 29
|
||||
#define EDMA_TXDESC_PREHEADER BIT(EDMA_TXDESC_PREHEADER_SHIFT)
|
||||
#define EDMA_TXDESC_DATA_OFFSET_SHIFT 16
|
||||
@@ -195,6 +196,7 @@
|
||||
/* TX preheader fields */
|
||||
#define EDMA_TX_PRE4_ADV_OFFLOAD_EN BIT(28)
|
||||
#define EDMA_TX_PRE6_CSUM_MODE_L4 (0x1 << 29)
|
||||
#define EDMA_TX_PRE6_MSS_MASK 0x3fff
|
||||
#define EDMA_TX_PRE6_IP_CSUM_EN BIT(31)
|
||||
|
||||
/* Preheader fields */
|
||||
|
||||
Reference in new issue
Block a user