Skip to content

Commit 58262a3

Browse files
committed
Merge: CNB97: lib: packing: introduce and use (un)pack_fields
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6894 JIRA: https://issues.redhat.com/browse/RHEL-92666 The lib/packing update required by the ICE driver. Signed-off-by: Petr Oros <[email protected]> Approved-by: Michal Schmidt <[email protected]> Approved-by: Jan Stancek <[email protected]> Approved-by: CKI KWF Bot <[email protected]> Merged-by: Jan Stancek <[email protected]>
2 parents a5a7efb + 8309415 commit 58262a3

File tree

15 files changed

+1544
-166
lines changed

15 files changed

+1544
-166
lines changed

Documentation/core-api/packing.rst

Lines changed: 184 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,195 @@ the more significant 4-byte word.
151151
We always think of our offsets as if there were no quirk, and we translate
152152
them afterwards, before accessing the memory region.
153153

154+
Note on buffer lengths not multiple of 4
155+
----------------------------------------
156+
157+
To deal with memory layout quirks where groups of 4 bytes are laid out "little
158+
endian" relative to each other, but "big endian" within the group itself, the
159+
concept of groups of 4 bytes is intrinsic to the packing API (not to be
160+
confused with the memory access, which is performed byte by byte, though).
161+
162+
With buffer lengths not multiple of 4, this means one group will be incomplete.
163+
Depending on the quirks, this may lead to discontinuities in the bit fields
164+
accessible through the buffer. The packing API assumes discontinuities were not
165+
the intention of the memory layout, so it avoids them by effectively logically
166+
shortening the most significant group of 4 octets to the number of octets
167+
actually available.
168+
169+
Example with a 31 byte sized buffer given below. Physical buffer offsets are
170+
implicit, and increase from left to right within a group, and from top to
171+
bottom within a column.
172+
173+
No quirks:
174+
175+
::
176+
177+
31 29 28 | Group 7 (most significant)
178+
27 26 25 24 | Group 6
179+
23 22 21 20 | Group 5
180+
19 18 17 16 | Group 4
181+
15 14 13 12 | Group 3
182+
11 10 9 8 | Group 2
183+
7 6 5 4 | Group 1
184+
3 2 1 0 | Group 0 (least significant)
185+
186+
QUIRK_LSW32_IS_FIRST:
187+
188+
::
189+
190+
3 2 1 0 | Group 0 (least significant)
191+
7 6 5 4 | Group 1
192+
11 10 9 8 | Group 2
193+
15 14 13 12 | Group 3
194+
19 18 17 16 | Group 4
195+
23 22 21 20 | Group 5
196+
27 26 25 24 | Group 6
197+
30 29 28 | Group 7 (most significant)
198+
199+
QUIRK_LITTLE_ENDIAN:
200+
201+
::
202+
203+
30 28 29 | Group 7 (most significant)
204+
24 25 26 27 | Group 6
205+
20 21 22 23 | Group 5
206+
16 17 18 19 | Group 4
207+
12 13 14 15 | Group 3
208+
8 9 10 11 | Group 2
209+
4 5 6 7 | Group 1
210+
0 1 2 3 | Group 0 (least significant)
211+
212+
QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST:
213+
214+
::
215+
216+
0 1 2 3 | Group 0 (least significant)
217+
4 5 6 7 | Group 1
218+
8 9 10 11 | Group 2
219+
12 13 14 15 | Group 3
220+
16 17 18 19 | Group 4
221+
20 21 22 23 | Group 5
222+
24 25 26 27 | Group 6
223+
28 29 30 | Group 7 (most significant)
224+
154225
Intended use
155226
------------
156227

157228
Drivers that opt to use this API first need to identify which of the above 3
158229
quirk combinations (for a total of 8) match what the hardware documentation
159-
describes. Then they should wrap the packing() function, creating a new
160-
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.
161238

162239
The packing() function returns an int-encoded error code, which protects the
163240
programmer against incorrect API use. The errors are not expected to occur
164-
durring runtime, therefore it is reasonable for xxx_packing() to return void
165-
and simply swallow those errors. Optionally it can dump stack or print the
166-
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+
}

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14641,6 +14641,8 @@ S: Supported
1464114641
F: Documentation/core-api/packing.rst
1464214642
F: include/linux/packing.h
1464314643
F: lib/packing.c
14644+
F: lib/packing_test.c
14645+
F: scripts/gen_packed_field_checks.c
1464414646

1464514647
PADATA PARALLEL EXECUTION MECHANISM
1464614648
M: Steffen Klassert <[email protected]>

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,10 @@ PHONY += scripts_unifdef
13851385
scripts_unifdef: scripts_basic
13861386
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
13871387

1388+
PHONY += scripts_gen_packed_field_checks
1389+
scripts_gen_packed_field_checks: scripts_basic
1390+
$(Q)$(MAKE) $(build)=scripts scripts/gen_packed_field_checks
1391+
13881392
# ---------------------------------------------------------------------------
13891393
# Install
13901394

drivers/net/dsa/sja1105/sja1105_static_config.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,8 @@ void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len)
2626
pr_err("Start bit (%d) expected to be larger than end (%d)\n",
2727
start, end);
2828
} else if (rc == -ERANGE) {
29-
if ((start - end + 1) > 64)
30-
pr_err("Field %d-%d too large for 64 bits!\n",
31-
start, end);
32-
else
33-
pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
34-
*val, start, end);
29+
pr_err("Field %d-%d too large for 64 bits!\n",
30+
start, end);
3531
}
3632
dump_stack();
3733
}

0 commit comments

Comments
 (0)