xref: /linux/net/dsa/tag_xrs700x.c (revision 0be3ff0c)
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 {
30 	int source_port;
31 	u8 *trailer;
32 
33 	trailer = skb_tail_pointer(skb) - 1;
34 
35 	source_port = ffs((int)trailer[0]) - 1;
36 
37 	if (source_port < 0)
38 		return NULL;
39 
40 	skb->dev = dsa_master_find_slave(dev, 0, source_port);
41 	if (!skb->dev)
42 		return NULL;
43 
44 	if (pskb_trim_rcsum(skb, skb->len - 1))
45 		return NULL;
46 
47 	/* Frame is forwarded by hardware, don't forward in software. */
48 	dsa_default_offload_fwd_mark(skb);
49 
50 	return skb;
51 }
52 
53 static const struct dsa_device_ops xrs700x_netdev_ops = {
54 	.name	= "xrs700x",
55 	.proto	= DSA_TAG_PROTO_XRS700X,
56 	.xmit	= xrs700x_xmit,
57 	.rcv	= xrs700x_rcv,
58 	.needed_tailroom = 1,
59 };
60 
61 MODULE_LICENSE("GPL");
62 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_XRS700X);
63 
64 module_dsa_tag_driver(xrs700x_netdev_ops);
65