Commit | Line | Data |
---|---|---|
79691192 HM |
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 | ||
bd954b82 | 13 | #include "tag.h" |
79691192 | 14 | |
94793a56 VO |
15 | #define GSWIP_NAME "gswip" |
16 | ||
79691192 HM |
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_SHIFT 1 | |
52 | #define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1) | |
53 | ||
54 | #define GSWIP_RX_HEADER_LEN 8 | |
55 | ||
56 | /* special tag in RX path header */ | |
57 | /* Byte 7 */ | |
58 | #define GSWIP_RX_SPPID_SHIFT 4 | |
59 | #define GSWIP_RX_SPPID_MASK GENMASK(6, 4) | |
60 | ||
61 | static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb, | |
62 | struct net_device *dev) | |
63 | { | |
6ca80638 | 64 | struct dsa_port *dp = dsa_user_to_port(dev); |
79691192 HM |
65 | u8 *gswip_tag; |
66 | ||
79691192 HM |
67 | skb_push(skb, GSWIP_TX_HEADER_LEN); |
68 | ||
69 | gswip_tag = skb->data; | |
70 | gswip_tag[0] = GSWIP_TX_SLPID_CPU; | |
71 | gswip_tag[1] = GSWIP_TX_DPID_ELAN; | |
72 | gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL; | |
73 | gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK; | |
74 | gswip_tag[3] |= GSWIP_TX_DPID_EN; | |
75 | ||
76 | return skb; | |
77 | } | |
78 | ||
79 | static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb, | |
29a097b7 | 80 | struct net_device *dev) |
79691192 HM |
81 | { |
82 | int port; | |
83 | u8 *gswip_tag; | |
84 | ||
85 | if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN))) | |
86 | return NULL; | |
87 | ||
88 | gswip_tag = skb->data - ETH_HLEN; | |
89 | ||
90 | /* Get source port information */ | |
91 | port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT; | |
6ca80638 | 92 | skb->dev = dsa_conduit_find_user(dev, 0, port); |
79691192 HM |
93 | if (!skb->dev) |
94 | return NULL; | |
95 | ||
96 | /* remove GSWIP tag */ | |
97 | skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN); | |
98 | ||
99 | return skb; | |
100 | } | |
101 | ||
f81a43e8 | 102 | static const struct dsa_device_ops gswip_netdev_ops = { |
94793a56 | 103 | .name = GSWIP_NAME, |
056eed2f | 104 | .proto = DSA_TAG_PROTO_GSWIP, |
79691192 HM |
105 | .xmit = gswip_tag_xmit, |
106 | .rcv = gswip_tag_rcv, | |
4e500251 | 107 | .needed_headroom = GSWIP_RX_HEADER_LEN, |
79691192 | 108 | }; |
0b42f033 | 109 | |
0ed6e952 | 110 | MODULE_DESCRIPTION("DSA tag driver for Lantiq / Intel GSWIP switches"); |
f18bba50 | 111 | MODULE_LICENSE("GPL"); |
94793a56 | 112 | MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_GSWIP, GSWIP_NAME); |
d3b8c049 AL |
113 | |
114 | module_dsa_tag_driver(gswip_netdev_ops); |