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/kthread.h>
9 #include <linux/packing.h>
10 #include <linux/skbuff.h>
11 #include <net/dsa.h>
12 
13 struct ocelot_skb_cb {
14 	struct sk_buff *clone;
15 	unsigned int ptp_class; /* valid only for clones */
16 	u32 tstamp_lo;
17 	u8 ptp_cmd;
18 	u8 ts_id;
19 };
20 
21 #define OCELOT_SKB_CB(skb) \
22 	((struct ocelot_skb_cb *)((skb)->cb))
23 
24 #define IFH_TAG_TYPE_C			0
25 #define IFH_TAG_TYPE_S			1
26 
27 #define IFH_REW_OP_NOOP			0x0
28 #define IFH_REW_OP_DSCP			0x1
29 #define IFH_REW_OP_ONE_STEP_PTP		0x2
30 #define IFH_REW_OP_TWO_STEP_PTP		0x3
31 #define IFH_REW_OP_ORIGIN_PTP		0x5
32 
33 #define OCELOT_TAG_LEN			16
34 #define OCELOT_SHORT_PREFIX_LEN		4
35 #define OCELOT_LONG_PREFIX_LEN		16
36 #define OCELOT_TOTAL_TAG_LEN	(OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN)
37 
38 /* The CPU injection header and the CPU extraction header can have 3 types of
39  * prefixes: long, short and no prefix. The format of the header itself is the
40  * same in all 3 cases.
41  *
42  * Extraction with long prefix:
43  *
44  * +-------------------+-------------------+------+------+------------+-------+
45  * | ff:ff:ff:ff:ff:ff | fe:ff:ff:ff:ff:ff | 8880 | 000a | extraction | frame |
46  * |                   |                   |      |      |   header   |       |
47  * +-------------------+-------------------+------+------+------------+-------+
48  *        48 bits             48 bits      16 bits 16 bits  128 bits
49  *
50  * Extraction with short prefix:
51  *
52  *                                         +------+------+------------+-------+
53  *                                         | 8880 | 000a | extraction | frame |
54  *                                         |      |      |   header   |       |
55  *                                         +------+------+------------+-------+
56  *                                         16 bits 16 bits  128 bits
57  *
58  * Extraction with no prefix:
59  *
60  *                                                       +------------+-------+
61  *                                                       | extraction | frame |
62  *                                                       |   header   |       |
63  *                                                       +------------+-------+
64  *                                                          128 bits
65  *
66  *
67  * Injection with long prefix:
68  *
69  * +-------------------+-------------------+------+------+------------+-------+
70  * |      any dmac     |      any smac     | 8880 | 000a | injection  | frame |
71  * |                   |                   |      |      |   header   |       |
72  * +-------------------+-------------------+------+------+------------+-------+
73  *        48 bits             48 bits      16 bits 16 bits  128 bits
74  *
75  * Injection with short prefix:
76  *
77  *                                         +------+------+------------+-------+
78  *                                         | 8880 | 000a | injection  | frame |
79  *                                         |      |      |   header   |       |
80  *                                         +------+------+------------+-------+
81  *                                         16 bits 16 bits  128 bits
82  *
83  * Injection with no prefix:
84  *
85  *                                                       +------------+-------+
86  *                                                       | injection  | frame |
87  *                                                       |   header   |       |
88  *                                                       +------------+-------+
89  *                                                          128 bits
90  *
91  * The injection header looks like this (network byte order, bit 127
92  * is part of lowest address byte in memory, bit 0 is part of highest
93  * address byte):
94  *
95  *         +------+------+------+------+------+------+------+------+
96  * 127:120 |BYPASS| MASQ |          MASQ_PORT        |REW_OP|REW_OP|
97  *         +------+------+------+------+------+------+------+------+
98  * 119:112 |                         REW_OP                        |
99  *         +------+------+------+------+------+------+------+------+
100  * 111:104 |                         REW_VAL                       |
101  *         +------+------+------+------+------+------+------+------+
102  * 103: 96 |                         REW_VAL                       |
103  *         +------+------+------+------+------+------+------+------+
104  *  95: 88 |                         REW_VAL                       |
105  *         +------+------+------+------+------+------+------+------+
106  *  87: 80 |                         REW_VAL                       |
107  *         +------+------+------+------+------+------+------+------+
108  *  79: 72 |                          RSV                          |
109  *         +------+------+------+------+------+------+------+------+
110  *  71: 64 |            RSV            |           DEST            |
111  *         +------+------+------+------+------+------+------+------+
112  *  63: 56 |                         DEST                          |
113  *         +------+------+------+------+------+------+------+------+
114  *  55: 48 |                          RSV                          |
115  *         +------+------+------+------+------+------+------+------+
116  *  47: 40 |  RSV |         SRC_PORT          |     RSV     |TFRM_TIMER|
117  *         +------+------+------+------+------+------+------+------+
118  *  39: 32 |     TFRM_TIMER     |               RSV                |
119  *         +------+------+------+------+------+------+------+------+
120  *  31: 24 |  RSV |  DP  |   POP_CNT   |           CPUQ            |
121  *         +------+------+------+------+------+------+------+------+
122  *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
123  *         +------+------+------+------+------+------+------+------+
124  *  15:  8 |         PCP        |  DEI |            VID            |
125  *         +------+------+------+------+------+------+------+------+
126  *   7:  0 |                          VID                          |
127  *         +------+------+------+------+------+------+------+------+
128  *
129  * And the extraction header looks like this:
130  *
131  *         +------+------+------+------+------+------+------+------+
132  * 127:120 |  RSV |                  REW_OP                        |
133  *         +------+------+------+------+------+------+------+------+
134  * 119:112 |       REW_OP       |              REW_VAL             |
135  *         +------+------+------+------+------+------+------+------+
136  * 111:104 |                         REW_VAL                       |
137  *         +------+------+------+------+------+------+------+------+
138  * 103: 96 |                         REW_VAL                       |
139  *         +------+------+------+------+------+------+------+------+
140  *  95: 88 |                         REW_VAL                       |
141  *         +------+------+------+------+------+------+------+------+
142  *  87: 80 |       REW_VAL      |               LLEN               |
143  *         +------+------+------+------+------+------+------+------+
144  *  79: 72 | LLEN |                      WLEN                      |
145  *         +------+------+------+------+------+------+------+------+
146  *  71: 64 | WLEN |                      RSV                       |
147  *         +------+------+------+------+------+------+------+------+
148  *  63: 56 |                          RSV                          |
149  *         +------+------+------+------+------+------+------+------+
150  *  55: 48 |                          RSV                          |
151  *         +------+------+------+------+------+------+------+------+
152  *  47: 40 | RSV  |          SRC_PORT         |       ACL_ID       |
153  *         +------+------+------+------+------+------+------+------+
154  *  39: 32 |       ACL_ID       |  RSV |         SFLOW_ID          |
155  *         +------+------+------+------+------+------+------+------+
156  *  31: 24 |ACL_HIT| DP  |  LRN_FLAGS  |           CPUQ            |
157  *         +------+------+------+------+------+------+------+------+
158  *  23: 16 |           CPUQ            |      QOS_CLASS     |TAG_TYPE|
159  *         +------+------+------+------+------+------+------+------+
160  *  15:  8 |         PCP        |  DEI |            VID            |
161  *         +------+------+------+------+------+------+------+------+
162  *   7:  0 |                          VID                          |
163  *         +------+------+------+------+------+------+------+------+
164  */
165 
166 struct felix_deferred_xmit_work {
167 	struct dsa_port *dp;
168 	struct sk_buff *skb;
169 	struct kthread_work work;
170 };
171 
172 struct ocelot_8021q_tagger_data {
173 	void (*xmit_work_fn)(struct kthread_work *work);
174 };
175 
176 static inline struct ocelot_8021q_tagger_data *
ocelot_8021q_tagger_data(struct dsa_switch * ds)177 ocelot_8021q_tagger_data(struct dsa_switch *ds)
178 {
179 	BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_OCELOT_8021Q);
180 
181 	return ds->tagger_data;
182 }
183 
ocelot_xfh_get_rew_val(void * extraction,u64 * rew_val)184 static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val)
185 {
186 	packing(extraction, rew_val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0);
187 }
188 
ocelot_xfh_get_len(void * extraction,u64 * len)189 static inline void ocelot_xfh_get_len(void *extraction, u64 *len)
190 {
191 	u64 llen, wlen;
192 
193 	packing(extraction, &llen, 84, 79, OCELOT_TAG_LEN, UNPACK, 0);
194 	packing(extraction, &wlen, 78, 71, OCELOT_TAG_LEN, UNPACK, 0);
195 
196 	*len = 60 * wlen + llen - 80;
197 }
198 
ocelot_xfh_get_src_port(void * extraction,u64 * src_port)199 static inline void ocelot_xfh_get_src_port(void *extraction, u64 *src_port)
200 {
201 	packing(extraction, src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0);
202 }
203 
ocelot_xfh_get_qos_class(void * extraction,u64 * qos_class)204 static inline void ocelot_xfh_get_qos_class(void *extraction, u64 *qos_class)
205 {
206 	packing(extraction, qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
207 }
208 
ocelot_xfh_get_tag_type(void * extraction,u64 * tag_type)209 static inline void ocelot_xfh_get_tag_type(void *extraction, u64 *tag_type)
210 {
211 	packing(extraction, tag_type, 16, 16, OCELOT_TAG_LEN, UNPACK, 0);
212 }
213 
ocelot_xfh_get_vlan_tci(void * extraction,u64 * vlan_tci)214 static inline void ocelot_xfh_get_vlan_tci(void *extraction, u64 *vlan_tci)
215 {
216 	packing(extraction, vlan_tci, 15, 0, OCELOT_TAG_LEN, UNPACK, 0);
217 }
218 
ocelot_ifh_set_bypass(void * injection,u64 bypass)219 static inline void ocelot_ifh_set_bypass(void *injection, u64 bypass)
220 {
221 	packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
222 }
223 
ocelot_ifh_set_rew_op(void * injection,u64 rew_op)224 static inline void ocelot_ifh_set_rew_op(void *injection, u64 rew_op)
225 {
226 	packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
227 }
228 
ocelot_ifh_set_dest(void * injection,u64 dest)229 static inline void ocelot_ifh_set_dest(void *injection, u64 dest)
230 {
231 	packing(injection, &dest, 67, 56, OCELOT_TAG_LEN, PACK, 0);
232 }
233 
ocelot_ifh_set_qos_class(void * injection,u64 qos_class)234 static inline void ocelot_ifh_set_qos_class(void *injection, u64 qos_class)
235 {
236 	packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0);
237 }
238 
seville_ifh_set_dest(void * injection,u64 dest)239 static inline void seville_ifh_set_dest(void *injection, u64 dest)
240 {
241 	packing(injection, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0);
242 }
243 
ocelot_ifh_set_src(void * injection,u64 src)244 static inline void ocelot_ifh_set_src(void *injection, u64 src)
245 {
246 	packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
247 }
248 
ocelot_ifh_set_tag_type(void * injection,u64 tag_type)249 static inline void ocelot_ifh_set_tag_type(void *injection, u64 tag_type)
250 {
251 	packing(injection, &tag_type, 16, 16, OCELOT_TAG_LEN, PACK, 0);
252 }
253 
ocelot_ifh_set_vlan_tci(void * injection,u64 vlan_tci)254 static inline void ocelot_ifh_set_vlan_tci(void *injection, u64 vlan_tci)
255 {
256 	packing(injection, &vlan_tci, 15, 0, OCELOT_TAG_LEN, PACK, 0);
257 }
258 
259 /* Determine the PTP REW_OP to use for injecting the given skb */
ocelot_ptp_rew_op(struct sk_buff * skb)260 static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb)
261 {
262 	struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone;
263 	u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd;
264 	u32 rew_op = 0;
265 
266 	if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) {
267 		rew_op = ptp_cmd;
268 		rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3;
269 	} else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) {
270 		rew_op = ptp_cmd;
271 	}
272 
273 	return rew_op;
274 }
275 
276 #endif
277