Skip to content

Commit 2e13b94

Browse files
committed
lib: packing: document recently added APIs
JIRA: https://issues.redhat.com/browse/RHEL-92666 Upstream commit(s): commit a9ad2a8 Author: Jacob Keller <jacob.e.keller@intel.com> Date: Tue Dec 10 12:27:13 2024 -0800 lib: packing: document recently added APIs Extend the documentation for the packing library, covering the intended use for the recently added APIs. This includes the pack() and unpack() macros, as well as the pack_fields() and unpack_fields() macros. Add a note that the packing() API is now deprecated in favor of pack() and unpack(). For the pack_fields() and unpack_fields() APIs, explain the rationale for when a driver may want to select this API. Provide an example which shows how to define the fields and call the pack_fields() and unpack_fields() macros. Co-developed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://patch.msgid.link/20241210-packing-pack-fields-and-ice-implementation-v10-4-ee56a47479ac@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Petr Oros <poros@redhat.com>
1 parent bc30735 commit 2e13b94

File tree

1 file changed

+113
-5
lines changed

1 file changed

+113
-5
lines changed

Documentation/core-api/packing.rst

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,119 @@ Intended use
227227

228228
Drivers that opt to use this API first need to identify which of the above 3
229229
quirk combinations (for a total of 8) match what the hardware documentation
230-
describes. Then they should wrap the packing() function, creating a new
231-
xxx_packing() that calls it using the proper QUIRK_* one-hot bits set.
230+
describes.
231+
232+
There are 3 supported usage patterns, detailed below.
233+
234+
packing()
235+
^^^^^^^^^
236+
237+
This API function is deprecated.
232238

233239
The packing() function returns an int-encoded error code, which protects the
234240
programmer against incorrect API use. The errors are not expected to occur
235-
during runtime, therefore it is reasonable for xxx_packing() to return void
236-
and simply swallow those errors. Optionally it can dump stack or print the
237-
error description.
241+
during runtime, therefore it is reasonable to wrap packing() into a custom
242+
function which returns void and swallows those errors. Optionally it can
243+
dump stack or print the error description.
244+
245+
.. code-block:: c
246+
247+
void my_packing(void *buf, u64 *val, int startbit, int endbit,
248+
size_t len, enum packing_op op)
249+
{
250+
int err;
251+
252+
/* Adjust quirks accordingly */
253+
err = packing(buf, val, startbit, endbit, len, op, QUIRK_LSW32_IS_FIRST);
254+
if (likely(!err))
255+
return;
256+
257+
if (err == -EINVAL) {
258+
pr_err("Start bit (%d) expected to be larger than end (%d)\n",
259+
startbit, endbit);
260+
} else if (err == -ERANGE) {
261+
if ((startbit - endbit + 1) > 64)
262+
pr_err("Field %d-%d too large for 64 bits!\n",
263+
startbit, endbit);
264+
else
265+
pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
266+
*val, startbit, endbit);
267+
}
268+
dump_stack();
269+
}
270+
271+
pack() and unpack()
272+
^^^^^^^^^^^^^^^^^^^
273+
274+
These are const-correct variants of packing(), and eliminate the last "enum
275+
packing_op op" argument.
276+
277+
Calling pack(...) is equivalent, and preferred, to calling packing(..., PACK).
278+
279+
Calling unpack(...) is equivalent, and preferred, to calling packing(..., UNPACK).
280+
281+
pack_fields() and unpack_fields()
282+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
283+
284+
The library exposes optimized functions for the scenario where there are many
285+
fields represented in a buffer, and it encourages consumer drivers to avoid
286+
repetitive calls to pack() and unpack() for each field, but instead use
287+
pack_fields() and unpack_fields(), which reduces the code footprint.
288+
289+
These APIs use field definitions in arrays of ``struct packed_field_u8`` or
290+
``struct packed_field_u16``, allowing consumer drivers to minimize the size
291+
of these arrays according to their custom requirements.
292+
293+
The pack_fields() and unpack_fields() API functions are actually macros which
294+
automatically select the appropriate function at compile time, based on the
295+
type of the fields array passed in.
296+
297+
An additional benefit over pack() and unpack() is that sanity checks on the
298+
field definitions are handled at compile time with ``BUILD_BUG_ON`` rather
299+
than only when the offending code is executed. These functions return void and
300+
wrapping them to handle unexpected errors is not necessary.
301+
302+
It is recommended, but not required, that you wrap your packed buffer into a
303+
structured type with a fixed size. This generally makes it easier for the
304+
compiler to enforce that the correct size buffer is used.
305+
306+
Here is an example of how to use the fields APIs:
307+
308+
.. code-block:: c
309+
310+
/* Ordering inside the unpacked structure is flexible and can be different
311+
* from the packed buffer. Here, it is optimized to reduce padding.
312+
*/
313+
struct data {
314+
u64 field3;
315+
u32 field4;
316+
u16 field1;
317+
u8 field2;
318+
};
319+
320+
#define SIZE 13
321+
322+
typdef struct __packed { u8 buf[SIZE]; } packed_buf_t;
323+
324+
static const struct packed_field_u8 fields[] = {
325+
PACKED_FIELD(100, 90, struct data, field1),
326+
PACKED_FIELD(90, 87, struct data, field2),
327+
PACKED_FIELD(86, 30, struct data, field3),
328+
PACKED_FIELD(29, 0, struct data, field4),
329+
};
330+
331+
void unpack_your_data(const packed_buf_t *buf, struct data *unpacked)
332+
{
333+
BUILD_BUG_ON(sizeof(*buf) != SIZE;
334+
335+
unpack_fields(buf, sizeof(*buf), unpacked, fields,
336+
QUIRK_LITTLE_ENDIAN);
337+
}
338+
339+
void pack_your_data(const struct data *unpacked, packed_buf_t *buf)
340+
{
341+
BUILD_BUG_ON(sizeof(*buf) != SIZE;
342+
343+
pack_fields(buf, sizeof(*buf), unpacked, fields,
344+
QUIRK_LITTLE_ENDIAN);
345+
}

0 commit comments

Comments
 (0)