// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2025-2026 NXP */ #include #include "tag.h" #define NETC_NAME "nxp_netc" /* Forward NXP switch tag */ #define NETC_TAG_FORWARD 0 /* To_Port NXP switch tag */ #define NETC_TAG_TO_PORT 1 /* SubType0: No request to perform timestamping */ #define NETC_TAG_TP_SUBTYPE0 0 /* To_Host NXP switch tag */ #define NETC_TAG_TO_HOST 2 /* SubType0: frames redirected or copied to CPU port */ #define NETC_TAG_TH_SUBTYPE0 0 /* SubType1: frames redirected or copied to CPU port with timestamp */ #define NETC_TAG_TH_SUBTYPE1 1 /* SubType2: Transmit timestamp response (two-step timestamping) */ #define NETC_TAG_TH_SUBTYPE2 2 /* NETC switch tag lengths */ #define NETC_TAG_FORWARD_LEN 6 #define NETC_TAG_TP_SUBTYPE0_LEN 6 #define NETC_TAG_TH_SUBTYPE0_LEN 6 #define NETC_TAG_TH_SUBTYPE1_LEN 14 #define NETC_TAG_TH_SUBTYPE2_LEN 14 #define NETC_TAG_CMN_LEN 5 #define NETC_TAG_SUBTYPE GENMASK(3, 0) #define NETC_TAG_TYPE GENMASK(7, 4) #define NETC_TAG_QV BIT(0) #define NETC_TAG_IPV GENMASK(4, 2) #define NETC_TAG_SWITCH GENMASK(2, 0) #define NETC_TAG_PORT GENMASK(7, 3) struct netc_tag_cmn { __be16 tpid; u8 type; u8 qos; u8 switch_port; } __packed; static void netc_fill_common_tag(struct netc_tag_cmn *tag, u8 type, u8 subtype, u8 sw_id, u8 port, u8 ipv) { tag->tpid = htons(ETH_P_NXP_NETC); tag->type = FIELD_PREP(NETC_TAG_TYPE, type) | FIELD_PREP(NETC_TAG_SUBTYPE, subtype); tag->qos = NETC_TAG_QV | FIELD_PREP(NETC_TAG_IPV, ipv); tag->switch_port = FIELD_PREP(NETC_TAG_SWITCH, sw_id) | FIELD_PREP(NETC_TAG_PORT, port); } static void *netc_fill_common_tp_tag(struct sk_buff *skb, struct net_device *ndev, u8 subtype, int tag_len) { struct dsa_port *dp = dsa_user_to_port(ndev); u16 queue = skb_get_queue_mapping(skb); s8 ipv = netdev_txq_to_tc(ndev, queue); void *tag; if (unlikely(ipv < 0)) ipv = 0; skb_push(skb, tag_len); dsa_alloc_etype_header(skb, tag_len); tag = dsa_etype_header_pos_tx(skb); memset(tag + NETC_TAG_CMN_LEN, 0, tag_len - NETC_TAG_CMN_LEN); /* As 'dsa,member' is a required property for NETC switch, the member * is used to specify the switch ID (thus the hardware switch ID and * the software switch ID are consistent), its range is 1 ~ 7. The * NETC switch driver will check this value, and if it is invalid, * the switch driver will fail the probe. * In addition, according to the nxp,netc-switch.yaml doc, the port * index will not be greater than 0xf. */ netc_fill_common_tag(tag, NETC_TAG_TO_PORT, subtype, dp->ds->index, dp->index, ipv); return tag; } static void netc_fill_tp_tag_subtype0(struct sk_buff *skb, struct net_device *ndev) { netc_fill_common_tp_tag(skb, ndev, NETC_TAG_TP_SUBTYPE0, NETC_TAG_TP_SUBTYPE0_LEN); } /* Currently only support To_Port tag, subtype 0 */ static struct sk_buff *netc_xmit(struct sk_buff *skb, struct net_device *ndev) { netc_fill_tp_tag_subtype0(skb, ndev); return skb; } static int netc_get_rx_tag_len(int type, int subtype) { /* Only NETC_TAG_TO_HOST and NETC_TAG_FORWARD are expected in RX, * NETC_TAG_TO_PORT is a TX switch tag that does not exist in RX. */ if (type == NETC_TAG_TO_HOST) { if (subtype == NETC_TAG_TH_SUBTYPE1) return NETC_TAG_TH_SUBTYPE1_LEN; else if (subtype == NETC_TAG_TH_SUBTYPE2) return NETC_TAG_TH_SUBTYPE2_LEN; else return NETC_TAG_TH_SUBTYPE0_LEN; } return NETC_TAG_FORWARD_LEN; } static struct sk_buff *netc_rcv(struct sk_buff *skb, struct net_device *ndev) { struct netc_tag_cmn *tag_cmn; int tag_len, sw_id, port; int type, subtype; if (unlikely(!pskb_may_pull(skb, NETC_TAG_MAX_LEN))) goto err_free_skb; tag_cmn = dsa_etype_header_pos_rx(skb); if (ntohs(tag_cmn->tpid) != ETH_P_NXP_NETC) { dev_warn_ratelimited(&ndev->dev, "Unknown TPID 0x%04x\n", ntohs(tag_cmn->tpid)); goto err_free_skb; } if (tag_cmn->qos & NETC_TAG_QV) skb->priority = FIELD_GET(NETC_TAG_IPV, tag_cmn->qos); sw_id = FIELD_GET(NETC_TAG_SWITCH, tag_cmn->switch_port); /* ENETC VEPA switch ID (0) is not supported yet */ if (!sw_id) { dev_warn_ratelimited(&ndev->dev, "VEPA switch ID is not supported yet\n"); goto err_free_skb; } port = FIELD_GET(NETC_TAG_PORT, tag_cmn->switch_port); skb->dev = dsa_conduit_find_user(ndev, sw_id, port); if (!skb->dev) goto err_free_skb; type = FIELD_GET(NETC_TAG_TYPE, tag_cmn->type); subtype = FIELD_GET(NETC_TAG_SUBTYPE, tag_cmn->type); if (type == NETC_TAG_FORWARD) { dsa_default_offload_fwd_mark(skb); } else if (type == NETC_TAG_TO_HOST) { /* Currently only subtype0 supported */ if (subtype != NETC_TAG_TH_SUBTYPE0) goto err_free_skb; } else { dev_warn_ratelimited(&ndev->dev, "Unexpected tag type %d\n", type); goto err_free_skb; } /* Remove Switch tag from the frame */ tag_len = netc_get_rx_tag_len(type, subtype); skb_pull_rcsum(skb, tag_len); dsa_strip_etype_header(skb, tag_len); return skb; err_free_skb: kfree_skb(skb); return NULL; } static void netc_flow_dissect(const struct sk_buff *skb, __be16 *proto, int *offset) { struct netc_tag_cmn *tag_cmn = (struct netc_tag_cmn *)(skb->data - 2); int subtype = FIELD_GET(NETC_TAG_SUBTYPE, tag_cmn->type); int type = FIELD_GET(NETC_TAG_TYPE, tag_cmn->type); int tag_len = netc_get_rx_tag_len(type, subtype); /* The RX minimum frame length of the NETC switch port is 64 bytes, * and the frame is received by the ENETC driver. From the hardware * perspective, the receive buffer of RX BD is at least 128 bytes, * so the switch tag header is guaranteed to be in the linear region * of the skb. */ *offset = tag_len; *proto = ((__be16 *)skb->data)[(tag_len / 2) - 1]; } static const struct dsa_device_ops netc_netdev_ops = { .name = NETC_NAME, .proto = DSA_TAG_PROTO_NETC, .xmit = netc_xmit, .rcv = netc_rcv, .needed_headroom = NETC_TAG_MAX_LEN, .flow_dissect = netc_flow_dissect, }; MODULE_DESCRIPTION("DSA tag driver for NXP NETC switch family"); MODULE_LICENSE("GPL"); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_NETC, NETC_NAME); module_dsa_tag_driver(netc_netdev_ops);