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