1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright (c) 2016-2018, NXP Semiconductors
3 * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
5 #include "sja1105_static_config.h"
6 #include <linux/crc32.h>
7 #include <linux/slab.h>
8 #include <linux/string.h>
9 #include <linux/errno.h>
11 /* Convenience wrappers over the generic packing functions. These take into
12 * account the SJA1105 memory layout quirks and provide some level of
13 * programmer protection against incorrect API use. The errors are not expected
14 * to occur durring runtime, therefore printing and swallowing them here is
15 * appropriate instead of clutterring up higher-level code.
17 void sja1105_pack(void *buf
, const u64
*val
, int start
, int end
, size_t len
)
19 int rc
= packing(buf
, (u64
*)val
, start
, end
, len
,
20 PACK
, QUIRK_LSW32_IS_FIRST
);
26 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
28 } else if (rc
== -ERANGE
) {
29 if ((start
- end
+ 1) > 64)
30 pr_err("Field %d-%d too large for 64 bits!\n",
33 pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
39 void sja1105_unpack(const void *buf
, u64
*val
, int start
, int end
, size_t len
)
41 int rc
= packing((void *)buf
, val
, start
, end
, len
,
42 UNPACK
, QUIRK_LSW32_IS_FIRST
);
48 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
50 else if (rc
== -ERANGE
)
51 pr_err("Field %d-%d too large for 64 bits!\n",
56 void sja1105_packing(void *buf
, u64
*val
, int start
, int end
,
57 size_t len
, enum packing_op op
)
59 int rc
= packing(buf
, val
, start
, end
, len
, op
, QUIRK_LSW32_IS_FIRST
);
65 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
67 } else if (rc
== -ERANGE
) {
68 if ((start
- end
+ 1) > 64)
69 pr_err("Field %d-%d too large for 64 bits!\n",
72 pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
78 /* Little-endian Ethernet CRC32 of data packed as big-endian u32 words */
79 u32
sja1105_crc32(const void *buf
, size_t len
)
87 for (i
= 0; i
< len
; i
+= 4) {
88 sja1105_unpack((void *)buf
+ i
, &word
, 31, 0, 4);
89 crc
= crc32_le(crc
, (u8
*)&word
, 4);
94 static size_t sja1105et_avb_params_entry_packing(void *buf
, void *entry_ptr
,
97 const size_t size
= SJA1105ET_SIZE_AVB_PARAMS_ENTRY
;
98 struct sja1105_avb_params_entry
*entry
= entry_ptr
;
100 sja1105_packing(buf
, &entry
->destmeta
, 95, 48, size
, op
);
101 sja1105_packing(buf
, &entry
->srcmeta
, 47, 0, size
, op
);
105 static size_t sja1105pqrs_avb_params_entry_packing(void *buf
, void *entry_ptr
,
108 const size_t size
= SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY
;
109 struct sja1105_avb_params_entry
*entry
= entry_ptr
;
111 sja1105_packing(buf
, &entry
->destmeta
, 125, 78, size
, op
);
112 sja1105_packing(buf
, &entry
->srcmeta
, 77, 30, size
, op
);
116 static size_t sja1105et_general_params_entry_packing(void *buf
, void *entry_ptr
,
119 const size_t size
= SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY
;
120 struct sja1105_general_params_entry
*entry
= entry_ptr
;
122 sja1105_packing(buf
, &entry
->vllupformat
, 319, 319, size
, op
);
123 sja1105_packing(buf
, &entry
->mirr_ptacu
, 318, 318, size
, op
);
124 sja1105_packing(buf
, &entry
->switchid
, 317, 315, size
, op
);
125 sja1105_packing(buf
, &entry
->hostprio
, 314, 312, size
, op
);
126 sja1105_packing(buf
, &entry
->mac_fltres1
, 311, 264, size
, op
);
127 sja1105_packing(buf
, &entry
->mac_fltres0
, 263, 216, size
, op
);
128 sja1105_packing(buf
, &entry
->mac_flt1
, 215, 168, size
, op
);
129 sja1105_packing(buf
, &entry
->mac_flt0
, 167, 120, size
, op
);
130 sja1105_packing(buf
, &entry
->incl_srcpt1
, 119, 119, size
, op
);
131 sja1105_packing(buf
, &entry
->incl_srcpt0
, 118, 118, size
, op
);
132 sja1105_packing(buf
, &entry
->send_meta1
, 117, 117, size
, op
);
133 sja1105_packing(buf
, &entry
->send_meta0
, 116, 116, size
, op
);
134 sja1105_packing(buf
, &entry
->casc_port
, 115, 113, size
, op
);
135 sja1105_packing(buf
, &entry
->host_port
, 112, 110, size
, op
);
136 sja1105_packing(buf
, &entry
->mirr_port
, 109, 107, size
, op
);
137 sja1105_packing(buf
, &entry
->vlmarker
, 106, 75, size
, op
);
138 sja1105_packing(buf
, &entry
->vlmask
, 74, 43, size
, op
);
139 sja1105_packing(buf
, &entry
->tpid
, 42, 27, size
, op
);
140 sja1105_packing(buf
, &entry
->ignore2stf
, 26, 26, size
, op
);
141 sja1105_packing(buf
, &entry
->tpid2
, 25, 10, size
, op
);
145 /* TPID and TPID2 are intentionally reversed so that semantic
146 * compatibility with E/T is kept.
149 sja1105pqrs_general_params_entry_packing(void *buf
, void *entry_ptr
,
152 const size_t size
= SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY
;
153 struct sja1105_general_params_entry
*entry
= entry_ptr
;
155 sja1105_packing(buf
, &entry
->vllupformat
, 351, 351, size
, op
);
156 sja1105_packing(buf
, &entry
->mirr_ptacu
, 350, 350, size
, op
);
157 sja1105_packing(buf
, &entry
->switchid
, 349, 347, size
, op
);
158 sja1105_packing(buf
, &entry
->hostprio
, 346, 344, size
, op
);
159 sja1105_packing(buf
, &entry
->mac_fltres1
, 343, 296, size
, op
);
160 sja1105_packing(buf
, &entry
->mac_fltres0
, 295, 248, size
, op
);
161 sja1105_packing(buf
, &entry
->mac_flt1
, 247, 200, size
, op
);
162 sja1105_packing(buf
, &entry
->mac_flt0
, 199, 152, size
, op
);
163 sja1105_packing(buf
, &entry
->incl_srcpt1
, 151, 151, size
, op
);
164 sja1105_packing(buf
, &entry
->incl_srcpt0
, 150, 150, size
, op
);
165 sja1105_packing(buf
, &entry
->send_meta1
, 149, 149, size
, op
);
166 sja1105_packing(buf
, &entry
->send_meta0
, 148, 148, size
, op
);
167 sja1105_packing(buf
, &entry
->casc_port
, 147, 145, size
, op
);
168 sja1105_packing(buf
, &entry
->host_port
, 144, 142, size
, op
);
169 sja1105_packing(buf
, &entry
->mirr_port
, 141, 139, size
, op
);
170 sja1105_packing(buf
, &entry
->vlmarker
, 138, 107, size
, op
);
171 sja1105_packing(buf
, &entry
->vlmask
, 106, 75, size
, op
);
172 sja1105_packing(buf
, &entry
->tpid2
, 74, 59, size
, op
);
173 sja1105_packing(buf
, &entry
->ignore2stf
, 58, 58, size
, op
);
174 sja1105_packing(buf
, &entry
->tpid
, 57, 42, size
, op
);
175 sja1105_packing(buf
, &entry
->queue_ts
, 41, 41, size
, op
);
176 sja1105_packing(buf
, &entry
->egrmirrvid
, 40, 29, size
, op
);
177 sja1105_packing(buf
, &entry
->egrmirrpcp
, 28, 26, size
, op
);
178 sja1105_packing(buf
, &entry
->egrmirrdei
, 25, 25, size
, op
);
179 sja1105_packing(buf
, &entry
->replay_port
, 24, 22, size
, op
);
184 sja1105_l2_forwarding_params_entry_packing(void *buf
, void *entry_ptr
,
187 const size_t size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
;
188 struct sja1105_l2_forwarding_params_entry
*entry
= entry_ptr
;
191 sja1105_packing(buf
, &entry
->max_dynp
, 95, 93, size
, op
);
192 for (i
= 0, offset
= 13; i
< 8; i
++, offset
+= 10)
193 sja1105_packing(buf
, &entry
->part_spc
[i
],
194 offset
+ 9, offset
+ 0, size
, op
);
198 size_t sja1105_l2_forwarding_entry_packing(void *buf
, void *entry_ptr
,
201 const size_t size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
;
202 struct sja1105_l2_forwarding_entry
*entry
= entry_ptr
;
205 sja1105_packing(buf
, &entry
->bc_domain
, 63, 59, size
, op
);
206 sja1105_packing(buf
, &entry
->reach_port
, 58, 54, size
, op
);
207 sja1105_packing(buf
, &entry
->fl_domain
, 53, 49, size
, op
);
208 for (i
= 0, offset
= 25; i
< 8; i
++, offset
+= 3)
209 sja1105_packing(buf
, &entry
->vlan_pmap
[i
],
210 offset
+ 2, offset
+ 0, size
, op
);
215 sja1105et_l2_lookup_params_entry_packing(void *buf
, void *entry_ptr
,
218 const size_t size
= SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY
;
219 struct sja1105_l2_lookup_params_entry
*entry
= entry_ptr
;
221 sja1105_packing(buf
, &entry
->maxage
, 31, 17, size
, op
);
222 sja1105_packing(buf
, &entry
->dyn_tbsz
, 16, 14, size
, op
);
223 sja1105_packing(buf
, &entry
->poly
, 13, 6, size
, op
);
224 sja1105_packing(buf
, &entry
->shared_learn
, 5, 5, size
, op
);
225 sja1105_packing(buf
, &entry
->no_enf_hostprt
, 4, 4, size
, op
);
226 sja1105_packing(buf
, &entry
->no_mgmt_learn
, 3, 3, size
, op
);
231 sja1105pqrs_l2_lookup_params_entry_packing(void *buf
, void *entry_ptr
,
234 const size_t size
= SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY
;
235 struct sja1105_l2_lookup_params_entry
*entry
= entry_ptr
;
238 for (i
= 0, offset
= 58; i
< 5; i
++, offset
+= 11)
239 sja1105_packing(buf
, &entry
->maxaddrp
[i
],
240 offset
+ 10, offset
+ 0, size
, op
);
241 sja1105_packing(buf
, &entry
->maxage
, 57, 43, size
, op
);
242 sja1105_packing(buf
, &entry
->start_dynspc
, 42, 33, size
, op
);
243 sja1105_packing(buf
, &entry
->drpnolearn
, 32, 28, size
, op
);
244 sja1105_packing(buf
, &entry
->shared_learn
, 27, 27, size
, op
);
245 sja1105_packing(buf
, &entry
->no_enf_hostprt
, 26, 26, size
, op
);
246 sja1105_packing(buf
, &entry
->no_mgmt_learn
, 25, 25, size
, op
);
247 sja1105_packing(buf
, &entry
->use_static
, 24, 24, size
, op
);
248 sja1105_packing(buf
, &entry
->owr_dyn
, 23, 23, size
, op
);
249 sja1105_packing(buf
, &entry
->learn_once
, 22, 22, size
, op
);
253 size_t sja1105et_l2_lookup_entry_packing(void *buf
, void *entry_ptr
,
256 const size_t size
= SJA1105ET_SIZE_L2_LOOKUP_ENTRY
;
257 struct sja1105_l2_lookup_entry
*entry
= entry_ptr
;
259 sja1105_packing(buf
, &entry
->vlanid
, 95, 84, size
, op
);
260 sja1105_packing(buf
, &entry
->macaddr
, 83, 36, size
, op
);
261 sja1105_packing(buf
, &entry
->destports
, 35, 31, size
, op
);
262 sja1105_packing(buf
, &entry
->enfport
, 30, 30, size
, op
);
263 sja1105_packing(buf
, &entry
->index
, 29, 20, size
, op
);
267 size_t sja1105pqrs_l2_lookup_entry_packing(void *buf
, void *entry_ptr
,
270 const size_t size
= SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY
;
271 struct sja1105_l2_lookup_entry
*entry
= entry_ptr
;
273 if (entry
->lockeds
) {
274 sja1105_packing(buf
, &entry
->tsreg
, 159, 159, size
, op
);
275 sja1105_packing(buf
, &entry
->mirrvlan
, 158, 147, size
, op
);
276 sja1105_packing(buf
, &entry
->takets
, 146, 146, size
, op
);
277 sja1105_packing(buf
, &entry
->mirr
, 145, 145, size
, op
);
278 sja1105_packing(buf
, &entry
->retag
, 144, 144, size
, op
);
280 sja1105_packing(buf
, &entry
->touched
, 159, 159, size
, op
);
281 sja1105_packing(buf
, &entry
->age
, 158, 144, size
, op
);
283 sja1105_packing(buf
, &entry
->mask_iotag
, 143, 143, size
, op
);
284 sja1105_packing(buf
, &entry
->mask_vlanid
, 142, 131, size
, op
);
285 sja1105_packing(buf
, &entry
->mask_macaddr
, 130, 83, size
, op
);
286 sja1105_packing(buf
, &entry
->iotag
, 82, 82, size
, op
);
287 sja1105_packing(buf
, &entry
->vlanid
, 81, 70, size
, op
);
288 sja1105_packing(buf
, &entry
->macaddr
, 69, 22, size
, op
);
289 sja1105_packing(buf
, &entry
->destports
, 21, 17, size
, op
);
290 sja1105_packing(buf
, &entry
->enfport
, 16, 16, size
, op
);
291 sja1105_packing(buf
, &entry
->index
, 15, 6, size
, op
);
295 static size_t sja1105_l2_policing_entry_packing(void *buf
, void *entry_ptr
,
298 const size_t size
= SJA1105_SIZE_L2_POLICING_ENTRY
;
299 struct sja1105_l2_policing_entry
*entry
= entry_ptr
;
301 sja1105_packing(buf
, &entry
->sharindx
, 63, 58, size
, op
);
302 sja1105_packing(buf
, &entry
->smax
, 57, 42, size
, op
);
303 sja1105_packing(buf
, &entry
->rate
, 41, 26, size
, op
);
304 sja1105_packing(buf
, &entry
->maxlen
, 25, 15, size
, op
);
305 sja1105_packing(buf
, &entry
->partition
, 14, 12, size
, op
);
309 static size_t sja1105et_mac_config_entry_packing(void *buf
, void *entry_ptr
,
312 const size_t size
= SJA1105ET_SIZE_MAC_CONFIG_ENTRY
;
313 struct sja1105_mac_config_entry
*entry
= entry_ptr
;
316 for (i
= 0, offset
= 72; i
< 8; i
++, offset
+= 19) {
317 sja1105_packing(buf
, &entry
->enabled
[i
],
318 offset
+ 0, offset
+ 0, size
, op
);
319 sja1105_packing(buf
, &entry
->base
[i
],
320 offset
+ 9, offset
+ 1, size
, op
);
321 sja1105_packing(buf
, &entry
->top
[i
],
322 offset
+ 18, offset
+ 10, size
, op
);
324 sja1105_packing(buf
, &entry
->ifg
, 71, 67, size
, op
);
325 sja1105_packing(buf
, &entry
->speed
, 66, 65, size
, op
);
326 sja1105_packing(buf
, &entry
->tp_delin
, 64, 49, size
, op
);
327 sja1105_packing(buf
, &entry
->tp_delout
, 48, 33, size
, op
);
328 sja1105_packing(buf
, &entry
->maxage
, 32, 25, size
, op
);
329 sja1105_packing(buf
, &entry
->vlanprio
, 24, 22, size
, op
);
330 sja1105_packing(buf
, &entry
->vlanid
, 21, 10, size
, op
);
331 sja1105_packing(buf
, &entry
->ing_mirr
, 9, 9, size
, op
);
332 sja1105_packing(buf
, &entry
->egr_mirr
, 8, 8, size
, op
);
333 sja1105_packing(buf
, &entry
->drpnona664
, 7, 7, size
, op
);
334 sja1105_packing(buf
, &entry
->drpdtag
, 6, 6, size
, op
);
335 sja1105_packing(buf
, &entry
->drpuntag
, 5, 5, size
, op
);
336 sja1105_packing(buf
, &entry
->retag
, 4, 4, size
, op
);
337 sja1105_packing(buf
, &entry
->dyn_learn
, 3, 3, size
, op
);
338 sja1105_packing(buf
, &entry
->egress
, 2, 2, size
, op
);
339 sja1105_packing(buf
, &entry
->ingress
, 1, 1, size
, op
);
343 size_t sja1105pqrs_mac_config_entry_packing(void *buf
, void *entry_ptr
,
346 const size_t size
= SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY
;
347 struct sja1105_mac_config_entry
*entry
= entry_ptr
;
350 for (i
= 0, offset
= 104; i
< 8; i
++, offset
+= 19) {
351 sja1105_packing(buf
, &entry
->enabled
[i
],
352 offset
+ 0, offset
+ 0, size
, op
);
353 sja1105_packing(buf
, &entry
->base
[i
],
354 offset
+ 9, offset
+ 1, size
, op
);
355 sja1105_packing(buf
, &entry
->top
[i
],
356 offset
+ 18, offset
+ 10, size
, op
);
358 sja1105_packing(buf
, &entry
->ifg
, 103, 99, size
, op
);
359 sja1105_packing(buf
, &entry
->speed
, 98, 97, size
, op
);
360 sja1105_packing(buf
, &entry
->tp_delin
, 96, 81, size
, op
);
361 sja1105_packing(buf
, &entry
->tp_delout
, 80, 65, size
, op
);
362 sja1105_packing(buf
, &entry
->maxage
, 64, 57, size
, op
);
363 sja1105_packing(buf
, &entry
->vlanprio
, 56, 54, size
, op
);
364 sja1105_packing(buf
, &entry
->vlanid
, 53, 42, size
, op
);
365 sja1105_packing(buf
, &entry
->ing_mirr
, 41, 41, size
, op
);
366 sja1105_packing(buf
, &entry
->egr_mirr
, 40, 40, size
, op
);
367 sja1105_packing(buf
, &entry
->drpnona664
, 39, 39, size
, op
);
368 sja1105_packing(buf
, &entry
->drpdtag
, 38, 38, size
, op
);
369 sja1105_packing(buf
, &entry
->drpuntag
, 35, 35, size
, op
);
370 sja1105_packing(buf
, &entry
->retag
, 34, 34, size
, op
);
371 sja1105_packing(buf
, &entry
->dyn_learn
, 33, 33, size
, op
);
372 sja1105_packing(buf
, &entry
->egress
, 32, 32, size
, op
);
373 sja1105_packing(buf
, &entry
->ingress
, 31, 31, size
, op
);
378 sja1105_schedule_entry_points_params_entry_packing(void *buf
, void *entry_ptr
,
381 struct sja1105_schedule_entry_points_params_entry
*entry
= entry_ptr
;
382 const size_t size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY
;
384 sja1105_packing(buf
, &entry
->clksrc
, 31, 30, size
, op
);
385 sja1105_packing(buf
, &entry
->actsubsch
, 29, 27, size
, op
);
390 sja1105_schedule_entry_points_entry_packing(void *buf
, void *entry_ptr
,
393 struct sja1105_schedule_entry_points_entry
*entry
= entry_ptr
;
394 const size_t size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY
;
396 sja1105_packing(buf
, &entry
->subschindx
, 31, 29, size
, op
);
397 sja1105_packing(buf
, &entry
->delta
, 28, 11, size
, op
);
398 sja1105_packing(buf
, &entry
->address
, 10, 1, size
, op
);
402 static size_t sja1105_schedule_params_entry_packing(void *buf
, void *entry_ptr
,
405 const size_t size
= SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY
;
406 struct sja1105_schedule_params_entry
*entry
= entry_ptr
;
409 for (i
= 0, offset
= 16; i
< 8; i
++, offset
+= 10)
410 sja1105_packing(buf
, &entry
->subscheind
[i
],
411 offset
+ 9, offset
+ 0, size
, op
);
415 static size_t sja1105_schedule_entry_packing(void *buf
, void *entry_ptr
,
418 const size_t size
= SJA1105_SIZE_SCHEDULE_ENTRY
;
419 struct sja1105_schedule_entry
*entry
= entry_ptr
;
421 sja1105_packing(buf
, &entry
->winstindex
, 63, 54, size
, op
);
422 sja1105_packing(buf
, &entry
->winend
, 53, 53, size
, op
);
423 sja1105_packing(buf
, &entry
->winst
, 52, 52, size
, op
);
424 sja1105_packing(buf
, &entry
->destports
, 51, 47, size
, op
);
425 sja1105_packing(buf
, &entry
->setvalid
, 46, 46, size
, op
);
426 sja1105_packing(buf
, &entry
->txen
, 45, 45, size
, op
);
427 sja1105_packing(buf
, &entry
->resmedia_en
, 44, 44, size
, op
);
428 sja1105_packing(buf
, &entry
->resmedia
, 43, 36, size
, op
);
429 sja1105_packing(buf
, &entry
->vlindex
, 35, 26, size
, op
);
430 sja1105_packing(buf
, &entry
->delta
, 25, 8, size
, op
);
434 size_t sja1105_vlan_lookup_entry_packing(void *buf
, void *entry_ptr
,
437 const size_t size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
;
438 struct sja1105_vlan_lookup_entry
*entry
= entry_ptr
;
440 sja1105_packing(buf
, &entry
->ving_mirr
, 63, 59, size
, op
);
441 sja1105_packing(buf
, &entry
->vegr_mirr
, 58, 54, size
, op
);
442 sja1105_packing(buf
, &entry
->vmemb_port
, 53, 49, size
, op
);
443 sja1105_packing(buf
, &entry
->vlan_bc
, 48, 44, size
, op
);
444 sja1105_packing(buf
, &entry
->tag_port
, 43, 39, size
, op
);
445 sja1105_packing(buf
, &entry
->vlanid
, 38, 27, size
, op
);
449 static size_t sja1105_xmii_params_entry_packing(void *buf
, void *entry_ptr
,
452 const size_t size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
;
453 struct sja1105_xmii_params_entry
*entry
= entry_ptr
;
456 for (i
= 0, offset
= 17; i
< 5; i
++, offset
+= 3) {
457 sja1105_packing(buf
, &entry
->xmii_mode
[i
],
458 offset
+ 1, offset
+ 0, size
, op
);
459 sja1105_packing(buf
, &entry
->phy_mac
[i
],
460 offset
+ 2, offset
+ 2, size
, op
);
465 size_t sja1105_table_header_packing(void *buf
, void *entry_ptr
,
468 const size_t size
= SJA1105_SIZE_TABLE_HEADER
;
469 struct sja1105_table_header
*entry
= entry_ptr
;
471 sja1105_packing(buf
, &entry
->block_id
, 31, 24, size
, op
);
472 sja1105_packing(buf
, &entry
->len
, 55, 32, size
, op
);
473 sja1105_packing(buf
, &entry
->crc
, 95, 64, size
, op
);
477 /* WARNING: the *hdr pointer is really non-const, because it is
478 * modifying the CRC of the header for a 2-stage packing operation
481 sja1105_table_header_pack_with_crc(void *buf
, struct sja1105_table_header
*hdr
)
483 /* First pack the table as-is, then calculate the CRC, and
484 * finally put the proper CRC into the packed buffer
486 memset(buf
, 0, SJA1105_SIZE_TABLE_HEADER
);
487 sja1105_table_header_packing(buf
, hdr
, PACK
);
488 hdr
->crc
= sja1105_crc32(buf
, SJA1105_SIZE_TABLE_HEADER
- 4);
489 sja1105_pack(buf
+ SJA1105_SIZE_TABLE_HEADER
- 4, &hdr
->crc
, 31, 0, 4);
492 static void sja1105_table_write_crc(u8
*table_start
, u8
*crc_ptr
)
497 len_bytes
= (uintptr_t)(crc_ptr
- table_start
);
498 computed_crc
= sja1105_crc32(table_start
, len_bytes
);
499 sja1105_pack(crc_ptr
, &computed_crc
, 31, 0, 4);
502 /* The block IDs that the switches support are unfortunately sparse, so keep a
503 * mapping table to "block indices" and translate back and forth so that we
504 * don't waste useless memory in struct sja1105_static_config.
505 * Also, since the block id comes from essentially untrusted input (unpacking
506 * the static config from userspace) it has to be sanitized (range-checked)
507 * before blindly indexing kernel memory with the blk_idx.
509 static u64 blk_id_map
[BLK_IDX_MAX
] = {
510 [BLK_IDX_SCHEDULE
] = BLKID_SCHEDULE
,
511 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = BLKID_SCHEDULE_ENTRY_POINTS
,
512 [BLK_IDX_L2_LOOKUP
] = BLKID_L2_LOOKUP
,
513 [BLK_IDX_L2_POLICING
] = BLKID_L2_POLICING
,
514 [BLK_IDX_VLAN_LOOKUP
] = BLKID_VLAN_LOOKUP
,
515 [BLK_IDX_L2_FORWARDING
] = BLKID_L2_FORWARDING
,
516 [BLK_IDX_MAC_CONFIG
] = BLKID_MAC_CONFIG
,
517 [BLK_IDX_SCHEDULE_PARAMS
] = BLKID_SCHEDULE_PARAMS
,
518 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = BLKID_SCHEDULE_ENTRY_POINTS_PARAMS
,
519 [BLK_IDX_L2_LOOKUP_PARAMS
] = BLKID_L2_LOOKUP_PARAMS
,
520 [BLK_IDX_L2_FORWARDING_PARAMS
] = BLKID_L2_FORWARDING_PARAMS
,
521 [BLK_IDX_AVB_PARAMS
] = BLKID_AVB_PARAMS
,
522 [BLK_IDX_GENERAL_PARAMS
] = BLKID_GENERAL_PARAMS
,
523 [BLK_IDX_XMII_PARAMS
] = BLKID_XMII_PARAMS
,
526 const char *sja1105_static_config_error_msg
[] = {
527 [SJA1105_CONFIG_OK
] = "",
528 [SJA1105_TTETHERNET_NOT_SUPPORTED
] =
529 "schedule-table present, but TTEthernet is "
530 "only supported on T and Q/S",
531 [SJA1105_INCORRECT_TTETHERNET_CONFIGURATION
] =
532 "schedule-table present, but one of "
533 "schedule-entry-points-table, schedule-parameters-table or "
534 "schedule-entry-points-parameters table is empty",
535 [SJA1105_MISSING_L2_POLICING_TABLE
] =
536 "l2-policing-table needs to have at least one entry",
537 [SJA1105_MISSING_L2_FORWARDING_TABLE
] =
538 "l2-forwarding-table is either missing or incomplete",
539 [SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE
] =
540 "l2-forwarding-parameters-table is missing",
541 [SJA1105_MISSING_GENERAL_PARAMS_TABLE
] =
542 "general-parameters-table is missing",
543 [SJA1105_MISSING_VLAN_TABLE
] =
544 "vlan-lookup-table needs to have at least the default untagged VLAN",
545 [SJA1105_MISSING_XMII_TABLE
] =
546 "xmii-table is missing",
547 [SJA1105_MISSING_MAC_TABLE
] =
548 "mac-configuration-table needs to contain an entry for each port",
549 [SJA1105_OVERCOMMITTED_FRAME_MEMORY
] =
550 "Not allowed to overcommit frame memory. L2 memory partitions "
551 "and VL memory partitions share the same space. The sum of all "
552 "16 memory partitions is not allowed to be larger than 929 "
553 "128-byte blocks (or 910 with retagging). Please adjust "
554 "l2-forwarding-parameters-table.part_spc and/or "
555 "vl-forwarding-parameters-table.partspc.",
558 static sja1105_config_valid_t
559 static_config_check_memory_size(const struct sja1105_table
*tables
)
561 const struct sja1105_l2_forwarding_params_entry
*l2_fwd_params
;
564 l2_fwd_params
= tables
[BLK_IDX_L2_FORWARDING_PARAMS
].entries
;
566 for (i
= 0; i
< 8; i
++)
567 mem
+= l2_fwd_params
->part_spc
[i
];
569 if (mem
> SJA1105_MAX_FRAME_MEMORY
)
570 return SJA1105_OVERCOMMITTED_FRAME_MEMORY
;
572 return SJA1105_CONFIG_OK
;
575 sja1105_config_valid_t
576 sja1105_static_config_check_valid(const struct sja1105_static_config
*config
)
578 const struct sja1105_table
*tables
= config
->tables
;
579 #define IS_FULL(blk_idx) \
580 (tables[blk_idx].entry_count == tables[blk_idx].ops->max_entry_count)
582 if (tables
[BLK_IDX_SCHEDULE
].entry_count
) {
583 if (config
->device_id
!= SJA1105T_DEVICE_ID
&&
584 config
->device_id
!= SJA1105QS_DEVICE_ID
)
585 return SJA1105_TTETHERNET_NOT_SUPPORTED
;
587 if (tables
[BLK_IDX_SCHEDULE_ENTRY_POINTS
].entry_count
== 0)
588 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION
;
590 if (!IS_FULL(BLK_IDX_SCHEDULE_PARAMS
))
591 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION
;
593 if (!IS_FULL(BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
))
594 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION
;
597 if (tables
[BLK_IDX_L2_POLICING
].entry_count
== 0)
598 return SJA1105_MISSING_L2_POLICING_TABLE
;
600 if (tables
[BLK_IDX_VLAN_LOOKUP
].entry_count
== 0)
601 return SJA1105_MISSING_VLAN_TABLE
;
603 if (!IS_FULL(BLK_IDX_L2_FORWARDING
))
604 return SJA1105_MISSING_L2_FORWARDING_TABLE
;
606 if (!IS_FULL(BLK_IDX_MAC_CONFIG
))
607 return SJA1105_MISSING_MAC_TABLE
;
609 if (!IS_FULL(BLK_IDX_L2_FORWARDING_PARAMS
))
610 return SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE
;
612 if (!IS_FULL(BLK_IDX_GENERAL_PARAMS
))
613 return SJA1105_MISSING_GENERAL_PARAMS_TABLE
;
615 if (!IS_FULL(BLK_IDX_XMII_PARAMS
))
616 return SJA1105_MISSING_XMII_TABLE
;
618 return static_config_check_memory_size(tables
);
623 sja1105_static_config_pack(void *buf
, struct sja1105_static_config
*config
)
625 struct sja1105_table_header header
= {0};
626 enum sja1105_blk_idx i
;
630 sja1105_pack(p
, &config
->device_id
, 31, 0, 4);
631 p
+= SJA1105_SIZE_DEVICE_ID
;
633 for (i
= 0; i
< BLK_IDX_MAX
; i
++) {
634 const struct sja1105_table
*table
;
637 table
= &config
->tables
[i
];
638 if (!table
->entry_count
)
641 header
.block_id
= blk_id_map
[i
];
642 header
.len
= table
->entry_count
*
643 table
->ops
->packed_entry_size
/ 4;
644 sja1105_table_header_pack_with_crc(p
, &header
);
645 p
+= SJA1105_SIZE_TABLE_HEADER
;
647 for (j
= 0; j
< table
->entry_count
; j
++) {
648 u8
*entry_ptr
= table
->entries
;
650 entry_ptr
+= j
* table
->ops
->unpacked_entry_size
;
651 memset(p
, 0, table
->ops
->packed_entry_size
);
652 table
->ops
->packing(p
, entry_ptr
, PACK
);
653 p
+= table
->ops
->packed_entry_size
;
655 sja1105_table_write_crc(table_start
, p
);
659 * Block ID does not matter
660 * Length of 0 marks that header is final
661 * CRC will be replaced on-the-fly on "config upload"
665 header
.crc
= 0xDEADBEEF;
666 memset(p
, 0, SJA1105_SIZE_TABLE_HEADER
);
667 sja1105_table_header_packing(p
, &header
, PACK
);
671 sja1105_static_config_get_length(const struct sja1105_static_config
*config
)
674 unsigned int header_count
;
675 enum sja1105_blk_idx i
;
679 sum
= SJA1105_SIZE_DEVICE_ID
;
681 /* Tables (headers and entries) */
682 for (i
= 0; i
< BLK_IDX_MAX
; i
++) {
683 const struct sja1105_table
*table
;
685 table
= &config
->tables
[i
];
686 if (table
->entry_count
)
689 sum
+= table
->ops
->packed_entry_size
* table
->entry_count
;
691 /* Headers have an additional CRC at the end */
692 sum
+= header_count
* (SJA1105_SIZE_TABLE_HEADER
+ 4);
693 /* Last header does not have an extra CRC because there is no data */
699 /* Compatibility matrices */
701 /* SJA1105E: First generation, no TTEthernet */
702 struct sja1105_table_ops sja1105e_table_ops
[BLK_IDX_MAX
] = {
703 [BLK_IDX_SCHEDULE
] = {0},
704 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {0},
705 [BLK_IDX_L2_LOOKUP
] = {
706 .packing
= sja1105et_l2_lookup_entry_packing
,
707 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
708 .packed_entry_size
= SJA1105ET_SIZE_L2_LOOKUP_ENTRY
,
709 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
711 [BLK_IDX_L2_POLICING
] = {
712 .packing
= sja1105_l2_policing_entry_packing
,
713 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
714 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
715 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
717 [BLK_IDX_VLAN_LOOKUP
] = {
718 .packing
= sja1105_vlan_lookup_entry_packing
,
719 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
720 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
721 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
723 [BLK_IDX_L2_FORWARDING
] = {
724 .packing
= sja1105_l2_forwarding_entry_packing
,
725 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
726 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
727 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
729 [BLK_IDX_MAC_CONFIG
] = {
730 .packing
= sja1105et_mac_config_entry_packing
,
731 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
732 .packed_entry_size
= SJA1105ET_SIZE_MAC_CONFIG_ENTRY
,
733 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
735 [BLK_IDX_SCHEDULE_PARAMS
] = {0},
736 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {0},
737 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
738 .packing
= sja1105et_l2_lookup_params_entry_packing
,
739 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
740 .packed_entry_size
= SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
741 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
743 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
744 .packing
= sja1105_l2_forwarding_params_entry_packing
,
745 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
746 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
747 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
749 [BLK_IDX_AVB_PARAMS
] = {
750 .packing
= sja1105et_avb_params_entry_packing
,
751 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
752 .packed_entry_size
= SJA1105ET_SIZE_AVB_PARAMS_ENTRY
,
753 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
755 [BLK_IDX_GENERAL_PARAMS
] = {
756 .packing
= sja1105et_general_params_entry_packing
,
757 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
758 .packed_entry_size
= SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY
,
759 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
761 [BLK_IDX_XMII_PARAMS
] = {
762 .packing
= sja1105_xmii_params_entry_packing
,
763 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
764 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
765 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
769 /* SJA1105T: First generation, TTEthernet */
770 struct sja1105_table_ops sja1105t_table_ops
[BLK_IDX_MAX
] = {
771 [BLK_IDX_SCHEDULE
] = {
772 .packing
= sja1105_schedule_entry_packing
,
773 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry
),
774 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY
,
775 .max_entry_count
= SJA1105_MAX_SCHEDULE_COUNT
,
777 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {
778 .packing
= sja1105_schedule_entry_points_entry_packing
,
779 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_entry
),
780 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY
,
781 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT
,
783 [BLK_IDX_L2_LOOKUP
] = {
784 .packing
= sja1105et_l2_lookup_entry_packing
,
785 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
786 .packed_entry_size
= SJA1105ET_SIZE_L2_LOOKUP_ENTRY
,
787 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
789 [BLK_IDX_L2_POLICING
] = {
790 .packing
= sja1105_l2_policing_entry_packing
,
791 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
792 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
793 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
795 [BLK_IDX_VLAN_LOOKUP
] = {
796 .packing
= sja1105_vlan_lookup_entry_packing
,
797 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
798 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
799 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
801 [BLK_IDX_L2_FORWARDING
] = {
802 .packing
= sja1105_l2_forwarding_entry_packing
,
803 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
804 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
805 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
807 [BLK_IDX_MAC_CONFIG
] = {
808 .packing
= sja1105et_mac_config_entry_packing
,
809 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
810 .packed_entry_size
= SJA1105ET_SIZE_MAC_CONFIG_ENTRY
,
811 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
813 [BLK_IDX_SCHEDULE_PARAMS
] = {
814 .packing
= sja1105_schedule_params_entry_packing
,
815 .unpacked_entry_size
= sizeof(struct sja1105_schedule_params_entry
),
816 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY
,
817 .max_entry_count
= SJA1105_MAX_SCHEDULE_PARAMS_COUNT
,
819 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {
820 .packing
= sja1105_schedule_entry_points_params_entry_packing
,
821 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_params_entry
),
822 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY
,
823 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT
,
825 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
826 .packing
= sja1105et_l2_lookup_params_entry_packing
,
827 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
828 .packed_entry_size
= SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
829 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
831 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
832 .packing
= sja1105_l2_forwarding_params_entry_packing
,
833 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
834 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
835 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
837 [BLK_IDX_AVB_PARAMS
] = {
838 .packing
= sja1105et_avb_params_entry_packing
,
839 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
840 .packed_entry_size
= SJA1105ET_SIZE_AVB_PARAMS_ENTRY
,
841 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
843 [BLK_IDX_GENERAL_PARAMS
] = {
844 .packing
= sja1105et_general_params_entry_packing
,
845 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
846 .packed_entry_size
= SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY
,
847 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
849 [BLK_IDX_XMII_PARAMS
] = {
850 .packing
= sja1105_xmii_params_entry_packing
,
851 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
852 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
853 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
857 /* SJA1105P: Second generation, no TTEthernet, no SGMII */
858 struct sja1105_table_ops sja1105p_table_ops
[BLK_IDX_MAX
] = {
859 [BLK_IDX_SCHEDULE
] = {0},
860 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {0},
861 [BLK_IDX_L2_LOOKUP
] = {
862 .packing
= sja1105pqrs_l2_lookup_entry_packing
,
863 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
864 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY
,
865 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
867 [BLK_IDX_L2_POLICING
] = {
868 .packing
= sja1105_l2_policing_entry_packing
,
869 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
870 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
871 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
873 [BLK_IDX_VLAN_LOOKUP
] = {
874 .packing
= sja1105_vlan_lookup_entry_packing
,
875 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
876 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
877 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
879 [BLK_IDX_L2_FORWARDING
] = {
880 .packing
= sja1105_l2_forwarding_entry_packing
,
881 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
882 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
883 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
885 [BLK_IDX_MAC_CONFIG
] = {
886 .packing
= sja1105pqrs_mac_config_entry_packing
,
887 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
888 .packed_entry_size
= SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY
,
889 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
891 [BLK_IDX_SCHEDULE_PARAMS
] = {0},
892 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {0},
893 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
894 .packing
= sja1105pqrs_l2_lookup_params_entry_packing
,
895 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
896 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
897 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
899 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
900 .packing
= sja1105_l2_forwarding_params_entry_packing
,
901 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
902 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
903 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
905 [BLK_IDX_AVB_PARAMS
] = {
906 .packing
= sja1105pqrs_avb_params_entry_packing
,
907 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
908 .packed_entry_size
= SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY
,
909 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
911 [BLK_IDX_GENERAL_PARAMS
] = {
912 .packing
= sja1105pqrs_general_params_entry_packing
,
913 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
914 .packed_entry_size
= SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY
,
915 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
917 [BLK_IDX_XMII_PARAMS
] = {
918 .packing
= sja1105_xmii_params_entry_packing
,
919 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
920 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
921 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
925 /* SJA1105Q: Second generation, TTEthernet, no SGMII */
926 struct sja1105_table_ops sja1105q_table_ops
[BLK_IDX_MAX
] = {
927 [BLK_IDX_SCHEDULE
] = {
928 .packing
= sja1105_schedule_entry_packing
,
929 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry
),
930 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY
,
931 .max_entry_count
= SJA1105_MAX_SCHEDULE_COUNT
,
933 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {
934 .packing
= sja1105_schedule_entry_points_entry_packing
,
935 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_entry
),
936 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY
,
937 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT
,
939 [BLK_IDX_L2_LOOKUP
] = {
940 .packing
= sja1105pqrs_l2_lookup_entry_packing
,
941 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
942 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY
,
943 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
945 [BLK_IDX_L2_POLICING
] = {
946 .packing
= sja1105_l2_policing_entry_packing
,
947 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
948 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
949 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
951 [BLK_IDX_VLAN_LOOKUP
] = {
952 .packing
= sja1105_vlan_lookup_entry_packing
,
953 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
954 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
955 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
957 [BLK_IDX_L2_FORWARDING
] = {
958 .packing
= sja1105_l2_forwarding_entry_packing
,
959 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
960 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
961 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
963 [BLK_IDX_MAC_CONFIG
] = {
964 .packing
= sja1105pqrs_mac_config_entry_packing
,
965 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
966 .packed_entry_size
= SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY
,
967 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
969 [BLK_IDX_SCHEDULE_PARAMS
] = {
970 .packing
= sja1105_schedule_params_entry_packing
,
971 .unpacked_entry_size
= sizeof(struct sja1105_schedule_params_entry
),
972 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY
,
973 .max_entry_count
= SJA1105_MAX_SCHEDULE_PARAMS_COUNT
,
975 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {
976 .packing
= sja1105_schedule_entry_points_params_entry_packing
,
977 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_params_entry
),
978 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY
,
979 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT
,
981 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
982 .packing
= sja1105pqrs_l2_lookup_params_entry_packing
,
983 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
984 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
985 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
987 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
988 .packing
= sja1105_l2_forwarding_params_entry_packing
,
989 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
990 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
991 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
993 [BLK_IDX_AVB_PARAMS
] = {
994 .packing
= sja1105pqrs_avb_params_entry_packing
,
995 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
996 .packed_entry_size
= SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY
,
997 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
999 [BLK_IDX_GENERAL_PARAMS
] = {
1000 .packing
= sja1105pqrs_general_params_entry_packing
,
1001 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
1002 .packed_entry_size
= SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY
,
1003 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
1005 [BLK_IDX_XMII_PARAMS
] = {
1006 .packing
= sja1105_xmii_params_entry_packing
,
1007 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
1008 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
1009 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
1013 /* SJA1105R: Second generation, no TTEthernet, SGMII */
1014 struct sja1105_table_ops sja1105r_table_ops
[BLK_IDX_MAX
] = {
1015 [BLK_IDX_SCHEDULE
] = {0},
1016 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {0},
1017 [BLK_IDX_L2_LOOKUP
] = {
1018 .packing
= sja1105pqrs_l2_lookup_entry_packing
,
1019 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
1020 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY
,
1021 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
1023 [BLK_IDX_L2_POLICING
] = {
1024 .packing
= sja1105_l2_policing_entry_packing
,
1025 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
1026 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
1027 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
1029 [BLK_IDX_VLAN_LOOKUP
] = {
1030 .packing
= sja1105_vlan_lookup_entry_packing
,
1031 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
1032 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
1033 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
1035 [BLK_IDX_L2_FORWARDING
] = {
1036 .packing
= sja1105_l2_forwarding_entry_packing
,
1037 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
1038 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
1039 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
1041 [BLK_IDX_MAC_CONFIG
] = {
1042 .packing
= sja1105pqrs_mac_config_entry_packing
,
1043 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
1044 .packed_entry_size
= SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY
,
1045 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
1047 [BLK_IDX_SCHEDULE_PARAMS
] = {0},
1048 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {0},
1049 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
1050 .packing
= sja1105pqrs_l2_lookup_params_entry_packing
,
1051 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
1052 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
1053 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
1055 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
1056 .packing
= sja1105_l2_forwarding_params_entry_packing
,
1057 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
1058 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
1059 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
1061 [BLK_IDX_AVB_PARAMS
] = {
1062 .packing
= sja1105pqrs_avb_params_entry_packing
,
1063 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
1064 .packed_entry_size
= SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY
,
1065 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
1067 [BLK_IDX_GENERAL_PARAMS
] = {
1068 .packing
= sja1105pqrs_general_params_entry_packing
,
1069 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
1070 .packed_entry_size
= SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY
,
1071 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
1073 [BLK_IDX_XMII_PARAMS
] = {
1074 .packing
= sja1105_xmii_params_entry_packing
,
1075 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
1076 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
1077 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
1081 /* SJA1105S: Second generation, TTEthernet, SGMII */
1082 struct sja1105_table_ops sja1105s_table_ops
[BLK_IDX_MAX
] = {
1083 [BLK_IDX_SCHEDULE
] = {
1084 .packing
= sja1105_schedule_entry_packing
,
1085 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry
),
1086 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY
,
1087 .max_entry_count
= SJA1105_MAX_SCHEDULE_COUNT
,
1089 [BLK_IDX_SCHEDULE_ENTRY_POINTS
] = {
1090 .packing
= sja1105_schedule_entry_points_entry_packing
,
1091 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_entry
),
1092 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY
,
1093 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT
,
1095 [BLK_IDX_L2_LOOKUP
] = {
1096 .packing
= sja1105pqrs_l2_lookup_entry_packing
,
1097 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_entry
),
1098 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY
,
1099 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_COUNT
,
1101 [BLK_IDX_L2_POLICING
] = {
1102 .packing
= sja1105_l2_policing_entry_packing
,
1103 .unpacked_entry_size
= sizeof(struct sja1105_l2_policing_entry
),
1104 .packed_entry_size
= SJA1105_SIZE_L2_POLICING_ENTRY
,
1105 .max_entry_count
= SJA1105_MAX_L2_POLICING_COUNT
,
1107 [BLK_IDX_VLAN_LOOKUP
] = {
1108 .packing
= sja1105_vlan_lookup_entry_packing
,
1109 .unpacked_entry_size
= sizeof(struct sja1105_vlan_lookup_entry
),
1110 .packed_entry_size
= SJA1105_SIZE_VLAN_LOOKUP_ENTRY
,
1111 .max_entry_count
= SJA1105_MAX_VLAN_LOOKUP_COUNT
,
1113 [BLK_IDX_L2_FORWARDING
] = {
1114 .packing
= sja1105_l2_forwarding_entry_packing
,
1115 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_entry
),
1116 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_ENTRY
,
1117 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_COUNT
,
1119 [BLK_IDX_MAC_CONFIG
] = {
1120 .packing
= sja1105pqrs_mac_config_entry_packing
,
1121 .unpacked_entry_size
= sizeof(struct sja1105_mac_config_entry
),
1122 .packed_entry_size
= SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY
,
1123 .max_entry_count
= SJA1105_MAX_MAC_CONFIG_COUNT
,
1125 [BLK_IDX_SCHEDULE_PARAMS
] = {
1126 .packing
= sja1105_schedule_params_entry_packing
,
1127 .unpacked_entry_size
= sizeof(struct sja1105_schedule_params_entry
),
1128 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY
,
1129 .max_entry_count
= SJA1105_MAX_SCHEDULE_PARAMS_COUNT
,
1131 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS
] = {
1132 .packing
= sja1105_schedule_entry_points_params_entry_packing
,
1133 .unpacked_entry_size
= sizeof(struct sja1105_schedule_entry_points_params_entry
),
1134 .packed_entry_size
= SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY
,
1135 .max_entry_count
= SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT
,
1137 [BLK_IDX_L2_LOOKUP_PARAMS
] = {
1138 .packing
= sja1105pqrs_l2_lookup_params_entry_packing
,
1139 .unpacked_entry_size
= sizeof(struct sja1105_l2_lookup_params_entry
),
1140 .packed_entry_size
= SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY
,
1141 .max_entry_count
= SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT
,
1143 [BLK_IDX_L2_FORWARDING_PARAMS
] = {
1144 .packing
= sja1105_l2_forwarding_params_entry_packing
,
1145 .unpacked_entry_size
= sizeof(struct sja1105_l2_forwarding_params_entry
),
1146 .packed_entry_size
= SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY
,
1147 .max_entry_count
= SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT
,
1149 [BLK_IDX_AVB_PARAMS
] = {
1150 .packing
= sja1105pqrs_avb_params_entry_packing
,
1151 .unpacked_entry_size
= sizeof(struct sja1105_avb_params_entry
),
1152 .packed_entry_size
= SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY
,
1153 .max_entry_count
= SJA1105_MAX_AVB_PARAMS_COUNT
,
1155 [BLK_IDX_GENERAL_PARAMS
] = {
1156 .packing
= sja1105pqrs_general_params_entry_packing
,
1157 .unpacked_entry_size
= sizeof(struct sja1105_general_params_entry
),
1158 .packed_entry_size
= SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY
,
1159 .max_entry_count
= SJA1105_MAX_GENERAL_PARAMS_COUNT
,
1161 [BLK_IDX_XMII_PARAMS
] = {
1162 .packing
= sja1105_xmii_params_entry_packing
,
1163 .unpacked_entry_size
= sizeof(struct sja1105_xmii_params_entry
),
1164 .packed_entry_size
= SJA1105_SIZE_XMII_PARAMS_ENTRY
,
1165 .max_entry_count
= SJA1105_MAX_XMII_PARAMS_COUNT
,
1169 int sja1105_static_config_init(struct sja1105_static_config
*config
,
1170 const struct sja1105_table_ops
*static_ops
,
1173 enum sja1105_blk_idx i
;
1175 *config
= (struct sja1105_static_config
) {0};
1177 /* Transfer static_ops array from priv into per-table ops
1178 * for handier access
1180 for (i
= 0; i
< BLK_IDX_MAX
; i
++)
1181 config
->tables
[i
].ops
= &static_ops
[i
];
1183 config
->device_id
= device_id
;
1187 void sja1105_static_config_free(struct sja1105_static_config
*config
)
1189 enum sja1105_blk_idx i
;
1191 for (i
= 0; i
< BLK_IDX_MAX
; i
++) {
1192 if (config
->tables
[i
].entry_count
) {
1193 kfree(config
->tables
[i
].entries
);
1194 config
->tables
[i
].entry_count
= 0;
1199 int sja1105_table_delete_entry(struct sja1105_table
*table
, int i
)
1201 size_t entry_size
= table
->ops
->unpacked_entry_size
;
1202 u8
*entries
= table
->entries
;
1204 if (i
> table
->entry_count
)
1207 memmove(entries
+ i
* entry_size
, entries
+ (i
+ 1) * entry_size
,
1208 (table
->entry_count
- i
) * entry_size
);
1210 table
->entry_count
--;
1215 /* No pointers to table->entries should be kept when this is called. */
1216 int sja1105_table_resize(struct sja1105_table
*table
, size_t new_count
)
1218 size_t entry_size
= table
->ops
->unpacked_entry_size
;
1219 void *new_entries
, *old_entries
= table
->entries
;
1221 if (new_count
> table
->ops
->max_entry_count
)
1224 new_entries
= kcalloc(new_count
, entry_size
, GFP_KERNEL
);
1228 memcpy(new_entries
, old_entries
, min(new_count
, table
->entry_count
) *
1231 table
->entries
= new_entries
;
1232 table
->entry_count
= new_count
;