xref: /linux-6.15/include/linux/packing.h (revision 41d7ea30)
1554aae35SVladimir Oltean /* SPDX-License-Identifier: BSD-3-Clause
23c9cfb52SVladimir Oltean  * Copyright 2016-2018 NXP
3554aae35SVladimir Oltean  * Copyright (c) 2018-2019, Vladimir Oltean <[email protected]>
4554aae35SVladimir Oltean  */
5554aae35SVladimir Oltean #ifndef _LINUX_PACKING_H
6554aae35SVladimir Oltean #define _LINUX_PACKING_H
7554aae35SVladimir Oltean 
8554aae35SVladimir Oltean #include <linux/types.h>
9554aae35SVladimir Oltean #include <linux/bitops.h>
10554aae35SVladimir Oltean 
11*41d7ea30SVladimir Oltean #define GEN_PACKED_FIELD_STRUCT(__type) \
12*41d7ea30SVladimir Oltean 	struct packed_field_ ## __type { \
13*41d7ea30SVladimir Oltean 		__type startbit; \
14*41d7ea30SVladimir Oltean 		__type endbit; \
15*41d7ea30SVladimir Oltean 		__type offset; \
16*41d7ea30SVladimir Oltean 		__type size; \
17*41d7ea30SVladimir Oltean 	}
18*41d7ea30SVladimir Oltean 
19*41d7ea30SVladimir Oltean /* struct packed_field_u8. Use with bit offsets < 256, buffers < 32B and
20*41d7ea30SVladimir Oltean  * unpacked structures < 256B.
21*41d7ea30SVladimir Oltean  */
22*41d7ea30SVladimir Oltean GEN_PACKED_FIELD_STRUCT(u8);
23*41d7ea30SVladimir Oltean 
24*41d7ea30SVladimir Oltean /* struct packed_field_u16. Use with bit offsets < 65536, buffers < 8KB and
25*41d7ea30SVladimir Oltean  * unpacked structures < 64KB.
26*41d7ea30SVladimir Oltean  */
27*41d7ea30SVladimir Oltean GEN_PACKED_FIELD_STRUCT(u16);
28*41d7ea30SVladimir Oltean 
29*41d7ea30SVladimir Oltean #define PACKED_FIELD(start, end, struct_name, struct_field) \
30*41d7ea30SVladimir Oltean { \
31*41d7ea30SVladimir Oltean 	(start), \
32*41d7ea30SVladimir Oltean 	(end), \
33*41d7ea30SVladimir Oltean 	offsetof(struct_name, struct_field), \
34*41d7ea30SVladimir Oltean 	sizeof_field(struct_name, struct_field), \
35*41d7ea30SVladimir Oltean }
36*41d7ea30SVladimir Oltean 
37*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELD_OVERLAP(fields, index1, index2) ({ \
38*41d7ea30SVladimir Oltean 	typeof(&(fields)[0]) __f = (fields); \
39*41d7ea30SVladimir Oltean 	typeof(__f[0]) _f1 = __f[index1]; typeof(__f[0]) _f2 = __f[index2]; \
40*41d7ea30SVladimir Oltean 	const bool _ascending = __f[0].startbit < __f[1].startbit; \
41*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(_ascending && _f1.startbit >= _f2.startbit, \
42*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index2) \
43*41d7ea30SVladimir Oltean 			 " breaks ascending order"); \
44*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(!_ascending && _f1.startbit <= _f2.startbit, \
45*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index2) \
46*41d7ea30SVladimir Oltean 			 " breaks descending order"); \
47*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(max(_f1.endbit, _f2.endbit) <= \
48*41d7ea30SVladimir Oltean 			 min(_f1.startbit, _f2.startbit), \
49*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index2) \
50*41d7ea30SVladimir Oltean 			 " overlaps with previous field"); \
51*41d7ea30SVladimir Oltean })
52*41d7ea30SVladimir Oltean 
53*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELD(fields, index) ({ \
54*41d7ea30SVladimir Oltean 	typeof(&(fields)[0]) _f = (fields); \
55*41d7ea30SVladimir Oltean 	typeof(_f[0]) __f = _f[index]; \
56*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(__f.startbit < __f.endbit, \
57*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index) \
58*41d7ea30SVladimir Oltean 			 " start bit must not be smaller than end bit"); \
59*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(__f.size != 1 && __f.size != 2 && \
60*41d7ea30SVladimir Oltean 			 __f.size != 4 && __f.size != 8, \
61*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index) \
62*41d7ea30SVladimir Oltean 			" has unsupported unpacked storage size"); \
63*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(__f.startbit - __f.endbit >= BITS_PER_BYTE * __f.size, \
64*41d7ea30SVladimir Oltean 			 __stringify(fields) " field " __stringify(index) \
65*41d7ea30SVladimir Oltean 			 " exceeds unpacked storage size"); \
66*41d7ea30SVladimir Oltean 	__builtin_choose_expr(index != 0, \
67*41d7ea30SVladimir Oltean 			      CHECK_PACKED_FIELD_OVERLAP(fields, index - 1, index), \
68*41d7ea30SVladimir Oltean 			      1); \
69*41d7ea30SVladimir Oltean })
70*41d7ea30SVladimir Oltean 
71*41d7ea30SVladimir Oltean /* Note that the packed fields may be either in ascending or descending order.
72*41d7ea30SVladimir Oltean  * Thus, we must check that both the first and last field wit within the
73*41d7ea30SVladimir Oltean  * packed buffer size.
74*41d7ea30SVladimir Oltean  */
75*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_SIZE(fields, pbuflen) ({ \
76*41d7ea30SVladimir Oltean 	typeof(&(fields)[0]) _f = (fields); \
77*41d7ea30SVladimir Oltean 	typeof(pbuflen) _len = (pbuflen); \
78*41d7ea30SVladimir Oltean 	const size_t num_fields = ARRAY_SIZE(fields); \
79*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(!__builtin_constant_p(_len), \
80*41d7ea30SVladimir Oltean 			 __stringify(fields) " pbuflen " __stringify(pbuflen) \
81*41d7ea30SVladimir Oltean 			 " must be a compile time constant"); \
82*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(_f[0].startbit >= BITS_PER_BYTE * _len, \
83*41d7ea30SVladimir Oltean 			 __stringify(fields) " first field exceeds packed buffer size"); \
84*41d7ea30SVladimir Oltean 	BUILD_BUG_ON_MSG(_f[num_fields - 1].startbit >= BITS_PER_BYTE * _len, \
85*41d7ea30SVladimir Oltean 			 __stringify(fields) " last field exceeds packed buffer size"); \
86*41d7ea30SVladimir Oltean })
87*41d7ea30SVladimir Oltean 
88554aae35SVladimir Oltean #define QUIRK_MSB_ON_THE_RIGHT	BIT(0)
89554aae35SVladimir Oltean #define QUIRK_LITTLE_ENDIAN	BIT(1)
90554aae35SVladimir Oltean #define QUIRK_LSW32_IS_FIRST	BIT(2)
91554aae35SVladimir Oltean 
92554aae35SVladimir Oltean enum packing_op {
93554aae35SVladimir Oltean 	PACK,
94554aae35SVladimir Oltean 	UNPACK,
95554aae35SVladimir Oltean };
96554aae35SVladimir Oltean 
97554aae35SVladimir Oltean int packing(void *pbuf, u64 *uval, int startbit, int endbit, size_t pbuflen,
98554aae35SVladimir Oltean 	    enum packing_op op, u8 quirks);
99554aae35SVladimir Oltean 
10028aec9caSVladimir Oltean int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
10128aec9caSVladimir Oltean 	 u8 quirks);
1027263f64eSVladimir Oltean 
1037263f64eSVladimir Oltean int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
1047263f64eSVladimir Oltean 	   size_t pbuflen, u8 quirks);
1057263f64eSVladimir Oltean 
106*41d7ea30SVladimir Oltean void pack_fields_u8(void *pbuf, size_t pbuflen, const void *ustruct,
107*41d7ea30SVladimir Oltean 		    const struct packed_field_u8 *fields, size_t num_fields,
108*41d7ea30SVladimir Oltean 		    u8 quirks);
109*41d7ea30SVladimir Oltean 
110*41d7ea30SVladimir Oltean void pack_fields_u16(void *pbuf, size_t pbuflen, const void *ustruct,
111*41d7ea30SVladimir Oltean 		     const struct packed_field_u16 *fields, size_t num_fields,
112*41d7ea30SVladimir Oltean 		     u8 quirks);
113*41d7ea30SVladimir Oltean 
114*41d7ea30SVladimir Oltean void unpack_fields_u8(const void *pbuf, size_t pbuflen, void *ustruct,
115*41d7ea30SVladimir Oltean 		      const struct packed_field_u8 *fields, size_t num_fields,
116*41d7ea30SVladimir Oltean 		      u8 quirks);
117*41d7ea30SVladimir Oltean 
118*41d7ea30SVladimir Oltean void unpack_fields_u16(const void *pbuf, size_t pbuflen, void *ustruct,
119*41d7ea30SVladimir Oltean 		       const struct packed_field_u16 *fields, size_t num_fields,
120*41d7ea30SVladimir Oltean 		       u8 quirks);
121*41d7ea30SVladimir Oltean 
122*41d7ea30SVladimir Oltean /* Do not hand-edit the following packed field check macros!
123*41d7ea30SVladimir Oltean  *
124*41d7ea30SVladimir Oltean  * They are generated using scripts/gen_packed_field_checks.c, which may be
125*41d7ea30SVladimir Oltean  * built via "make scripts_gen_packed_field_checks". If larger macro sizes are
126*41d7ea30SVladimir Oltean  * needed in the future, please use this program to re-generate the macros and
127*41d7ea30SVladimir Oltean  * insert them here.
128*41d7ea30SVladimir Oltean  */
129*41d7ea30SVladimir Oltean 
130*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_1(fields) \
131*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 0)
132*41d7ea30SVladimir Oltean 
133*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_2(fields) do { \
134*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_1(fields); \
135*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 1); \
136*41d7ea30SVladimir Oltean } while (0)
137*41d7ea30SVladimir Oltean 
138*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_3(fields) do { \
139*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_2(fields); \
140*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 2); \
141*41d7ea30SVladimir Oltean } while (0)
142*41d7ea30SVladimir Oltean 
143*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_4(fields) do { \
144*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_3(fields); \
145*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 3); \
146*41d7ea30SVladimir Oltean } while (0)
147*41d7ea30SVladimir Oltean 
148*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_5(fields) do { \
149*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_4(fields); \
150*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 4); \
151*41d7ea30SVladimir Oltean } while (0)
152*41d7ea30SVladimir Oltean 
153*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_6(fields) do { \
154*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_5(fields); \
155*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 5); \
156*41d7ea30SVladimir Oltean } while (0)
157*41d7ea30SVladimir Oltean 
158*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_7(fields) do { \
159*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_6(fields); \
160*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 6); \
161*41d7ea30SVladimir Oltean } while (0)
162*41d7ea30SVladimir Oltean 
163*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_8(fields) do { \
164*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_7(fields); \
165*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 7); \
166*41d7ea30SVladimir Oltean } while (0)
167*41d7ea30SVladimir Oltean 
168*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_9(fields) do { \
169*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_8(fields); \
170*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 8); \
171*41d7ea30SVladimir Oltean } while (0)
172*41d7ea30SVladimir Oltean 
173*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_10(fields) do { \
174*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_9(fields); \
175*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 9); \
176*41d7ea30SVladimir Oltean } while (0)
177*41d7ea30SVladimir Oltean 
178*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_11(fields) do { \
179*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_10(fields); \
180*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 10); \
181*41d7ea30SVladimir Oltean } while (0)
182*41d7ea30SVladimir Oltean 
183*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_12(fields) do { \
184*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_11(fields); \
185*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 11); \
186*41d7ea30SVladimir Oltean } while (0)
187*41d7ea30SVladimir Oltean 
188*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_13(fields) do { \
189*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_12(fields); \
190*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 12); \
191*41d7ea30SVladimir Oltean } while (0)
192*41d7ea30SVladimir Oltean 
193*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_14(fields) do { \
194*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_13(fields); \
195*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 13); \
196*41d7ea30SVladimir Oltean } while (0)
197*41d7ea30SVladimir Oltean 
198*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_15(fields) do { \
199*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_14(fields); \
200*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 14); \
201*41d7ea30SVladimir Oltean } while (0)
202*41d7ea30SVladimir Oltean 
203*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_16(fields) do { \
204*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_15(fields); \
205*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 15); \
206*41d7ea30SVladimir Oltean } while (0)
207*41d7ea30SVladimir Oltean 
208*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_17(fields) do { \
209*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_16(fields); \
210*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 16); \
211*41d7ea30SVladimir Oltean } while (0)
212*41d7ea30SVladimir Oltean 
213*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_18(fields) do { \
214*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_17(fields); \
215*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 17); \
216*41d7ea30SVladimir Oltean } while (0)
217*41d7ea30SVladimir Oltean 
218*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_19(fields) do { \
219*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_18(fields); \
220*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 18); \
221*41d7ea30SVladimir Oltean } while (0)
222*41d7ea30SVladimir Oltean 
223*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_20(fields) do { \
224*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_19(fields); \
225*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 19); \
226*41d7ea30SVladimir Oltean } while (0)
227*41d7ea30SVladimir Oltean 
228*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_21(fields) do { \
229*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_20(fields); \
230*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 20); \
231*41d7ea30SVladimir Oltean } while (0)
232*41d7ea30SVladimir Oltean 
233*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_22(fields) do { \
234*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_21(fields); \
235*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 21); \
236*41d7ea30SVladimir Oltean } while (0)
237*41d7ea30SVladimir Oltean 
238*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_23(fields) do { \
239*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_22(fields); \
240*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 22); \
241*41d7ea30SVladimir Oltean } while (0)
242*41d7ea30SVladimir Oltean 
243*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_24(fields) do { \
244*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_23(fields); \
245*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 23); \
246*41d7ea30SVladimir Oltean } while (0)
247*41d7ea30SVladimir Oltean 
248*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_25(fields) do { \
249*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_24(fields); \
250*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 24); \
251*41d7ea30SVladimir Oltean } while (0)
252*41d7ea30SVladimir Oltean 
253*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_26(fields) do { \
254*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_25(fields); \
255*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 25); \
256*41d7ea30SVladimir Oltean } while (0)
257*41d7ea30SVladimir Oltean 
258*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_27(fields) do { \
259*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_26(fields); \
260*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 26); \
261*41d7ea30SVladimir Oltean } while (0)
262*41d7ea30SVladimir Oltean 
263*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_28(fields) do { \
264*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_27(fields); \
265*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 27); \
266*41d7ea30SVladimir Oltean } while (0)
267*41d7ea30SVladimir Oltean 
268*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_29(fields) do { \
269*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_28(fields); \
270*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 28); \
271*41d7ea30SVladimir Oltean } while (0)
272*41d7ea30SVladimir Oltean 
273*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_30(fields) do { \
274*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_29(fields); \
275*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 29); \
276*41d7ea30SVladimir Oltean } while (0)
277*41d7ea30SVladimir Oltean 
278*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_31(fields) do { \
279*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_30(fields); \
280*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 30); \
281*41d7ea30SVladimir Oltean } while (0)
282*41d7ea30SVladimir Oltean 
283*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_32(fields) do { \
284*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_31(fields); \
285*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 31); \
286*41d7ea30SVladimir Oltean } while (0)
287*41d7ea30SVladimir Oltean 
288*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_33(fields) do { \
289*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_32(fields); \
290*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 32); \
291*41d7ea30SVladimir Oltean } while (0)
292*41d7ea30SVladimir Oltean 
293*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_34(fields) do { \
294*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_33(fields); \
295*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 33); \
296*41d7ea30SVladimir Oltean } while (0)
297*41d7ea30SVladimir Oltean 
298*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_35(fields) do { \
299*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_34(fields); \
300*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 34); \
301*41d7ea30SVladimir Oltean } while (0)
302*41d7ea30SVladimir Oltean 
303*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_36(fields) do { \
304*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_35(fields); \
305*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 35); \
306*41d7ea30SVladimir Oltean } while (0)
307*41d7ea30SVladimir Oltean 
308*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_37(fields) do { \
309*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_36(fields); \
310*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 36); \
311*41d7ea30SVladimir Oltean } while (0)
312*41d7ea30SVladimir Oltean 
313*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_38(fields) do { \
314*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_37(fields); \
315*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 37); \
316*41d7ea30SVladimir Oltean } while (0)
317*41d7ea30SVladimir Oltean 
318*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_39(fields) do { \
319*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_38(fields); \
320*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 38); \
321*41d7ea30SVladimir Oltean } while (0)
322*41d7ea30SVladimir Oltean 
323*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_40(fields) do { \
324*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_39(fields); \
325*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 39); \
326*41d7ea30SVladimir Oltean } while (0)
327*41d7ea30SVladimir Oltean 
328*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_41(fields) do { \
329*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_40(fields); \
330*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 40); \
331*41d7ea30SVladimir Oltean } while (0)
332*41d7ea30SVladimir Oltean 
333*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_42(fields) do { \
334*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_41(fields); \
335*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 41); \
336*41d7ea30SVladimir Oltean } while (0)
337*41d7ea30SVladimir Oltean 
338*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_43(fields) do { \
339*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_42(fields); \
340*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 42); \
341*41d7ea30SVladimir Oltean } while (0)
342*41d7ea30SVladimir Oltean 
343*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_44(fields) do { \
344*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_43(fields); \
345*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 43); \
346*41d7ea30SVladimir Oltean } while (0)
347*41d7ea30SVladimir Oltean 
348*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_45(fields) do { \
349*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_44(fields); \
350*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 44); \
351*41d7ea30SVladimir Oltean } while (0)
352*41d7ea30SVladimir Oltean 
353*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_46(fields) do { \
354*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_45(fields); \
355*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 45); \
356*41d7ea30SVladimir Oltean } while (0)
357*41d7ea30SVladimir Oltean 
358*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_47(fields) do { \
359*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_46(fields); \
360*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 46); \
361*41d7ea30SVladimir Oltean } while (0)
362*41d7ea30SVladimir Oltean 
363*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_48(fields) do { \
364*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_47(fields); \
365*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 47); \
366*41d7ea30SVladimir Oltean } while (0)
367*41d7ea30SVladimir Oltean 
368*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_49(fields) do { \
369*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_48(fields); \
370*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 48); \
371*41d7ea30SVladimir Oltean } while (0)
372*41d7ea30SVladimir Oltean 
373*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS_50(fields) do { \
374*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELDS_49(fields); \
375*41d7ea30SVladimir Oltean 	CHECK_PACKED_FIELD(fields, 49); \
376*41d7ea30SVladimir Oltean } while (0)
377*41d7ea30SVladimir Oltean 
378*41d7ea30SVladimir Oltean #define CHECK_PACKED_FIELDS(fields) \
379*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 1, ({ CHECK_PACKED_FIELDS_1(fields); }), \
380*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 2, ({ CHECK_PACKED_FIELDS_2(fields); }), \
381*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 3, ({ CHECK_PACKED_FIELDS_3(fields); }), \
382*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 4, ({ CHECK_PACKED_FIELDS_4(fields); }), \
383*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 5, ({ CHECK_PACKED_FIELDS_5(fields); }), \
384*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 6, ({ CHECK_PACKED_FIELDS_6(fields); }), \
385*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 7, ({ CHECK_PACKED_FIELDS_7(fields); }), \
386*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 8, ({ CHECK_PACKED_FIELDS_8(fields); }), \
387*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 9, ({ CHECK_PACKED_FIELDS_9(fields); }), \
388*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 10, ({ CHECK_PACKED_FIELDS_10(fields); }), \
389*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 11, ({ CHECK_PACKED_FIELDS_11(fields); }), \
390*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 12, ({ CHECK_PACKED_FIELDS_12(fields); }), \
391*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 13, ({ CHECK_PACKED_FIELDS_13(fields); }), \
392*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 14, ({ CHECK_PACKED_FIELDS_14(fields); }), \
393*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 15, ({ CHECK_PACKED_FIELDS_15(fields); }), \
394*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 16, ({ CHECK_PACKED_FIELDS_16(fields); }), \
395*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 17, ({ CHECK_PACKED_FIELDS_17(fields); }), \
396*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 18, ({ CHECK_PACKED_FIELDS_18(fields); }), \
397*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 19, ({ CHECK_PACKED_FIELDS_19(fields); }), \
398*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 20, ({ CHECK_PACKED_FIELDS_20(fields); }), \
399*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 21, ({ CHECK_PACKED_FIELDS_21(fields); }), \
400*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 22, ({ CHECK_PACKED_FIELDS_22(fields); }), \
401*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 23, ({ CHECK_PACKED_FIELDS_23(fields); }), \
402*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 24, ({ CHECK_PACKED_FIELDS_24(fields); }), \
403*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 25, ({ CHECK_PACKED_FIELDS_25(fields); }), \
404*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 26, ({ CHECK_PACKED_FIELDS_26(fields); }), \
405*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 27, ({ CHECK_PACKED_FIELDS_27(fields); }), \
406*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 28, ({ CHECK_PACKED_FIELDS_28(fields); }), \
407*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 29, ({ CHECK_PACKED_FIELDS_29(fields); }), \
408*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 30, ({ CHECK_PACKED_FIELDS_30(fields); }), \
409*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 31, ({ CHECK_PACKED_FIELDS_31(fields); }), \
410*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 32, ({ CHECK_PACKED_FIELDS_32(fields); }), \
411*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 33, ({ CHECK_PACKED_FIELDS_33(fields); }), \
412*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 34, ({ CHECK_PACKED_FIELDS_34(fields); }), \
413*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 35, ({ CHECK_PACKED_FIELDS_35(fields); }), \
414*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 36, ({ CHECK_PACKED_FIELDS_36(fields); }), \
415*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 37, ({ CHECK_PACKED_FIELDS_37(fields); }), \
416*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 38, ({ CHECK_PACKED_FIELDS_38(fields); }), \
417*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 39, ({ CHECK_PACKED_FIELDS_39(fields); }), \
418*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 40, ({ CHECK_PACKED_FIELDS_40(fields); }), \
419*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 41, ({ CHECK_PACKED_FIELDS_41(fields); }), \
420*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 42, ({ CHECK_PACKED_FIELDS_42(fields); }), \
421*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 43, ({ CHECK_PACKED_FIELDS_43(fields); }), \
422*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 44, ({ CHECK_PACKED_FIELDS_44(fields); }), \
423*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 45, ({ CHECK_PACKED_FIELDS_45(fields); }), \
424*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 46, ({ CHECK_PACKED_FIELDS_46(fields); }), \
425*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 47, ({ CHECK_PACKED_FIELDS_47(fields); }), \
426*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 48, ({ CHECK_PACKED_FIELDS_48(fields); }), \
427*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 49, ({ CHECK_PACKED_FIELDS_49(fields); }), \
428*41d7ea30SVladimir Oltean 	__builtin_choose_expr(ARRAY_SIZE(fields) == 50, ({ CHECK_PACKED_FIELDS_50(fields); }), \
429*41d7ea30SVladimir Oltean 	({ BUILD_BUG_ON_MSG(1, "CHECK_PACKED_FIELDS() must be regenerated to support array sizes larger than 50."); }) \
430*41d7ea30SVladimir Oltean ))))))))))))))))))))))))))))))))))))))))))))))))))
431*41d7ea30SVladimir Oltean 
432*41d7ea30SVladimir Oltean /* End of generated content */
433*41d7ea30SVladimir Oltean 
434*41d7ea30SVladimir Oltean #define pack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
435*41d7ea30SVladimir Oltean 	({ \
436*41d7ea30SVladimir Oltean 		CHECK_PACKED_FIELDS(fields); \
437*41d7ea30SVladimir Oltean 		CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
438*41d7ea30SVladimir Oltean 		_Generic((fields), \
439*41d7ea30SVladimir Oltean 			 const struct packed_field_u8 * : pack_fields_u8, \
440*41d7ea30SVladimir Oltean 			 const struct packed_field_u16 * : pack_fields_u16 \
441*41d7ea30SVladimir Oltean 			)((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
442*41d7ea30SVladimir Oltean 	})
443*41d7ea30SVladimir Oltean 
444*41d7ea30SVladimir Oltean #define unpack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
445*41d7ea30SVladimir Oltean 	({ \
446*41d7ea30SVladimir Oltean 		CHECK_PACKED_FIELDS(fields); \
447*41d7ea30SVladimir Oltean 		CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
448*41d7ea30SVladimir Oltean 		_Generic((fields), \
449*41d7ea30SVladimir Oltean 			 const struct packed_field_u8 * : unpack_fields_u8, \
450*41d7ea30SVladimir Oltean 			 const struct packed_field_u16 * : unpack_fields_u16 \
451*41d7ea30SVladimir Oltean 			)((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
452*41d7ea30SVladimir Oltean 	})
453*41d7ea30SVladimir Oltean 
454554aae35SVladimir Oltean #endif
455