Linux 5.11-rc1
[linux/fpc-iii.git] / net / dsa / tag_gswip.c
blob2f5bd5e338ab5c908984690833e3d7fb100d2318
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Intel / Lantiq GSWIP V2.0 PMAC tag support
5 * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
6 */
8 #include <linux/bitops.h>
9 #include <linux/etherdevice.h>
10 #include <linux/skbuff.h>
11 #include <net/dsa.h>
13 #include "dsa_priv.h"
15 #define GSWIP_TX_HEADER_LEN 4
17 /* special tag in TX path header */
18 /* Byte 0 */
19 #define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */
20 #define GSWIP_TX_SLPID_CPU 2
21 #define GSWIP_TX_SLPID_APP1 3
22 #define GSWIP_TX_SLPID_APP2 4
23 #define GSWIP_TX_SLPID_APP3 5
24 #define GSWIP_TX_SLPID_APP4 6
25 #define GSWIP_TX_SLPID_APP5 7
27 /* Byte 1 */
28 #define GSWIP_TX_CRCGEN_DIS BIT(7)
29 #define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */
30 #define GSWIP_TX_DPID_ELAN 0
31 #define GSWIP_TX_DPID_EWAN 1
32 #define GSWIP_TX_DPID_CPU 2
33 #define GSWIP_TX_DPID_APP1 3
34 #define GSWIP_TX_DPID_APP2 4
35 #define GSWIP_TX_DPID_APP3 5
36 #define GSWIP_TX_DPID_APP4 6
37 #define GSWIP_TX_DPID_APP5 7
39 /* Byte 2 */
40 #define GSWIP_TX_PORT_MAP_EN BIT(7)
41 #define GSWIP_TX_PORT_MAP_SEL BIT(6)
42 #define GSWIP_TX_LRN_DIS BIT(5)
43 #define GSWIP_TX_CLASS_EN BIT(4)
44 #define GSWIP_TX_CLASS_SHIFT 0
45 #define GSWIP_TX_CLASS_MASK GENMASK(3, 0)
47 /* Byte 3 */
48 #define GSWIP_TX_DPID_EN BIT(0)
49 #define GSWIP_TX_PORT_MAP_SHIFT 1
50 #define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
52 #define GSWIP_RX_HEADER_LEN 8
54 /* special tag in RX path header */
55 /* Byte 7 */
56 #define GSWIP_RX_SPPID_SHIFT 4
57 #define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
59 static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
60 struct net_device *dev)
62 struct dsa_port *dp = dsa_slave_to_port(dev);
63 u8 *gswip_tag;
65 skb_push(skb, GSWIP_TX_HEADER_LEN);
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] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
72 gswip_tag[3] |= GSWIP_TX_DPID_EN;
74 return skb;
77 static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
78 struct net_device *dev,
79 struct packet_type *pt)
81 int port;
82 u8 *gswip_tag;
84 if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
85 return NULL;
87 gswip_tag = skb->data - ETH_HLEN;
89 /* Get source port information */
90 port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
91 skb->dev = dsa_master_find_slave(dev, 0, port);
92 if (!skb->dev)
93 return NULL;
95 /* remove GSWIP tag */
96 skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
98 return skb;
101 static const struct dsa_device_ops gswip_netdev_ops = {
102 .name = "gswip",
103 .proto = DSA_TAG_PROTO_GSWIP,
104 .xmit = gswip_tag_xmit,
105 .rcv = gswip_tag_rcv,
106 .overhead = GSWIP_RX_HEADER_LEN,
109 MODULE_LICENSE("GPL");
110 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP);
112 module_dsa_tag_driver(gswip_netdev_ops);