1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright (c) 2016-2018, NXP Semiconductors
3 * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
4 */
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>
10
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.
16 */
sja1105_pack(void * buf,const u64 * val,int start,int end,size_t len)17 void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len)
18 {
19 int rc = packing(buf, (u64 *)val, start, end, len,
20 PACK, QUIRK_LSW32_IS_FIRST);
21
22 if (likely(!rc))
23 return;
24
25 if (rc == -EINVAL) {
26 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
27 start, end);
28 } else if (rc == -ERANGE) {
29 if ((start - end + 1) > 64)
30 pr_err("Field %d-%d too large for 64 bits!\n",
31 start, end);
32 else
33 pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
34 *val, start, end);
35 }
36 dump_stack();
37 }
38
sja1105_unpack(const void * buf,u64 * val,int start,int end,size_t len)39 void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len)
40 {
41 int rc = packing((void *)buf, val, start, end, len,
42 UNPACK, QUIRK_LSW32_IS_FIRST);
43
44 if (likely(!rc))
45 return;
46
47 if (rc == -EINVAL)
48 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
49 start, end);
50 else if (rc == -ERANGE)
51 pr_err("Field %d-%d too large for 64 bits!\n",
52 start, end);
53 dump_stack();
54 }
55
sja1105_packing(void * buf,u64 * val,int start,int end,size_t len,enum packing_op op)56 void sja1105_packing(void *buf, u64 *val, int start, int end,
57 size_t len, enum packing_op op)
58 {
59 int rc = packing(buf, val, start, end, len, op, QUIRK_LSW32_IS_FIRST);
60
61 if (likely(!rc))
62 return;
63
64 if (rc == -EINVAL) {
65 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
66 start, end);
67 } else if (rc == -ERANGE) {
68 if ((start - end + 1) > 64)
69 pr_err("Field %d-%d too large for 64 bits!\n",
70 start, end);
71 else
72 pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
73 *val, start, end);
74 }
75 dump_stack();
76 }
77
78 /* Little-endian Ethernet CRC32 of data packed as big-endian u32 words */
sja1105_crc32(const void * buf,size_t len)79 u32 sja1105_crc32(const void *buf, size_t len)
80 {
81 unsigned int i;
82 u64 word;
83 u32 crc;
84
85 /* seed */
86 crc = ~0;
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);
90 }
91 return ~crc;
92 }
93
sja1105et_avb_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)94 static size_t sja1105et_avb_params_entry_packing(void *buf, void *entry_ptr,
95 enum packing_op op)
96 {
97 const size_t size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY;
98 struct sja1105_avb_params_entry *entry = entry_ptr;
99
100 sja1105_packing(buf, &entry->destmeta, 95, 48, size, op);
101 sja1105_packing(buf, &entry->srcmeta, 47, 0, size, op);
102 return size;
103 }
104
sja1105pqrs_avb_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)105 size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr,
106 enum packing_op op)
107 {
108 const size_t size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY;
109 struct sja1105_avb_params_entry *entry = entry_ptr;
110
111 sja1105_packing(buf, &entry->cas_master, 126, 126, size, op);
112 sja1105_packing(buf, &entry->destmeta, 125, 78, size, op);
113 sja1105_packing(buf, &entry->srcmeta, 77, 30, size, op);
114 return size;
115 }
116
sja1105et_general_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)117 static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
118 enum packing_op op)
119 {
120 const size_t size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY;
121 struct sja1105_general_params_entry *entry = entry_ptr;
122
123 sja1105_packing(buf, &entry->vllupformat, 319, 319, size, op);
124 sja1105_packing(buf, &entry->mirr_ptacu, 318, 318, size, op);
125 sja1105_packing(buf, &entry->switchid, 317, 315, size, op);
126 sja1105_packing(buf, &entry->hostprio, 314, 312, size, op);
127 sja1105_packing(buf, &entry->mac_fltres1, 311, 264, size, op);
128 sja1105_packing(buf, &entry->mac_fltres0, 263, 216, size, op);
129 sja1105_packing(buf, &entry->mac_flt1, 215, 168, size, op);
130 sja1105_packing(buf, &entry->mac_flt0, 167, 120, size, op);
131 sja1105_packing(buf, &entry->incl_srcpt1, 119, 119, size, op);
132 sja1105_packing(buf, &entry->incl_srcpt0, 118, 118, size, op);
133 sja1105_packing(buf, &entry->send_meta1, 117, 117, size, op);
134 sja1105_packing(buf, &entry->send_meta0, 116, 116, size, op);
135 sja1105_packing(buf, &entry->casc_port, 115, 113, size, op);
136 sja1105_packing(buf, &entry->host_port, 112, 110, size, op);
137 sja1105_packing(buf, &entry->mirr_port, 109, 107, size, op);
138 sja1105_packing(buf, &entry->vlmarker, 106, 75, size, op);
139 sja1105_packing(buf, &entry->vlmask, 74, 43, size, op);
140 sja1105_packing(buf, &entry->tpid, 42, 27, size, op);
141 sja1105_packing(buf, &entry->ignore2stf, 26, 26, size, op);
142 sja1105_packing(buf, &entry->tpid2, 25, 10, size, op);
143 return size;
144 }
145
146 /* TPID and TPID2 are intentionally reversed so that semantic
147 * compatibility with E/T is kept.
148 */
sja1105pqrs_general_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)149 size_t sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
150 enum packing_op op)
151 {
152 const size_t size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
153 struct sja1105_general_params_entry *entry = entry_ptr;
154
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);
180 return size;
181 }
182
183 static size_t
sja1105_l2_forwarding_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)184 sja1105_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
185 enum packing_op op)
186 {
187 const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
188 struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
189 int offset, i;
190
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);
195 return size;
196 }
197
sja1105_l2_forwarding_entry_packing(void * buf,void * entry_ptr,enum packing_op op)198 size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
199 enum packing_op op)
200 {
201 const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
202 struct sja1105_l2_forwarding_entry *entry = entry_ptr;
203 int offset, i;
204
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);
211 return size;
212 }
213
214 static size_t
sja1105et_l2_lookup_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)215 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
216 enum packing_op op)
217 {
218 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY;
219 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
220
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);
227 return size;
228 }
229
sja1105pqrs_l2_lookup_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)230 size_t sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
231 enum packing_op op)
232 {
233 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
234 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
235 int offset, i;
236
237 for (i = 0, offset = 58; i < 5; i++, offset += 11)
238 sja1105_packing(buf, &entry->maxaddrp[i],
239 offset + 10, offset + 0, size, op);
240 sja1105_packing(buf, &entry->maxage, 57, 43, size, op);
241 sja1105_packing(buf, &entry->start_dynspc, 42, 33, size, op);
242 sja1105_packing(buf, &entry->drpnolearn, 32, 28, size, op);
243 sja1105_packing(buf, &entry->shared_learn, 27, 27, size, op);
244 sja1105_packing(buf, &entry->no_enf_hostprt, 26, 26, size, op);
245 sja1105_packing(buf, &entry->no_mgmt_learn, 25, 25, size, op);
246 sja1105_packing(buf, &entry->use_static, 24, 24, size, op);
247 sja1105_packing(buf, &entry->owr_dyn, 23, 23, size, op);
248 sja1105_packing(buf, &entry->learn_once, 22, 22, size, op);
249 return size;
250 }
251
sja1105et_l2_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)252 size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr,
253 enum packing_op op)
254 {
255 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
256 struct sja1105_l2_lookup_entry *entry = entry_ptr;
257
258 sja1105_packing(buf, &entry->vlanid, 95, 84, size, op);
259 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op);
260 sja1105_packing(buf, &entry->destports, 35, 31, size, op);
261 sja1105_packing(buf, &entry->enfport, 30, 30, size, op);
262 sja1105_packing(buf, &entry->index, 29, 20, size, op);
263 return size;
264 }
265
sja1105pqrs_l2_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)266 size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr,
267 enum packing_op op)
268 {
269 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
270 struct sja1105_l2_lookup_entry *entry = entry_ptr;
271
272 if (entry->lockeds) {
273 sja1105_packing(buf, &entry->tsreg, 159, 159, size, op);
274 sja1105_packing(buf, &entry->mirrvlan, 158, 147, size, op);
275 sja1105_packing(buf, &entry->takets, 146, 146, size, op);
276 sja1105_packing(buf, &entry->mirr, 145, 145, size, op);
277 sja1105_packing(buf, &entry->retag, 144, 144, size, op);
278 } else {
279 sja1105_packing(buf, &entry->touched, 159, 159, size, op);
280 sja1105_packing(buf, &entry->age, 158, 144, size, op);
281 }
282 sja1105_packing(buf, &entry->mask_iotag, 143, 143, size, op);
283 sja1105_packing(buf, &entry->mask_vlanid, 142, 131, size, op);
284 sja1105_packing(buf, &entry->mask_macaddr, 130, 83, size, op);
285 sja1105_packing(buf, &entry->iotag, 82, 82, size, op);
286 sja1105_packing(buf, &entry->vlanid, 81, 70, size, op);
287 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op);
288 sja1105_packing(buf, &entry->destports, 21, 17, size, op);
289 sja1105_packing(buf, &entry->enfport, 16, 16, size, op);
290 sja1105_packing(buf, &entry->index, 15, 6, size, op);
291 return size;
292 }
293
sja1105_l2_policing_entry_packing(void * buf,void * entry_ptr,enum packing_op op)294 static size_t sja1105_l2_policing_entry_packing(void *buf, void *entry_ptr,
295 enum packing_op op)
296 {
297 const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
298 struct sja1105_l2_policing_entry *entry = entry_ptr;
299
300 sja1105_packing(buf, &entry->sharindx, 63, 58, size, op);
301 sja1105_packing(buf, &entry->smax, 57, 42, size, op);
302 sja1105_packing(buf, &entry->rate, 41, 26, size, op);
303 sja1105_packing(buf, &entry->maxlen, 25, 15, size, op);
304 sja1105_packing(buf, &entry->partition, 14, 12, size, op);
305 return size;
306 }
307
sja1105et_mac_config_entry_packing(void * buf,void * entry_ptr,enum packing_op op)308 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
309 enum packing_op op)
310 {
311 const size_t size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY;
312 struct sja1105_mac_config_entry *entry = entry_ptr;
313 int offset, i;
314
315 for (i = 0, offset = 72; i < 8; i++, offset += 19) {
316 sja1105_packing(buf, &entry->enabled[i],
317 offset + 0, offset + 0, size, op);
318 sja1105_packing(buf, &entry->base[i],
319 offset + 9, offset + 1, size, op);
320 sja1105_packing(buf, &entry->top[i],
321 offset + 18, offset + 10, size, op);
322 }
323 sja1105_packing(buf, &entry->ifg, 71, 67, size, op);
324 sja1105_packing(buf, &entry->speed, 66, 65, size, op);
325 sja1105_packing(buf, &entry->tp_delin, 64, 49, size, op);
326 sja1105_packing(buf, &entry->tp_delout, 48, 33, size, op);
327 sja1105_packing(buf, &entry->maxage, 32, 25, size, op);
328 sja1105_packing(buf, &entry->vlanprio, 24, 22, size, op);
329 sja1105_packing(buf, &entry->vlanid, 21, 10, size, op);
330 sja1105_packing(buf, &entry->ing_mirr, 9, 9, size, op);
331 sja1105_packing(buf, &entry->egr_mirr, 8, 8, size, op);
332 sja1105_packing(buf, &entry->drpnona664, 7, 7, size, op);
333 sja1105_packing(buf, &entry->drpdtag, 6, 6, size, op);
334 sja1105_packing(buf, &entry->drpuntag, 5, 5, size, op);
335 sja1105_packing(buf, &entry->retag, 4, 4, size, op);
336 sja1105_packing(buf, &entry->dyn_learn, 3, 3, size, op);
337 sja1105_packing(buf, &entry->egress, 2, 2, size, op);
338 sja1105_packing(buf, &entry->ingress, 1, 1, size, op);
339 return size;
340 }
341
sja1105pqrs_mac_config_entry_packing(void * buf,void * entry_ptr,enum packing_op op)342 size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
343 enum packing_op op)
344 {
345 const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
346 struct sja1105_mac_config_entry *entry = entry_ptr;
347 int offset, i;
348
349 for (i = 0, offset = 104; i < 8; i++, offset += 19) {
350 sja1105_packing(buf, &entry->enabled[i],
351 offset + 0, offset + 0, size, op);
352 sja1105_packing(buf, &entry->base[i],
353 offset + 9, offset + 1, size, op);
354 sja1105_packing(buf, &entry->top[i],
355 offset + 18, offset + 10, size, op);
356 }
357 sja1105_packing(buf, &entry->ifg, 103, 99, size, op);
358 sja1105_packing(buf, &entry->speed, 98, 97, size, op);
359 sja1105_packing(buf, &entry->tp_delin, 96, 81, size, op);
360 sja1105_packing(buf, &entry->tp_delout, 80, 65, size, op);
361 sja1105_packing(buf, &entry->maxage, 64, 57, size, op);
362 sja1105_packing(buf, &entry->vlanprio, 56, 54, size, op);
363 sja1105_packing(buf, &entry->vlanid, 53, 42, size, op);
364 sja1105_packing(buf, &entry->ing_mirr, 41, 41, size, op);
365 sja1105_packing(buf, &entry->egr_mirr, 40, 40, size, op);
366 sja1105_packing(buf, &entry->drpnona664, 39, 39, size, op);
367 sja1105_packing(buf, &entry->drpdtag, 38, 38, size, op);
368 sja1105_packing(buf, &entry->drpuntag, 35, 35, size, op);
369 sja1105_packing(buf, &entry->retag, 34, 34, size, op);
370 sja1105_packing(buf, &entry->dyn_learn, 33, 33, size, op);
371 sja1105_packing(buf, &entry->egress, 32, 32, size, op);
372 sja1105_packing(buf, &entry->ingress, 31, 31, size, op);
373 return size;
374 }
375
376 static size_t
sja1105_schedule_entry_points_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)377 sja1105_schedule_entry_points_params_entry_packing(void *buf, void *entry_ptr,
378 enum packing_op op)
379 {
380 struct sja1105_schedule_entry_points_params_entry *entry = entry_ptr;
381 const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY;
382
383 sja1105_packing(buf, &entry->clksrc, 31, 30, size, op);
384 sja1105_packing(buf, &entry->actsubsch, 29, 27, size, op);
385 return size;
386 }
387
388 static size_t
sja1105_schedule_entry_points_entry_packing(void * buf,void * entry_ptr,enum packing_op op)389 sja1105_schedule_entry_points_entry_packing(void *buf, void *entry_ptr,
390 enum packing_op op)
391 {
392 struct sja1105_schedule_entry_points_entry *entry = entry_ptr;
393 const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY;
394
395 sja1105_packing(buf, &entry->subschindx, 31, 29, size, op);
396 sja1105_packing(buf, &entry->delta, 28, 11, size, op);
397 sja1105_packing(buf, &entry->address, 10, 1, size, op);
398 return size;
399 }
400
sja1105_schedule_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)401 static size_t sja1105_schedule_params_entry_packing(void *buf, void *entry_ptr,
402 enum packing_op op)
403 {
404 const size_t size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY;
405 struct sja1105_schedule_params_entry *entry = entry_ptr;
406 int offset, i;
407
408 for (i = 0, offset = 16; i < 8; i++, offset += 10)
409 sja1105_packing(buf, &entry->subscheind[i],
410 offset + 9, offset + 0, size, op);
411 return size;
412 }
413
sja1105_schedule_entry_packing(void * buf,void * entry_ptr,enum packing_op op)414 static size_t sja1105_schedule_entry_packing(void *buf, void *entry_ptr,
415 enum packing_op op)
416 {
417 const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY;
418 struct sja1105_schedule_entry *entry = entry_ptr;
419
420 sja1105_packing(buf, &entry->winstindex, 63, 54, size, op);
421 sja1105_packing(buf, &entry->winend, 53, 53, size, op);
422 sja1105_packing(buf, &entry->winst, 52, 52, size, op);
423 sja1105_packing(buf, &entry->destports, 51, 47, size, op);
424 sja1105_packing(buf, &entry->setvalid, 46, 46, size, op);
425 sja1105_packing(buf, &entry->txen, 45, 45, size, op);
426 sja1105_packing(buf, &entry->resmedia_en, 44, 44, size, op);
427 sja1105_packing(buf, &entry->resmedia, 43, 36, size, op);
428 sja1105_packing(buf, &entry->vlindex, 35, 26, size, op);
429 sja1105_packing(buf, &entry->delta, 25, 8, size, op);
430 return size;
431 }
432
433 static size_t
sja1105_vl_forwarding_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)434 sja1105_vl_forwarding_params_entry_packing(void *buf, void *entry_ptr,
435 enum packing_op op)
436 {
437 struct sja1105_vl_forwarding_params_entry *entry = entry_ptr;
438 const size_t size = SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY;
439 int offset, i;
440
441 for (i = 0, offset = 16; i < 8; i++, offset += 10)
442 sja1105_packing(buf, &entry->partspc[i],
443 offset + 9, offset + 0, size, op);
444 sja1105_packing(buf, &entry->debugen, 15, 15, size, op);
445 return size;
446 }
447
sja1105_vl_forwarding_entry_packing(void * buf,void * entry_ptr,enum packing_op op)448 static size_t sja1105_vl_forwarding_entry_packing(void *buf, void *entry_ptr,
449 enum packing_op op)
450 {
451 struct sja1105_vl_forwarding_entry *entry = entry_ptr;
452 const size_t size = SJA1105_SIZE_VL_FORWARDING_ENTRY;
453
454 sja1105_packing(buf, &entry->type, 31, 31, size, op);
455 sja1105_packing(buf, &entry->priority, 30, 28, size, op);
456 sja1105_packing(buf, &entry->partition, 27, 25, size, op);
457 sja1105_packing(buf, &entry->destports, 24, 20, size, op);
458 return size;
459 }
460
sja1105_vl_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)461 size_t sja1105_vl_lookup_entry_packing(void *buf, void *entry_ptr,
462 enum packing_op op)
463 {
464 struct sja1105_vl_lookup_entry *entry = entry_ptr;
465 const size_t size = SJA1105_SIZE_VL_LOOKUP_ENTRY;
466
467 if (entry->format == SJA1105_VL_FORMAT_PSFP) {
468 /* Interpreting vllupformat as 0 */
469 sja1105_packing(buf, &entry->destports,
470 95, 91, size, op);
471 sja1105_packing(buf, &entry->iscritical,
472 90, 90, size, op);
473 sja1105_packing(buf, &entry->macaddr,
474 89, 42, size, op);
475 sja1105_packing(buf, &entry->vlanid,
476 41, 30, size, op);
477 sja1105_packing(buf, &entry->port,
478 29, 27, size, op);
479 sja1105_packing(buf, &entry->vlanprior,
480 26, 24, size, op);
481 } else {
482 /* Interpreting vllupformat as 1 */
483 sja1105_packing(buf, &entry->egrmirr,
484 95, 91, size, op);
485 sja1105_packing(buf, &entry->ingrmirr,
486 90, 90, size, op);
487 sja1105_packing(buf, &entry->vlid,
488 57, 42, size, op);
489 sja1105_packing(buf, &entry->port,
490 29, 27, size, op);
491 }
492 return size;
493 }
494
sja1105_vl_policing_entry_packing(void * buf,void * entry_ptr,enum packing_op op)495 static size_t sja1105_vl_policing_entry_packing(void *buf, void *entry_ptr,
496 enum packing_op op)
497 {
498 struct sja1105_vl_policing_entry *entry = entry_ptr;
499 const size_t size = SJA1105_SIZE_VL_POLICING_ENTRY;
500
501 sja1105_packing(buf, &entry->type, 63, 63, size, op);
502 sja1105_packing(buf, &entry->maxlen, 62, 52, size, op);
503 sja1105_packing(buf, &entry->sharindx, 51, 42, size, op);
504 if (entry->type == 0) {
505 sja1105_packing(buf, &entry->bag, 41, 28, size, op);
506 sja1105_packing(buf, &entry->jitter, 27, 18, size, op);
507 }
508 return size;
509 }
510
sja1105_vlan_lookup_entry_packing(void * buf,void * entry_ptr,enum packing_op op)511 size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
512 enum packing_op op)
513 {
514 const size_t size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY;
515 struct sja1105_vlan_lookup_entry *entry = entry_ptr;
516
517 sja1105_packing(buf, &entry->ving_mirr, 63, 59, size, op);
518 sja1105_packing(buf, &entry->vegr_mirr, 58, 54, size, op);
519 sja1105_packing(buf, &entry->vmemb_port, 53, 49, size, op);
520 sja1105_packing(buf, &entry->vlan_bc, 48, 44, size, op);
521 sja1105_packing(buf, &entry->tag_port, 43, 39, size, op);
522 sja1105_packing(buf, &entry->vlanid, 38, 27, size, op);
523 return size;
524 }
525
sja1105_xmii_params_entry_packing(void * buf,void * entry_ptr,enum packing_op op)526 static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr,
527 enum packing_op op)
528 {
529 const size_t size = SJA1105_SIZE_XMII_PARAMS_ENTRY;
530 struct sja1105_xmii_params_entry *entry = entry_ptr;
531 int offset, i;
532
533 for (i = 0, offset = 17; i < 5; i++, offset += 3) {
534 sja1105_packing(buf, &entry->xmii_mode[i],
535 offset + 1, offset + 0, size, op);
536 sja1105_packing(buf, &entry->phy_mac[i],
537 offset + 2, offset + 2, size, op);
538 }
539 return size;
540 }
541
sja1105_retagging_entry_packing(void * buf,void * entry_ptr,enum packing_op op)542 size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr,
543 enum packing_op op)
544 {
545 struct sja1105_retagging_entry *entry = entry_ptr;
546 const size_t size = SJA1105_SIZE_RETAGGING_ENTRY;
547
548 sja1105_packing(buf, &entry->egr_port, 63, 59, size, op);
549 sja1105_packing(buf, &entry->ing_port, 58, 54, size, op);
550 sja1105_packing(buf, &entry->vlan_ing, 53, 42, size, op);
551 sja1105_packing(buf, &entry->vlan_egr, 41, 30, size, op);
552 sja1105_packing(buf, &entry->do_not_learn, 29, 29, size, op);
553 sja1105_packing(buf, &entry->use_dest_ports, 28, 28, size, op);
554 sja1105_packing(buf, &entry->destports, 27, 23, size, op);
555 return size;
556 }
557
sja1105_table_header_packing(void * buf,void * entry_ptr,enum packing_op op)558 size_t sja1105_table_header_packing(void *buf, void *entry_ptr,
559 enum packing_op op)
560 {
561 const size_t size = SJA1105_SIZE_TABLE_HEADER;
562 struct sja1105_table_header *entry = entry_ptr;
563
564 sja1105_packing(buf, &entry->block_id, 31, 24, size, op);
565 sja1105_packing(buf, &entry->len, 55, 32, size, op);
566 sja1105_packing(buf, &entry->crc, 95, 64, size, op);
567 return size;
568 }
569
570 /* WARNING: the *hdr pointer is really non-const, because it is
571 * modifying the CRC of the header for a 2-stage packing operation
572 */
573 void
sja1105_table_header_pack_with_crc(void * buf,struct sja1105_table_header * hdr)574 sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr)
575 {
576 /* First pack the table as-is, then calculate the CRC, and
577 * finally put the proper CRC into the packed buffer
578 */
579 memset(buf, 0, SJA1105_SIZE_TABLE_HEADER);
580 sja1105_table_header_packing(buf, hdr, PACK);
581 hdr->crc = sja1105_crc32(buf, SJA1105_SIZE_TABLE_HEADER - 4);
582 sja1105_pack(buf + SJA1105_SIZE_TABLE_HEADER - 4, &hdr->crc, 31, 0, 4);
583 }
584
sja1105_table_write_crc(u8 * table_start,u8 * crc_ptr)585 static void sja1105_table_write_crc(u8 *table_start, u8 *crc_ptr)
586 {
587 u64 computed_crc;
588 int len_bytes;
589
590 len_bytes = (uintptr_t)(crc_ptr - table_start);
591 computed_crc = sja1105_crc32(table_start, len_bytes);
592 sja1105_pack(crc_ptr, &computed_crc, 31, 0, 4);
593 }
594
595 /* The block IDs that the switches support are unfortunately sparse, so keep a
596 * mapping table to "block indices" and translate back and forth so that we
597 * don't waste useless memory in struct sja1105_static_config.
598 * Also, since the block id comes from essentially untrusted input (unpacking
599 * the static config from userspace) it has to be sanitized (range-checked)
600 * before blindly indexing kernel memory with the blk_idx.
601 */
602 static u64 blk_id_map[BLK_IDX_MAX] = {
603 [BLK_IDX_SCHEDULE] = BLKID_SCHEDULE,
604 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = BLKID_SCHEDULE_ENTRY_POINTS,
605 [BLK_IDX_VL_LOOKUP] = BLKID_VL_LOOKUP,
606 [BLK_IDX_VL_POLICING] = BLKID_VL_POLICING,
607 [BLK_IDX_VL_FORWARDING] = BLKID_VL_FORWARDING,
608 [BLK_IDX_L2_LOOKUP] = BLKID_L2_LOOKUP,
609 [BLK_IDX_L2_POLICING] = BLKID_L2_POLICING,
610 [BLK_IDX_VLAN_LOOKUP] = BLKID_VLAN_LOOKUP,
611 [BLK_IDX_L2_FORWARDING] = BLKID_L2_FORWARDING,
612 [BLK_IDX_MAC_CONFIG] = BLKID_MAC_CONFIG,
613 [BLK_IDX_SCHEDULE_PARAMS] = BLKID_SCHEDULE_PARAMS,
614 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = BLKID_SCHEDULE_ENTRY_POINTS_PARAMS,
615 [BLK_IDX_VL_FORWARDING_PARAMS] = BLKID_VL_FORWARDING_PARAMS,
616 [BLK_IDX_L2_LOOKUP_PARAMS] = BLKID_L2_LOOKUP_PARAMS,
617 [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS,
618 [BLK_IDX_AVB_PARAMS] = BLKID_AVB_PARAMS,
619 [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS,
620 [BLK_IDX_RETAGGING] = BLKID_RETAGGING,
621 [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS,
622 };
623
624 const char *sja1105_static_config_error_msg[] = {
625 [SJA1105_CONFIG_OK] = "",
626 [SJA1105_TTETHERNET_NOT_SUPPORTED] =
627 "schedule-table present, but TTEthernet is "
628 "only supported on T and Q/S",
629 [SJA1105_INCORRECT_TTETHERNET_CONFIGURATION] =
630 "schedule-table present, but one of "
631 "schedule-entry-points-table, schedule-parameters-table or "
632 "schedule-entry-points-parameters table is empty",
633 [SJA1105_INCORRECT_VIRTUAL_LINK_CONFIGURATION] =
634 "vl-lookup-table present, but one of vl-policing-table, "
635 "vl-forwarding-table or vl-forwarding-parameters-table is empty",
636 [SJA1105_MISSING_L2_POLICING_TABLE] =
637 "l2-policing-table needs to have at least one entry",
638 [SJA1105_MISSING_L2_FORWARDING_TABLE] =
639 "l2-forwarding-table is either missing or incomplete",
640 [SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE] =
641 "l2-forwarding-parameters-table is missing",
642 [SJA1105_MISSING_GENERAL_PARAMS_TABLE] =
643 "general-parameters-table is missing",
644 [SJA1105_MISSING_VLAN_TABLE] =
645 "vlan-lookup-table needs to have at least the default untagged VLAN",
646 [SJA1105_MISSING_XMII_TABLE] =
647 "xmii-table is missing",
648 [SJA1105_MISSING_MAC_TABLE] =
649 "mac-configuration-table needs to contain an entry for each port",
650 [SJA1105_OVERCOMMITTED_FRAME_MEMORY] =
651 "Not allowed to overcommit frame memory. L2 memory partitions "
652 "and VL memory partitions share the same space. The sum of all "
653 "16 memory partitions is not allowed to be larger than 929 "
654 "128-byte blocks (or 910 with retagging). Please adjust "
655 "l2-forwarding-parameters-table.part_spc and/or "
656 "vl-forwarding-parameters-table.partspc.",
657 };
658
659 static sja1105_config_valid_t
static_config_check_memory_size(const struct sja1105_table * tables)660 static_config_check_memory_size(const struct sja1105_table *tables)
661 {
662 const struct sja1105_l2_forwarding_params_entry *l2_fwd_params;
663 const struct sja1105_vl_forwarding_params_entry *vl_fwd_params;
664 int i, max_mem, mem = 0;
665
666 l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries;
667
668 for (i = 0; i < 8; i++)
669 mem += l2_fwd_params->part_spc[i];
670
671 if (tables[BLK_IDX_VL_FORWARDING_PARAMS].entry_count) {
672 vl_fwd_params = tables[BLK_IDX_VL_FORWARDING_PARAMS].entries;
673 for (i = 0; i < 8; i++)
674 mem += vl_fwd_params->partspc[i];
675 }
676
677 if (tables[BLK_IDX_RETAGGING].entry_count)
678 max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING;
679 else
680 max_mem = SJA1105_MAX_FRAME_MEMORY;
681
682 if (mem > max_mem)
683 return SJA1105_OVERCOMMITTED_FRAME_MEMORY;
684
685 return SJA1105_CONFIG_OK;
686 }
687
688 sja1105_config_valid_t
sja1105_static_config_check_valid(const struct sja1105_static_config * config)689 sja1105_static_config_check_valid(const struct sja1105_static_config *config)
690 {
691 const struct sja1105_table *tables = config->tables;
692 #define IS_FULL(blk_idx) \
693 (tables[blk_idx].entry_count == tables[blk_idx].ops->max_entry_count)
694
695 if (tables[BLK_IDX_SCHEDULE].entry_count) {
696 if (config->device_id != SJA1105T_DEVICE_ID &&
697 config->device_id != SJA1105QS_DEVICE_ID)
698 return SJA1105_TTETHERNET_NOT_SUPPORTED;
699
700 if (tables[BLK_IDX_SCHEDULE_ENTRY_POINTS].entry_count == 0)
701 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
702
703 if (!IS_FULL(BLK_IDX_SCHEDULE_PARAMS))
704 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
705
706 if (!IS_FULL(BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS))
707 return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
708 }
709 if (tables[BLK_IDX_VL_LOOKUP].entry_count) {
710 struct sja1105_vl_lookup_entry *vl_lookup;
711 bool has_critical_links = false;
712 int i;
713
714 vl_lookup = tables[BLK_IDX_VL_LOOKUP].entries;
715
716 for (i = 0; i < tables[BLK_IDX_VL_LOOKUP].entry_count; i++) {
717 if (vl_lookup[i].iscritical) {
718 has_critical_links = true;
719 break;
720 }
721 }
722
723 if (tables[BLK_IDX_VL_POLICING].entry_count == 0 &&
724 has_critical_links)
725 return SJA1105_INCORRECT_VIRTUAL_LINK_CONFIGURATION;
726
727 if (tables[BLK_IDX_VL_FORWARDING].entry_count == 0 &&
728 has_critical_links)
729 return SJA1105_INCORRECT_VIRTUAL_LINK_CONFIGURATION;
730
731 if (tables[BLK_IDX_VL_FORWARDING_PARAMS].entry_count == 0 &&
732 has_critical_links)
733 return SJA1105_INCORRECT_VIRTUAL_LINK_CONFIGURATION;
734 }
735
736 if (tables[BLK_IDX_L2_POLICING].entry_count == 0)
737 return SJA1105_MISSING_L2_POLICING_TABLE;
738
739 if (tables[BLK_IDX_VLAN_LOOKUP].entry_count == 0)
740 return SJA1105_MISSING_VLAN_TABLE;
741
742 if (!IS_FULL(BLK_IDX_L2_FORWARDING))
743 return SJA1105_MISSING_L2_FORWARDING_TABLE;
744
745 if (!IS_FULL(BLK_IDX_MAC_CONFIG))
746 return SJA1105_MISSING_MAC_TABLE;
747
748 if (!IS_FULL(BLK_IDX_L2_FORWARDING_PARAMS))
749 return SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE;
750
751 if (!IS_FULL(BLK_IDX_GENERAL_PARAMS))
752 return SJA1105_MISSING_GENERAL_PARAMS_TABLE;
753
754 if (!IS_FULL(BLK_IDX_XMII_PARAMS))
755 return SJA1105_MISSING_XMII_TABLE;
756
757 return static_config_check_memory_size(tables);
758 #undef IS_FULL
759 }
760
761 void
sja1105_static_config_pack(void * buf,struct sja1105_static_config * config)762 sja1105_static_config_pack(void *buf, struct sja1105_static_config *config)
763 {
764 struct sja1105_table_header header = {0};
765 enum sja1105_blk_idx i;
766 char *p = buf;
767 int j;
768
769 sja1105_pack(p, &config->device_id, 31, 0, 4);
770 p += SJA1105_SIZE_DEVICE_ID;
771
772 for (i = 0; i < BLK_IDX_MAX; i++) {
773 const struct sja1105_table *table;
774 char *table_start;
775
776 table = &config->tables[i];
777 if (!table->entry_count)
778 continue;
779
780 header.block_id = blk_id_map[i];
781 header.len = table->entry_count *
782 table->ops->packed_entry_size / 4;
783 sja1105_table_header_pack_with_crc(p, &header);
784 p += SJA1105_SIZE_TABLE_HEADER;
785 table_start = p;
786 for (j = 0; j < table->entry_count; j++) {
787 u8 *entry_ptr = table->entries;
788
789 entry_ptr += j * table->ops->unpacked_entry_size;
790 memset(p, 0, table->ops->packed_entry_size);
791 table->ops->packing(p, entry_ptr, PACK);
792 p += table->ops->packed_entry_size;
793 }
794 sja1105_table_write_crc(table_start, p);
795 p += 4;
796 }
797 /* Final header:
798 * Block ID does not matter
799 * Length of 0 marks that header is final
800 * CRC will be replaced on-the-fly on "config upload"
801 */
802 header.block_id = 0;
803 header.len = 0;
804 header.crc = 0xDEADBEEF;
805 memset(p, 0, SJA1105_SIZE_TABLE_HEADER);
806 sja1105_table_header_packing(p, &header, PACK);
807 }
808
809 size_t
sja1105_static_config_get_length(const struct sja1105_static_config * config)810 sja1105_static_config_get_length(const struct sja1105_static_config *config)
811 {
812 unsigned int sum;
813 unsigned int header_count;
814 enum sja1105_blk_idx i;
815
816 /* Ending header */
817 header_count = 1;
818 sum = SJA1105_SIZE_DEVICE_ID;
819
820 /* Tables (headers and entries) */
821 for (i = 0; i < BLK_IDX_MAX; i++) {
822 const struct sja1105_table *table;
823
824 table = &config->tables[i];
825 if (table->entry_count)
826 header_count++;
827
828 sum += table->ops->packed_entry_size * table->entry_count;
829 }
830 /* Headers have an additional CRC at the end */
831 sum += header_count * (SJA1105_SIZE_TABLE_HEADER + 4);
832 /* Last header does not have an extra CRC because there is no data */
833 sum -= 4;
834
835 return sum;
836 }
837
838 /* Compatibility matrices */
839
840 /* SJA1105E: First generation, no TTEthernet */
841 const struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX] = {
842 [BLK_IDX_L2_LOOKUP] = {
843 .packing = sja1105et_l2_lookup_entry_packing,
844 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
845 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
846 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
847 },
848 [BLK_IDX_L2_POLICING] = {
849 .packing = sja1105_l2_policing_entry_packing,
850 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
851 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
852 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
853 },
854 [BLK_IDX_VLAN_LOOKUP] = {
855 .packing = sja1105_vlan_lookup_entry_packing,
856 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
857 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
858 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
859 },
860 [BLK_IDX_L2_FORWARDING] = {
861 .packing = sja1105_l2_forwarding_entry_packing,
862 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
863 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
864 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
865 },
866 [BLK_IDX_MAC_CONFIG] = {
867 .packing = sja1105et_mac_config_entry_packing,
868 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
869 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
870 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
871 },
872 [BLK_IDX_L2_LOOKUP_PARAMS] = {
873 .packing = sja1105et_l2_lookup_params_entry_packing,
874 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
875 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
876 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
877 },
878 [BLK_IDX_L2_FORWARDING_PARAMS] = {
879 .packing = sja1105_l2_forwarding_params_entry_packing,
880 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
881 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
882 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
883 },
884 [BLK_IDX_AVB_PARAMS] = {
885 .packing = sja1105et_avb_params_entry_packing,
886 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
887 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
888 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
889 },
890 [BLK_IDX_GENERAL_PARAMS] = {
891 .packing = sja1105et_general_params_entry_packing,
892 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
893 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
894 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
895 },
896 [BLK_IDX_RETAGGING] = {
897 .packing = sja1105_retagging_entry_packing,
898 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
899 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
900 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
901 },
902 [BLK_IDX_XMII_PARAMS] = {
903 .packing = sja1105_xmii_params_entry_packing,
904 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
905 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
906 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
907 },
908 };
909
910 /* SJA1105T: First generation, TTEthernet */
911 const struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX] = {
912 [BLK_IDX_SCHEDULE] = {
913 .packing = sja1105_schedule_entry_packing,
914 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
915 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
916 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
917 },
918 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
919 .packing = sja1105_schedule_entry_points_entry_packing,
920 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
921 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
922 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
923 },
924 [BLK_IDX_VL_LOOKUP] = {
925 .packing = sja1105_vl_lookup_entry_packing,
926 .unpacked_entry_size = sizeof(struct sja1105_vl_lookup_entry),
927 .packed_entry_size = SJA1105_SIZE_VL_LOOKUP_ENTRY,
928 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
929 },
930 [BLK_IDX_VL_POLICING] = {
931 .packing = sja1105_vl_policing_entry_packing,
932 .unpacked_entry_size = sizeof(struct sja1105_vl_policing_entry),
933 .packed_entry_size = SJA1105_SIZE_VL_POLICING_ENTRY,
934 .max_entry_count = SJA1105_MAX_VL_POLICING_COUNT,
935 },
936 [BLK_IDX_VL_FORWARDING] = {
937 .packing = sja1105_vl_forwarding_entry_packing,
938 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_entry),
939 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_ENTRY,
940 .max_entry_count = SJA1105_MAX_VL_FORWARDING_COUNT,
941 },
942 [BLK_IDX_L2_LOOKUP] = {
943 .packing = sja1105et_l2_lookup_entry_packing,
944 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
945 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
946 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
947 },
948 [BLK_IDX_L2_POLICING] = {
949 .packing = sja1105_l2_policing_entry_packing,
950 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
951 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
952 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
953 },
954 [BLK_IDX_VLAN_LOOKUP] = {
955 .packing = sja1105_vlan_lookup_entry_packing,
956 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
957 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
958 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
959 },
960 [BLK_IDX_L2_FORWARDING] = {
961 .packing = sja1105_l2_forwarding_entry_packing,
962 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
963 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
964 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
965 },
966 [BLK_IDX_MAC_CONFIG] = {
967 .packing = sja1105et_mac_config_entry_packing,
968 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
969 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
970 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
971 },
972 [BLK_IDX_SCHEDULE_PARAMS] = {
973 .packing = sja1105_schedule_params_entry_packing,
974 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
975 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
976 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
977 },
978 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
979 .packing = sja1105_schedule_entry_points_params_entry_packing,
980 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
981 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
982 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
983 },
984 [BLK_IDX_VL_FORWARDING_PARAMS] = {
985 .packing = sja1105_vl_forwarding_params_entry_packing,
986 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_params_entry),
987 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY,
988 .max_entry_count = SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT,
989 },
990 [BLK_IDX_L2_LOOKUP_PARAMS] = {
991 .packing = sja1105et_l2_lookup_params_entry_packing,
992 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
993 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
994 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
995 },
996 [BLK_IDX_L2_FORWARDING_PARAMS] = {
997 .packing = sja1105_l2_forwarding_params_entry_packing,
998 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
999 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1000 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1001 },
1002 [BLK_IDX_AVB_PARAMS] = {
1003 .packing = sja1105et_avb_params_entry_packing,
1004 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1005 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
1006 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1007 },
1008 [BLK_IDX_GENERAL_PARAMS] = {
1009 .packing = sja1105et_general_params_entry_packing,
1010 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1011 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
1012 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1013 },
1014 [BLK_IDX_RETAGGING] = {
1015 .packing = sja1105_retagging_entry_packing,
1016 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
1017 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
1018 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1019 },
1020 [BLK_IDX_XMII_PARAMS] = {
1021 .packing = sja1105_xmii_params_entry_packing,
1022 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1023 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1024 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1025 },
1026 };
1027
1028 /* SJA1105P: Second generation, no TTEthernet, no SGMII */
1029 const struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX] = {
1030 [BLK_IDX_L2_LOOKUP] = {
1031 .packing = sja1105pqrs_l2_lookup_entry_packing,
1032 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1033 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1034 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1035 },
1036 [BLK_IDX_L2_POLICING] = {
1037 .packing = sja1105_l2_policing_entry_packing,
1038 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1039 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1040 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1041 },
1042 [BLK_IDX_VLAN_LOOKUP] = {
1043 .packing = sja1105_vlan_lookup_entry_packing,
1044 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1045 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1046 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1047 },
1048 [BLK_IDX_L2_FORWARDING] = {
1049 .packing = sja1105_l2_forwarding_entry_packing,
1050 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1051 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1052 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1053 },
1054 [BLK_IDX_MAC_CONFIG] = {
1055 .packing = sja1105pqrs_mac_config_entry_packing,
1056 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1057 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1058 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1059 },
1060 [BLK_IDX_L2_LOOKUP_PARAMS] = {
1061 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1062 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1063 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1064 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1065 },
1066 [BLK_IDX_L2_FORWARDING_PARAMS] = {
1067 .packing = sja1105_l2_forwarding_params_entry_packing,
1068 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1069 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1070 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1071 },
1072 [BLK_IDX_AVB_PARAMS] = {
1073 .packing = sja1105pqrs_avb_params_entry_packing,
1074 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1075 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1076 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1077 },
1078 [BLK_IDX_GENERAL_PARAMS] = {
1079 .packing = sja1105pqrs_general_params_entry_packing,
1080 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1081 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1082 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1083 },
1084 [BLK_IDX_RETAGGING] = {
1085 .packing = sja1105_retagging_entry_packing,
1086 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
1087 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
1088 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1089 },
1090 [BLK_IDX_XMII_PARAMS] = {
1091 .packing = sja1105_xmii_params_entry_packing,
1092 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1093 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1094 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1095 },
1096 };
1097
1098 /* SJA1105Q: Second generation, TTEthernet, no SGMII */
1099 const struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX] = {
1100 [BLK_IDX_SCHEDULE] = {
1101 .packing = sja1105_schedule_entry_packing,
1102 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
1103 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
1104 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
1105 },
1106 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
1107 .packing = sja1105_schedule_entry_points_entry_packing,
1108 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
1109 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
1110 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
1111 },
1112 [BLK_IDX_VL_LOOKUP] = {
1113 .packing = sja1105_vl_lookup_entry_packing,
1114 .unpacked_entry_size = sizeof(struct sja1105_vl_lookup_entry),
1115 .packed_entry_size = SJA1105_SIZE_VL_LOOKUP_ENTRY,
1116 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
1117 },
1118 [BLK_IDX_VL_POLICING] = {
1119 .packing = sja1105_vl_policing_entry_packing,
1120 .unpacked_entry_size = sizeof(struct sja1105_vl_policing_entry),
1121 .packed_entry_size = SJA1105_SIZE_VL_POLICING_ENTRY,
1122 .max_entry_count = SJA1105_MAX_VL_POLICING_COUNT,
1123 },
1124 [BLK_IDX_VL_FORWARDING] = {
1125 .packing = sja1105_vl_forwarding_entry_packing,
1126 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_entry),
1127 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_ENTRY,
1128 .max_entry_count = SJA1105_MAX_VL_FORWARDING_COUNT,
1129 },
1130 [BLK_IDX_L2_LOOKUP] = {
1131 .packing = sja1105pqrs_l2_lookup_entry_packing,
1132 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1133 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1134 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1135 },
1136 [BLK_IDX_L2_POLICING] = {
1137 .packing = sja1105_l2_policing_entry_packing,
1138 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1139 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1140 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1141 },
1142 [BLK_IDX_VLAN_LOOKUP] = {
1143 .packing = sja1105_vlan_lookup_entry_packing,
1144 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1145 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1146 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1147 },
1148 [BLK_IDX_L2_FORWARDING] = {
1149 .packing = sja1105_l2_forwarding_entry_packing,
1150 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1151 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1152 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1153 },
1154 [BLK_IDX_MAC_CONFIG] = {
1155 .packing = sja1105pqrs_mac_config_entry_packing,
1156 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1157 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1158 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1159 },
1160 [BLK_IDX_SCHEDULE_PARAMS] = {
1161 .packing = sja1105_schedule_params_entry_packing,
1162 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
1163 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
1164 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
1165 },
1166 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
1167 .packing = sja1105_schedule_entry_points_params_entry_packing,
1168 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
1169 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
1170 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
1171 },
1172 [BLK_IDX_VL_FORWARDING_PARAMS] = {
1173 .packing = sja1105_vl_forwarding_params_entry_packing,
1174 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_params_entry),
1175 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY,
1176 .max_entry_count = SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT,
1177 },
1178 [BLK_IDX_L2_LOOKUP_PARAMS] = {
1179 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1180 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1181 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1182 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1183 },
1184 [BLK_IDX_L2_FORWARDING_PARAMS] = {
1185 .packing = sja1105_l2_forwarding_params_entry_packing,
1186 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1187 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1188 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1189 },
1190 [BLK_IDX_AVB_PARAMS] = {
1191 .packing = sja1105pqrs_avb_params_entry_packing,
1192 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1193 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1194 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1195 },
1196 [BLK_IDX_GENERAL_PARAMS] = {
1197 .packing = sja1105pqrs_general_params_entry_packing,
1198 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1199 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1200 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1201 },
1202 [BLK_IDX_RETAGGING] = {
1203 .packing = sja1105_retagging_entry_packing,
1204 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
1205 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
1206 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1207 },
1208 [BLK_IDX_XMII_PARAMS] = {
1209 .packing = sja1105_xmii_params_entry_packing,
1210 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1211 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1212 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1213 },
1214 };
1215
1216 /* SJA1105R: Second generation, no TTEthernet, SGMII */
1217 const struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX] = {
1218 [BLK_IDX_L2_LOOKUP] = {
1219 .packing = sja1105pqrs_l2_lookup_entry_packing,
1220 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1221 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1222 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1223 },
1224 [BLK_IDX_L2_POLICING] = {
1225 .packing = sja1105_l2_policing_entry_packing,
1226 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1227 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1228 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1229 },
1230 [BLK_IDX_VLAN_LOOKUP] = {
1231 .packing = sja1105_vlan_lookup_entry_packing,
1232 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1233 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1234 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1235 },
1236 [BLK_IDX_L2_FORWARDING] = {
1237 .packing = sja1105_l2_forwarding_entry_packing,
1238 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1239 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1240 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1241 },
1242 [BLK_IDX_MAC_CONFIG] = {
1243 .packing = sja1105pqrs_mac_config_entry_packing,
1244 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1245 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1246 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1247 },
1248 [BLK_IDX_L2_LOOKUP_PARAMS] = {
1249 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1250 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1251 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1252 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1253 },
1254 [BLK_IDX_L2_FORWARDING_PARAMS] = {
1255 .packing = sja1105_l2_forwarding_params_entry_packing,
1256 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1257 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1258 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1259 },
1260 [BLK_IDX_AVB_PARAMS] = {
1261 .packing = sja1105pqrs_avb_params_entry_packing,
1262 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1263 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1264 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1265 },
1266 [BLK_IDX_GENERAL_PARAMS] = {
1267 .packing = sja1105pqrs_general_params_entry_packing,
1268 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1269 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1270 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1271 },
1272 [BLK_IDX_RETAGGING] = {
1273 .packing = sja1105_retagging_entry_packing,
1274 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
1275 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
1276 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1277 },
1278 [BLK_IDX_XMII_PARAMS] = {
1279 .packing = sja1105_xmii_params_entry_packing,
1280 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1281 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1282 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1283 },
1284 };
1285
1286 /* SJA1105S: Second generation, TTEthernet, SGMII */
1287 const struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX] = {
1288 [BLK_IDX_SCHEDULE] = {
1289 .packing = sja1105_schedule_entry_packing,
1290 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
1291 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
1292 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
1293 },
1294 [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
1295 .packing = sja1105_schedule_entry_points_entry_packing,
1296 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
1297 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
1298 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
1299 },
1300 [BLK_IDX_VL_LOOKUP] = {
1301 .packing = sja1105_vl_lookup_entry_packing,
1302 .unpacked_entry_size = sizeof(struct sja1105_vl_lookup_entry),
1303 .packed_entry_size = SJA1105_SIZE_VL_LOOKUP_ENTRY,
1304 .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
1305 },
1306 [BLK_IDX_VL_POLICING] = {
1307 .packing = sja1105_vl_policing_entry_packing,
1308 .unpacked_entry_size = sizeof(struct sja1105_vl_policing_entry),
1309 .packed_entry_size = SJA1105_SIZE_VL_POLICING_ENTRY,
1310 .max_entry_count = SJA1105_MAX_VL_POLICING_COUNT,
1311 },
1312 [BLK_IDX_VL_FORWARDING] = {
1313 .packing = sja1105_vl_forwarding_entry_packing,
1314 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_entry),
1315 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_ENTRY,
1316 .max_entry_count = SJA1105_MAX_VL_FORWARDING_COUNT,
1317 },
1318 [BLK_IDX_L2_LOOKUP] = {
1319 .packing = sja1105pqrs_l2_lookup_entry_packing,
1320 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1321 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1322 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1323 },
1324 [BLK_IDX_L2_POLICING] = {
1325 .packing = sja1105_l2_policing_entry_packing,
1326 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1327 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1328 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1329 },
1330 [BLK_IDX_VLAN_LOOKUP] = {
1331 .packing = sja1105_vlan_lookup_entry_packing,
1332 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1333 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1334 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1335 },
1336 [BLK_IDX_L2_FORWARDING] = {
1337 .packing = sja1105_l2_forwarding_entry_packing,
1338 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1339 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1340 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1341 },
1342 [BLK_IDX_MAC_CONFIG] = {
1343 .packing = sja1105pqrs_mac_config_entry_packing,
1344 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1345 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1346 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1347 },
1348 [BLK_IDX_SCHEDULE_PARAMS] = {
1349 .packing = sja1105_schedule_params_entry_packing,
1350 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
1351 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
1352 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
1353 },
1354 [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
1355 .packing = sja1105_schedule_entry_points_params_entry_packing,
1356 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
1357 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
1358 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
1359 },
1360 [BLK_IDX_VL_FORWARDING_PARAMS] = {
1361 .packing = sja1105_vl_forwarding_params_entry_packing,
1362 .unpacked_entry_size = sizeof(struct sja1105_vl_forwarding_params_entry),
1363 .packed_entry_size = SJA1105_SIZE_VL_FORWARDING_PARAMS_ENTRY,
1364 .max_entry_count = SJA1105_MAX_VL_FORWARDING_PARAMS_COUNT,
1365 },
1366 [BLK_IDX_L2_LOOKUP_PARAMS] = {
1367 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1368 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1369 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1370 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1371 },
1372 [BLK_IDX_L2_FORWARDING_PARAMS] = {
1373 .packing = sja1105_l2_forwarding_params_entry_packing,
1374 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1375 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1376 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1377 },
1378 [BLK_IDX_AVB_PARAMS] = {
1379 .packing = sja1105pqrs_avb_params_entry_packing,
1380 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1381 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1382 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1383 },
1384 [BLK_IDX_GENERAL_PARAMS] = {
1385 .packing = sja1105pqrs_general_params_entry_packing,
1386 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1387 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1388 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1389 },
1390 [BLK_IDX_RETAGGING] = {
1391 .packing = sja1105_retagging_entry_packing,
1392 .unpacked_entry_size = sizeof(struct sja1105_retagging_entry),
1393 .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY,
1394 .max_entry_count = SJA1105_MAX_RETAGGING_COUNT,
1395 },
1396 [BLK_IDX_XMII_PARAMS] = {
1397 .packing = sja1105_xmii_params_entry_packing,
1398 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1399 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1400 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1401 },
1402 };
1403
sja1105_static_config_init(struct sja1105_static_config * config,const struct sja1105_table_ops * static_ops,u64 device_id)1404 int sja1105_static_config_init(struct sja1105_static_config *config,
1405 const struct sja1105_table_ops *static_ops,
1406 u64 device_id)
1407 {
1408 enum sja1105_blk_idx i;
1409
1410 *config = (struct sja1105_static_config) {0};
1411
1412 /* Transfer static_ops array from priv into per-table ops
1413 * for handier access
1414 */
1415 for (i = 0; i < BLK_IDX_MAX; i++)
1416 config->tables[i].ops = &static_ops[i];
1417
1418 config->device_id = device_id;
1419 return 0;
1420 }
1421
sja1105_static_config_free(struct sja1105_static_config * config)1422 void sja1105_static_config_free(struct sja1105_static_config *config)
1423 {
1424 enum sja1105_blk_idx i;
1425
1426 for (i = 0; i < BLK_IDX_MAX; i++) {
1427 if (config->tables[i].entry_count) {
1428 kfree(config->tables[i].entries);
1429 config->tables[i].entry_count = 0;
1430 }
1431 }
1432 }
1433
sja1105_table_delete_entry(struct sja1105_table * table,int i)1434 int sja1105_table_delete_entry(struct sja1105_table *table, int i)
1435 {
1436 size_t entry_size = table->ops->unpacked_entry_size;
1437 u8 *entries = table->entries;
1438
1439 if (i > table->entry_count)
1440 return -ERANGE;
1441
1442 memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
1443 (table->entry_count - i) * entry_size);
1444
1445 table->entry_count--;
1446
1447 return 0;
1448 }
1449
1450 /* No pointers to table->entries should be kept when this is called. */
sja1105_table_resize(struct sja1105_table * table,size_t new_count)1451 int sja1105_table_resize(struct sja1105_table *table, size_t new_count)
1452 {
1453 size_t entry_size = table->ops->unpacked_entry_size;
1454 void *new_entries, *old_entries = table->entries;
1455
1456 if (new_count > table->ops->max_entry_count)
1457 return -ERANGE;
1458
1459 new_entries = kcalloc(new_count, entry_size, GFP_KERNEL);
1460 if (!new_entries)
1461 return -ENOMEM;
1462
1463 memcpy(new_entries, old_entries, min(new_count, table->entry_count) *
1464 entry_size);
1465
1466 table->entries = new_entries;
1467 table->entry_count = new_count;
1468 kfree(old_entries);
1469 return 0;
1470 }
1471