OSDN Git Service

0d03e13e99092e36c93adcb946f7f0f26f717b1b
[tomoyo/tomoyo-test1.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 static 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->destmeta,   125,  78, size, op);
112         sja1105_packing(buf, &entry->srcmeta,     77,  30, size, op);
113         return size;
114 }
115
116 static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
117                                                      enum packing_op op)
118 {
119         const size_t size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY;
120         struct sja1105_general_params_entry *entry = entry_ptr;
121
122         sja1105_packing(buf, &entry->vllupformat, 319, 319, size, op);
123         sja1105_packing(buf, &entry->mirr_ptacu,  318, 318, size, op);
124         sja1105_packing(buf, &entry->switchid,    317, 315, size, op);
125         sja1105_packing(buf, &entry->hostprio,    314, 312, size, op);
126         sja1105_packing(buf, &entry->mac_fltres1, 311, 264, size, op);
127         sja1105_packing(buf, &entry->mac_fltres0, 263, 216, size, op);
128         sja1105_packing(buf, &entry->mac_flt1,    215, 168, size, op);
129         sja1105_packing(buf, &entry->mac_flt0,    167, 120, size, op);
130         sja1105_packing(buf, &entry->incl_srcpt1, 119, 119, size, op);
131         sja1105_packing(buf, &entry->incl_srcpt0, 118, 118, size, op);
132         sja1105_packing(buf, &entry->send_meta1,  117, 117, size, op);
133         sja1105_packing(buf, &entry->send_meta0,  116, 116, size, op);
134         sja1105_packing(buf, &entry->casc_port,   115, 113, size, op);
135         sja1105_packing(buf, &entry->host_port,   112, 110, size, op);
136         sja1105_packing(buf, &entry->mirr_port,   109, 107, size, op);
137         sja1105_packing(buf, &entry->vlmarker,    106,  75, size, op);
138         sja1105_packing(buf, &entry->vlmask,       74,  43, size, op);
139         sja1105_packing(buf, &entry->tpid,         42,  27, size, op);
140         sja1105_packing(buf, &entry->ignore2stf,   26,  26, size, op);
141         sja1105_packing(buf, &entry->tpid2,        25,  10, size, op);
142         return size;
143 }
144
145 static size_t
146 sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
147                                          enum packing_op op)
148 {
149         const size_t size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY;
150         struct sja1105_general_params_entry *entry = entry_ptr;
151
152         sja1105_packing(buf, &entry->vllupformat, 351, 351, size, op);
153         sja1105_packing(buf, &entry->mirr_ptacu,  350, 350, size, op);
154         sja1105_packing(buf, &entry->switchid,    349, 347, size, op);
155         sja1105_packing(buf, &entry->hostprio,    346, 344, size, op);
156         sja1105_packing(buf, &entry->mac_fltres1, 343, 296, size, op);
157         sja1105_packing(buf, &entry->mac_fltres0, 295, 248, size, op);
158         sja1105_packing(buf, &entry->mac_flt1,    247, 200, size, op);
159         sja1105_packing(buf, &entry->mac_flt0,    199, 152, size, op);
160         sja1105_packing(buf, &entry->incl_srcpt1, 151, 151, size, op);
161         sja1105_packing(buf, &entry->incl_srcpt0, 150, 150, size, op);
162         sja1105_packing(buf, &entry->send_meta1,  149, 149, size, op);
163         sja1105_packing(buf, &entry->send_meta0,  148, 148, size, op);
164         sja1105_packing(buf, &entry->casc_port,   147, 145, size, op);
165         sja1105_packing(buf, &entry->host_port,   144, 142, size, op);
166         sja1105_packing(buf, &entry->mirr_port,   141, 139, size, op);
167         sja1105_packing(buf, &entry->vlmarker,    138, 107, size, op);
168         sja1105_packing(buf, &entry->vlmask,      106,  75, size, op);
169         sja1105_packing(buf, &entry->tpid,         74,  59, size, op);
170         sja1105_packing(buf, &entry->ignore2stf,   58,  58, size, op);
171         sja1105_packing(buf, &entry->tpid2,        57,  42, size, op);
172         sja1105_packing(buf, &entry->queue_ts,     41,  41, size, op);
173         sja1105_packing(buf, &entry->egrmirrvid,   40,  29, size, op);
174         sja1105_packing(buf, &entry->egrmirrpcp,   28,  26, size, op);
175         sja1105_packing(buf, &entry->egrmirrdei,   25,  25, size, op);
176         sja1105_packing(buf, &entry->replay_port,  24,  22, size, op);
177         return size;
178 }
179
180 static size_t
181 sja1105_l2_forwarding_params_entry_packing(void *buf, void *entry_ptr,
182                                            enum packing_op op)
183 {
184         const size_t size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY;
185         struct sja1105_l2_forwarding_params_entry *entry = entry_ptr;
186         int offset, i;
187
188         sja1105_packing(buf, &entry->max_dynp, 95, 93, size, op);
189         for (i = 0, offset = 13; i < 8; i++, offset += 10)
190                 sja1105_packing(buf, &entry->part_spc[i],
191                                 offset + 9, offset + 0, size, op);
192         return size;
193 }
194
195 size_t sja1105_l2_forwarding_entry_packing(void *buf, void *entry_ptr,
196                                            enum packing_op op)
197 {
198         const size_t size = SJA1105_SIZE_L2_FORWARDING_ENTRY;
199         struct sja1105_l2_forwarding_entry *entry = entry_ptr;
200         int offset, i;
201
202         sja1105_packing(buf, &entry->bc_domain,  63, 59, size, op);
203         sja1105_packing(buf, &entry->reach_port, 58, 54, size, op);
204         sja1105_packing(buf, &entry->fl_domain,  53, 49, size, op);
205         for (i = 0, offset = 25; i < 8; i++, offset += 3)
206                 sja1105_packing(buf, &entry->vlan_pmap[i],
207                                 offset + 2, offset + 0, size, op);
208         return size;
209 }
210
211 static size_t
212 sja1105et_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
213                                          enum packing_op op)
214 {
215         const size_t size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY;
216         struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
217
218         sja1105_packing(buf, &entry->maxage,         31, 17, size, op);
219         sja1105_packing(buf, &entry->dyn_tbsz,       16, 14, size, op);
220         sja1105_packing(buf, &entry->poly,           13,  6, size, op);
221         sja1105_packing(buf, &entry->shared_learn,    5,  5, size, op);
222         sja1105_packing(buf, &entry->no_enf_hostprt,  4,  4, size, op);
223         sja1105_packing(buf, &entry->no_mgmt_learn,   3,  3, size, op);
224         return size;
225 }
226
227 static size_t
228 sja1105pqrs_l2_lookup_params_entry_packing(void *buf, void *entry_ptr,
229                                            enum packing_op op)
230 {
231         const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY;
232         struct sja1105_l2_lookup_params_entry *entry = entry_ptr;
233         int offset, i;
234
235         for (i = 0, offset = 58; i < 5; i++, offset += 11)
236                 sja1105_packing(buf, &entry->maxaddrp[i],
237                                 offset + 10, offset + 0, size, op);
238         sja1105_packing(buf, &entry->maxage,         57,  43, size, op);
239         sja1105_packing(buf, &entry->start_dynspc,   42,  33, size, op);
240         sja1105_packing(buf, &entry->drpnolearn,     32,  28, size, op);
241         sja1105_packing(buf, &entry->shared_learn,   27,  27, size, op);
242         sja1105_packing(buf, &entry->no_enf_hostprt, 26,  26, size, op);
243         sja1105_packing(buf, &entry->no_mgmt_learn,  25,  25, size, op);
244         sja1105_packing(buf, &entry->use_static,     24,  24, size, op);
245         sja1105_packing(buf, &entry->owr_dyn,        23,  23, size, op);
246         sja1105_packing(buf, &entry->learn_once,     22,  22, size, op);
247         return size;
248 }
249
250 size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr,
251                                          enum packing_op op)
252 {
253         const size_t size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
254         struct sja1105_l2_lookup_entry *entry = entry_ptr;
255
256         sja1105_packing(buf, &entry->vlanid,    95, 84, size, op);
257         sja1105_packing(buf, &entry->macaddr,   83, 36, size, op);
258         sja1105_packing(buf, &entry->destports, 35, 31, size, op);
259         sja1105_packing(buf, &entry->enfport,   30, 30, size, op);
260         sja1105_packing(buf, &entry->index,     29, 20, size, op);
261         return size;
262 }
263
264 size_t sja1105pqrs_l2_lookup_entry_packing(void *buf, void *entry_ptr,
265                                            enum packing_op op)
266 {
267         const size_t size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY;
268         struct sja1105_l2_lookup_entry *entry = entry_ptr;
269
270         if (entry->lockeds) {
271                 sja1105_packing(buf, &entry->tsreg,    159, 159, size, op);
272                 sja1105_packing(buf, &entry->mirrvlan, 158, 147, size, op);
273                 sja1105_packing(buf, &entry->takets,   146, 146, size, op);
274                 sja1105_packing(buf, &entry->mirr,     145, 145, size, op);
275                 sja1105_packing(buf, &entry->retag,    144, 144, size, op);
276         } else {
277                 sja1105_packing(buf, &entry->touched,  159, 159, size, op);
278                 sja1105_packing(buf, &entry->age,      158, 144, size, op);
279         }
280         sja1105_packing(buf, &entry->mask_iotag,   143, 143, size, op);
281         sja1105_packing(buf, &entry->mask_vlanid,  142, 131, size, op);
282         sja1105_packing(buf, &entry->mask_macaddr, 130,  83, size, op);
283         sja1105_packing(buf, &entry->iotag,         82,  82, size, op);
284         sja1105_packing(buf, &entry->vlanid,        81,  70, size, op);
285         sja1105_packing(buf, &entry->macaddr,       69,  22, size, op);
286         sja1105_packing(buf, &entry->destports,     21,  17, size, op);
287         sja1105_packing(buf, &entry->enfport,       16,  16, size, op);
288         sja1105_packing(buf, &entry->index,         15,   6, size, op);
289         return size;
290 }
291
292 static size_t sja1105_l2_policing_entry_packing(void *buf, void *entry_ptr,
293                                                 enum packing_op op)
294 {
295         const size_t size = SJA1105_SIZE_L2_POLICING_ENTRY;
296         struct sja1105_l2_policing_entry *entry = entry_ptr;
297
298         sja1105_packing(buf, &entry->sharindx,  63, 58, size, op);
299         sja1105_packing(buf, &entry->smax,      57, 42, size, op);
300         sja1105_packing(buf, &entry->rate,      41, 26, size, op);
301         sja1105_packing(buf, &entry->maxlen,    25, 15, size, op);
302         sja1105_packing(buf, &entry->partition, 14, 12, size, op);
303         return size;
304 }
305
306 static size_t sja1105et_mac_config_entry_packing(void *buf, void *entry_ptr,
307                                                  enum packing_op op)
308 {
309         const size_t size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY;
310         struct sja1105_mac_config_entry *entry = entry_ptr;
311         int offset, i;
312
313         for (i = 0, offset = 72; i < 8; i++, offset += 19) {
314                 sja1105_packing(buf, &entry->enabled[i],
315                                 offset +  0, offset +  0, size, op);
316                 sja1105_packing(buf, &entry->base[i],
317                                 offset +  9, offset +  1, size, op);
318                 sja1105_packing(buf, &entry->top[i],
319                                 offset + 18, offset + 10, size, op);
320         }
321         sja1105_packing(buf, &entry->ifg,       71, 67, size, op);
322         sja1105_packing(buf, &entry->speed,     66, 65, size, op);
323         sja1105_packing(buf, &entry->tp_delin,  64, 49, size, op);
324         sja1105_packing(buf, &entry->tp_delout, 48, 33, size, op);
325         sja1105_packing(buf, &entry->maxage,    32, 25, size, op);
326         sja1105_packing(buf, &entry->vlanprio,  24, 22, size, op);
327         sja1105_packing(buf, &entry->vlanid,    21, 10, size, op);
328         sja1105_packing(buf, &entry->ing_mirr,   9,  9, size, op);
329         sja1105_packing(buf, &entry->egr_mirr,   8,  8, size, op);
330         sja1105_packing(buf, &entry->drpnona664, 7,  7, size, op);
331         sja1105_packing(buf, &entry->drpdtag,    6,  6, size, op);
332         sja1105_packing(buf, &entry->drpuntag,   5,  5, size, op);
333         sja1105_packing(buf, &entry->retag,      4,  4, size, op);
334         sja1105_packing(buf, &entry->dyn_learn,  3,  3, size, op);
335         sja1105_packing(buf, &entry->egress,     2,  2, size, op);
336         sja1105_packing(buf, &entry->ingress,    1,  1, size, op);
337         return size;
338 }
339
340 size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr,
341                                             enum packing_op op)
342 {
343         const size_t size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY;
344         struct sja1105_mac_config_entry *entry = entry_ptr;
345         int offset, i;
346
347         for (i = 0, offset = 104; i < 8; i++, offset += 19) {
348                 sja1105_packing(buf, &entry->enabled[i],
349                                 offset +  0, offset +  0, size, op);
350                 sja1105_packing(buf, &entry->base[i],
351                                 offset +  9, offset +  1, size, op);
352                 sja1105_packing(buf, &entry->top[i],
353                                 offset + 18, offset + 10, size, op);
354         }
355         sja1105_packing(buf, &entry->ifg,       103, 99, size, op);
356         sja1105_packing(buf, &entry->speed,      98, 97, size, op);
357         sja1105_packing(buf, &entry->tp_delin,   96, 81, size, op);
358         sja1105_packing(buf, &entry->tp_delout,  80, 65, size, op);
359         sja1105_packing(buf, &entry->maxage,     64, 57, size, op);
360         sja1105_packing(buf, &entry->vlanprio,   56, 54, size, op);
361         sja1105_packing(buf, &entry->vlanid,     53, 42, size, op);
362         sja1105_packing(buf, &entry->ing_mirr,   41, 41, size, op);
363         sja1105_packing(buf, &entry->egr_mirr,   40, 40, size, op);
364         sja1105_packing(buf, &entry->drpnona664, 39, 39, size, op);
365         sja1105_packing(buf, &entry->drpdtag,    38, 38, size, op);
366         sja1105_packing(buf, &entry->drpuntag,   35, 35, size, op);
367         sja1105_packing(buf, &entry->retag,      34, 34, size, op);
368         sja1105_packing(buf, &entry->dyn_learn,  33, 33, size, op);
369         sja1105_packing(buf, &entry->egress,     32, 32, size, op);
370         sja1105_packing(buf, &entry->ingress,    31, 31, size, op);
371         return size;
372 }
373
374 static size_t
375 sja1105_schedule_entry_points_params_entry_packing(void *buf, void *entry_ptr,
376                                                    enum packing_op op)
377 {
378         struct sja1105_schedule_entry_points_params_entry *entry = entry_ptr;
379         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY;
380
381         sja1105_packing(buf, &entry->clksrc,    31, 30, size, op);
382         sja1105_packing(buf, &entry->actsubsch, 29, 27, size, op);
383         return size;
384 }
385
386 static size_t
387 sja1105_schedule_entry_points_entry_packing(void *buf, void *entry_ptr,
388                                             enum packing_op op)
389 {
390         struct sja1105_schedule_entry_points_entry *entry = entry_ptr;
391         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY;
392
393         sja1105_packing(buf, &entry->subschindx, 31, 29, size, op);
394         sja1105_packing(buf, &entry->delta,      28, 11, size, op);
395         sja1105_packing(buf, &entry->address,    10, 1,  size, op);
396         return size;
397 }
398
399 static size_t sja1105_schedule_params_entry_packing(void *buf, void *entry_ptr,
400                                                     enum packing_op op)
401 {
402         const size_t size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY;
403         struct sja1105_schedule_params_entry *entry = entry_ptr;
404         int offset, i;
405
406         for (i = 0, offset = 16; i < 8; i++, offset += 10)
407                 sja1105_packing(buf, &entry->subscheind[i],
408                                 offset + 9, offset + 0, size, op);
409         return size;
410 }
411
412 static size_t sja1105_schedule_entry_packing(void *buf, void *entry_ptr,
413                                              enum packing_op op)
414 {
415         const size_t size = SJA1105_SIZE_SCHEDULE_ENTRY;
416         struct sja1105_schedule_entry *entry = entry_ptr;
417
418         sja1105_packing(buf, &entry->winstindex,  63, 54, size, op);
419         sja1105_packing(buf, &entry->winend,      53, 53, size, op);
420         sja1105_packing(buf, &entry->winst,       52, 52, size, op);
421         sja1105_packing(buf, &entry->destports,   51, 47, size, op);
422         sja1105_packing(buf, &entry->setvalid,    46, 46, size, op);
423         sja1105_packing(buf, &entry->txen,        45, 45, size, op);
424         sja1105_packing(buf, &entry->resmedia_en, 44, 44, size, op);
425         sja1105_packing(buf, &entry->resmedia,    43, 36, size, op);
426         sja1105_packing(buf, &entry->vlindex,     35, 26, size, op);
427         sja1105_packing(buf, &entry->delta,       25, 8,  size, op);
428         return size;
429 }
430
431 size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr,
432                                          enum packing_op op)
433 {
434         const size_t size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY;
435         struct sja1105_vlan_lookup_entry *entry = entry_ptr;
436
437         sja1105_packing(buf, &entry->ving_mirr,  63, 59, size, op);
438         sja1105_packing(buf, &entry->vegr_mirr,  58, 54, size, op);
439         sja1105_packing(buf, &entry->vmemb_port, 53, 49, size, op);
440         sja1105_packing(buf, &entry->vlan_bc,    48, 44, size, op);
441         sja1105_packing(buf, &entry->tag_port,   43, 39, size, op);
442         sja1105_packing(buf, &entry->vlanid,     38, 27, size, op);
443         return size;
444 }
445
446 static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr,
447                                                 enum packing_op op)
448 {
449         const size_t size = SJA1105_SIZE_XMII_PARAMS_ENTRY;
450         struct sja1105_xmii_params_entry *entry = entry_ptr;
451         int offset, i;
452
453         for (i = 0, offset = 17; i < 5; i++, offset += 3) {
454                 sja1105_packing(buf, &entry->xmii_mode[i],
455                                 offset + 1, offset + 0, size, op);
456                 sja1105_packing(buf, &entry->phy_mac[i],
457                                 offset + 2, offset + 2, size, op);
458         }
459         return size;
460 }
461
462 size_t sja1105_table_header_packing(void *buf, void *entry_ptr,
463                                     enum packing_op op)
464 {
465         const size_t size = SJA1105_SIZE_TABLE_HEADER;
466         struct sja1105_table_header *entry = entry_ptr;
467
468         sja1105_packing(buf, &entry->block_id, 31, 24, size, op);
469         sja1105_packing(buf, &entry->len,      55, 32, size, op);
470         sja1105_packing(buf, &entry->crc,      95, 64, size, op);
471         return size;
472 }
473
474 /* WARNING: the *hdr pointer is really non-const, because it is
475  * modifying the CRC of the header for a 2-stage packing operation
476  */
477 void
478 sja1105_table_header_pack_with_crc(void *buf, struct sja1105_table_header *hdr)
479 {
480         /* First pack the table as-is, then calculate the CRC, and
481          * finally put the proper CRC into the packed buffer
482          */
483         memset(buf, 0, SJA1105_SIZE_TABLE_HEADER);
484         sja1105_table_header_packing(buf, hdr, PACK);
485         hdr->crc = sja1105_crc32(buf, SJA1105_SIZE_TABLE_HEADER - 4);
486         sja1105_pack(buf + SJA1105_SIZE_TABLE_HEADER - 4, &hdr->crc, 31, 0, 4);
487 }
488
489 static void sja1105_table_write_crc(u8 *table_start, u8 *crc_ptr)
490 {
491         u64 computed_crc;
492         int len_bytes;
493
494         len_bytes = (uintptr_t)(crc_ptr - table_start);
495         computed_crc = sja1105_crc32(table_start, len_bytes);
496         sja1105_pack(crc_ptr, &computed_crc, 31, 0, 4);
497 }
498
499 /* The block IDs that the switches support are unfortunately sparse, so keep a
500  * mapping table to "block indices" and translate back and forth so that we
501  * don't waste useless memory in struct sja1105_static_config.
502  * Also, since the block id comes from essentially untrusted input (unpacking
503  * the static config from userspace) it has to be sanitized (range-checked)
504  * before blindly indexing kernel memory with the blk_idx.
505  */
506 static u64 blk_id_map[BLK_IDX_MAX] = {
507         [BLK_IDX_SCHEDULE] = BLKID_SCHEDULE,
508         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = BLKID_SCHEDULE_ENTRY_POINTS,
509         [BLK_IDX_L2_LOOKUP] = BLKID_L2_LOOKUP,
510         [BLK_IDX_L2_POLICING] = BLKID_L2_POLICING,
511         [BLK_IDX_VLAN_LOOKUP] = BLKID_VLAN_LOOKUP,
512         [BLK_IDX_L2_FORWARDING] = BLKID_L2_FORWARDING,
513         [BLK_IDX_MAC_CONFIG] = BLKID_MAC_CONFIG,
514         [BLK_IDX_SCHEDULE_PARAMS] = BLKID_SCHEDULE_PARAMS,
515         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = BLKID_SCHEDULE_ENTRY_POINTS_PARAMS,
516         [BLK_IDX_L2_LOOKUP_PARAMS] = BLKID_L2_LOOKUP_PARAMS,
517         [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS,
518         [BLK_IDX_AVB_PARAMS] = BLKID_AVB_PARAMS,
519         [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS,
520         [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS,
521 };
522
523 const char *sja1105_static_config_error_msg[] = {
524         [SJA1105_CONFIG_OK] = "",
525         [SJA1105_TTETHERNET_NOT_SUPPORTED] =
526                 "schedule-table present, but TTEthernet is "
527                 "only supported on T and Q/S",
528         [SJA1105_INCORRECT_TTETHERNET_CONFIGURATION] =
529                 "schedule-table present, but one of "
530                 "schedule-entry-points-table, schedule-parameters-table or "
531                 "schedule-entry-points-parameters table is empty",
532         [SJA1105_MISSING_L2_POLICING_TABLE] =
533                 "l2-policing-table needs to have at least one entry",
534         [SJA1105_MISSING_L2_FORWARDING_TABLE] =
535                 "l2-forwarding-table is either missing or incomplete",
536         [SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE] =
537                 "l2-forwarding-parameters-table is missing",
538         [SJA1105_MISSING_GENERAL_PARAMS_TABLE] =
539                 "general-parameters-table is missing",
540         [SJA1105_MISSING_VLAN_TABLE] =
541                 "vlan-lookup-table needs to have at least the default untagged VLAN",
542         [SJA1105_MISSING_XMII_TABLE] =
543                 "xmii-table is missing",
544         [SJA1105_MISSING_MAC_TABLE] =
545                 "mac-configuration-table needs to contain an entry for each port",
546         [SJA1105_OVERCOMMITTED_FRAME_MEMORY] =
547                 "Not allowed to overcommit frame memory. L2 memory partitions "
548                 "and VL memory partitions share the same space. The sum of all "
549                 "16 memory partitions is not allowed to be larger than 929 "
550                 "128-byte blocks (or 910 with retagging). Please adjust "
551                 "l2-forwarding-parameters-table.part_spc and/or "
552                 "vl-forwarding-parameters-table.partspc.",
553 };
554
555 static sja1105_config_valid_t
556 static_config_check_memory_size(const struct sja1105_table *tables)
557 {
558         const struct sja1105_l2_forwarding_params_entry *l2_fwd_params;
559         int i, mem = 0;
560
561         l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries;
562
563         for (i = 0; i < 8; i++)
564                 mem += l2_fwd_params->part_spc[i];
565
566         if (mem > SJA1105_MAX_FRAME_MEMORY)
567                 return SJA1105_OVERCOMMITTED_FRAME_MEMORY;
568
569         return SJA1105_CONFIG_OK;
570 }
571
572 sja1105_config_valid_t
573 sja1105_static_config_check_valid(const struct sja1105_static_config *config)
574 {
575         const struct sja1105_table *tables = config->tables;
576 #define IS_FULL(blk_idx) \
577         (tables[blk_idx].entry_count == tables[blk_idx].ops->max_entry_count)
578
579         if (tables[BLK_IDX_SCHEDULE].entry_count) {
580                 if (config->device_id != SJA1105T_DEVICE_ID &&
581                     config->device_id != SJA1105QS_DEVICE_ID)
582                         return SJA1105_TTETHERNET_NOT_SUPPORTED;
583
584                 if (tables[BLK_IDX_SCHEDULE_ENTRY_POINTS].entry_count == 0)
585                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
586
587                 if (!IS_FULL(BLK_IDX_SCHEDULE_PARAMS))
588                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
589
590                 if (!IS_FULL(BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS))
591                         return SJA1105_INCORRECT_TTETHERNET_CONFIGURATION;
592         }
593
594         if (tables[BLK_IDX_L2_POLICING].entry_count == 0)
595                 return SJA1105_MISSING_L2_POLICING_TABLE;
596
597         if (tables[BLK_IDX_VLAN_LOOKUP].entry_count == 0)
598                 return SJA1105_MISSING_VLAN_TABLE;
599
600         if (!IS_FULL(BLK_IDX_L2_FORWARDING))
601                 return SJA1105_MISSING_L2_FORWARDING_TABLE;
602
603         if (!IS_FULL(BLK_IDX_MAC_CONFIG))
604                 return SJA1105_MISSING_MAC_TABLE;
605
606         if (!IS_FULL(BLK_IDX_L2_FORWARDING_PARAMS))
607                 return SJA1105_MISSING_L2_FORWARDING_PARAMS_TABLE;
608
609         if (!IS_FULL(BLK_IDX_GENERAL_PARAMS))
610                 return SJA1105_MISSING_GENERAL_PARAMS_TABLE;
611
612         if (!IS_FULL(BLK_IDX_XMII_PARAMS))
613                 return SJA1105_MISSING_XMII_TABLE;
614
615         return static_config_check_memory_size(tables);
616 #undef IS_FULL
617 }
618
619 void
620 sja1105_static_config_pack(void *buf, struct sja1105_static_config *config)
621 {
622         struct sja1105_table_header header = {0};
623         enum sja1105_blk_idx i;
624         char *p = buf;
625         int j;
626
627         sja1105_pack(p, &config->device_id, 31, 0, 4);
628         p += SJA1105_SIZE_DEVICE_ID;
629
630         for (i = 0; i < BLK_IDX_MAX; i++) {
631                 const struct sja1105_table *table;
632                 char *table_start;
633
634                 table = &config->tables[i];
635                 if (!table->entry_count)
636                         continue;
637
638                 header.block_id = blk_id_map[i];
639                 header.len = table->entry_count *
640                              table->ops->packed_entry_size / 4;
641                 sja1105_table_header_pack_with_crc(p, &header);
642                 p += SJA1105_SIZE_TABLE_HEADER;
643                 table_start = p;
644                 for (j = 0; j < table->entry_count; j++) {
645                         u8 *entry_ptr = table->entries;
646
647                         entry_ptr += j * table->ops->unpacked_entry_size;
648                         memset(p, 0, table->ops->packed_entry_size);
649                         table->ops->packing(p, entry_ptr, PACK);
650                         p += table->ops->packed_entry_size;
651                 }
652                 sja1105_table_write_crc(table_start, p);
653                 p += 4;
654         }
655         /* Final header:
656          * Block ID does not matter
657          * Length of 0 marks that header is final
658          * CRC will be replaced on-the-fly on "config upload"
659          */
660         header.block_id = 0;
661         header.len = 0;
662         header.crc = 0xDEADBEEF;
663         memset(p, 0, SJA1105_SIZE_TABLE_HEADER);
664         sja1105_table_header_packing(p, &header, PACK);
665 }
666
667 size_t
668 sja1105_static_config_get_length(const struct sja1105_static_config *config)
669 {
670         unsigned int sum;
671         unsigned int header_count;
672         enum sja1105_blk_idx i;
673
674         /* Ending header */
675         header_count = 1;
676         sum = SJA1105_SIZE_DEVICE_ID;
677
678         /* Tables (headers and entries) */
679         for (i = 0; i < BLK_IDX_MAX; i++) {
680                 const struct sja1105_table *table;
681
682                 table = &config->tables[i];
683                 if (table->entry_count)
684                         header_count++;
685
686                 sum += table->ops->packed_entry_size * table->entry_count;
687         }
688         /* Headers have an additional CRC at the end */
689         sum += header_count * (SJA1105_SIZE_TABLE_HEADER + 4);
690         /* Last header does not have an extra CRC because there is no data */
691         sum -= 4;
692
693         return sum;
694 }
695
696 /* Compatibility matrices */
697
698 /* SJA1105E: First generation, no TTEthernet */
699 struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX] = {
700         [BLK_IDX_SCHEDULE] = {0},
701         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
702         [BLK_IDX_L2_LOOKUP] = {
703                 .packing = sja1105et_l2_lookup_entry_packing,
704                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
705                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
706                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
707         },
708         [BLK_IDX_L2_POLICING] = {
709                 .packing = sja1105_l2_policing_entry_packing,
710                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
711                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
712                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
713         },
714         [BLK_IDX_VLAN_LOOKUP] = {
715                 .packing = sja1105_vlan_lookup_entry_packing,
716                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
717                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
718                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
719         },
720         [BLK_IDX_L2_FORWARDING] = {
721                 .packing = sja1105_l2_forwarding_entry_packing,
722                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
723                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
724                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
725         },
726         [BLK_IDX_MAC_CONFIG] = {
727                 .packing = sja1105et_mac_config_entry_packing,
728                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
729                 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
730                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
731         },
732         [BLK_IDX_SCHEDULE_PARAMS] = {0},
733         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
734         [BLK_IDX_L2_LOOKUP_PARAMS] = {
735                 .packing = sja1105et_l2_lookup_params_entry_packing,
736                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
737                 .packed_entry_size = SJA1105ET_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_AVB_PARAMS] = {
747                 .packing = sja1105et_avb_params_entry_packing,
748                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
749                 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
750                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
751         },
752         [BLK_IDX_GENERAL_PARAMS] = {
753                 .packing = sja1105et_general_params_entry_packing,
754                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
755                 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
756                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
757         },
758         [BLK_IDX_XMII_PARAMS] = {
759                 .packing = sja1105_xmii_params_entry_packing,
760                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
761                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
762                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
763         },
764 };
765
766 /* SJA1105T: First generation, TTEthernet */
767 struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX] = {
768         [BLK_IDX_SCHEDULE] = {
769                 .packing = sja1105_schedule_entry_packing,
770                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
771                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
772                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
773         },
774         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
775                 .packing = sja1105_schedule_entry_points_entry_packing,
776                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
777                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
778                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
779         },
780         [BLK_IDX_L2_LOOKUP] = {
781                 .packing = sja1105et_l2_lookup_entry_packing,
782                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
783                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_ENTRY,
784                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
785         },
786         [BLK_IDX_L2_POLICING] = {
787                 .packing = sja1105_l2_policing_entry_packing,
788                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
789                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
790                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
791         },
792         [BLK_IDX_VLAN_LOOKUP] = {
793                 .packing = sja1105_vlan_lookup_entry_packing,
794                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
795                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
796                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
797         },
798         [BLK_IDX_L2_FORWARDING] = {
799                 .packing = sja1105_l2_forwarding_entry_packing,
800                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
801                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
802                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
803         },
804         [BLK_IDX_MAC_CONFIG] = {
805                 .packing = sja1105et_mac_config_entry_packing,
806                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
807                 .packed_entry_size = SJA1105ET_SIZE_MAC_CONFIG_ENTRY,
808                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
809         },
810         [BLK_IDX_SCHEDULE_PARAMS] = {
811                 .packing = sja1105_schedule_params_entry_packing,
812                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
813                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
814                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
815         },
816         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
817                 .packing = sja1105_schedule_entry_points_params_entry_packing,
818                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
819                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
820                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
821         },
822         [BLK_IDX_L2_LOOKUP_PARAMS] = {
823                 .packing = sja1105et_l2_lookup_params_entry_packing,
824                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
825                 .packed_entry_size = SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY,
826                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
827         },
828         [BLK_IDX_L2_FORWARDING_PARAMS] = {
829                 .packing = sja1105_l2_forwarding_params_entry_packing,
830                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
831                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
832                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
833         },
834         [BLK_IDX_AVB_PARAMS] = {
835                 .packing = sja1105et_avb_params_entry_packing,
836                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
837                 .packed_entry_size = SJA1105ET_SIZE_AVB_PARAMS_ENTRY,
838                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
839         },
840         [BLK_IDX_GENERAL_PARAMS] = {
841                 .packing = sja1105et_general_params_entry_packing,
842                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
843                 .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY,
844                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
845         },
846         [BLK_IDX_XMII_PARAMS] = {
847                 .packing = sja1105_xmii_params_entry_packing,
848                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
849                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
850                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
851         },
852 };
853
854 /* SJA1105P: Second generation, no TTEthernet, no SGMII */
855 struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX] = {
856         [BLK_IDX_SCHEDULE] = {0},
857         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
858         [BLK_IDX_L2_LOOKUP] = {
859                 .packing = sja1105pqrs_l2_lookup_entry_packing,
860                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
861                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
862                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
863         },
864         [BLK_IDX_L2_POLICING] = {
865                 .packing = sja1105_l2_policing_entry_packing,
866                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
867                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
868                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
869         },
870         [BLK_IDX_VLAN_LOOKUP] = {
871                 .packing = sja1105_vlan_lookup_entry_packing,
872                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
873                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
874                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
875         },
876         [BLK_IDX_L2_FORWARDING] = {
877                 .packing = sja1105_l2_forwarding_entry_packing,
878                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
879                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
880                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
881         },
882         [BLK_IDX_MAC_CONFIG] = {
883                 .packing = sja1105pqrs_mac_config_entry_packing,
884                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
885                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
886                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
887         },
888         [BLK_IDX_SCHEDULE_PARAMS] = {0},
889         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
890         [BLK_IDX_L2_LOOKUP_PARAMS] = {
891                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
892                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
893                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
894                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
895         },
896         [BLK_IDX_L2_FORWARDING_PARAMS] = {
897                 .packing = sja1105_l2_forwarding_params_entry_packing,
898                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
899                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
900                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
901         },
902         [BLK_IDX_AVB_PARAMS] = {
903                 .packing = sja1105pqrs_avb_params_entry_packing,
904                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
905                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
906                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
907         },
908         [BLK_IDX_GENERAL_PARAMS] = {
909                 .packing = sja1105pqrs_general_params_entry_packing,
910                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
911                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
912                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
913         },
914         [BLK_IDX_XMII_PARAMS] = {
915                 .packing = sja1105_xmii_params_entry_packing,
916                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
917                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
918                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
919         },
920 };
921
922 /* SJA1105Q: Second generation, TTEthernet, no SGMII */
923 struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX] = {
924         [BLK_IDX_SCHEDULE] = {
925                 .packing = sja1105_schedule_entry_packing,
926                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
927                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
928                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
929         },
930         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
931                 .packing = sja1105_schedule_entry_points_entry_packing,
932                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
933                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
934                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
935         },
936         [BLK_IDX_L2_LOOKUP] = {
937                 .packing = sja1105pqrs_l2_lookup_entry_packing,
938                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
939                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
940                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
941         },
942         [BLK_IDX_L2_POLICING] = {
943                 .packing = sja1105_l2_policing_entry_packing,
944                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
945                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
946                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
947         },
948         [BLK_IDX_VLAN_LOOKUP] = {
949                 .packing = sja1105_vlan_lookup_entry_packing,
950                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
951                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
952                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
953         },
954         [BLK_IDX_L2_FORWARDING] = {
955                 .packing = sja1105_l2_forwarding_entry_packing,
956                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
957                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
958                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
959         },
960         [BLK_IDX_MAC_CONFIG] = {
961                 .packing = sja1105pqrs_mac_config_entry_packing,
962                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
963                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
964                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
965         },
966         [BLK_IDX_SCHEDULE_PARAMS] = {
967                 .packing = sja1105_schedule_params_entry_packing,
968                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
969                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
970                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
971         },
972         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
973                 .packing = sja1105_schedule_entry_points_params_entry_packing,
974                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
975                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
976                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
977         },
978         [BLK_IDX_L2_LOOKUP_PARAMS] = {
979                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
980                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
981                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
982                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
983         },
984         [BLK_IDX_L2_FORWARDING_PARAMS] = {
985                 .packing = sja1105_l2_forwarding_params_entry_packing,
986                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
987                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
988                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
989         },
990         [BLK_IDX_AVB_PARAMS] = {
991                 .packing = sja1105pqrs_avb_params_entry_packing,
992                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
993                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
994                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
995         },
996         [BLK_IDX_GENERAL_PARAMS] = {
997                 .packing = sja1105pqrs_general_params_entry_packing,
998                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
999                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1000                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1001         },
1002         [BLK_IDX_XMII_PARAMS] = {
1003                 .packing = sja1105_xmii_params_entry_packing,
1004                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1005                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1006                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1007         },
1008 };
1009
1010 /* SJA1105R: Second generation, no TTEthernet, SGMII */
1011 struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX] = {
1012         [BLK_IDX_SCHEDULE] = {0},
1013         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {0},
1014         [BLK_IDX_L2_LOOKUP] = {
1015                 .packing = sja1105pqrs_l2_lookup_entry_packing,
1016                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1017                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1018                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1019         },
1020         [BLK_IDX_L2_POLICING] = {
1021                 .packing = sja1105_l2_policing_entry_packing,
1022                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1023                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1024                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1025         },
1026         [BLK_IDX_VLAN_LOOKUP] = {
1027                 .packing = sja1105_vlan_lookup_entry_packing,
1028                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1029                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1030                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1031         },
1032         [BLK_IDX_L2_FORWARDING] = {
1033                 .packing = sja1105_l2_forwarding_entry_packing,
1034                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1035                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1036                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1037         },
1038         [BLK_IDX_MAC_CONFIG] = {
1039                 .packing = sja1105pqrs_mac_config_entry_packing,
1040                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1041                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1042                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1043         },
1044         [BLK_IDX_SCHEDULE_PARAMS] = {0},
1045         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {0},
1046         [BLK_IDX_L2_LOOKUP_PARAMS] = {
1047                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1048                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1049                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1050                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1051         },
1052         [BLK_IDX_L2_FORWARDING_PARAMS] = {
1053                 .packing = sja1105_l2_forwarding_params_entry_packing,
1054                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1055                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1056                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1057         },
1058         [BLK_IDX_AVB_PARAMS] = {
1059                 .packing = sja1105pqrs_avb_params_entry_packing,
1060                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1061                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1062                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1063         },
1064         [BLK_IDX_GENERAL_PARAMS] = {
1065                 .packing = sja1105pqrs_general_params_entry_packing,
1066                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1067                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1068                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1069         },
1070         [BLK_IDX_XMII_PARAMS] = {
1071                 .packing = sja1105_xmii_params_entry_packing,
1072                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1073                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1074                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1075         },
1076 };
1077
1078 /* SJA1105S: Second generation, TTEthernet, SGMII */
1079 struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX] = {
1080         [BLK_IDX_SCHEDULE] = {
1081                 .packing = sja1105_schedule_entry_packing,
1082                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry),
1083                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY,
1084                 .max_entry_count = SJA1105_MAX_SCHEDULE_COUNT,
1085         },
1086         [BLK_IDX_SCHEDULE_ENTRY_POINTS] = {
1087                 .packing = sja1105_schedule_entry_points_entry_packing,
1088                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_entry),
1089                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_ENTRY,
1090                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_COUNT,
1091         },
1092         [BLK_IDX_L2_LOOKUP] = {
1093                 .packing = sja1105pqrs_l2_lookup_entry_packing,
1094                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_entry),
1095                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY,
1096                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
1097         },
1098         [BLK_IDX_L2_POLICING] = {
1099                 .packing = sja1105_l2_policing_entry_packing,
1100                 .unpacked_entry_size = sizeof(struct sja1105_l2_policing_entry),
1101                 .packed_entry_size = SJA1105_SIZE_L2_POLICING_ENTRY,
1102                 .max_entry_count = SJA1105_MAX_L2_POLICING_COUNT,
1103         },
1104         [BLK_IDX_VLAN_LOOKUP] = {
1105                 .packing = sja1105_vlan_lookup_entry_packing,
1106                 .unpacked_entry_size = sizeof(struct sja1105_vlan_lookup_entry),
1107                 .packed_entry_size = SJA1105_SIZE_VLAN_LOOKUP_ENTRY,
1108                 .max_entry_count = SJA1105_MAX_VLAN_LOOKUP_COUNT,
1109         },
1110         [BLK_IDX_L2_FORWARDING] = {
1111                 .packing = sja1105_l2_forwarding_entry_packing,
1112                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_entry),
1113                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_ENTRY,
1114                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_COUNT,
1115         },
1116         [BLK_IDX_MAC_CONFIG] = {
1117                 .packing = sja1105pqrs_mac_config_entry_packing,
1118                 .unpacked_entry_size = sizeof(struct sja1105_mac_config_entry),
1119                 .packed_entry_size = SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY,
1120                 .max_entry_count = SJA1105_MAX_MAC_CONFIG_COUNT,
1121         },
1122         [BLK_IDX_SCHEDULE_PARAMS] = {
1123                 .packing = sja1105_schedule_params_entry_packing,
1124                 .unpacked_entry_size = sizeof(struct sja1105_schedule_params_entry),
1125                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY,
1126                 .max_entry_count = SJA1105_MAX_SCHEDULE_PARAMS_COUNT,
1127         },
1128         [BLK_IDX_SCHEDULE_ENTRY_POINTS_PARAMS] = {
1129                 .packing = sja1105_schedule_entry_points_params_entry_packing,
1130                 .unpacked_entry_size = sizeof(struct sja1105_schedule_entry_points_params_entry),
1131                 .packed_entry_size = SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY,
1132                 .max_entry_count = SJA1105_MAX_SCHEDULE_ENTRY_POINTS_PARAMS_COUNT,
1133         },
1134         [BLK_IDX_L2_LOOKUP_PARAMS] = {
1135                 .packing = sja1105pqrs_l2_lookup_params_entry_packing,
1136                 .unpacked_entry_size = sizeof(struct sja1105_l2_lookup_params_entry),
1137                 .packed_entry_size = SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY,
1138                 .max_entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
1139         },
1140         [BLK_IDX_L2_FORWARDING_PARAMS] = {
1141                 .packing = sja1105_l2_forwarding_params_entry_packing,
1142                 .unpacked_entry_size = sizeof(struct sja1105_l2_forwarding_params_entry),
1143                 .packed_entry_size = SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY,
1144                 .max_entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
1145         },
1146         [BLK_IDX_AVB_PARAMS] = {
1147                 .packing = sja1105pqrs_avb_params_entry_packing,
1148                 .unpacked_entry_size = sizeof(struct sja1105_avb_params_entry),
1149                 .packed_entry_size = SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY,
1150                 .max_entry_count = SJA1105_MAX_AVB_PARAMS_COUNT,
1151         },
1152         [BLK_IDX_GENERAL_PARAMS] = {
1153                 .packing = sja1105pqrs_general_params_entry_packing,
1154                 .unpacked_entry_size = sizeof(struct sja1105_general_params_entry),
1155                 .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY,
1156                 .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT,
1157         },
1158         [BLK_IDX_XMII_PARAMS] = {
1159                 .packing = sja1105_xmii_params_entry_packing,
1160                 .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry),
1161                 .packed_entry_size = SJA1105_SIZE_XMII_PARAMS_ENTRY,
1162                 .max_entry_count = SJA1105_MAX_XMII_PARAMS_COUNT,
1163         },
1164 };
1165
1166 int sja1105_static_config_init(struct sja1105_static_config *config,
1167                                const struct sja1105_table_ops *static_ops,
1168                                u64 device_id)
1169 {
1170         enum sja1105_blk_idx i;
1171
1172         *config = (struct sja1105_static_config) {0};
1173
1174         /* Transfer static_ops array from priv into per-table ops
1175          * for handier access
1176          */
1177         for (i = 0; i < BLK_IDX_MAX; i++)
1178                 config->tables[i].ops = &static_ops[i];
1179
1180         config->device_id = device_id;
1181         return 0;
1182 }
1183
1184 void sja1105_static_config_free(struct sja1105_static_config *config)
1185 {
1186         enum sja1105_blk_idx i;
1187
1188         for (i = 0; i < BLK_IDX_MAX; i++) {
1189                 if (config->tables[i].entry_count) {
1190                         kfree(config->tables[i].entries);
1191                         config->tables[i].entry_count = 0;
1192                 }
1193         }
1194 }
1195
1196 int sja1105_table_delete_entry(struct sja1105_table *table, int i)
1197 {
1198         size_t entry_size = table->ops->unpacked_entry_size;
1199         u8 *entries = table->entries;
1200
1201         if (i > table->entry_count)
1202                 return -ERANGE;
1203
1204         memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
1205                 (table->entry_count - i) * entry_size);
1206
1207         table->entry_count--;
1208
1209         return 0;
1210 }
1211
1212 /* No pointers to table->entries should be kept when this is called. */
1213 int sja1105_table_resize(struct sja1105_table *table, size_t new_count)
1214 {
1215         size_t entry_size = table->ops->unpacked_entry_size;
1216         void *new_entries, *old_entries = table->entries;
1217
1218         if (new_count > table->ops->max_entry_count)
1219                 return -ERANGE;
1220
1221         new_entries = kcalloc(new_count, entry_size, GFP_KERNEL);
1222         if (!new_entries)
1223                 return -ENOMEM;
1224
1225         memcpy(new_entries, old_entries, min(new_count, table->entry_count) *
1226                 entry_size);
1227
1228         table->entries = new_entries;
1229         table->entry_count = new_count;
1230         kfree(old_entries);
1231         return 0;
1232 }