Message ID | 20241115024744.1903377-3-wei.fang@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Add more feautues for ENETC v4 - round 1 | expand |
On Fri, 15 Nov 2024 10:47:41 +0800 Wei Fang wrote: > +static inline bool enetc_skb_is_ipv6(struct sk_buff *skb) > +{ > + return vlan_get_protocol(skb) == htons(ETH_P_IPV6); > +} > + > +static inline bool enetc_skb_is_tcp(struct sk_buff *skb) > +{ > + return skb->csum_offset == offsetof(struct tcphdr, check); > +} Please don't use "inline" for trivial functions, compiler will inline them anyway, and it hides unused code. In addition to being pointless. > static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) > { > bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false; > @@ -160,6 +181,27 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) > dma_addr_t dma; > u8 flags = 0; > > + enetc_clear_tx_bd(&temp_bd); > + if (skb->ip_summed == CHECKSUM_PARTIAL) { > + /* Can not support TSD and checksum offload at the same time */ > + if (priv->active_offloads & ENETC_F_TXCSUM && > + enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) { > + temp_bd.l3_start = skb_network_offset(skb); > + temp_bd.ipcs = enetc_skb_is_ipv6(skb) ? 0 : 1; Linux calculates the IPv4 csum, always, no need. > + temp_bd.l3_hdr_size = skb_network_header_len(skb) / 4; > + temp_bd.l3t = enetc_skb_is_ipv6(skb) ? 1 : 0; no need for ternary op, simply : temp_bd.l3t = enetc_skb_is_ipv6(skb); > + temp_bd.l4t = enetc_skb_is_tcp(skb) ? ENETC_TXBD_L4T_TCP : > + ENETC_TXBD_L4T_UDP; > + flags |= ENETC_TXBD_FLAGS_CSUM_LSO | ENETC_TXBD_FLAGS_L4CS; > + } else { > + if (skb_checksum_help(skb)) { > + dev_err(tx_ring->dev, "skb_checksum_help() error\n"); > + > + return 0; don't print errors on the datapath, it may flood the logs
> On Fri, 15 Nov 2024 10:47:41 +0800 Wei Fang wrote: > > +static inline bool enetc_skb_is_ipv6(struct sk_buff *skb) { > > + return vlan_get_protocol(skb) == htons(ETH_P_IPV6); } > > + > > +static inline bool enetc_skb_is_tcp(struct sk_buff *skb) { > > + return skb->csum_offset == offsetof(struct tcphdr, check); } > > Please don't use "inline" for trivial functions, compiler will inline them anyway, > and it hides unused code. In addition to being pointless. > > > static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct > > sk_buff *skb) { > > bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false; > > @@ -160,6 +181,27 @@ static int enetc_map_tx_buffs(struct enetc_bdr > *tx_ring, struct sk_buff *skb) > > dma_addr_t dma; > > u8 flags = 0; > > > > + enetc_clear_tx_bd(&temp_bd); > > + if (skb->ip_summed == CHECKSUM_PARTIAL) { > > + /* Can not support TSD and checksum offload at the same time */ > > + if (priv->active_offloads & ENETC_F_TXCSUM && > > + enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) { > > + temp_bd.l3_start = skb_network_offset(skb); > > + temp_bd.ipcs = enetc_skb_is_ipv6(skb) ? 0 : 1; > > Linux calculates the IPv4 csum, always, no need. > > > + temp_bd.l3_hdr_size = skb_network_header_len(skb) / 4; > > + temp_bd.l3t = enetc_skb_is_ipv6(skb) ? 1 : 0; > > no need for ternary op, simply : > > temp_bd.l3t = enetc_skb_is_ipv6(skb); > > > + temp_bd.l4t = enetc_skb_is_tcp(skb) ? ENETC_TXBD_L4T_TCP : > > + ENETC_TXBD_L4T_UDP; > > + flags |= ENETC_TXBD_FLAGS_CSUM_LSO | > ENETC_TXBD_FLAGS_L4CS; > > + } else { > > + if (skb_checksum_help(skb)) { > > + dev_err(tx_ring->dev, "skb_checksum_help() error\n"); > > + > > + return 0; > > don't print errors on the datapath, it may flood the logs Thanks for the comments, I will improve this patch. > -- > pw-bot: cr
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 3137b6ee62d3..eeefd536d051 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -143,6 +143,27 @@ static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp, return 0; } +static bool enetc_tx_csum_offload_check(struct sk_buff *skb) +{ + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + case offsetof(struct udphdr, check): + return true; + default: + return false; + } +} + +static inline bool enetc_skb_is_ipv6(struct sk_buff *skb) +{ + return vlan_get_protocol(skb) == htons(ETH_P_IPV6); +} + +static inline bool enetc_skb_is_tcp(struct sk_buff *skb) +{ + return skb->csum_offset == offsetof(struct tcphdr, check); +} + static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) { bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false; @@ -160,6 +181,27 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) dma_addr_t dma; u8 flags = 0; + enetc_clear_tx_bd(&temp_bd); + if (skb->ip_summed == CHECKSUM_PARTIAL) { + /* Can not support TSD and checksum offload at the same time */ + if (priv->active_offloads & ENETC_F_TXCSUM && + enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) { + temp_bd.l3_start = skb_network_offset(skb); + temp_bd.ipcs = enetc_skb_is_ipv6(skb) ? 0 : 1; + temp_bd.l3_hdr_size = skb_network_header_len(skb) / 4; + temp_bd.l3t = enetc_skb_is_ipv6(skb) ? 1 : 0; + temp_bd.l4t = enetc_skb_is_tcp(skb) ? ENETC_TXBD_L4T_TCP : + ENETC_TXBD_L4T_UDP; + flags |= ENETC_TXBD_FLAGS_CSUM_LSO | ENETC_TXBD_FLAGS_L4CS; + } else { + if (skb_checksum_help(skb)) { + dev_err(tx_ring->dev, "skb_checksum_help() error\n"); + + return 0; + } + } + } + i = tx_ring->next_to_use; txbd = ENETC_TXBD(*tx_ring, i); prefetchw(txbd); @@ -170,7 +212,6 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) temp_bd.addr = cpu_to_le64(dma); temp_bd.buf_len = cpu_to_le16(len); - temp_bd.lstatus = 0; tx_swbd = &tx_ring->tx_swbd[i]; tx_swbd->dma = dma; @@ -591,7 +632,7 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb, { struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_bdr *tx_ring; - int count, err; + int count; /* Queue one-step Sync packet if already locked */ if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) { @@ -624,11 +665,6 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (skb->ip_summed == CHECKSUM_PARTIAL) { - err = skb_checksum_help(skb); - if (err) - goto drop_packet_err; - } enetc_lock_mdio(); count = enetc_map_tx_buffs(tx_ring, skb); enetc_unlock_mdio(); @@ -3287,6 +3323,7 @@ static const struct enetc_drvdata enetc4_pf_data = { .sysclk_freq = ENETC_CLK_333M, .pmac_offset = ENETC4_PMAC_OFFSET, .rx_csum = 1, + .tx_csum = 1, .eth_ops = &enetc4_pf_ethtool_ops, }; diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index 5b65f79e05be..ee11ff97e9ed 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -235,6 +235,7 @@ enum enetc_errata { struct enetc_drvdata { u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */ u8 rx_csum:1; + u8 tx_csum:1; u64 sysclk_freq; const struct ethtool_ops *eth_ops; }; @@ -343,6 +344,7 @@ enum enetc_active_offloads { ENETC_F_QCI = BIT(10), ENETC_F_QBU = BIT(11), ENETC_F_RXCSUM = BIT(12), + ENETC_F_TXCSUM = BIT(13), }; enum enetc_flags_bit { diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index 4b8fd1879005..590b1412fadf 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -558,7 +558,12 @@ union enetc_tx_bd { __le16 frm_len; union { struct { - u8 reserved[3]; + u8 l3_start:7; + u8 ipcs:1; + u8 l3_hdr_size:7; + u8 l3t:1; + u8 resv:5; + u8 l4t:3; u8 flags; }; /* default layout */ __le32 txstart; @@ -582,10 +587,10 @@ union enetc_tx_bd { }; enum enetc_txbd_flags { - ENETC_TXBD_FLAGS_RES0 = BIT(0), /* reserved */ + ENETC_TXBD_FLAGS_L4CS = BIT(0), /* For ENETC 4.1 and later */ ENETC_TXBD_FLAGS_TSE = BIT(1), ENETC_TXBD_FLAGS_W = BIT(2), - ENETC_TXBD_FLAGS_RES3 = BIT(3), /* reserved */ + ENETC_TXBD_FLAGS_CSUM_LSO = BIT(3), /* For ENETC 4.1 and later */ ENETC_TXBD_FLAGS_TXSTART = BIT(4), ENETC_TXBD_FLAGS_EX = BIT(6), ENETC_TXBD_FLAGS_F = BIT(7) @@ -594,6 +599,9 @@ enum enetc_txbd_flags { #define ENETC_TXBD_TXSTART_MASK GENMASK(24, 0) #define ENETC_TXBD_FLAGS_OFFSET 24 +#define ENETC_TXBD_L4T_UDP BIT(0) +#define ENETC_TXBD_L4T_TCP BIT(1) + static inline __le32 enetc_txbd_set_tx_start(u64 tx_start, u8 flags) { u32 temp; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c index 91e79582a541..3a8a5b6d8c26 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c @@ -122,6 +122,9 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, if (si->drvdata->rx_csum) priv->active_offloads |= ENETC_F_RXCSUM; + if (si->drvdata->tx_csum) + priv->active_offloads |= ENETC_F_TXCSUM; + /* TODO: currently, i.MX95 ENETC driver does not support advanced features */ if (!is_enetc_rev1(si)) { ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);