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