GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / net / dsa / sja1105 / sja1105_static_config.c
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  */
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
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
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 */
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
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
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
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  */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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. */
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 }