$sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget$/translations/zh_CN/core-api/packingmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/zh_TW/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/it_IT/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ja_JP/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ko_KR/core-api/packingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/sp_SP/core-api/packingmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(h0Generic bitfield packing and unpacking functionsh]h0Generic bitfield packing and unpacking functions}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhh>/var/lib/git/docbuild/linux/Documentation/core-api/packing.rsthKubh)}(hhh](h)}(hProblem statementh]hProblem statement}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hXWhen working with hardware, one has to choose between several approaches of interfacing with it. One can memory-map a pointer to a carefully crafted struct over the hardware device's memory region, and access its fields as struct members (potentially declared as bitfields). But writing code this way would make it less portable, due to potential endianness mismatches between the CPU and the hardware device. Additionally, one has to pay close attention when translating register definitions from the hardware documentation into bit field indices for the structs. Also, some hardware (typically networking equipment) tends to group its register fields in ways that violate any reasonable word boundaries (sometimes even 64 bit ones). This creates the inconvenience of having to define "high" and "low" portions of register fields within the struct. A more robust alternative to struct field definitions would be to extract the required fields by shifting the appropriate number of bits. But this would still not protect from endianness mismatches, except if all memory accesses were performed byte-by-byte. Also the code can easily get cluttered, and the high-level idea might get lost among the many bit shifts required. Many drivers take the bit-shifting approach and then attempt to reduce the clutter with tailored macros, but more often than not these macros take shortcuts that still prevent the code from being truly portable.h]hXWhen working with hardware, one has to choose between several approaches of interfacing with it. One can memory-map a pointer to a carefully crafted struct over the hardware device’s memory region, and access its fields as struct members (potentially declared as bitfields). But writing code this way would make it less portable, due to potential endianness mismatches between the CPU and the hardware device. Additionally, one has to pay close attention when translating register definitions from the hardware documentation into bit field indices for the structs. Also, some hardware (typically networking equipment) tends to group its register fields in ways that violate any reasonable word boundaries (sometimes even 64 bit ones). This creates the inconvenience of having to define “high” and “low” portions of register fields within the struct. A more robust alternative to struct field definitions would be to extract the required fields by shifting the appropriate number of bits. But this would still not protect from endianness mismatches, except if all memory accesses were performed byte-by-byte. Also the code can easily get cluttered, and the high-level idea might get lost among the many bit shifts required. Many drivers take the bit-shifting approach and then attempt to reduce the clutter with tailored macros, but more often than not these macros take shortcuts that still prevent the code from being truly portable.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]problem-statementah ]h"]problem statementah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h The solutionh]h The solution}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(h'This API deals with 2 basic operations:h]h'This API deals with 2 basic operations:}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh block_quote)}(h- Packing a CPU-usable number into a memory buffer (with hardware constraints/quirks) - Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number. h]h bullet_list)}(hhh](h list_item)}(hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)h]h)}(hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)h]hSPacking a CPU-usable number into a memory buffer (with hardware constraints/quirks)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hj ubah}(h]h ]h"]h$]h&]uh1j hjubj )}(h\Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number. h]h)}(h[Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number.h]h[Unpacking a memory buffer (which has hardware constraints/quirks) into a CPU-usable number.}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hj$ubah}(h]h ]h"]h$]h&]uh1j hjubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhK"hjubah}(h]h ]h"]h$]h&]uh1hhhhK"hhhhubh)}(hThe API offers an abstraction over said hardware constraints and quirks, over CPU endianness and therefore between possible mismatches between the two.h]hThe API offers an abstraction over said hardware constraints and quirks, over CPU endianness and therefore between possible mismatches between the two.}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK'hhhhubh)}(hThe basic unit of these API functions is the u64. From the CPU's perspective, bit 63 always means bit offset 7 of byte 7, albeit only logically. The question is: where do we lay this bit out in memory?h]hThe basic unit of these API functions is the u64. From the CPU’s perspective, bit 63 always means bit offset 7 of byte 7, albeit only logically. The question is: where do we lay this bit out in memory?}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hhhhubh)}(hThe following examples cover the memory layout of a packed u64 field. The byte offsets in the packed buffer are always implicitly 0, 1, ... 7. What the examples show is where the logical bytes and bits sit.h]hThe following examples cover the memory layout of a packed u64 field. The byte offsets in the packed buffer are always implicitly 0, 1, ... 7. What the examples show is where the logical bytes and bits sit.}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK/hhhhubhenumerated_list)}(hhh]j )}(h0Normally (no quirks), we would do it like this: h]h)}(h/Normally (no quirks), we would do it like this:h]h/Normally (no quirks), we would do it like this:}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjyubah}(h]h ]h"]h$]h&]uh1j hjvhhhhhNubah}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix.uh1jthhhhhhhK3ubh literal_block)}(hXU63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0h]hXU63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0}hjsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1jhhhK7hhhhubh)}(hX2That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the LSByte (0) of the u64 sits at memory offset 7. This corresponds to what most folks would regard to as "big endian", where bit i corresponds to the number 2^i. This is also referred to in the code comments as "logical" notation.h]hX:That is, the MSByte (7) of the CPU-usable u64 sits at memory offset 0, and the LSByte (0) of the u64 sits at memory offset 7. This corresponds to what most folks would regard to as “big endian”, where bit i corresponds to the number 2^i. This is also referred to in the code comments as “logical” notation.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK]hj:ubah}(h]h ]h"]h$]h&]uh1j hj7hhhhhNubah}(h]h ]h"]h$]h&]jjjhjjjKuh1jthhhhhhhK]ubj)}(hXS32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 4 5 6 7 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3h]hXS32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 4 5 6 7 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3}hjXsbah}(h]h ]h"]h$]h&]jjuh1jhhhKbhhhhubju)}(hhh]j )}(h9If just QUIRK_LSW32_IS_FIRST is set, we do it like this: h]h)}(h8If just QUIRK_LSW32_IS_FIRST is set, we do it like this:h]h8If just QUIRK_LSW32_IS_FIRST is set, we do it like this:}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhjiubah}(h]h ]h"]h$]h&]uh1j hjfhhhhhNubah}(h]h ]h"]h$]h&]jjjhjjjKuh1jthhhhhhhKhubj)}(hXU31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4h]hXU31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 3 2 1 0 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 7 6 5 4}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKlhhhhubh)}(hIn this case the 8 byte memory region is interpreted as follows: first 4 bytes correspond to the least significant 4-byte word, next 4 bytes to the more significant 4-byte word.h]hIn this case the 8 byte memory region is interpreted as follows: first 4 bytes correspond to the least significant 4-byte word, next 4 bytes to the more significant 4-byte word.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKqhhhhubju)}(hhh]j )}(hPIf QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like this: h]h)}(hOIf QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like this:h]hOIf QUIRK_LSW32_IS_FIRST and QUIRK_MSB_ON_THE_RIGHT are set, we do it like this:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKvhjubah}(h]h ]h"]h$]h&]uh1j hjhhhhhNubah}(h]h ]h"]h$]h&]jjjhjjjKuh1jthhhhhhhKvubj)}(hXU24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 3 2 1 0 56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 7 6 5 4h]hXU24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 3 2 1 0 56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39 7 6 5 4}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhK{hhhhubju)}(hhh]j )}(hMIf QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like this: h]h)}(hLIf QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like this:h]hLIf QUIRK_LSW32_IS_FIRST and QUIRK_LITTLE_ENDIAN are set, it looks like this:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1j hjhhhhhNubah}(h]h ]h"]h$]h&]jjjhjjjKuh1jthhhhhhhKubj)}(hXS7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 0 1 2 3 39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 4 5 6 7h]hXS7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 0 1 2 3 39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56 4 5 6 7}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKhhhhubju)}(hhh]j )}(heIf QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT are set, it looks like this: h]h)}(hdIf QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT are set, it looks like this:h]hdIf QUIRK_LSW32_IS_FIRST, QUIRK_LITTLE_ENDIAN and QUIRK_MSB_ON_THE_RIGHT are set, it looks like this:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1j hjhhhhhNubah}(h]h ]h"]h$]h&]jjjhjjjKuh1jthhhhhhhKubj)}(hXS0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 4 5 6 7h]hXS0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0 1 2 3 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 4 5 6 7}hj"sbah}(h]h ]h"]h$]h&]jjuh1jhhhKhhhhubh)}(hWe always think of our offsets as if there were no quirk, and we translate them afterwards, before accessing the memory region.h]hWe always think of our offsets as if there were no quirk, and we translate them afterwards, before accessing the memory region.}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h] the-solutionah ]h"] the solutionah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h(Note on buffer lengths not multiple of 4h]h(Note on buffer lengths not multiple of 4}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjFhhhhhKubh)}(hX/To deal with memory layout quirks where groups of 4 bytes are laid out "little endian" relative to each other, but "big endian" within the group itself, the concept of groups of 4 bytes is intrinsic to the packing API (not to be confused with the memory access, which is performed byte by byte, though).h]hX7To deal with memory layout quirks where groups of 4 bytes are laid out “little endian” relative to each other, but “big endian” within the group itself, the concept of groups of 4 bytes is intrinsic to the packing API (not to be confused with the memory access, which is performed byte by byte, though).}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubh)}(hXWith buffer lengths not multiple of 4, this means one group will be incomplete. Depending on the quirks, this may lead to discontinuities in the bit fields accessible through the buffer. The packing API assumes discontinuities were not the intention of the memory layout, so it avoids them by effectively logically shortening the most significant group of 4 octets to the number of octets actually available.h]hXWith buffer lengths not multiple of 4, this means one group will be incomplete. Depending on the quirks, this may lead to discontinuities in the bit fields accessible through the buffer. The packing API assumes discontinuities were not the intention of the memory layout, so it avoids them by effectively logically shortening the most significant group of 4 octets to the number of octets actually available.}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubh)}(hExample with a 31 byte sized buffer given below. Physical buffer offsets are implicit, and increase from left to right within a group, and from top to bottom within a column.h]hExample with a 31 byte sized buffer given below. Physical buffer offsets are implicit, and increase from left to right within a group, and from top to bottom within a column.}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubh)}(h No quirks:h]h No quirks:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubj)}(hX 31 29 28 | Group 7 (most significant) 27 26 25 24 | Group 6 23 22 21 20 | Group 5 19 18 17 16 | Group 4 15 14 13 12 | Group 3 11 10 9 8 | Group 2 7 6 5 4 | Group 1 3 2 1 0 | Group 0 (least significant)h]hX 31 29 28 | Group 7 (most significant) 27 26 25 24 | Group 6 23 22 21 20 | Group 5 19 18 17 16 | Group 4 15 14 13 12 | Group 3 11 10 9 8 | Group 2 7 6 5 4 | Group 1 3 2 1 0 | Group 0 (least significant)}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKhjFhhubh)}(hQUIRK_LSW32_IS_FIRST:h]hQUIRK_LSW32_IS_FIRST:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubj)}(hX 3 2 1 0 | Group 0 (least significant) 7 6 5 4 | Group 1 11 10 9 8 | Group 2 15 14 13 12 | Group 3 19 18 17 16 | Group 4 23 22 21 20 | Group 5 27 26 25 24 | Group 6 30 29 28 | Group 7 (most significant)h]hX 3 2 1 0 | Group 0 (least significant) 7 6 5 4 | Group 1 11 10 9 8 | Group 2 15 14 13 12 | Group 3 19 18 17 16 | Group 4 23 22 21 20 | Group 5 27 26 25 24 | Group 6 30 29 28 | Group 7 (most significant)}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKhjFhhubh)}(hQUIRK_LITTLE_ENDIAN:h]hQUIRK_LITTLE_ENDIAN:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubj)}(hX 30 28 29 | Group 7 (most significant) 24 25 26 27 | Group 6 20 21 22 23 | Group 5 16 17 18 19 | Group 4 12 13 14 15 | Group 3 8 9 10 11 | Group 2 4 5 6 7 | Group 1 0 1 2 3 | Group 0 (least significant)h]hX 30 28 29 | Group 7 (most significant) 24 25 26 27 | Group 6 20 21 22 23 | Group 5 16 17 18 19 | Group 4 12 13 14 15 | Group 3 8 9 10 11 | Group 2 4 5 6 7 | Group 1 0 1 2 3 | Group 0 (least significant)}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKhjFhhubh)}(h+QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST:h]h+QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjFhhubj)}(hX 0 1 2 3 | Group 0 (least significant) 4 5 6 7 | Group 1 8 9 10 11 | Group 2 12 13 14 15 | Group 3 16 17 18 19 | Group 4 20 21 22 23 | Group 5 24 25 26 27 | Group 6 28 29 30 | Group 7 (most significant)h]hX 0 1 2 3 | Group 0 (least significant) 4 5 6 7 | Group 1 8 9 10 11 | Group 2 12 13 14 15 | Group 3 16 17 18 19 | Group 4 20 21 22 23 | Group 5 24 25 26 27 | Group 6 28 29 30 | Group 7 (most significant)}hjsbah}(h]h ]h"]h$]h&]jjuh1jhhhKhjFhhubeh}(h](note-on-buffer-lengths-not-multiple-of-4ah ]h"](note on buffer lengths not multiple of 4ah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h Intended useh]h Intended use}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hDrivers that opt to use this API first need to identify which of the above 3 quirk combinations (for a total of 8) match what the hardware documentation describes.h]hDrivers that opt to use this API first need to identify which of the above 3 quirk combinations (for a total of 8) match what the hardware documentation describes.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h5There are 3 supported usage patterns, detailed below.h]h5There are 3 supported usage patterns, detailed below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hhh](h)}(h packing()h]h packing()}(hj)hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj&hhhhhKubh)}(h This API function is deprecated.h]h This API function is deprecated.}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj&hhubh)}(hXWThe packing() function returns an int-encoded error code, which protects the programmer against incorrect API use. The errors are not expected to occur during runtime, therefore it is reasonable to wrap packing() into a custom function which returns void and swallows those errors. Optionally it can dump stack or print the error description.h]hXWThe packing() function returns an int-encoded error code, which protects the programmer against incorrect API use. The errors are not expected to occur during runtime, therefore it is reasonable to wrap packing() into a custom function which returns void and swallows those errors. Optionally it can dump stack or print the error description.}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj&hhubj)}(hX^void my_packing(void *buf, u64 *val, int startbit, int endbit, size_t len, enum packing_op op) { int err; /* Adjust quirks accordingly */ err = packing(buf, val, startbit, endbit, len, op, QUIRK_LSW32_IS_FIRST); if (likely(!err)) return; if (err == -EINVAL) { pr_err("Start bit (%d) expected to be larger than end (%d)\n", startbit, endbit); } else if (err == -ERANGE) { if ((startbit - endbit + 1) > 64) pr_err("Field %d-%d too large for 64 bits!\n", startbit, endbit); else pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n", *val, startbit, endbit); } dump_stack(); }h]hX^void my_packing(void *buf, u64 *val, int startbit, int endbit, size_t len, enum packing_op op) { int err; /* Adjust quirks accordingly */ err = packing(buf, val, startbit, endbit, len, op, QUIRK_LSW32_IS_FIRST); if (likely(!err)) return; if (err == -EINVAL) { pr_err("Start bit (%d) expected to be larger than end (%d)\n", startbit, endbit); } else if (err == -ERANGE) { if ((startbit - endbit + 1) > 64) pr_err("Field %d-%d too large for 64 bits!\n", startbit, endbit); else pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n", *val, startbit, endbit); } dump_stack(); }}hjSsbah}(h]h ]h"]h$]h&]jjforcelanguagechighlight_args}uh1jhhhKhj&hhubeh}(h]packingah ]h"] packing()ah$]h&]uh1hhjhhhhhKubh)}(hhh](h)}(hpack() and unpack()h]hpack() and unpack()}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjnhhhhhMubh)}(hdThese are const-correct variants of packing(), and eliminate the last "enum packing_op op" argument.h]hhThese are const-correct variants of packing(), and eliminate the last “enum packing_op op” argument.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubh)}(hNCalling pack(...) is equivalent, and preferred, to calling packing(..., PACK).h]hNCalling pack(...) is equivalent, and preferred, to calling packing(..., PACK).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubh)}(hRCalling unpack(...) is equivalent, and preferred, to calling packing(..., UNPACK).h]hRCalling unpack(...) is equivalent, and preferred, to calling packing(..., UNPACK).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubeh}(h]pack-and-unpackah ]h"]pack() and unpack()ah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(h!pack_fields() and unpack_fields()h]h!pack_fields() and unpack_fields()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hX&The library exposes optimized functions for the scenario where there are many fields represented in a buffer, and it encourages consumer drivers to avoid repetitive calls to pack() and unpack() for each field, but instead use pack_fields() and unpack_fields(), which reduces the code footprint.h]hX&The library exposes optimized functions for the scenario where there are many fields represented in a buffer, and it encourages consumer drivers to avoid repetitive calls to pack() and unpack() for each field, but instead use pack_fields() and unpack_fields(), which reduces the code footprint.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hThese APIs use field definitions in arrays of ``struct packed_field_u8`` or ``struct packed_field_u16``, allowing consumer drivers to minimize the size of these arrays according to their custom requirements.h](h.These APIs use field definitions in arrays of }(hjhhhNhNubhliteral)}(h``struct packed_field_u8``h]hstruct packed_field_u8}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh or }(hjhhhNhNubj)}(h``struct packed_field_u16``h]hstruct packed_field_u16}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhh, allowing consumer drivers to minimize the size of these arrays according to their custom requirements.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM!hjhhubh)}(hThe pack_fields() and unpack_fields() API functions are actually macros which automatically select the appropriate function at compile time, based on the type of the fields array passed in.h]hThe pack_fields() and unpack_fields() API functions are actually macros which automatically select the appropriate function at compile time, based on the type of the fields array passed in.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM%hjhhubh)}(hX!An additional benefit over pack() and unpack() is that sanity checks on the field definitions are handled at compile time with ``BUILD_BUG_ON`` rather than only when the offending code is executed. These functions return void and wrapping them to handle unexpected errors is not necessary.h](hAn additional benefit over pack() and unpack() is that sanity checks on the field definitions are handled at compile time with }(hjhhhNhNubj)}(h``BUILD_BUG_ON``h]h BUILD_BUG_ON}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh rather than only when the offending code is executed. These functions return void and wrapping them to handle unexpected errors is not necessary.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM)hjhhubh)}(hIt is recommended, but not required, that you wrap your packed buffer into a structured type with a fixed size. This generally makes it easier for the compiler to enforce that the correct size buffer is used.h]hIt is recommended, but not required, that you wrap your packed buffer into a structured type with a fixed size. This generally makes it easier for the compiler to enforce that the correct size buffer is used.}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM.hjhhubh)}(h1Here is an example of how to use the fields APIs:h]h1Here is an example of how to use the fields APIs:}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM2hjhhubj)}(hX/* Ordering inside the unpacked structure is flexible and can be different * from the packed buffer. Here, it is optimized to reduce padding. */ struct data { u64 field3; u32 field4; u16 field1; u8 field2; }; #define SIZE 13 typdef struct __packed { u8 buf[SIZE]; } packed_buf_t; static const struct packed_field_u8 fields[] = { PACKED_FIELD(100, 90, struct data, field1), PACKED_FIELD(90, 87, struct data, field2), PACKED_FIELD(86, 30, struct data, field3), PACKED_FIELD(29, 0, struct data, field4), }; void unpack_your_data(const packed_buf_t *buf, struct data *unpacked) { BUILD_BUG_ON(sizeof(*buf) != SIZE; unpack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); } void pack_your_data(const struct data *unpacked, packed_buf_t *buf) { BUILD_BUG_ON(sizeof(*buf) != SIZE; pack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); }h]hX/* Ordering inside the unpacked structure is flexible and can be different * from the packed buffer. Here, it is optimized to reduce padding. */ struct data { u64 field3; u32 field4; u16 field1; u8 field2; }; #define SIZE 13 typdef struct __packed { u8 buf[SIZE]; } packed_buf_t; static const struct packed_field_u8 fields[] = { PACKED_FIELD(100, 90, struct data, field1), PACKED_FIELD(90, 87, struct data, field2), PACKED_FIELD(86, 30, struct data, field3), PACKED_FIELD(29, 0, struct data, field4), }; void unpack_your_data(const packed_buf_t *buf, struct data *unpacked) { BUILD_BUG_ON(sizeof(*buf) != SIZE; unpack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); } void pack_your_data(const struct data *unpacked, packed_buf_t *buf) { BUILD_BUG_ON(sizeof(*buf) != SIZE; pack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); }}hjNsbah}(h]h ]h"]h$]h&]jjjajbjcjd}uh1jhhhM4hjhhubeh}(h]pack-fields-and-unpack-fieldsah ]h"]!pack_fields() and unpack_fields()ah$]h&]uh1hhjhhhhhMubeh}(h] intended-useah ]h"] intended useah$]h&]uh1hhhhhhhhKubeh}(h]0generic-bitfield-packing-and-unpacking-functionsah ]h"]0generic bitfield packing and unpacking functionsah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jrjohhjCj@jjjjjgjkjhjjjbj_u nametypes}(jrh݉jCjjjjkjjbuh}(johhhj@hjjFjgjjhj&jjnj_ju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages](hsystem_message)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "2" (ordinal 2)h]h>Enumerated list start value not ordinal-1: “2” (ordinal 2)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypeINFOsourcehlineKuh1jhhhhhhhKCubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "3" (ordinal 3)h]h>Enumerated list start value not ordinal-1: “3” (ordinal 3)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhKPubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "4" (ordinal 4)h]h>Enumerated list start value not ordinal-1: “4” (ordinal 4)}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj3ubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhK]ubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "5" (ordinal 5)h]h>Enumerated list start value not ordinal-1: “5” (ordinal 5)}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjNubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhKhubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "6" (ordinal 6)h]h>Enumerated list start value not ordinal-1: “6” (ordinal 6)}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjiubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhKvubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "7" (ordinal 7)h]h>Enumerated list start value not ordinal-1: “7” (ordinal 7)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhKubj)}(hhh]h)}(h:Enumerated list start value not ordinal-1: "8" (ordinal 8)h]h>Enumerated list start value not ordinal-1: “8” (ordinal 8)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineKuh1jhhhhhhhKubetransform_messages] transformerN include_log] decorationNhhub.