xref: /linux/net/dsa/tag_gswip.c (revision cc4adab164b772a34b3340d644b7c4728498581e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel / Lantiq GSWIP V2.0 PMAC tag support
4  *
5  * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
6  */
7 
8 #include <linux/bitops.h>
9 #include <linux/etherdevice.h>
10 #include <linux/skbuff.h>
11 #include <net/dsa.h>
12 
13 #include "tag.h"
14 
15 #define GSWIP_NAME			"gswip"
16 
17 #define GSWIP_TX_HEADER_LEN		4
18 
19 /* special tag in TX path header */
20 /* Byte 0 */
21 #define GSWIP_TX_SLPID_SHIFT		0	/* source port ID */
22 #define  GSWIP_TX_SLPID_CPU		2
23 #define  GSWIP_TX_SLPID_APP1		3
24 #define  GSWIP_TX_SLPID_APP2		4
25 #define  GSWIP_TX_SLPID_APP3		5
26 #define  GSWIP_TX_SLPID_APP4		6
27 #define  GSWIP_TX_SLPID_APP5		7
28 
29 /* Byte 1 */
30 #define GSWIP_TX_CRCGEN_DIS		BIT(7)
31 #define GSWIP_TX_DPID_SHIFT		0	/* destination group ID */
32 #define  GSWIP_TX_DPID_ELAN		0
33 #define  GSWIP_TX_DPID_EWAN		1
34 #define  GSWIP_TX_DPID_CPU		2
35 #define  GSWIP_TX_DPID_APP1		3
36 #define  GSWIP_TX_DPID_APP2		4
37 #define  GSWIP_TX_DPID_APP3		5
38 #define  GSWIP_TX_DPID_APP4		6
39 #define  GSWIP_TX_DPID_APP5		7
40 
41 /* Byte 2 */
42 #define GSWIP_TX_PORT_MAP_EN		BIT(7)
43 #define GSWIP_TX_PORT_MAP_SEL		BIT(6)
44 #define GSWIP_TX_LRN_DIS		BIT(5)
45 #define GSWIP_TX_CLASS_EN		BIT(4)
46 #define GSWIP_TX_CLASS_SHIFT		0
47 #define GSWIP_TX_CLASS_MASK		GENMASK(3, 0)
48 
49 /* Byte 3 */
50 #define GSWIP_TX_DPID_EN		BIT(0)
51 #define GSWIP_TX_PORT_MAP		GENMASK(6, 1)
52 
53 #define GSWIP_RX_HEADER_LEN	8
54 
55 /* special tag in RX path header */
56 /* Byte 7 */
57 #define GSWIP_RX_SPPID_SHIFT		4
58 #define GSWIP_RX_SPPID_MASK		GENMASK(6, 4)
59 
60 static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
61 				      struct net_device *dev)
62 {
63 	u8 *gswip_tag;
64 
65 	skb_push(skb, GSWIP_TX_HEADER_LEN);
66 
67 	gswip_tag = skb->data;
68 	gswip_tag[0] = GSWIP_TX_SLPID_CPU;
69 	gswip_tag[1] = GSWIP_TX_DPID_ELAN;
70 	gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
71 	gswip_tag[3] = FIELD_PREP(GSWIP_TX_PORT_MAP, dsa_xmit_port_mask(skb, dev));
72 	gswip_tag[3] |= GSWIP_TX_DPID_EN;
73 
74 	return skb;
75 }
76 
77 static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
78 				     struct net_device *dev)
79 {
80 	int port;
81 	u8 *gswip_tag;
82 
83 	if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
84 		return NULL;
85 
86 	gswip_tag = skb->data - ETH_HLEN;
87 
88 	/* Get source port information */
89 	port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
90 	skb->dev = dsa_conduit_find_user(dev, 0, port);
91 	if (!skb->dev)
92 		return NULL;
93 
94 	/* remove GSWIP tag */
95 	skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
96 
97 	return skb;
98 }
99 
100 static const struct dsa_device_ops gswip_netdev_ops = {
101 	.name = GSWIP_NAME,
102 	.proto	= DSA_TAG_PROTO_GSWIP,
103 	.xmit = gswip_tag_xmit,
104 	.rcv = gswip_tag_rcv,
105 	.needed_headroom = GSWIP_RX_HEADER_LEN,
106 };
107 
108 MODULE_DESCRIPTION("DSA tag driver for Lantiq / Intel GSWIP switches");
109 MODULE_LICENSE("GPL");
110 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP, GSWIP_NAME);
111 
112 module_dsa_tag_driver(gswip_netdev_ops);
113