xref: /openbmc/linux/net/dsa/tag_hellcreek.c (revision 31e67366)
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * net/dsa/tag_hellcreek.c - Hirschmann Hellcreek switch tag format handling
4  *
5  * Copyright (C) 2019,2020 Linutronix GmbH
6  * Author Kurt Kanzenbach <kurt@linutronix.de>
7  *
8  * Based on tag_ksz.c.
9  */
10 
11 #include <linux/skbuff.h>
12 #include <net/dsa.h>
13 
14 #include "dsa_priv.h"
15 
16 #define HELLCREEK_TAG_LEN	1
17 
18 static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
19 				      struct net_device *dev)
20 {
21 	struct dsa_port *dp = dsa_slave_to_port(dev);
22 	u8 *tag;
23 
24 	/* Tag encoding */
25 	tag  = skb_put(skb, HELLCREEK_TAG_LEN);
26 	*tag = BIT(dp->index);
27 
28 	return skb;
29 }
30 
31 static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
32 				     struct net_device *dev,
33 				     struct packet_type *pt)
34 {
35 	/* Tag decoding */
36 	u8 *tag = skb_tail_pointer(skb) - HELLCREEK_TAG_LEN;
37 	unsigned int port = tag[0] & 0x03;
38 
39 	skb->dev = dsa_master_find_slave(dev, 0, port);
40 	if (!skb->dev) {
41 		netdev_warn(dev, "Failed to get source port: %d\n", port);
42 		return NULL;
43 	}
44 
45 	pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN);
46 
47 	skb->offload_fwd_mark = true;
48 
49 	return skb;
50 }
51 
52 static const struct dsa_device_ops hellcreek_netdev_ops = {
53 	.name	  = "hellcreek",
54 	.proto	  = DSA_TAG_PROTO_HELLCREEK,
55 	.xmit	  = hellcreek_xmit,
56 	.rcv	  = hellcreek_rcv,
57 	.overhead = HELLCREEK_TAG_LEN,
58 	.tail_tag = true,
59 };
60 
61 MODULE_LICENSE("Dual MIT/GPL");
62 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_HELLCREEK);
63 
64 module_dsa_tag_driver(hellcreek_netdev_ops);
65