xref: /openbmc/linux/net/dsa/tag_xrs700x.c (revision d2a266fa)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * XRS700x tag format handling
4  * Copyright (c) 2008-2009 Marvell Semiconductor
5  * Copyright (c) 2020 NovaTech LLC
6  */
7 
8 #include <linux/bitops.h>
9 
10 #include "dsa_priv.h"
11 
12 static struct sk_buff *xrs700x_xmit(struct sk_buff *skb, struct net_device *dev)
13 {
14 	struct dsa_port *partner, *dp = dsa_slave_to_port(dev);
15 	u8 *trailer;
16 
17 	trailer = skb_put(skb, 1);
18 	trailer[0] = BIT(dp->index);
19 
20 	if (dp->hsr_dev)
21 		dsa_hsr_foreach_port(partner, dp->ds, dp->hsr_dev)
22 			if (partner != dp)
23 				trailer[0] |= BIT(partner->index);
24 
25 	return skb;
26 }
27 
28 static struct sk_buff *xrs700x_rcv(struct sk_buff *skb, struct net_device *dev,
29 				   struct packet_type *pt)
30 {
31 	int source_port;
32 	u8 *trailer;
33 
34 	trailer = skb_tail_pointer(skb) - 1;
35 
36 	source_port = ffs((int)trailer[0]) - 1;
37 
38 	if (source_port < 0)
39 		return NULL;
40 
41 	skb->dev = dsa_master_find_slave(dev, 0, source_port);
42 	if (!skb->dev)
43 		return NULL;
44 
45 	if (pskb_trim_rcsum(skb, skb->len - 1))
46 		return NULL;
47 
48 	/* Frame is forwarded by hardware, don't forward in software. */
49 	skb->offload_fwd_mark = 1;
50 
51 	return skb;
52 }
53 
54 static const struct dsa_device_ops xrs700x_netdev_ops = {
55 	.name	= "xrs700x",
56 	.proto	= DSA_TAG_PROTO_XRS700X,
57 	.xmit	= xrs700x_xmit,
58 	.rcv	= xrs700x_rcv,
59 	.needed_tailroom = 1,
60 };
61 
62 MODULE_LICENSE("GPL");
63 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_XRS700X);
64 
65 module_dsa_tag_driver(xrs700x_netdev_ops);
66