File Index
Files and directories
Sign in
FILE

ocelot.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/dsa/ocelot.h C
  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
 15struct 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
169struct felix_deferred_xmit_work {
170	struct dsa_port *dp;
171	struct sk_buff *skb;
172	struct kthread_work work;
173};
174
175struct ocelot_8021q_tagger_data {
176	void (*xmit_work_fn)(struct kthread_work *work);
177};
178
179static inline struct ocelot_8021q_tagger_data *
180ocelot_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
187static 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
192static 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
202static 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
207static 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
212static 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
217static 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
222static inline void ocelot_ifh_set_bypass(void *injection, u64 bypass)
223{
224	packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0);
225}
226
227static 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
232static inline void ocelot_ifh_set_dest(void *injection, u64 dest)
233{
234	packing(injection, &dest, 67, 56, OCELOT_TAG_LEN, PACK, 0);
235}
236
237static 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
242static inline void seville_ifh_set_dest(void *injection, u64 dest)
243{
244	packing(injection, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0);
245}
246
247static inline void ocelot_ifh_set_src(void *injection, u64 src)
248{
249	packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0);
250}
251
252static 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
257static 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 */
263static 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 */
295static 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
~/ Read-only file preview.