All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Alison Schofield" <alison.schofield@intel.com>
Cc: linux-cxl@vger.kernel.org
Subject: Re: [PATCH v7 3/5] cxl/region: Support auto region granularity finer than the root
Date: Fri, 06 Nov 2026 22:22:37 +0000	[thread overview]
Message-ID: <sashiko-outbox-202327@kernel.org> (raw)
In-Reply-To: <15338cf5f174c87f414e4518b24edb3c1f8371bd.1794000806.git.alison.schofield@intel.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] cxl/region: passthrough parent granularity used in
  cxl_port_calc_interleave()
- [Medium] cxl/region: unvalidated endpoint positions in
  cxl_region_sort_targets()
--

commit d69ce1cc3e00f111d2894f426382e5b9afaa5815
Author: Alison Schofield <alison.schofield@intel.com>

cxl/region: Support auto region granularity finer than the root

This commit adds support for assembling auto-discovered CXL regions whose
interleave granularity is finer than the interleaving root decoder, and
updates unaligned region offset-to-DPA translation to use the region
granularity and ways.

> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 1594bec3930bf..0a39e634b4b0a 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c

[ ... ]

> @@ -1449,6 +1495,14 @@ static int cxl_port_peer_distance(struct cxl_port *port, struct cxl_region *cxlr
>  	struct cxl_port *iter = port;
>  	int distance = 1;
>  
> +	/*
> +	 * A finer-than-root region refines toward the endpoints, so peer
> +	 * targets at the finest interleaving level occupy consecutive region
> +	 * positions.
> +	 */
> +	if (cxl_region_is_finer_than_root(cxlr))
> +		return 1;
> +
>  	do {
>  		cxl_rr_iter = cxl_rr_load(iter, cxlr);
>  		distance *= cxl_rr_iter->nr_targets;

[Severity: Medium]
Can check_last_peer() index out of bounds or dereference NULL in
p->targets[] when cxl_port_peer_distance() returns 1?

During auto-region assembly in cxl_region_attach(),
cxl_region_sort_targets() runs before cxl_region_setup_targets() validates
intermediate decoder granularities.  cxl_port_interleave_pos() scales pos
by gran / region_gran using the unvalidated decoder granularity, and
cxl_region_sort_targets() only checks cxled->pos < 0 without verifying
that the sorted positions match 0 .. p->nr_targets - 1:

drivers/cxl/core/region.c:cxl_region_sort_targets() {
	for (i = 0; i < p->nr_targets; i++) {
		struct cxl_endpoint_decoder *cxled = p->targets[i];

		cxled->pos = cxl_calc_interleave_pos(cxled, cxlr);
		...
		if (cxled->pos < 0)
			rc = -ENXIO;
	}
	/* Keep the cxlr target list in interleave position order */
	sort(p->targets, p->nr_targets, sizeof(p->targets[0]),
	     cmp_interleave_pos, NULL);
}

If firmware programs a bogus granularity on an intermediate decoder,
cxled->pos can exceed p->nr_targets or CXL_DECODER_MAX_INTERLEAVE (or
produce duplicate positions).  When cxl_region_setup_targets() then calls
check_last_peer() with distance == 1 at an upper port, pos < distance only
rejects pos < 1 before indexing p->targets[pos - 1] and dereferencing
cxled_peer.  Because cxl_region_attach_position() attaches endpoints using
the loop index i while cxled->pos != i, later teardown in
__cxl_decoder_detach() also hits dev_WARN_ONCE() and fails to detach the
endpoint.

Validating that p->targets[i]->pos == i for all targets after sort() in
cxl_region_sort_targets() would catch both out-of-range and duplicate
positions before attachment and target setup proceed.

> @@ -1476,15 +1530,17 @@ static int cxl_port_parent_interleave(struct cxl_port *port,
>  	int parent_iw, parent_ig;
>  
>  	if (is_cxl_root(parent_port)) {
> -		/*
> -		 * Root decoder IG is always set to value in CFMWS which
> -		 * may be different than this region's IG.  We can use the
> -		 * region's IG here since interleave_granularity_store()
> -		 * does not allow interleaved host-bridges with
> -		 * root IG != region IG.
> -		 */
> -		parent_ig = p->interleave_granularity;
>  		parent_iw = cxlrd->cxlsd.cxld.interleave_ways;
> +		if (parent_iw > 1) {
> +			parent_ig = cxlrd->cxlsd.cxld.interleave_granularity;
> +		} else {
> +			/*
> +			 * A single-way root does not interleave, so its
> +			 * granularity does not constrain the region interleave.
> +			 * Use the region granularity instead.
> +			 */
> +			parent_ig = p->interleave_granularity;
> +		}
>  		if (!is_power_of_2(parent_iw))
>  			parent_iw /= 3;
>  	} else {
> @@ -1521,7 +1577,7 @@ static int cxl_port_calc_interleave(struct cxl_port *port, struct cxl_region *cx
>  				    struct cxl_region_ref *cxl_rr, int *out_iw,
>  				    int *out_ig)
>  {
> -	struct cxl_port *parent_port = to_cxl_port(port->dev.parent);
> +	struct cxl_region_params *p = &cxlr->params;
>  	struct cxl_decoder *cxld = cxl_rr->decoder;
>  	int parent_iw, parent_ig, iw, ig, rc;
>  	struct cxl_switch_decoder *cxlsd;
> @@ -1537,16 +1593,24 @@ static int cxl_port_calc_interleave(struct cxl_port *port, struct cxl_region *cx
>  		return -EINVAL;
>  	}
>  
> -	/*
> -	 * Interleave granularity is a multiple of @parent_port granularity.
> -	 * Multiplier is the parent port interleave ways.
> -	 */
> -	ig = parent_ig * parent_iw;
> +	/* Finer-than-root regions refine granularity toward the endpoints */
> +	if (cxl_region_is_finer_than_root(cxlr)) {
> +		ig = parent_ig / iw;
> +
> +		if (ig < p->interleave_granularity) {
> +			dev_dbg(&cxlr->dev,
> +				"%s:%s: granularity %d is finer than region granularity %d\n",
> +				dev_name(port->uport_dev), dev_name(&port->dev),
> +				ig, p->interleave_granularity);
> +			return -ENXIO;
> +		}
> +	} else {
> +		ig = parent_ig * parent_iw;
> +	}
>  
>  	if (!granularity_valid(ig)) {
> -		dev_dbg(&cxlr->dev,
> -			"%s: invalid granularity calculation (%d * %d)\n",
> -			dev_name(&parent_port->dev), parent_ig, parent_iw);
> +		dev_dbg(&cxlr->dev, "%s:%s: invalid granularity: %d\n",
> +			dev_name(port->uport_dev), dev_name(&port->dev), ig);
>  		return -EINVAL;
>  	}

[Severity: High]
Does cxl_port_calc_interleave() use an unvalidated passthrough decoder
granularity when an interleaving switch sits below a 1-way host bridge or
parent switch?

In cxl_port_setup_decoder(), an auto-region passthrough decoder (iw == 1)
is exempted from matching ig and its cxld->interleave_granularity is left
at whatever raw value firmware programmed in the hardware register (such
as 256B):

drivers/cxl/core/region.c:cxl_port_setup_decoder() {
	if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) {
		if (cxld->interleave_ways != iw ||
		    (iw > 1 && cxld->interleave_granularity != ig) ||
		    !spa_maps_hpa(p, &cxld->hpa_range) ||
		    ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) {
			...
			return -ENXIO;
		}
	}
}

When cxl_region_setup_targets() then descends to a downstream interleaving
switch port (for example, a 3-way root at 2 * IGB -> 1-way host bridge ->
2-way switch at IGB), the non-root branch of cxl_port_parent_interleave()
reads parent_ig = parent_cxld->interleave_granularity directly from that
passthrough host bridge decoder.  cxl_port_calc_interleave() then divides
that raw passthrough granularity by iw instead of using the granularity
from the nearest upstream interleaving decoder, causing auto-region
assembly to fail with -ENXIO.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1794000806.git.alison.schofield@intel.com?part=3

  reply	other threads:[~2026-11-06 22:22 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 21:57 [PATCH v7 0/5] CXL: Support region granularities finer than the root Alison Schofield
2026-11-06 21:57 ` [PATCH v7 1/5] Documentation/cxl: Describe region granularity " Alison Schofield
2026-11-06 21:57 ` [PATCH v7 2/5] cxl/region: Generalize endpoint position mapping Alison Schofield
2026-11-06 21:57 ` [PATCH v7 3/5] cxl/region: Support auto region granularity finer than the root Alison Schofield
2026-11-06 22:22   ` sashiko-bot [this message]
2026-11-07  0:59     ` Alison Schofield
2026-11-06 21:57 ` [PATCH v7 4/5] cxl/region: Support user " Alison Schofield
2026-11-06 21:57 ` [PATCH v7 5/5] cxl/test: Add a topology for " Alison Schofield

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-202327@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alison.schofield@intel.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.