All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Ming <ming.li@zohomail.com>
To: Davidlohr Bueso <dave@stgolabs.net>, dave.jiang@intel.com
Cc: jic23@kernel.org, alison.schofield@intel.com, icheng@nvidia.com,
	benjamin.cheatham@amd.com, alucerop@amd.com,
	linux-cxl@vger.kernel.org
Subject: Re: [PATCH v8 08/10] cxl: Allow auto-committed BI hdm decoders
Date: Thu, 10 Sep 2026 19:38:03 +0800	[thread overview]
Message-ID: <642c16ad-e46a-4232-bba1-35a56bcff7b5@zohomail.com> (raw)
In-Reply-To: <20260909170302.1550680-9-dave@stgolabs.net>


在 2026/9/10 01:03, Davidlohr Bueso 写道:
> Allow auto-committed BI hdm decoders on sane platforms, rejecting
> only broken paths (ie: one that cannot route BISnp, or BI paired
> with a host-only target range type).
>
> The respective region creation is done like any other committed
> decoder - with cxlds->bi set by the time an decoder attaches.
>
> Skipping the commit does not weaken the rule stated in "cxl/pci: Add
> BI topology enable/disable". Table 8-152 and Table 8-156 key it on a
> new BI device being enabled anywhere below the port, and a level
> firmware already brought up for this device is not seeing one.
>
> Whether it did is a property of the path, not of the dport: a level's
> committed state only proves firmware committed for some device below
> it, which need not be this one. So adoption starts from the
> endpoint's own BI Enable - only a device firmware itself enabled can
> have had its BI-ID accounted for above - and a level is then taken
> as found when nothing this driver routed sits below it, the control
> value this driver would write is the one already there, the decoder
> is committed, and the switch's route table - which carries a commit
> of its own that firmware may not have performed - is committed too.
> The first level that falls short ends it: from there up the driver
> is enabling something new, and programs and commits as for any
> other device.
>
> A committed decoder is refused when the window's restrictions do not
> permit its coherency model, on either axis: a BI decoder under a
> window without the BI restriction, or a host-only or device-coherent
> decoder under a window exposing only the other model (undefined
> behavior per the CFMWS Window Restrictions). Assembly so far never
> consulted the type bits, so a platform that sets them wrongly loses
> auto-assembly of the affected decoders, with the refusal naming the
> window.
>
> A committed decoder cannot inherit a region's coherency model the way
> a decoder this driver programs does, so the type-mismatch refusal
> that "cxl: Add HDM-DB region creation" removed from
> cxl_region_attach() in favor of inheritance returns there for
> committed decoders, on both axes: the committed Target Range Type,
> kept as the decoder's target_type since enumeration, must match the
> region's, and the committed BI bit, read back from the decoder since
> the driver keeps no copy of it, must match the root's. The refusal
> names both models.
>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
> ---
>   drivers/cxl/core/hdm.c    | 27 +++++++++-----
>   drivers/cxl/core/pci.c    | 75 ++++++++++++++++++++++++++++++++-------
>   drivers/cxl/core/region.c | 48 +++++++++++++++++++++++++
>   3 files changed, 130 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 35bd308156af..595fe8c99821 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -1049,13 +1049,23 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
>   		else
>   			cxld->target_type = CXL_DECODER_DEVMEM;
>   
> -		/*
> -		 * Autocommit BI-enabled decoders is not supported.
> -		 * At this point cxlds->bi is not yet setup, so there
> -		 * are no guarantees that the platform supports BI.
> -		 */
> -		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl))
> -			return -ENXIO;
> +		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl)) {
> +			struct cxl_dev_state *cxlds = cxled ?
> +				cxled_to_memdev(cxled)->cxlds : NULL;
> +
> +			if (cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
> +				dev_warn(&port->dev,
> +					 "decoder%d.%d: BI with host-only\n",
> +					 port->id, cxld->id);
> +				return -ENXIO;
> +			}
> +			if (cxlds && !cxlds->bi_capable) {
> +				dev_warn(&port->dev,
> +					 "decoder%d.%d: path not BI capable\n",
> +					 port->id, cxld->id);
> +				return -ENXIO;
> +			}
> +		}
>   
>   		guard(rwsem_write)(&cxl_rwsem.region);
>   		if (cxld->id != cxl_num_decoders_committed(port)) {
> @@ -1302,7 +1312,8 @@ int devm_cxl_endpoint_decoders_setup(struct cxl_port *port)
>   	 * Between the port's HDM state and its decoders: devres,
>   	 * unwinding in reverse, brings BI down only after the decoders
>   	 * quiesce, while its slow walk still precedes the HDM state
> -	 * free.
> +	 * free. Must also precede region discovery, where HDM-DB
> +	 * assembly requires cxlds->bi.
>   	 */
>   	rc = cxl_bi_setup(port);
>   	if (rc)
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index 95064be6faad..c5f3d9178513 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -1085,6 +1085,29 @@ static int __cxl_bi_commit_decoder(struct device *dev, void __iomem *bi)
>   				    scale, base);
>   }
>   
> +/* Committed, or no explicit commit required */
> +static bool cxl_bi_decoder_committed(void __iomem *bi)
> +{
> +	u32 caps = readl(bi + CXL_BI_DECODER_CAPS_OFFSET);
> +	u32 sts = readl(bi + CXL_BI_DECODER_STATUS_OFFSET);
> +
> +	if (!FIELD_GET(CXL_BI_DECODER_CAPS_EXPLICIT_COMMIT_REQ, caps))
> +		return true;
> +
> +	return FIELD_GET(CXL_BI_DECODER_STATUS_BI_COMMITTED, sts);
> +}
> +
> +static bool cxl_bi_rt_committed(void __iomem *bi)
> +{
> +	u32 caps = readl(bi + CXL_BI_RT_CAPS_OFFSET);
> +	u32 sts = readl(bi + CXL_BI_RT_STATUS_OFFSET);
> +
> +	if (!FIELD_GET(CXL_BI_RT_CAPS_EXPLICIT_COMMIT_REQ, caps))
> +		return true;
> +
> +	return FIELD_GET(CXL_BI_RT_STATUS_BI_COMMITTED, sts);
> +}
> +
>   static int cxl_bi_commit_dport(struct cxl_dport *dport)
>   {
>   	struct cxl_port *port = dport->port;
> @@ -1108,7 +1131,7 @@ static int cxl_bi_commit_dport(struct cxl_dport *dport)
>    * below it.
>    */
>   static int __cxl_bi_ctrl_dport(struct cxl_dport *dport, bool enable,
> -			       bool direct)
> +			       bool direct, bool *adopt)
>   {
>   	void __iomem *bi = dport->regs.bi_decoder;
>   	struct cxl_port *port = dport->port;
> @@ -1140,6 +1163,20 @@ static int __cxl_bi_ctrl_dport(struct cxl_dport *dport, bool enable,
>   		       CXL_BI_DECODER_CTRL_BI_ENABLE;
>   
>   	value = (ctrl | set) & ~clr;
> +
> +	/*
> +	 * Adopt this level as firmware left it: nothing below it that
> +	 * firmware did not account for, nothing this driver has routed
> +	 * through it, the value this walk would write already in place,
> +	 * and the decoder (and route table) committed.
> +	 */
> +	if (*adopt && !dport->nr_bi && value == ctrl &&
> +	    cxl_bi_decoder_committed(bi) &&
> +	    (!port->regs.bi_rt || cxl_bi_rt_committed(port->regs.bi_rt)))
> +		goto done;

May I know why needs to check dport->nr_bi here?

Assume all BI capabilities have been set up by firmware in two 
bi-capable EPs under a switch case.

After the first EP setup, the root_port->nr_bi is 1. Seems like the BI 
capability of the root port will be considered that is not configured by 
firmware during the second EP BI setup?

> +	/* firmware did not bring this level up, so nothing above may */
> +	*adopt = false;
> +
>   	if (value != ctrl)
>   		writel(value, bi + CXL_BI_DECODER_CTRL_OFFSET);
>   
> @@ -1153,19 +1190,21 @@ static int __cxl_bi_ctrl_dport(struct cxl_dport *dport, bool enable,
>   		}
>   		return rc;
>   	}
> +done:
>   	dport->nr_bi++;
>   
>   	return 0;
>   }
>   
> -static int cxl_bi_ctrl_dport_enable(struct cxl_dport *dport, bool direct)
> +static int cxl_bi_ctrl_dport_enable(struct cxl_dport *dport, bool direct,
> +				    bool *adopt)
>   {
> -	return __cxl_bi_ctrl_dport(dport, true, direct);
> +	return __cxl_bi_ctrl_dport(dport, true, direct, adopt);
>   }
>   
>   static int cxl_bi_ctrl_dport_disable(struct cxl_dport *dport)
>   {
> -	return __cxl_bi_ctrl_dport(dport, false, false);
> +	return __cxl_bi_ctrl_dport(dport, false, false, NULL);
>   }
>   
>   static int __cxl_bi_ctrl_endpoint(struct cxl_dev_state *cxlds, bool enable)
> @@ -1181,11 +1220,11 @@ static int __cxl_bi_ctrl_endpoint(struct cxl_dev_state *cxlds, bool enable)
>   
>   	if (enable) {
>   		if (FIELD_GET(CXL_BI_DECODER_CTRL_BI_ENABLE, ctrl)) {
> -			if (cxlds->bi)
> -				return 0;
> -			dev_err(cxlds->dev,
> -				"BI already enabled in hardware\n");
> -			return -EBUSY;
> +			/* adopt firmware enabled */
> +			if (!cxlds->bi)
> +				dev_dbg(cxlds->dev,
> +					"adopting firmware-enabled BI\n");
> +			goto done;
>   		}
>   		val = ctrl | CXL_BI_DECODER_CTRL_BI_ENABLE;
>   	} else {
> @@ -1200,11 +1239,11 @@ static int __cxl_bi_ctrl_endpoint(struct cxl_dev_state *cxlds, bool enable)
>   	}
>   
>   	writel(val, bi + CXL_BI_DECODER_CTRL_OFFSET);
> -	cxlds->bi = enable;
>   
>   	dev_dbg(cxlds->dev, "BI requests %s\n",
>   		str_enabled_disabled(enable));
> -
> +done:
> +	cxlds->bi = enable;
>   	return 0;
>   }
>   
> @@ -1262,14 +1301,26 @@ static void cxl_bi_dealloc(void *data)
>   static int cxl_bi_enable_path(struct cxl_dev_state *cxlds,
>   			      struct cxl_port *port, struct cxl_dport *dport)
>   {
> +	struct cxl_port *endpoint = cxlds->cxlmd->endpoint;
>   	struct cxl_dport *dport_iter, *failed;
>   	struct cxl_port *port_iter;
> +	bool adopt;
>   	int rc;
>   
> +	/*
> +	 * Adoption is a path property, not a per-dport one: only when
> +	 * firmware enabled the device itself does a dport's committed
> +	 * state cover this device's BI-ID.
> +	 */
> +	adopt = FIELD_GET(CXL_BI_DECODER_CTRL_BI_ENABLE,
> +			  readl(endpoint->regs.bi_decoder +
> +				CXL_BI_DECODER_CTRL_OFFSET));
> +
>   	port_iter = port;
>   	dport_iter = dport;
>   	while (!is_cxl_root(port_iter)) {
> -		rc = cxl_bi_ctrl_dport_enable(dport_iter, dport_iter == dport);
> +		rc = cxl_bi_ctrl_dport_enable(dport_iter, dport_iter == dport,
> +					      &adopt);
>   		if (rc)
>   			goto err_rollback;
>   
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 9874be7732d4..a9dcaff47a72 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -1843,6 +1843,20 @@ static int cxl_region_attach_position(struct cxl_region *cxlr,
>   	return rc;
>   }
>   
> +static bool cxled_committed_bi(struct cxl_endpoint_decoder *cxled)
> +{
> +	struct cxl_port *port = cxled_to_port(cxled);
> +	struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
> +	u32 ctrl;
> +
> +	if (!cxlhdm || !cxlhdm->regs.hdm_decoder)
> +		return false;
> +
> +	ctrl = readl(cxlhdm->regs.hdm_decoder +
> +		     CXL_HDM_DECODER0_CTRL_OFFSET(cxled->cxld.id));
> +	return FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl);
> +}
> +
>   static const char *cxl_coherency_name(enum cxl_decoder_type type, bool bi)
>   {
>   	if (type == CXL_DECODER_HOSTONLYMEM)
> @@ -2153,6 +2167,24 @@ static int cxl_region_attach(struct cxl_region *cxlr,
>   		return -ENXIO;
>   	}
>   
> +	/* a committed decoder cannot inherit the region's flavor */
> +	if (cxled->state == CXL_DECODER_STATE_AUTO) {
> +		bool bi = cxled_committed_bi(cxled);
> +		const char *have, *want;
> +
> +		have = cxl_coherency_name(cxled->cxld.target_type, bi);
> +		want = cxl_coherency_name(cxlr->type,
> +					  cxl_root_decoder_is_bi(cxlrd));
> +		if (cxled->cxld.target_type != cxlr->type ||
> +		    bi != cxl_root_decoder_is_bi(cxlrd)) {
> +			dev_err(&cxlr->dev,
> +				"%s:%s coherency model mismatch: %s vs %s\n",
> +				dev_name(&cxlmd->dev),
> +				dev_name(&cxled->cxld.dev), have, want);
> +			return -ENXIO;
> +		}
> +	}
> +
>   	if (!cxled->dpa_res) {
>   		dev_dbg(&cxlr->dev, "%s:%s: missing DPA allocation.\n",
>   			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
> @@ -3812,10 +3844,26 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
>   	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>   	int rc, part = READ_ONCE(cxled->part);
>   	struct cxl_region *cxlr;
> +	unsigned long need;
>   
>   	if (part < 0)
>   		return ERR_PTR(-EBUSY);
>   
> +	/*
> +	 * A committed decoder defines the region built from it, so no
> +	 * attach check can find its coherency model wrong. Only the
> +	 * window's restrictions can, on the BI and range type axes.
> +	 */
> +	need = cxled->cxld.target_type == CXL_DECODER_DEVMEM ?
> +	       CXL_DECODER_F_DEVMEM : CXL_DECODER_F_HOSTONLY;
> +	if (cxled_committed_bi(cxled) != cxl_root_decoder_is_bi(cxlrd) ||
> +	    !(cxlrd->cxlsd.cxld.flags & need)) {
> +		dev_err(&cxlrd->cxlsd.cxld.dev,
> +			"%s:%s coherency model not permitted by the window\n",
> +			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
> +		return ERR_PTR(-ENXIO);
> +	}
> +
>   	do {
>   		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
>   				       atomic_read(&cxlrd->region_id),

  parent reply	other threads:[~2026-09-10 11:38 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09 17:02 [PATCH v8 0/10] cxl: Support Back-Invalidate Davidlohr Bueso
2026-09-09 17:02 ` [PATCH v8 01/10] cxl: Add BI register probing and port initialization Davidlohr Bueso
2026-09-09 19:38   ` Jonathan Cameron
2026-09-09 17:02 ` [PATCH v8 02/10] cxl/pci: Add BI topology enable/disable Davidlohr Bueso
2026-09-09 21:21   ` Jonathan Cameron
2026-09-10  1:33     ` Davidlohr Bueso
2026-09-10  2:40   ` Li Ming
2026-09-09 17:02 ` [PATCH v8 03/10] cxl/hdm: Add BI coherency support for endpoint decoders Davidlohr Bueso
2026-09-09 21:27   ` Jonathan Cameron
2026-09-09 17:02 ` [PATCH v8 04/10] cxl: Add HDM-DB region creation Davidlohr Bueso
2026-09-09 17:48   ` sashiko-bot
2026-09-09 21:31   ` Jonathan Cameron
2026-09-09 17:02 ` [PATCH v8 05/10] cxl/hdm: Rename decoder coherency flags Davidlohr Bueso
2026-09-09 21:32   ` Jonathan Cameron
2026-09-09 17:02 ` [PATCH v8 06/10] cxl/region: Log the coherency model at region creation Davidlohr Bueso
2026-09-09 21:32   ` Jonathan Cameron
2026-09-09 17:02 ` [PATCH v8 07/10] cxl/pci: Split BI capability probe from setup Davidlohr Bueso
2026-09-09 21:40   ` Jonathan Cameron
2026-09-09 21:45     ` Davidlohr Bueso
2026-09-09 17:03 ` [PATCH v8 08/10] cxl: Allow auto-committed BI hdm decoders Davidlohr Bueso
2026-09-09 21:45   ` Jonathan Cameron
2026-09-10 11:38   ` Li Ming [this message]
2026-09-09 17:03 ` [PATCH v8 09/10] cxl/test: Add mock BI topology support Davidlohr Bueso
2026-09-09 21:49   ` Jonathan Cameron
2026-09-09 22:08     ` Davidlohr Bueso
2026-09-09 17:03 ` [PATCH v8 10/10] cxl/doc: Update maturity map with BI support Davidlohr Bueso
2026-09-09 21:50   ` Jonathan Cameron
2026-09-09 18:47 ` [PATCH v8 0/10] cxl: Support Back-Invalidate Davidlohr Bueso

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=642c16ad-e46a-4232-bba1-35a56bcff7b5@zohomail.com \
    --to=ming.li@zohomail.com \
    --cc=alison.schofield@intel.com \
    --cc=alucerop@amd.com \
    --cc=benjamin.cheatham@amd.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=icheng@nvidia.com \
    --cc=jic23@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    /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.