[PATCH v3 2/3] cxl/hdm: Make switch decoder target parsing endian-safe
Alison Schofield <[email protected]>
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <c09d201db3b716a6a9c664ccb8ff7fd9dc67b562.1784322343.git.alison.schofield@intel.com> |
Switch decoder target IDs are stored one per byte, starting with target
0 in the least significant byte. The current code accesses those bytes
in memory order, which only matches register order on little-endian
hosts.
On big-endian hosts, the target IDs are reversed and the decoder is
associated with the wrong downstream ports.
Extract each target ID from the register value with an explicit shift
and mask so the target mapping is independent of host endianness.
Fixes: d17d0540a0db ("cxl/core/hdm: Add CXL standard decoder enumeration to the core")
Reviewed-by: Richard Cheng <[email protected]>
Signed-off-by: Alison Schofield <[email protected]>
---
drivers/cxl/core/hdm.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index d81df45d8005..4aaadb842d90 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -976,14 +976,11 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
{
struct cxl_endpoint_decoder *cxled = NULL;
u64 size, base, skip, dpa_size, lo, hi;
+ u64 target_list;
bool committed;
u32 remainder;
int i, rc;
u32 ctrl;
- union {
- u64 value;
- unsigned char target_id[8];
- } target_list;
if (should_emulate_decoders(info))
return cxl_setup_hdm_decoder_from_dvsec(port, cxld, dpa_base,
@@ -1119,9 +1116,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
- target_list.value = (hi << 32) + lo;
+ target_list = (hi << 32) + lo;
for (i = 0; i < cxld->interleave_ways; i++)
- cxld->target_map[i] = target_list.target_id[i];
+ cxld->target_map[i] = (target_list >> (i * 8)) & 0xff;
return 0;
}
--
2.37.3