1
2
3
4
5
6
7#include <linux/etherdevice.h>
8#include <linux/list.h>
9#include <linux/slab.h>
10#include <net/dsa.h>
11#include "dsa_priv.h"
12
13
14#define KSZ_EGRESS_TAG_LEN 1
15#define KSZ_INGRESS_TAG_LEN 1
16
17static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
18 struct net_device *dev,
19 unsigned int port, unsigned int len)
20{
21 skb->dev = dsa_master_find_slave(dev, 0, port);
22 if (!skb->dev)
23 return NULL;
24
25 pskb_trim_rcsum(skb, skb->len - len);
26
27 dsa_default_offload_fwd_mark(skb);
28
29 return skb;
30}
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#define KSZ8795_TAIL_TAG_OVERRIDE BIT(6)
48#define KSZ8795_TAIL_TAG_LOOKUP BIT(7)
49
50static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
51{
52 struct dsa_port *dp = dsa_slave_to_port(dev);
53 u8 *tag;
54 u8 *addr;
55
56 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
57 return NULL;
58
59
60 tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
61 addr = skb_mac_header(skb);
62
63 *tag = 1 << dp->index;
64 if (is_link_local_ether_addr(addr))
65 *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
66
67 return skb;
68}
69
70static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
71{
72 u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
73
74 return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
75}
76
77static const struct dsa_device_ops ksz8795_netdev_ops = {
78 .name = "ksz8795",
79 .proto = DSA_TAG_PROTO_KSZ8795,
80 .xmit = ksz8795_xmit,
81 .rcv = ksz8795_rcv,
82 .needed_tailroom = KSZ_INGRESS_TAG_LEN,
83};
84
85DSA_TAG_DRIVER(ksz8795_netdev_ops);
86MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104#define KSZ9477_INGRESS_TAG_LEN 2
105#define KSZ9477_PTP_TAG_LEN 4
106#define KSZ9477_PTP_TAG_INDICATION 0x80
107
108#define KSZ9477_TAIL_TAG_OVERRIDE BIT(9)
109#define KSZ9477_TAIL_TAG_LOOKUP BIT(10)
110
111static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
112 struct net_device *dev)
113{
114 struct dsa_port *dp = dsa_slave_to_port(dev);
115 __be16 *tag;
116 u8 *addr;
117 u16 val;
118
119 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
120 return NULL;
121
122
123 tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN);
124 addr = skb_mac_header(skb);
125
126 val = BIT(dp->index);
127
128 if (is_link_local_ether_addr(addr))
129 val |= KSZ9477_TAIL_TAG_OVERRIDE;
130
131 *tag = cpu_to_be16(val);
132
133 return skb;
134}
135
136static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
137{
138
139 u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
140 unsigned int port = tag[0] & 7;
141 unsigned int len = KSZ_EGRESS_TAG_LEN;
142
143
144 if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
145 len += KSZ9477_PTP_TAG_LEN;
146
147 return ksz_common_rcv(skb, dev, port, len);
148}
149
150static const struct dsa_device_ops ksz9477_netdev_ops = {
151 .name = "ksz9477",
152 .proto = DSA_TAG_PROTO_KSZ9477,
153 .xmit = ksz9477_xmit,
154 .rcv = ksz9477_rcv,
155 .needed_tailroom = KSZ9477_INGRESS_TAG_LEN,
156};
157
158DSA_TAG_DRIVER(ksz9477_netdev_ops);
159MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477);
160
161#define KSZ9893_TAIL_TAG_OVERRIDE BIT(5)
162#define KSZ9893_TAIL_TAG_LOOKUP BIT(6)
163
164static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
165 struct net_device *dev)
166{
167 struct dsa_port *dp = dsa_slave_to_port(dev);
168 u8 *addr;
169 u8 *tag;
170
171 if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
172 return NULL;
173
174
175 tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
176 addr = skb_mac_header(skb);
177
178 *tag = BIT(dp->index);
179
180 if (is_link_local_ether_addr(addr))
181 *tag |= KSZ9893_TAIL_TAG_OVERRIDE;
182
183 return skb;
184}
185
186static const struct dsa_device_ops ksz9893_netdev_ops = {
187 .name = "ksz9893",
188 .proto = DSA_TAG_PROTO_KSZ9893,
189 .xmit = ksz9893_xmit,
190 .rcv = ksz9477_rcv,
191 .needed_tailroom = KSZ_INGRESS_TAG_LEN,
192};
193
194DSA_TAG_DRIVER(ksz9893_netdev_ops);
195MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
196
197static struct dsa_tag_driver *dsa_tag_driver_array[] = {
198 &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
199 &DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
200 &DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
201};
202
203module_dsa_tag_drivers(dsa_tag_driver_array);
204
205MODULE_LICENSE("GPL");
206