1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2020-2021 NXP
4 * An implementation of the software-defined tag_8021q.c tagger format, which
5 * also preserves full functionality under a vlan_filtering bridge. It does
6 * this by using the TCAM engines for:
7 * - pushing the RX VLAN as a second, outer tag, on egress towards the CPU port
8 * - redirecting towards the correct front port based on TX VLAN and popping
11 #include <linux/dsa/8021q.h>
12 #include <linux/dsa/ocelot.h>
13 #include <soc/mscc/ocelot.h>
14 #include <soc/mscc/ocelot_ptp.h>
17 static struct sk_buff
*ocelot_xmit(struct sk_buff
*skb
,
18 struct net_device
*netdev
)
20 struct dsa_port
*dp
= dsa_slave_to_port(netdev
);
21 u16 tx_vid
= dsa_8021q_tx_vid(dp
->ds
, dp
->index
);
22 u16 queue_mapping
= skb_get_queue_mapping(skb
);
23 u8 pcp
= netdev_txq_to_tc(netdev
, queue_mapping
);
24 struct ocelot
*ocelot
= dp
->ds
->priv
;
28 rew_op
= ocelot_ptp_rew_op(skb
);
30 if (!ocelot_can_inject(ocelot
, 0))
33 ocelot_port_inject_frame(ocelot
, port
, 0, rew_op
, skb
);
37 return dsa_8021q_xmit(skb
, netdev
, ETH_P_8021Q
,
38 ((pcp
<< VLAN_PRIO_SHIFT
) | tx_vid
));
41 static struct sk_buff
*ocelot_rcv(struct sk_buff
*skb
,
42 struct net_device
*netdev
)
44 int src_port
, switch_id
;
46 dsa_8021q_rcv(skb
, &src_port
, &switch_id
);
48 skb
->dev
= dsa_master_find_slave(netdev
, switch_id
, src_port
);
52 dsa_default_offload_fwd_mark(skb
);
57 static const struct dsa_device_ops ocelot_8021q_netdev_ops
= {
58 .name
= "ocelot-8021q",
59 .proto
= DSA_TAG_PROTO_OCELOT_8021Q
,
62 .needed_headroom
= VLAN_HLEN
,
63 .promisc_on_master
= true,
66 MODULE_LICENSE("GPL v2");
67 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OCELOT_8021Q
);
69 module_dsa_tag_driver(ocelot_8021q_netdev_ops
);