@@ -9,23 +9,6 @@
#include <linux/types.h>
#include <linux/bitrev.h>
-static void adjust_for_msb_right_quirk(u64 *to_write, size_t *box_start_bit,
- size_t *box_end_bit, u8 *box_mask)
-{
- size_t box_bit_width = *box_start_bit - *box_end_bit + 1;
- size_t new_box_start_bit, new_box_end_bit;
-
- *to_write >>= *box_end_bit;
- *to_write = bitrev8(*to_write) >> (8 - box_bit_width);
- *to_write <<= *box_end_bit;
-
- new_box_end_bit = box_bit_width - *box_start_bit - 1;
- new_box_start_bit = box_bit_width - *box_end_bit - 1;
- *box_mask = GENMASK_ULL(new_box_start_bit, new_box_end_bit);
- *box_start_bit = new_box_start_bit;
- *box_end_bit = new_box_end_bit;
-}
-
/**
* calculate_box_addr - Determine physical location of byte in buffer
* @box: Index of byte within buffer seen as a logical big-endian big number
@@ -170,13 +153,13 @@ int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
/* Write to pbuf, read from uval */
pval = uval & proj_mask;
pval >>= proj_end_bit;
- if (quirks & QUIRK_MSB_ON_THE_RIGHT)
- adjust_for_msb_right_quirk(&pval,
- &box_start_bit,
- &box_end_bit,
- &box_mask);
-
pval <<= box_end_bit;
+
+ if (quirks & QUIRK_MSB_ON_THE_RIGHT) {
+ pval = bitrev8(pval);
+ box_mask = bitrev8(box_mask);
+ }
+
((u8 *)pbuf)[box_addr] &= ~box_mask;
((u8 *)pbuf)[box_addr] |= pval;
}
@@ -276,12 +259,12 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
box_addr = calculate_box_addr(box, pbuflen, quirks);
/* Read from pbuf, write to uval */
- pval = ((u8 *)pbuf)[box_addr] & box_mask;
+ pval = ((u8 *)pbuf)[box_addr];
+
if (quirks & QUIRK_MSB_ON_THE_RIGHT)
- adjust_for_msb_right_quirk(&pval,
- &box_start_bit,
- &box_end_bit,
- &box_mask);
+ pval = bitrev8(pval);
+
+ pval &= box_mask;
pval >>= box_end_bit;
pval <<= proj_end_bit;
@@ -251,6 +251,42 @@ static const struct packing_test_case cases[] = {
.end_bit = 43,
.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
},
+ {
+ .desc = "msb right, 16 bytes, non-aligned",
+ PBUF(0x00, 0x00, 0x00, 0x91, 0x88, 0x59, 0x44, 0xd5,
+ 0xcc, 0x3d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00),
+ .uval = 0x1122334455667788,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT,
+ },
+ {
+ .desc = "msb right + lsw32 first, 16 bytes, non-aligned",
+ PBUF(0x00, 0x00, 0x00, 0x00, 0xcc, 0x3d, 0x02, 0x00,
+ 0x88, 0x59, 0x44, 0xd5, 0x00, 0x00, 0x00, 0x91),
+ .uval = 0x1122334455667788,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST,
+ },
+ {
+ .desc = "msb right + little endian words, 16 bytes, non-aligned",
+ PBUF(0x91, 0x00, 0x00, 0x00, 0xd5, 0x44, 0x59, 0x88,
+ 0x00, 0x02, 0x3d, 0xcc, 0x00, 0x00, 0x00, 0x00),
+ .uval = 0x1122334455667788,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LITTLE_ENDIAN,
+ },
+ {
+ .desc = "msb right + lsw32 first + little endian words, 16 bytes, non-aligned",
+ PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3d, 0xcc,
+ 0xd5, 0x44, 0x59, 0x88, 0x91, 0x00, 0x00, 0x00),
+ .uval = 0x1122334455667788,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
+ },
/* These tests pack and unpack a u64 with all bits set
* (0xffffffffffffffff) at an odd starting bit (43) within an
* otherwise zero array of 128 bits (16 bytes). They test all possible
@@ -292,6 +328,42 @@ static const struct packing_test_case cases[] = {
.end_bit = 43,
.quirks = QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
},
+ {
+ .desc = "msb right, 16 bytes, non-aligned, 0xff",
+ PBUF(0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00),
+ .uval = 0xffffffffffffffff,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT,
+ },
+ {
+ .desc = "msb right + lsw32 first, 16 bytes, non-aligned, 0xff",
+ PBUF(0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff),
+ .uval = 0xffffffffffffffff,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST,
+ },
+ {
+ .desc = "msb right + little endian words, 16 bytes, non-aligned, 0xff",
+ PBUF(0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00),
+ .uval = 0xffffffffffffffff,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LITTLE_ENDIAN,
+ },
+ {
+ .desc = "msb right + lsw32 first + little endian words, 16 bytes, non-aligned, 0xff",
+ PBUF(0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00),
+ .uval = 0xffffffffffffffff,
+ .start_bit = 106,
+ .end_bit = 43,
+ .quirks = QUIRK_MSB_ON_THE_RIGHT | QUIRK_LSW32_IS_FIRST | QUIRK_LITTLE_ENDIAN,
+ },
};
KUNIT_ARRAY_PARAM_DESC(packing, cases, desc);