xref: /linux/include/linux/dsa/ocelot.h (revision 150b567e0d572342ef08bace7ee7aff80fd75327)
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