net: dsa: sja1105: Export symbols for upcoming PTP driver
[linux-2.6-block.git] / drivers / net / dsa / sja1105 / sja1105_static_config.c
CommitLineData
8aa9ebcc
VO
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 */
17void 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}
28e8fb3e 38EXPORT_SYMBOL_GPL(sja1105_pack);
8aa9ebcc
VO
39
40void sja1105_unpack(const void *buf, u64 *val, int start, int end, size_t len)
41{
42 int rc = packing((void *)buf, val, start, end, len,
43 UNPACK, QUIRK_LSW32_IS_FIRST);
44
45 if (likely(!rc))
46 return;
47
48 if (rc == -EINVAL)
49 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
50 start, end);
51 else if (rc == -ERANGE)
52 pr_err("Field %d-%d too large for 64 bits!\n",
53 start, end);
54 dump_stack();
55}
28e8fb3e 56EXPORT_SYMBOL_GPL(sja1105_unpack);
8aa9ebcc
VO
57
58void sja1105_packing(void *buf, u64 *val, int start, int end,
59 size_t len, enum packing_op op)
60{
61 int rc = packing(buf, val, start, end, len, op, QUIRK_LSW32_IS_FIRST);
62
63 if (likely(!rc))
64 return;
65
66 if (rc == -EINVAL) {
67 pr_err("Start bit (%d) expected to be larger than end (%d)\n",
68 start, end);
69 } else if (rc == -ERANGE) {
70 if ((start - end + 1) > 64)
71 pr_err("Field %d-%d too large for 64 bits!\n",
72 start, end);
73 else
74 pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
75 *val, start, end);
76 }
77 dump_stack();
78}
28e8fb3e 79EXPORT_SYMBOL_GPL(sja1105_packing);
8aa9ebcc
VO
80
81/* Little-endian Ethernet CRC32 of data packed as big-endian u32 words */
82u32 sja1105_crc32(const void *buf, size_t len)
83{
84 unsigned int i;
85 u64 word;
86 u32 crc;
87
88 /* seed */
89 crc = ~0;
90 for (i = 0; i < len; i += 4) {
91 sja1105_unpack((void *)buf + i, &word, 31, 0, 4);
92 crc = crc32_le(crc, (u8 *)&word, 4);
93 }
94 return ~crc;
95}
96
97static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
98 enum packing_op op)
99{
100 const size_t size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY;
101 struct sja1105_general_params_entry *entry = entry_ptr;
102
103 sja1105_packing(buf, &entry->vllupformat, 319, 319, size, op);
104 sja1105_packing(buf, &entry->mirr_ptacu, 318, 318, size, op);
105 sja1105_packing(buf, &entry->switchid, 317, 315, size, op);
106 sja1105_packing(buf, &entry->hostprio, 314, 312, size, op);
107 sja1105_packing(buf, &entry->mac_fltres1, 311, 264, size, op);
108 sja1105_packing(buf, &entry->mac_fltres0, 263, 216, size, op);
109 sja1105_packing(buf, &entry->mac_flt1, 215, 168, size, op);
110 sja1105_packing(buf, &entry->mac_flt0, 167, 120, size, op);
111 sja1105_packing(buf, &entry->incl_srcpt1, 119, 119, size, op);
112 sja1105_packing(buf, &entry->incl_srcpt0, 118, 118, size, op);
113 sja1105_packing(buf, &entry->send_meta1, 117, 117, size, op);
114 sja1105_packing(buf, &entry->send_meta0, 116, 116, size, op);
115 sja1105_packing(buf, &entry->casc_port, 115, 113, size, op);
116 sja1105_packing(buf, &entry->host_port, 112, 110, size, op);
117 sja1105_packing(buf, &entry->mirr_port, 109, 107, size, op);
118 sja1105_packing(buf, &entry->vlmarker, 106, 75, size, op);
119 sja1105_packing(buf, &entry->vlmask, 74, 43, size, op);
120 sja1105_packing(buf, &entry->tpid, 42, 27, size, op);
121 sja1105_packing(buf, &entry->ignore2stf, 26, 26, size, op);
122 sja1105_packing(buf, &entry->tpid2, 25, 10, size, op);
123 return size;
124}
125
126static size_t
127sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
128 enum packing_op op)
129{
130 const size_t size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
131 struct sja1105_general_params_entry *entry = entry_ptr;
132
133 sja1105_packing(buf, &entry->vllupformat, 351, 351, size, op);
134 sja1105_packing(buf, &entry->mirr_ptacu, 350, 350, size, op);
135 sja1105_packing(buf, &entry->switchid, 349, 347, size, op);
136 sja1105_packing(buf, &entry->hostprio, 346, 344, size, op);
137 sja1105_packing(buf, &entry->mac_fltres1, 343, 296, size, op);
138 sja1105_packing(buf, &entry->mac_fltres0, 295, 248, size, op);
139 sja1105_packing(buf, &entry->mac_flt1, 247, 200, size, op);
140 sja1105_packing(buf, &entry->mac_flt0, 199, 152, size, op);
141 sja1105_packing(buf, &entry->incl_srcpt1, 151, 151, size, op);
142 sja1105_packing(buf, &entry->incl_srcpt0, 150, 150, size, op);
143 sja1105_packing(buf, &entry->send_meta1, 149, 149, size, op);
144 sja1105_packing(buf, &entry->send_meta0, 148, 148, size, op);
145 sja1105_packing(buf, &entry->casc_port, 147, 145, size, op);
146 sja1105_packing(buf, &entry->host_port, 144, 142, size, op);
147 sja1105_packing(buf, &entry->mirr_port, 141, 139, size, op);
148 sja1105_packing(buf, &entry->vlmarker, 138, 107, size, op);
149 sja1105_packing(buf, &entry->vlmask, 106, 75, size, op);
150 sja1105_packing(buf, &entry->tpid, 74, 59, size, op);
151 sja1105_packing(buf, &entry->ignore2stf, 58, 58, size, op);
152 sja1105_packing(buf, &entry->tpid2, 57, 42, size, op);
153 sja1105_packing(buf, &entry->queue_ts, 41, 41, size, op);
154 sja1105_packing(buf, &entry->egrmirrvid, 40, 29, size, op);
155 sja1105_packing(buf, &entry->egrmirrpcp, 28, 26, size, op);
156 sja1105_packing(buf, &entry->egrmirrdei, 25, 25, size, op);
157 sja1105_packing(buf, &entry->replay_port, 24, 22, size, op);
158 return size;
159}
160
161static size_t
162sja1105_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
163 enum packing_op op)
164{
165 const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
166 struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
167 int offset, i;
168
169 sja1105_packing(buf, &entry->max_dynp, 95, 93, size, op);
170 for (i = 0, offset = 13; i < 8; i++, offset += 10)
171 sja1105_packing(buf, &entry->part_spc[i],
172 offset + 9, offset + 0, size, op);
173 return size;
174}
175
176size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
177 enum packing_op op)
178{
179 const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
180 struct sja1105_l2_forwarding_entry *entry = entry_ptr;
181 int offset, i;
182
183 sja1105_packing(buf, &entry->bc_domain, 63, 59, size, op);
184 sja1105_packing(buf, &entry->reach_port, 58, 54, size, op);
185 sja1105_packing(buf, &entry->fl_domain, 53, 49, size, op);
186 for (i = 0, offset = 25; i < 8; i++, offset += 3)
187 sja1105_packing(buf, &entry->vlan_pmap[i],
188 offset + 2, offset + 0, size, op);
189 return size;
190}
191
192static size_t
193sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
194 enum packing_op op)
195{
196 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY;
197 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
198
199 sja1105_packing(buf, &entry->maxage, 31, 17, size, op);
200 sja1105_packing(buf, &entry->dyn_tbsz, 16, 14, size, op);
201 sja1105_packing(buf, &entry->poly, 13, 6, size, op);
202 sja1105_packing(buf, &entry->shared_learn, 5, 5, size, op);
203 sja1105_packing(buf, &entry->no_enf_hostprt, 4, 4, size, op);
204 sja1105_packing(buf, &entry->no_mgmt_learn, 3, 3, size, op);
205 return size;
206}
207
208static size_t
209sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
210 enum packing_op op)
211{
212 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
213 struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
214
215 sja1105_packing(buf, &entry->maxage, 57, 43, size, op);
216 sja1105_packing(buf, &entry->shared_learn, 27, 27, size, op);
217 sja1105_packing(buf, &entry->no_enf_hostprt, 26, 26, size, op);
218 sja1105_packing(buf, &entry->no_mgmt_learn, 25, 25, size, op);
219 return size;
220}
221
222size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr,
223 enum packing_op op)
224{
225 const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
226 struct sja1105_l2_lookup_entry *entry = entry_ptr;
227
228 sja1105_packing(buf, &entry->vlanid, 95, 84, size, op);
229 sja1105_packing(buf, &entry->macaddr, 83, 36, size, op);
230 sja1105_packing(buf, &entry->destports, 35, 31, size, op);
231 sja1105_packing(buf, &entry->enfport, 30, 30, size, op);
232 sja1105_packing(buf, &entry->index, 29, 20, size, op);
233 return size;
234}
235
236size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr,
237 enum packing_op op)
238{
239 const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
240 struct sja1105_l2_lookup_entry *entry = entry_ptr;
241
9c5098d9
VO
242 if (entry->lockeds) {
243 sja1105_packing(buf, &entry->tsreg, 159, 159, size, op);
244 sja1105_packing(buf, &entry->mirrvlan, 158, 147, size, op);
245 sja1105_packing(buf, &entry->takets, 146, 146, size, op);
246 sja1105_packing(buf, &entry->mirr, 145, 145, size, op);
247 sja1105_packing(buf, &entry->retag, 144, 144, size, op);
248 } else {
249 sja1105_packing(buf, &entry->touched, 159, 159, size, op);
250 sja1105_packing(buf, &entry->age, 158, 144, size, op);
251 }
252 sja1105_packing(buf, &entry->mask_iotag, 143, 143, size, op);
253 sja1105_packing(buf, &entry->mask_vlanid, 142, 131, size, op);
254 sja1105_packing(buf, &entry->mask_macaddr, 130, 83, size, op);
255 sja1105_packing(buf, &entry->iotag, 82, 82, size, op);
8aa9ebcc
VO
256 sja1105_packing(buf, &entry->vlanid, 81, 70, size, op);
257 sja1105_packing(buf, &entry->macaddr, 69, 22, size, op);
258 sja1105_packing(buf, &entry->destports, 21, 17, size, op);
259 sja1105_packing(buf, &entry->enfport, 16, 16, size, op);
260 sja1105_packing(buf, &entry->index, 15, 6, size, op);
261 return size;
262}
263
264static size_t sja1105_l2_policing_entry_packing(void *buf, void *entry_ptr,
265 enum packing_op op)
266{
267 const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
268 struct sja1105_l2_policing_entry *entry = entry_ptr;
269
270 sja1105_packing(buf, &entry->sharindx, 63, 58, size, op);
271 sja1105_packing(buf, &entry->smax, 57, 42, size, op);
272 sja1105_packing(buf, &entry->rate, 41, 26, size, op);
273 sja1105_packing(buf, &entry->maxlen, 25, 15, size, op);
274 sja1105_packing(buf, &entry->partition, 14, 12, size, op);
275 return size;
276}
277
278static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
279 enum packing_op op)
280{
281 const size_t size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY;
282 struct sja1105_mac_config_entry *entry = entry_ptr;
283 int offset, i;
284
285 for (i = 0, offset = 72; i < 8; i++, offset += 19) {
286 sja1105_packing(buf, &entry->enabled[i],
287 offset + 0, offset + 0, size, op);
288 sja1105_packing(buf, &entry->base[i],
289 offset + 9, offset + 1, size, op);
290 sja1105_packing(buf, &entry->top[i],
291 offset + 18, offset + 10, size, op);
292 }
293 sja1105_packing(buf, &entry->ifg, 71, 67, size, op);
294 sja1105_packing(buf, &entry->speed, 66, 65, size, op);
295 sja1105_packing(buf, &entry->tp_delin, 64, 49, size, op);
296 sja1105_packing(buf, &entry->tp_delout, 48, 33, size, op);
297 sja1105_packing(buf, &entry->maxage, 32, 25, size, op);
298 sja1105_packing(buf, &entry->vlanprio, 24, 22, size, op);
299 sja1105_packing(buf, &entry->vlanid, 21, 10, size, op);
300 sja1105_packing(buf, &entry->ing_mirr, 9, 9, size, op);
301 sja1105_packing(buf, &entry->egr_mirr, 8, 8, size, op);
302 sja1105_packing(buf, &entry->drpnona664, 7, 7, size, op);
303 sja1105_packing(buf, &entry->drpdtag, 6, 6, size, op);
304 sja1105_packing(buf, &entry->drpuntag, 5, 5, size, op);
305 sja1105_packing(buf, &entry->retag, 4, 4, size, op);
306 sja1105_packing(buf, &entry->dyn_learn, 3, 3, size, op);
307 sja1105_packing(buf, &entry->egress, 2, 2, size, op);
308 sja1105_packing(buf, &entry->ingress, 1, 1, size, op);
309 return size;
310}
311
312size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
313 enum packing_op op)
314{
315 const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
316 struct sja1105_mac_config_entry *entry = entry_ptr;
317 int offset, i;
318
319 for (i = 0, offset = 104; i < 8; i++, offset += 19) {
320 sja1105_packing(buf, &entry->enabled[i],
321 offset + 0, offset + 0, size, op);
322 sja1105_packing(buf, &entry->base[i],
323 offset + 9, offset + 1, size, op);
324 sja1105_packing(buf, &entry->top[i],
325 offset + 18, offset + 10, size, op);
326 }
327 sja1105_packing(buf, &entry->ifg, 103, 99, size, op);
328 sja1105_packing(buf, &entry->speed, 98, 97, size, op);
329 sja1105_packing(buf, &entry->tp_delin, 96, 81, size, op);
330 sja1105_packing(buf, &entry->tp_delout, 80, 65, size, op);
331 sja1105_packing(buf, &entry->maxage, 64, 57, size, op);
332 sja1105_packing(buf, &entry->vlanprio, 56, 54, size, op);
333 sja1105_packing(buf, &entry->vlanid, 53, 42, size, op);
334 sja1105_packing(buf, &entry->ing_mirr, 41, 41, size, op);
335 sja1105_packing(buf, &entry->egr_mirr, 40, 40, size, op);
336 sja1105_packing(buf, &entry->drpnona664, 39, 39, size, op);
337 sja1105_packing(buf, &entry->drpdtag, 38, 38, size, op);
338 sja1105_packing(buf, &entry->drpuntag, 35, 35, size, op);
339 sja1105_packing(buf, &entry->retag, 34, 34, size, op);
340 sja1105_packing(buf, &entry->dyn_learn, 33, 33, size, op);
341 sja1105_packing(buf, &entry->egress, 32, 32, size, op);
342 sja1105_packing(buf, &entry->ingress, 31, 31, size, op);
343 return size;
344}
345
346size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
347 enum packing_op op)
348{
349 const size_t size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY;
350 struct sja1105_vlan_lookup_entry *entry = entry_ptr;
351
352 sja1105_packing(buf, &entry->ving_mirr, 63, 59, size, op);
353 sja1105_packing(buf, &entry->vegr_mirr, 58, 54, size, op);
354 sja1105_packing(buf, &entry->vmemb_port, 53, 49, size, op);
355 sja1105_packing(buf, &entry->vlan_bc, 48, 44, size, op);
356 sja1105_packing(buf, &entry->tag_port, 43, 39, size, op);
357 sja1105_packing(buf, &entry->vlanid, 38, 27, size, op);
358 return size;
359}
360
361static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr,
362 enum packing_op op)
363{
364 const size_t size = SJA1105_SIZE_XMII_PARAMS_ENTRY;
365 struct sja1105_xmii_params_entry *entry = entry_ptr;
366 int offset, i;
367
368 for (i = 0, offset = 17; i < 5; i++, offset += 3) {
369 sja1105_packing(buf, &entry->xmii_mode[i],
370 offset + 1, offset + 0, size, op);
371 sja1105_packing(buf, &entry->phy_mac[i],
372 offset + 2, offset + 2, size, op);
373 }
374 return size;
375}
376
377size_t sja1105_table_header_packing(void *buf, void *entry_ptr,
378 enum packing_op op)
379{
380 const size_t size = SJA1105_SIZE_TABLE_HEADER;
381 struct sja1105_table_header *entry = entry_ptr;
382
383 sja1105_packing(buf, &entry->block_id, 31, 24, size, op);
384 sja1105_packing(buf, &entry->len, 55, 32, size, op);
385 sja1105_packing(buf, &entry->crc, 95, 64, size, op);
386 return size;
387}
388
389/* WARNING: the *hdr pointer is really non-const, because it is
390 * modifying the CRC of the header for a 2-stage packing operation
391 */
392void
393sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr)
394{
395 /* First pack the table as-is, then calculate the CRC, and
396 * finally put the proper CRC into the packed buffer
397 */
398 memset(buf, 0, SJA1105_SIZE_TABLE_HEADER);
399 sja1105_table_header_packing(buf, hdr, PACK);
400 hdr->crc = sja1105_crc32(buf, SJA1105_SIZE_TABLE_HEADER - 4);
401 sja1105_pack(buf + SJA1105_SIZE_TABLE_HEADER - 4, &hdr->crc, 31, 0, 4);
402}
403
404static void sja1105_table_write_crc(u8 *table_start, u8 *crc_ptr)
405{
406 u64 computed_crc;
407 int len_bytes;
408
409 len_bytes = (uintptr_t)(crc_ptr - table_start);
410 computed_crc = sja1105_crc32(table_start, len_bytes);
411 sja1105_pack(crc_ptr, &computed_crc, 31, 0, 4);
412}
413
414/* The block IDs that the switches support are unfortunately sparse, so keep a
415 * mapping table to "block indices" and translate back and forth so that we
416 * don't waste useless memory in struct sja1105_static_config.
417 * Also, since the block id comes from essentially untrusted input (unpacking
418 * the static config from userspace) it has to be sanitized (range-checked)
419 * before blindly indexing kernel memory with the blk_idx.
420 */
421static u64 blk_id_map[BLK_IDX_MAX] = {
422 [BLK_IDX_L2_LOOKUP] = BLKID_L2_LOOKUP,
423 [BLK_IDX_L2_POLICING] = BLKID_L2_POLICING,
424 [BLK_IDX_VLAN_LOOKUP] = BLKID_VLAN_LOOKUP,
425 [BLK_IDX_L2_FORWARDING] = BLKID_L2_FORWARDING,
426 [BLK_IDX_MAC_CONFIG] = BLKID_MAC_CONFIG,
427 [BLK_IDX_L2_LOOKUP_PARAMS] = BLKID_L2_LOOKUP_PARAMS,
428 [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS,
429 [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS,
430 [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS,
431};
432
433const char *sja1105_static_config_error_msg[] = {
434 [SJA1105_CONFIG_OK] = "",
435 [SJA1105_MISSING_L2_POLICING_TABLE] =
436 "l2-policing-table needs to have at least one entry",
437 [SJA1105_MISSING_L2_FORWARDING_TABLE] =
438 "l2-forwarding-table is either missing or incomplete",
439 [SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE] =
440 "l2-forwarding-parameters-table is missing",
441 [SJA1105_MISSING_GENERAL_PARAMS_TABLE] =
442 "general-parameters-table is missing",
443 [SJA1105_MISSING_VLAN_TABLE] =
444 "vlan-lookup-table needs to have at least the default untagged VLAN",
445 [SJA1105_MISSING_XMII_TABLE] =
446 "xmii-table is missing",
447 [SJA1105_MISSING_MAC_TABLE] =
448 "mac-configuration-table needs to contain an entry for each port",
449 [SJA1105_OVERCOMMITTED_FRAME_MEMORY] =
450 "Not allowed to overcommit frame memory. L2 memory partitions "
451 "and VL memory partitions share the same space. The sum of all "
452 "16 memory partitions is not allowed to be larger than 929 "
453 "128-byte blocks (or 910 with retagging). Please adjust "
454 "l2-forwarding-parameters-table.part_spc and/or "
455 "vl-forwarding-parameters-table.partspc.",
456};
457
5ee907f7 458static sja1105_config_valid_t
8aa9ebcc
VO
459static_config_check_memory_size(const struct sja1105_table *tables)
460{
461 const struct sja1105_l2_forwarding_params_entry *l2_fwd_params;
462 int i, mem = 0;
463
464 l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries;
465
466 for (i = 0; i < 8; i++)
467 mem += l2_fwd_params->part_spc[i];
468
469 if (mem > SJA1105_MAX_FRAME_MEMORY)
470 return SJA1105_OVERCOMMITTED_FRAME_MEMORY;
471
472 return SJA1105_CONFIG_OK;
473}
474
475sja1105_config_valid_t
476sja1105_static_config_check_valid(const struct sja1105_static_config *config)
477{
478 const struct sja1105_table *tables = config->tables;
479#define IS_FULL(blk_idx) \
480 (tables[blk_idx].entry_count == tables[blk_idx].ops->max_entry_count)
481
482 if (tables[BLK_IDX_L2_POLICING].entry_count == 0)
483 return SJA1105_MISSING_L2_POLICING_TABLE;
484
485 if (tables[BLK_IDX_VLAN_LOOKUP].entry_count == 0)
486 return SJA1105_MISSING_VLAN_TABLE;
487
488 if (!IS_FULL(BLK_IDX_L2_FORWARDING))
489 return SJA1105_MISSING_L2_FORWARDING_TABLE;
490
491 if (!IS_FULL(BLK_IDX_MAC_CONFIG))
492 return SJA1105_MISSING_MAC_TABLE;
493
494 if (!IS_FULL(BLK_IDX_L2_FORWARDING_PARAMS))
495 return SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE;
496
497 if (!IS_FULL(BLK_IDX_GENERAL_PARAMS))
498 return SJA1105_MISSING_GENERAL_PARAMS_TABLE;
499
500 if (!IS_FULL(BLK_IDX_XMII_PARAMS))
501 return SJA1105_MISSING_XMII_TABLE;
502
503 return static_config_check_memory_size(tables);
504#undef IS_FULL
505}
506
507void
508sja1105_static_config_pack(void *buf, struct sja1105_static_config *config)
509{
510 struct sja1105_table_header header = {0};
511 enum sja1105_blk_idx i;
512 char *p = buf;
513 int j;
514
515 sja1105_pack(p, &config->device_id, 31, 0, 4);
516 p += SJA1105_SIZE_DEVICE_ID;
517
518 for (i = 0; i < BLK_IDX_MAX; i++) {
519 const struct sja1105_table *table;
520 char *table_start;
521
522 table = &config->tables[i];
523 if (!table->entry_count)
524 continue;
525
526 header.block_id = blk_id_map[i];
527 header.len = table->entry_count *
528 table->ops->packed_entry_size / 4;
529 sja1105_table_header_pack_with_crc(p, &header);
530 p += SJA1105_SIZE_TABLE_HEADER;
531 table_start = p;
532 for (j = 0; j < table->entry_count; j++) {
533 u8 *entry_ptr = table->entries;
534
535 entry_ptr += j * table->ops->unpacked_entry_size;
536 memset(p, 0, table->ops->packed_entry_size);
537 table->ops->packing(p, entry_ptr, PACK);
538 p += table->ops->packed_entry_size;
539 }
540 sja1105_table_write_crc(table_start, p);
541 p += 4;
542 }
543 /* Final header:
544 * Block ID does not matter
545 * Length of 0 marks that header is final
546 * CRC will be replaced on-the-fly on "config upload"
547 */
548 header.block_id = 0;
549 header.len = 0;
550 header.crc = 0xDEADBEEF;
551 memset(p, 0, SJA1105_SIZE_TABLE_HEADER);
552 sja1105_table_header_packing(p, &header, PACK);
553}
554
555size_t
556sja1105_static_config_get_length(const struct sja1105_static_config *config)
557{
558 unsigned int sum;
559 unsigned int header_count;
560 enum sja1105_blk_idx i;
561
562 /* Ending header */
563 header_count = 1;
564 sum = SJA1105_SIZE_DEVICE_ID;
565
566 /* Tables (headers and entries) */
567 for (i = 0; i < BLK_IDX_MAX; i++) {
568 const struct sja1105_table *table;
569
570 table = &config->tables[i];
571 if (table->entry_count)
572 header_count++;
573
574 sum += table->ops->packed_entry_size * table->entry_count;
575 }
576 /* Headers have an additional CRC at the end */
577 sum += header_count * (SJA1105_SIZE_TABLE_HEADER + 4);
578 /* Last header does not have an extra CRC because there is no data */
579 sum -= 4;
580
581 return sum;
582}
583
584/* Compatibility matrices */
585
586/* SJA1105E: First generation, no TTEthernet */
587struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX] = {
588 [BLK_IDX_L2_LOOKUP] = {
589 .packing = sja1105et_l2_lookup_entry_packing,
590 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
591 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
592 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
593 },
594 [BLK_IDX_L2_POLICING] = {
595 .packing = sja1105_l2_policing_entry_packing,
596 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
597 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
598 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
599 },
600 [BLK_IDX_VLAN_LOOKUP] = {
601 .packing = sja1105_vlan_lookup_entry_packing,
602 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
603 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
604 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
605 },
606 [BLK_IDX_L2_FORWARDING] = {
607 .packing = sja1105_l2_forwarding_entry_packing,
608 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
609 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
610 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
611 },
612 [BLK_IDX_MAC_CONFIG] = {
613 .packing = sja1105et_mac_config_entry_packing,
614 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
615 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
616 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
617 },
618 [BLK_IDX_L2_LOOKUP_PARAMS] = {
619 .packing = sja1105et_l2_lookup_params_entry_packing,
620 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
621 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
622 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
623 },
624 [BLK_IDX_L2_FORWARDING_PARAMS] = {
625 .packing = sja1105_l2_forwarding_params_entry_packing,
626 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
627 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
628 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
629 },
630 [BLK_IDX_GENERAL_PARAMS] = {
631 .packing = sja1105et_general_params_entry_packing,
632 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
633 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
634 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
635 },
636 [BLK_IDX_XMII_PARAMS] = {
637 .packing = sja1105_xmii_params_entry_packing,
638 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
639 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
640 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
641 },
642};
643
644/* SJA1105T: First generation, TTEthernet */
645struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX] = {
646 [BLK_IDX_L2_LOOKUP] = {
647 .packing = sja1105et_l2_lookup_entry_packing,
648 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
649 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
650 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
651 },
652 [BLK_IDX_L2_POLICING] = {
653 .packing = sja1105_l2_policing_entry_packing,
654 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
655 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
656 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
657 },
658 [BLK_IDX_VLAN_LOOKUP] = {
659 .packing = sja1105_vlan_lookup_entry_packing,
660 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
661 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
662 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
663 },
664 [BLK_IDX_L2_FORWARDING] = {
665 .packing = sja1105_l2_forwarding_entry_packing,
666 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
667 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
668 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
669 },
670 [BLK_IDX_MAC_CONFIG] = {
671 .packing = sja1105et_mac_config_entry_packing,
672 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
673 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
674 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
675 },
676 [BLK_IDX_L2_LOOKUP_PARAMS] = {
677 .packing = sja1105et_l2_lookup_params_entry_packing,
678 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
679 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
680 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
681 },
682 [BLK_IDX_L2_FORWARDING_PARAMS] = {
683 .packing = sja1105_l2_forwarding_params_entry_packing,
684 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
685 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
686 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
687 },
688 [BLK_IDX_GENERAL_PARAMS] = {
689 .packing = sja1105et_general_params_entry_packing,
690 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
691 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
692 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
693 },
694 [BLK_IDX_XMII_PARAMS] = {
695 .packing = sja1105_xmii_params_entry_packing,
696 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
697 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
698 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
699 },
700};
701
702/* SJA1105P: Second generation, no TTEthernet, no SGMII */
703struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX] = {
704 [BLK_IDX_L2_LOOKUP] = {
705 .packing = sja1105pqrs_l2_lookup_entry_packing,
706 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
707 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
708 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
709 },
710 [BLK_IDX_L2_POLICING] = {
711 .packing = sja1105_l2_policing_entry_packing,
712 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
713 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
714 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
715 },
716 [BLK_IDX_VLAN_LOOKUP] = {
717 .packing = sja1105_vlan_lookup_entry_packing,
718 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
719 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
720 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
721 },
722 [BLK_IDX_L2_FORWARDING] = {
723 .packing = sja1105_l2_forwarding_entry_packing,
724 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
725 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
726 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
727 },
728 [BLK_IDX_MAC_CONFIG] = {
729 .packing = sja1105pqrs_mac_config_entry_packing,
730 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
731 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
732 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
733 },
734 [BLK_IDX_L2_LOOKUP_PARAMS] = {
735 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
736 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
737 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
738 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
739 },
740 [BLK_IDX_L2_FORWARDING_PARAMS] = {
741 .packing = sja1105_l2_forwarding_params_entry_packing,
742 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
743 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
744 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
745 },
746 [BLK_IDX_GENERAL_PARAMS] = {
747 .packing = sja1105pqrs_general_params_entry_packing,
748 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
749 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
750 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
751 },
752 [BLK_IDX_XMII_PARAMS] = {
753 .packing = sja1105_xmii_params_entry_packing,
754 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
755 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
756 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
757 },
758};
759
760/* SJA1105Q: Second generation, TTEthernet, no SGMII */
761struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX] = {
762 [BLK_IDX_L2_LOOKUP] = {
763 .packing = sja1105pqrs_l2_lookup_entry_packing,
764 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
765 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
766 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
767 },
768 [BLK_IDX_L2_POLICING] = {
769 .packing = sja1105_l2_policing_entry_packing,
770 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
771 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
772 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
773 },
774 [BLK_IDX_VLAN_LOOKUP] = {
775 .packing = sja1105_vlan_lookup_entry_packing,
776 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
777 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
778 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
779 },
780 [BLK_IDX_L2_FORWARDING] = {
781 .packing = sja1105_l2_forwarding_entry_packing,
782 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
783 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
784 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
785 },
786 [BLK_IDX_MAC_CONFIG] = {
787 .packing = sja1105pqrs_mac_config_entry_packing,
788 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
789 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
790 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
791 },
792 [BLK_IDX_L2_LOOKUP_PARAMS] = {
793 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
794 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
795 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
796 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
797 },
798 [BLK_IDX_L2_FORWARDING_PARAMS] = {
799 .packing = sja1105_l2_forwarding_params_entry_packing,
800 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
801 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
802 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
803 },
804 [BLK_IDX_GENERAL_PARAMS] = {
805 .packing = sja1105pqrs_general_params_entry_packing,
806 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
807 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
808 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
809 },
810 [BLK_IDX_XMII_PARAMS] = {
811 .packing = sja1105_xmii_params_entry_packing,
812 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
813 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
814 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
815 },
816};
817
818/* SJA1105R: Second generation, no TTEthernet, SGMII */
819struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX] = {
820 [BLK_IDX_L2_LOOKUP] = {
821 .packing = sja1105pqrs_l2_lookup_entry_packing,
822 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
823 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
824 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
825 },
826 [BLK_IDX_L2_POLICING] = {
827 .packing = sja1105_l2_policing_entry_packing,
828 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
829 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
830 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
831 },
832 [BLK_IDX_VLAN_LOOKUP] = {
833 .packing = sja1105_vlan_lookup_entry_packing,
834 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
835 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
836 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
837 },
838 [BLK_IDX_L2_FORWARDING] = {
839 .packing = sja1105_l2_forwarding_entry_packing,
840 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
841 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
842 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
843 },
844 [BLK_IDX_MAC_CONFIG] = {
845 .packing = sja1105pqrs_mac_config_entry_packing,
846 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
847 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
848 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
849 },
850 [BLK_IDX_L2_LOOKUP_PARAMS] = {
851 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
852 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
853 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
854 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
855 },
856 [BLK_IDX_L2_FORWARDING_PARAMS] = {
857 .packing = sja1105_l2_forwarding_params_entry_packing,
858 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
859 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
860 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
861 },
862 [BLK_IDX_GENERAL_PARAMS] = {
863 .packing = sja1105pqrs_general_params_entry_packing,
864 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
865 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
866 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
867 },
868 [BLK_IDX_XMII_PARAMS] = {
869 .packing = sja1105_xmii_params_entry_packing,
870 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
871 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
872 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
873 },
874};
875
876/* SJA1105S: Second generation, TTEthernet, SGMII */
877struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX] = {
878 [BLK_IDX_L2_LOOKUP] = {
879 .packing = sja1105pqrs_l2_lookup_entry_packing,
880 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
881 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
882 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
883 },
884 [BLK_IDX_L2_POLICING] = {
885 .packing = sja1105_l2_policing_entry_packing,
886 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
887 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
888 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
889 },
890 [BLK_IDX_VLAN_LOOKUP] = {
891 .packing = sja1105_vlan_lookup_entry_packing,
892 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
893 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
894 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
895 },
896 [BLK_IDX_L2_FORWARDING] = {
897 .packing = sja1105_l2_forwarding_entry_packing,
898 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
899 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
900 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
901 },
902 [BLK_IDX_MAC_CONFIG] = {
903 .packing = sja1105pqrs_mac_config_entry_packing,
904 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
905 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
906 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
907 },
908 [BLK_IDX_L2_LOOKUP_PARAMS] = {
909 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
910 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
911 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
912 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
913 },
914 [BLK_IDX_L2_FORWARDING_PARAMS] = {
915 .packing = sja1105_l2_forwarding_params_entry_packing,
916 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
917 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
918 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
919 },
920 [BLK_IDX_GENERAL_PARAMS] = {
921 .packing = sja1105pqrs_general_params_entry_packing,
922 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
923 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
924 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
925 },
926 [BLK_IDX_XMII_PARAMS] = {
927 .packing = sja1105_xmii_params_entry_packing,
928 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
929 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
930 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
931 },
932};
933
934int sja1105_static_config_init(struct sja1105_static_config *config,
935 const struct sja1105_table_ops *static_ops,
936 u64 device_id)
937{
938 enum sja1105_blk_idx i;
939
940 *config = (struct sja1105_static_config) {0};
941
942 /* Transfer static_ops array from priv into per-table ops
943 * for handier access
944 */
945 for (i = 0; i < BLK_IDX_MAX; i++)
946 config->tables[i].ops = &static_ops[i];
947
948 config->device_id = device_id;
949 return 0;
950}
951
952void sja1105_static_config_free(struct sja1105_static_config *config)
953{
954 enum sja1105_blk_idx i;
955
956 for (i = 0; i < BLK_IDX_MAX; i++) {
957 if (config->tables[i].entry_count) {
958 kfree(config->tables[i].entries);
959 config->tables[i].entry_count = 0;
960 }
961 }
962}
6666cebc
VO
963
964int sja1105_table_delete_entry(struct sja1105_table *table, int i)
965{
966 size_t entry_size = table->ops->unpacked_entry_size;
967 u8 *entries = table->entries;
968
969 if (i > table->entry_count)
970 return -ERANGE;
971
972 memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
973 (table->entry_count - i) * entry_size);
974
975 table->entry_count--;
976
977 return 0;
978}
979
980/* No pointers to table->entries should be kept when this is called. */
981int sja1105_table_resize(struct sja1105_table *table, size_t new_count)
982{
983 size_t entry_size = table->ops->unpacked_entry_size;
984 void *new_entries, *old_entries = table->entries;
985
986 if (new_count > table->ops->max_entry_count)
987 return -ERANGE;
988
989 new_entries = kcalloc(new_count, entry_size, GFP_KERNEL);
990 if (!new_entries)
991 return -ENOMEM;
992
993 memcpy(new_entries, old_entries, min(new_count, table->entry_count) *
994 entry_size);
995
996 table->entries = new_entries;
997 table->entry_count = new_count;
998 kfree(old_entries);
999 return 0;
1000}