Re: [PATCH v4 3/4] cxl/hdm: Make switch decoder target parsing endian-safe

Jonathan Cameron <[email protected]>
Newsgroups org.kernel.vger.linux-cxl
Message-ID <20260722020749.1826e787@jic23-huawei>
On Mon, 20 Jul 2026 18:59:39 -0700
Alison Schofield <[email protected]> wrote:

> 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]>
> Reviewed-by: Li Ming <[email protected]>
> Signed-off-by: Alison Schofield <[email protected]>

Suggestion for explicitly handling the endian issue inline.
I'm also fine if you stick with what you have here.

Reviewed-by: Jonathan Cameron <[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 1f995191baf5..077aface1a2a 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;

Maybe alternative approach along the lines of:

> -	union {
> -		u64 value;
		struct {
			__le32 lo;
			__le32 hi;
		};
> -		unsigned char target_id[8];
> -	} target_list;
>  
>  	if (should_emulate_decoders(info))
>  		return cxl_setup_hdm_decoder_from_dvsec(port, cxld, dpa_base,
> @@ -1122,9 +1119,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.lo = cpu_to_le32(readl());
		target_list.hi = cpu_to_le32(readl());

or just have a byte array and

		put_unaligned_le32(&target_id[0], readl());
		put_unaligned_le32(&target_id[4], readl());

> -		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;
>  	}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.