[PATCH net-next 07/10] net: dsa: tag_ksz: share code for KSZ8795 and KSZ9893 xmit operations

From: Bastien Curutchet (Schneider Electric)

Date: Thu Jul 09 2026 - 02:50:36 EST


KSZ8795 and KSZ9893 have very similar tag handling in the xmit path,
leading to code duplication.

There are only two differences between the two ksz*_xmit():
- the KSZ8795 doesn't handle priorities between frames
- ksz8795_xmit() directly returns the SKB instead of calling
ksz_defer_xmit(). Yet, ksz_defer_xmit() also returns directly the SKB
if no clone is present inside the SKB. Clones are only created by the KSZ
driver when the PTP feature is enabled. Since KSZ8795 doesn't support
PTP, returning the SKB directly or ksz_defer_xmit() is the same.

The upcoming support for the KSZ8463 also requires a similar xmit().

Gather the common code from ksz8795_xmit() and ksz9893_xmit() into a new
ksz_common_xmit() function that takes three input arguments:
- do_tstamp to tell whether ksz_xmit_timestamp() should be called
- prio to give the priority tag (if any)
- override_mask to give the location of the override bit (if any)

Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@xxxxxxxxxxx>
---
net/dsa/tag_ksz.c | 73 ++++++++++++++++++++++++++-----------------------------
1 file changed, 35 insertions(+), 38 deletions(-)

diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index f58ce0f0e9e4..f8b40437c5fa 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -218,6 +218,37 @@ static struct sk_buff *ksz_defer_xmit(struct dsa_port *dp, struct sk_buff *skb)
return NULL;
}

+static struct sk_buff *ksz_common_xmit(struct sk_buff *skb,
+ struct net_device *dev,
+ bool do_tstamp,
+ u8 prio,
+ u8 override_mask)
+{
+ struct dsa_port *dp = dsa_user_to_port(dev);
+ struct ethhdr *hdr;
+ u8 *tag;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ /* Tag encoding */
+ if (do_tstamp)
+ ksz_xmit_timestamp(dp, skb);
+
+ tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
+ hdr = skb_eth_hdr(skb);
+
+ *tag = dsa_xmit_port_mask(skb, dev);
+ *tag |= prio;
+
+ if (is_link_local_ether_addr(hdr->h_dest))
+ *tag |= override_mask;
+
+ return ksz_defer_xmit(dp, skb);
+}
+
static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -308,23 +339,7 @@ MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477, KSZ9477_NAME);

static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ethhdr *hdr;
- u8 *tag;
-
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
- kfree_skb(skb);
- return NULL;
- }
-
- /* Tag encoding */
- tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
- hdr = skb_eth_hdr(skb);
-
- *tag = dsa_xmit_port_mask(skb, dev);
- if (is_link_local_ether_addr(hdr->h_dest))
- *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
-
- return skb;
+ return ksz_common_xmit(skb, dev, false, 0, KSZ8795_TAIL_TAG_OVERRIDE);
}

static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
@@ -362,28 +377,10 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
{
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 prio = netdev_txq_to_tc(dev, queue_mapping);
- struct dsa_port *dp = dsa_user_to_port(dev);
- struct ethhdr *hdr;
- u8 *tag;
-
- if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb)) {
- kfree_skb(skb);
- return NULL;
- }
-
- /* Tag encoding */
- ksz_xmit_timestamp(dp, skb);
-
- tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
- hdr = skb_eth_hdr(skb);
-
- *tag = dsa_xmit_port_mask(skb, dev);
- *tag |= FIELD_PREP(KSZ9893_TAIL_TAG_PRIO, prio);

- if (is_link_local_ether_addr(hdr->h_dest))
- *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
-
- return ksz_defer_xmit(dp, skb);
+ return ksz_common_xmit(skb, dev, true,
+ FIELD_PREP(KSZ9893_TAIL_TAG_PRIO, prio),
+ KSZ9893_TAIL_TAG_OVERRIDE);
}

static const struct dsa_device_ops ksz9893_netdev_ops = {

--
2.54.0