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