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