1 /* SPDX-License-Identifier: GPL-2.0
2 * Copyright 2019-2021 NXP
3 */
4
5 #ifndef _NET_DSA_TAG_OCELOT_H
6 #define _NET_DSA_TAG_OCELOT_H
7
8 #include <linux/if_bridge.h>
9 #include <linux/if_vlan.h>
10 #include <linux/kthread.h>
11 #include <linux/packing.h>
12 #include <linux/skbuff.h>
13 #include <net/dsa.h>
14
15 struct ocelot_skb_cb {
16 struct sk_buff *clone;
17 unsigned int ptp_class; /* valid only for clones */
18 unsigned long ptp_tx_time; /* valid only for clones */
19 u32 tstamp_lo;
20 u8 ptp_cmd;
21 u8 ts_id;
22 };
23
24 #define OCELOT_SKB_CB(skb) \
25 ((struct ocelot_skb_cb *)((skb)->cb))
26
27 #define IFH_TAG_TYPE_C 0
28 #define IFH_TAG_TYPE_S 1
29
30 #define IFH_REW_OP_NOOP 0x0
31 #define IFH_REW_OP_DSCP 0x1
32 #define IFH_REW_OP_ONE_STEP_PTP 0x2
33 #define IFH_REW_OP_TWO_STEP_PTP 0x3
34 #define IFH_REW_OP_ORIGIN_PTP 0x5
35
36 #define OCELOT_TAG_LEN 16
37 #define OCELOT_SHORT_PREFIX_LEN 4
38 #define OCELOT_LONG_PREFIX_LEN 16
39 #define OCELOT_TOTAL_TAG_LEN (OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
40
41 /* The CPU injection header and the CPU extraction header can have 3 types of
42 * prefixes: long, short and no prefix. The format of the header itself is the
43 * same in all 3 cases.
44 *
45 * Extraction with long prefix:
46 *
47 * +-------------------+-------------------+------+------+------------+-------+
48 * | ff:ff:ff:ff:ff:ff | fe:ff:ff:ff:ff:ff | 8880 | 000a | extraction | frame |
49 * | | | | | header | |
50 * +-------------------+-------------------+------+------+------------+-------+
51 * 48 bits 48 bits 16 bits 16 bits 128 bits
52 *
53 * Extraction with short prefix:
54 *
55 * +------+------+------------+-------+
56 * | 8880 | 000a | extraction | frame |
57 * | | | header | |
58 * +------+------+------------+-------+
59 * 16 bits 16 bits 128 bits
60 *
61 * Extraction with no prefix:
62 *
63 * +------------+-------+
64 * | extraction | frame |
65 * | header | |
66 * +------------+-------+
67 * 128 bits
68 *
69 *
70 * Injection with long prefix:
71 *
72 * +-------------------+-------------------+------+------+------------+-------+
73 * | any dmac | any smac | 8880 | 000a | injection | frame |
74 * | | | | | header | |
75 * +-------------------+-------------------+------+------+------------+-------+
76 * 48 bits 48 bits 16 bits 16 bits 128 bits
77 *
78 * Injection with short prefix:
79 *
80 * +------+------+------------+-------+
81 * | 8880 | 000a | injection | frame |
82 * | | | header | |
83 * +------+------+------------+-------+
84 * 16 bits 16 bits 128 bits
85 *
86 * Injection with no prefix:
87 *
88 * +------------+-------+
89 * | injection | frame |
90 * | header | |
91 * +------------+-------+
92 * 128 bits
93 *
94 * The injection header looks like this (network byte order, bit 127
95 * is part of lowest address byte in memory, bit 0 is part of highest
96 * address byte):
97 *
98 * +------+------+------+------+------+------+------+------+
99 * 127:120 |BYPASS| MASQ | MASQ_PORT |REW_OP|REW_OP|
100 * +------+------+------+------+------+------+------+------+
101 * 119:112 | REW_OP |
102 * +------+------+------+------+------+------+------+------+
103 * 111:104 | REW_VAL |
104 * +------+------+------+------+------+------+------+------+
105 * 103: 96 | REW_VAL |
106 * +------+------+------+------+------+------+------+------+
107 * 95: 88 | REW_VAL |
108 * +------+------+------+------+------+------+------+------+
109 * 87: 80 | REW_VAL |
110 * +------+------+------+------+------+------+------+------+
111 * 79: 72 | RSV |
112 * +------+------+------+------+------+------+------+------+
113 * 71: 64 | RSV | DEST |
114 * +------+------+------+------+------+------+------+------+
115 * 63: 56 | DEST |
116 * +------+------+------+------+------+------+------+------+
117 * 55: 48 | RSV |
118 * +------+------+------+------+------+------+------+------+
119 * 47: 40 | RSV | SRC_PORT | RSV |TFRM_TIMER|
120 * +------+------+------+------+------+------+------+------+
121 * 39: 32 | TFRM_TIMER | RSV |
122 * +------+------+------+------+------+------+------+------+
123 * 31: 24 | RSV | DP | POP_CNT | CPUQ |
124 * +------+------+------+------+------+------+------+------+
125 * 23: 16 | CPUQ | QOS_CLASS |TAG_TYPE|
126 * +------+------+------+------+------+------+------+------+
127 * 15: 8 | PCP | DEI | VID |
128 * +------+------+------+------+------+------+------+------+
129 * 7: 0 | VID |
130 * +------+------+------+------+------+------+------+------+
131 *
132 * And the extraction header looks like this:
133 *
134 * +------+------+------+------+------+------+------+------+
135 * 127:120 | RSV | REW_OP |
136 * +------+------+------+------+------+------+------+------+
137 * 119:112 | REW_OP | REW_VAL |
138 * +------+------+------+------+------+------+------+------+
139 * 111:104 | REW_VAL |
140 * +------+------+------+------+------+------+------+------+
141 * 103: 96 | REW_VAL |
142 * +------+------+------+------+------+------+------+------+
143 * 95: 88 | REW_VAL |
144 * +------+------+------+------+------+------+------+------+
145 * 87: 80 | REW_VAL | LLEN |
146 * +------+------+------+------+------+------+------+------+
147 * 79: 72 | LLEN | WLEN |
148 * +------+------+------+------+------+------+------+------+
149 * 71: 64 | WLEN | RSV |
150 * +------+------+------+------+------+------+------+------+
151 * 63: 56 | RSV |
152 * +------+------+------+------+------+------+------+------+
153 * 55: 48 | RSV |
154 * +------+------+------+------+------+------+------+------+
155 * 47: 40 | RSV | SRC_PORT | ACL_ID |
156 * +------+------+------+------+------+------+------+------+
157 * 39: 32 | ACL_ID | RSV | SFLOW_ID |
158 * +------+------+------+------+------+------+------+------+
159 * 31: 24 |ACL_HIT| DP | LRN_FLAGS | CPUQ |
160 * +------+------+------+------+------+------+------+------+
161 * 23: 16 | CPUQ | QOS_CLASS |TAG_TYPE|
162 * +------+------+------+------+------+------+------+------+
163 * 15: 8 | PCP | DEI | VID |
164 * +------+------+------+------+------+------+------+------+
165 * 7: 0 | VID |
166 * +------+------+------+------+------+------+------+------+
167 */
168
169 struct felix_deferred_xmit_work {
170 struct dsa_port *dp;
171 struct sk_buff *skb;
172 struct kthread_work work;
173 };
174
175 struct ocelot_8021q_tagger_data {
176 void (*xmit_work_fn)(struct kthread_work *work);
177 };
178
179 static inline struct ocelot_8021q_tagger_data *
ocelot_8021q_tagger_data(struct dsa_switch * ds)180 ocelot_8021q_tagger_data(struct dsa_switch *ds)
181 {
182 BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_OCELOT_8021Q);
183
184 return ds->tagger_data;
185 }
186
ocelot_xfh_get_rew_val(void * extraction,u64 * rew_val)187 static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val)
188 {
189 packing(extraction, rew_val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0);
190 }
191
ocelot_xfh_get_len(void * extraction,u64 * len)192 static inline void ocelot_xfh_get_len(void *extraction, u64 *len)
193 {
194 u64 llen, wlen;
195
196 packing(extraction, &llen, 84, 79, OCELOT_TAG_LEN, UNPACK, 0);
197 packing(extraction, &wlen, 78, 71, OCELOT_TAG_LEN, UNPACK, 0);
198
199 *len = 60 * wlen + llen - 80;
200 }
201
ocelot_xfh_get_src_port(void * extraction,u64 * src_port)202 static inline void ocelot_xfh_get_src_port(void *extraction, u64 *src_port)
203 {
204 packing(extraction, src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0);
205 }
206
ocelot_xfh_get_qos_class(void * extraction,u64 * qos_class)207 static inline void ocelot_xfh_get_qos_class(void *extraction, u64 *qos_class)
208 {
209 packing(extraction, qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
210 }
211
ocelot_xfh_get_tag_type(void * extraction,u64 * tag_type)212 static inline void ocelot_xfh_get_tag_type(void *extraction, u64 *tag_type)
213 {
214 packing(extraction, tag_type, 16, 16, OCELOT_TAG_LEN, UNPACK, 0);
215 }
216
ocelot_xfh_get_vlan_tci(void * extraction,u64 * vlan_tci)217 static inline void ocelot_xfh_get_vlan_tci(void *extraction, u64 *vlan_tci)
218 {
219 packing(extraction, vlan_tci, 15, 0, OCELOT_TAG_LEN, UNPACK, 0);
220 }
221
ocelot_ifh_set_bypass(void * injection,u64 bypass)222 static inline void ocelot_ifh_set_bypass(void *injection, u64 bypass)
223 {
224 packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
225 }
226
ocelot_ifh_set_rew_op(void * injection,u64 rew_op)227 static inline void ocelot_ifh_set_rew_op(void *injection, u64 rew_op)
228 {
229 packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
230 }
231
ocelot_ifh_set_dest(void * injection,u64 dest)232 static inline void ocelot_ifh_set_dest(void *injection, u64 dest)
233 {
234 packing(injection, &dest, 67, 56, OCELOT_TAG_LEN, PACK, 0);
235 }
236
ocelot_ifh_set_qos_class(void * injection,u64 qos_class)237 static inline void ocelot_ifh_set_qos_class(void *injection, u64 qos_class)
238 {
239 packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0);
240 }
241
seville_ifh_set_dest(void * injection,u64 dest)242 static inline void seville_ifh_set_dest(void *injection, u64 dest)
243 {
244 packing(injection, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0);
245 }
246
ocelot_ifh_set_src(void * injection,u64 src)247 static inline void ocelot_ifh_set_src(void *injection, u64 src)
248 {
249 packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
250 }
251
ocelot_ifh_set_tag_type(void * injection,u64 tag_type)252 static inline void ocelot_ifh_set_tag_type(void *injection, u64 tag_type)
253 {
254 packing(injection, &tag_type, 16, 16, OCELOT_TAG_LEN, PACK, 0);
255 }
256
ocelot_ifh_set_vlan_tci(void * injection,u64 vlan_tci)257 static inline void ocelot_ifh_set_vlan_tci(void *injection, u64 vlan_tci)
258 {
259 packing(injection, &vlan_tci, 15, 0, OCELOT_TAG_LEN, PACK, 0);
260 }
261
262 /* Determine the PTP REW_OP to use for injecting the given skb */
ocelot_ptp_rew_op(struct sk_buff * skb)263 static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb)
264 {
265 struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
266 u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd;
267 u32 rew_op = 0;
268
269 if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) {
270 rew_op = ptp_cmd;
271 rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3;
272 } else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
273 rew_op = ptp_cmd;
274 }
275
276 return rew_op;
277 }
278
279 /**
280 * ocelot_xmit_get_vlan_info: Determine VLAN_TCI and TAG_TYPE for injected frame
281 * @skb: Pointer to socket buffer
282 * @br: Pointer to bridge device that the port is under, if any
283 * @vlan_tci:
284 * @tag_type:
285 *
286 * If the port is under a VLAN-aware bridge, remove the VLAN header from the
287 * payload and move it into the DSA tag, which will make the switch classify
288 * the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero,
289 * which is the pvid of standalone ports (OCELOT_STANDALONE_PVID), although not
290 * of VLAN-unaware bridge ports (that would be ocelot_vlan_unaware_pvid()).
291 * Anyway, VID 0 is fine because it is stripped on egress for these port modes,
292 * and source address learning is not performed for packets injected from the
293 * CPU anyway, so it doesn't matter that the VID is "wrong".
294 */
ocelot_xmit_get_vlan_info(struct sk_buff * skb,struct net_device * br,u64 * vlan_tci,u64 * tag_type)295 static inline void ocelot_xmit_get_vlan_info(struct sk_buff *skb,
296 struct net_device *br,
297 u64 *vlan_tci, u64 *tag_type)
298 {
299 struct vlan_ethhdr *hdr;
300 u16 proto, tci;
301
302 if (!br || !br_vlan_enabled(br)) {
303 *vlan_tci = 0;
304 *tag_type = IFH_TAG_TYPE_C;
305 return;
306 }
307
308 hdr = (struct vlan_ethhdr *)skb_mac_header(skb);
309 br_vlan_get_proto(br, &proto);
310
311 if (ntohs(hdr->h_vlan_proto) == proto) {
312 vlan_remove_tag(skb, &tci);
313 *vlan_tci = tci;
314 } else {
315 rcu_read_lock();
316 br_vlan_get_pvid_rcu(br, &tci);
317 rcu_read_unlock();
318 *vlan_tci = tci;
319 }
320
321 *tag_type = (proto != ETH_P_8021Q) ? IFH_TAG_TYPE_S : IFH_TAG_TYPE_C;
322 }
323
324 #endif
325