From: Dave Jiang <dave.jiang@intel.com>
To: Davidlohr Bueso <dave@stgolabs.net>
Cc: jic23@kernel.org, alison.schofield@intel.com, icheng@nvidia.com,
benjamin.cheatham@amd.com, alucerop@amd.com,
dongjoo.seo1@samsung.com, linux-cxl@vger.kernel.org
Subject: Re: [PATCH v7 4/8] cxl: Add HDM-DB region creation
Date: Tue, 4 Aug 2026 15:28:03 -0700 [thread overview]
Message-ID: <30e839e7-20b7-4d68-8fb7-bf6ee333c2b5@intel.com> (raw)
In-Reply-To: <20260728144136.709882-5-dave@stgolabs.net>
On 7/28/26 7:41 AM, Davidlohr Bueso wrote:
> A region inherits its coherency from the chosen root decoder: HDM-DB
> if the root has CXL_DECODER_F_BI, otherwise HDM-H.
>
> Surface the topology through read-only sysfs:
>
> - decoderX.Y/cap_bi (root): CFMWS BI restriction.
> - decoderX.Y/bi (endpoint): '1' when configured for HDM-DB.
>
> cxl_region_attach() rejects endpoints whose device or HDM cannot
> serve the region's type; target_type is inherited from cxlr->type
> in cxl_rr_assign_decoder() and restored to the endpoint default on
> detach and on a failed attach.
>
> The HDM Decoder Control BI bit is set at commit time only when the
> target_type is DEVMEM and the BI capability is advertised
> (cxlds->bi for endpoints, root F_BI for switches).
>
> Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> ---
> Documentation/ABI/testing/sysfs-bus-cxl | 18 ++++++--
> drivers/cxl/acpi.c | 15 +++++++
> drivers/cxl/core/hdm.c | 23 ++++++++++
> drivers/cxl/core/port.c | 39 +++++++++++++++--
> drivers/cxl/core/region.c | 57 +++++++++++++++++++------
> drivers/cxl/cxl.h | 5 +++
> 6 files changed, 136 insertions(+), 21 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl
> index 16a9b3d2e2c0..370c6fd7d245 100644
> --- a/Documentation/ABI/testing/sysfs-bus-cxl
> +++ b/Documentation/ABI/testing/sysfs-bus-cxl
> @@ -297,7 +297,7 @@ Description:
> Each entry in the list is a dport id.
>
>
> -What: /sys/bus/cxl/devices/decoderX.Y/cap_{pmem,ram,type2,type3}
> +What: /sys/bus/cxl/devices/decoderX.Y/cap_{pmem,ram,type2,type3,bi}
> Date: June, 2021
> KernelVersion: v5.14
> Contact: linux-cxl@vger.kernel.org
> @@ -306,8 +306,9 @@ Description:
> represents a fixed memory window identified by platform
> firmware. A fixed window may only support a subset of memory
> types. The 'cap_*' attributes indicate whether persistent
> - memory, volatile memory, accelerator memory, and / or expander
> - memory may be mapped behind this decoder's memory window.
> + memory, volatile memory, accelerator memory, expander memory,
> + and / or back-invalidate (HDM-DB) memory may be mapped behind
> + this decoder's memory window.
>
>
> What: /sys/bus/cxl/devices/decoderX.Y/target_type
> @@ -426,6 +427,17 @@ Description:
> current cached value.
>
>
> +What: /sys/bus/cxl/devices/decoderX.Y/bi
> +Date: July, 2026
> +KernelVersion: v7.3
> +Contact: linux-cxl@vger.kernel.org
> +Description:
> + (RO) Shows '1' if this endpoint decoder is currently configured
> + for HDM-DB (device-managed coherency with back-invalidate).
> + The HDM-DB state is inherited from the region the decoder is
> + attached to, which is in turn set from the chosen root
> + decoder's CFMWS BI restriction (see cap_bi).
> +
> What: /sys/bus/cxl/devices/decoderX.Y/delete_region
> Date: May, 2022
> KernelVersion: v6.0
> diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
> index 3b818adbd38b..eceb8dd97df2 100644
> --- a/drivers/cxl/acpi.c
> +++ b/drivers/cxl/acpi.c
> @@ -152,6 +152,8 @@ static unsigned long cfmws_to_decoder_flags(int restrictions)
> flags |= CXL_DECODER_F_PMEM;
> if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_FIXED)
> flags |= CXL_DECODER_F_LOCK;
> + if (restrictions & ACPI_CEDT_CFMWS_RESTRICT_BI)
> + flags |= CXL_DECODER_F_BI;
>
> return flags;
> }
> @@ -198,6 +200,12 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
> dev_dbg(dev, "CFMWS length %d greater than expected %d\n",
> cfmws->header.length, expected_len);
>
> + if ((cfmws->restrictions & ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM) &&
> + (cfmws->restrictions & ACPI_CEDT_CFMWS_RESTRICT_BI)) {
> + dev_err(dev, "CFMWS cannot have both HDM-H and HDM-DB\n");
> + return -EINVAL;
> + }
> +
> return 0;
> }
>
> @@ -437,7 +445,14 @@ static int __cxl_parse_cfmws(struct acpi_cedt_cfmws *cfmws,
>
> cxld = &cxlrd->cxlsd.cxld;
> cxld->flags = cfmws_to_decoder_flags(cfmws->restrictions);
> + /* host-only wins if firmware sets both coherency restrictions */
> cxld->target_type = CXL_DECODER_HOSTONLYMEM;
> + if (cxld->flags & CXL_DECODER_F_TYPE2) {
> + if (cxld->flags & CXL_DECODER_F_TYPE3)
> + dev_dbg(dev, "CFMWS has both HDM-H and HDM-D\n");
> + else
> + cxld->target_type = CXL_DECODER_DEVMEM;
> + }
> cxld->hpa_range = (struct range) {
> .start = cfmws->base_hpa,
> .end = cfmws->base_hpa + cfmws->window_size - 1,
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 9da8aa211609..f437fe15c6df 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -705,9 +705,25 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl)
>
> static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
> {
> + bool bi = cxld->target_type == CXL_DECODER_DEVMEM;
> +
> + if (bi) {
> + if (is_endpoint_decoder(&cxld->dev)) {
> + struct cxl_endpoint_decoder *cxled =
> + to_cxl_endpoint_decoder(&cxld->dev);
> + struct cxl_dev_state *cxlds =
> + cxled_to_memdev(cxled)->cxlds;
> +
> + bi = cxlds->bi;
> + } else if (cxld->region) {
> + bi = cxl_root_decoder_is_bi(cxld->region->cxlrd);
> + }
> + }
> +
> u32p_replace_bits(ctrl,
> !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
> CXL_HDM_DECODER0_CTRL_HOSTONLY);
> + u32p_replace_bits(ctrl, bi, CXL_HDM_DECODER0_CTRL_BI);
> }
>
> static void cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
> @@ -970,6 +986,13 @@ static int cxl_setup_hdm_decoder_from_dvsec(
> return 0;
> }
>
> +/*
> + * HDMs that advertise support for both coherency modes
> + * (CXL_HDM_DECODER_COHERENCY_BOTH) default to host-only; the region
> + * attach path switches target_type to device-coherent if the region's
> + * root decoder has the CFMWS BI bit set. Only HDMs that strictly
> + * support device-coherent mode default to HDM-DB.
> + */
> enum cxl_decoder_type cxled_default_type(struct cxl_endpoint_decoder *cxled)
> {
> struct cxl_dev_state *cxlds = cxled_to_memdev(cxled)->cxlds;
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index 7817109026b1..2dbd8c24f968 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -131,6 +131,7 @@ CXL_DECODER_FLAG_ATTR(cap_ram, CXL_DECODER_F_RAM);
> CXL_DECODER_FLAG_ATTR(cap_type2, CXL_DECODER_F_TYPE2);
> CXL_DECODER_FLAG_ATTR(cap_type3, CXL_DECODER_F_TYPE3);
> CXL_DECODER_FLAG_ATTR(locked, CXL_DECODER_F_LOCK);
> +CXL_DECODER_FLAG_ATTR(cap_bi, CXL_DECODER_F_BI);
>
> static ssize_t target_type_show(struct device *dev,
> struct device_attribute *attr, char *buf)
> @@ -233,6 +234,26 @@ static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
> }
> static DEVICE_ATTR_RW(mode);
>
> +static ssize_t bi_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
> + struct cxl_dev_state *cxlds = cxled_to_memdev(cxled)->cxlds;
> + struct cxl_region *cxlr;
> +
> + guard(rwsem_read)(&cxl_rwsem.region);
> + /*
> + * An endpoint decoder is HDM-DB when the device advertises BI
> + * (cxlds->bi) and it is attached to a device-coherent (DEVMEM)
> + * region whose root decoder advertises the CFMWS BI restriction.
> + */
> + cxlr = cxled->cxld.region;
> + return sysfs_emit(buf, "%d\n", cxlds->bi && cxlr &&
> + cxled->cxld.target_type == CXL_DECODER_DEVMEM &&
> + cxl_root_decoder_is_bi(cxlr->cxlrd));
> +}
> +static DEVICE_ATTR_RO(bi);
> +
> static ssize_t dpa_resource_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> @@ -329,6 +350,7 @@ static struct attribute *cxl_decoder_root_attrs[] = {
> &dev_attr_cap_ram.attr,
> &dev_attr_cap_type2.attr,
> &dev_attr_cap_type3.attr,
> + &dev_attr_cap_bi.attr,
> &dev_attr_target_list.attr,
> &dev_attr_qos_class.attr,
> SET_CXL_REGION_ATTR(create_pmem_region)
> @@ -339,16 +361,24 @@ static struct attribute *cxl_decoder_root_attrs[] = {
>
> static bool can_create_pmem(struct cxl_root_decoder *cxlrd)
> {
> - unsigned long flags = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_PMEM;
> + unsigned long flags = cxlrd->cxlsd.cxld.flags;
> + unsigned long hdm_h, hdm_db;
>
> - return (cxlrd->cxlsd.cxld.flags & flags) == flags;
> + hdm_h = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_PMEM;
> + hdm_db = CXL_DECODER_F_TYPE2 | CXL_DECODER_F_BI | CXL_DECODER_F_PMEM;
> +
> + return (flags & hdm_h) == hdm_h || (flags & hdm_db) == hdm_db;
> }
>
> static bool can_create_ram(struct cxl_root_decoder *cxlrd)
> {
> - unsigned long flags = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_RAM;
> + unsigned long flags = cxlrd->cxlsd.cxld.flags;
> + unsigned long hdm_h, hdm_db;
> +
> + hdm_h = CXL_DECODER_F_TYPE3 | CXL_DECODER_F_RAM;
> + hdm_db = CXL_DECODER_F_TYPE2 | CXL_DECODER_F_BI | CXL_DECODER_F_RAM;
>
> - return (cxlrd->cxlsd.cxld.flags & flags) == flags;
> + return (flags & hdm_h) == hdm_h || (flags & hdm_db) == hdm_db;
> }
>
> static umode_t cxl_root_decoder_visible(struct kobject *kobj, struct attribute *a, int n)
> @@ -402,6 +432,7 @@ static const struct attribute_group *cxl_decoder_switch_attribute_groups[] = {
> static struct attribute *cxl_decoder_endpoint_attrs[] = {
> &dev_attr_target_type.attr,
> &dev_attr_mode.attr,
> + &dev_attr_bi.attr,
> &dev_attr_dpa_size.attr,
> &dev_attr_dpa_resource.attr,
> SET_CXL_REGION_ATTR(region)
> diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> index 1e211542b6b6..840acc330ede 100644
> --- a/drivers/cxl/core/region.c
> +++ b/drivers/cxl/core/region.c
> @@ -1130,16 +1130,11 @@ static int cxl_rr_assign_decoder(struct cxl_port *port, struct cxl_region *cxlr,
> }
>
> /*
> - * Endpoints should already match the region type, but backstop that
> - * assumption with an assertion. Switch-decoders change mapping-type
> - * based on what is mapped when they are assigned to a region.
> + * Endpoint decoders inherit their type from cxlr->type; broken
> + * pairings were already rejected by the coherency checks in
> + * cxl_region_attach(). Switch-decoders change mapping-type based
> + * on what is mapped when they are assigned to a region.
> */
> - dev_WARN_ONCE(&cxlr->dev,
> - port == cxled_to_port(cxled) &&
> - cxld->target_type != cxlr->type,
> - "%s:%s mismatch decoder type %d -> %d\n",
> - dev_name(&cxled_to_memdev(cxled)->dev),
> - dev_name(&cxld->dev), cxld->target_type, cxlr->type);
> cxld->target_type = cxlr->type;
> cxl_rr->decoder = cxld;
> return 0;
> @@ -1827,6 +1822,8 @@ static int cxl_region_attach_position(struct cxl_region *cxlr,
> for (iter = cxled_to_port(cxled); !is_cxl_root(iter);
> iter = to_cxl_port(iter->dev.parent))
> cxl_port_detach_region(iter, cxlr, cxled);
> + /* undo cxl_rr_assign_decoder() type inheritance */
> + cxled->cxld.target_type = cxled_default_type(cxled);
> return rc;
> }
>
> @@ -2059,6 +2056,7 @@ static int cxl_region_attach(struct cxl_region *cxlr,
> struct cxl_region_params *p = &cxlr->params;
> struct cxl_port *ep_port, *root_port;
> struct cxl_dport *dport;
> + struct cxl_hdm *cxlhdm;
> int rc = -ENXIO;
>
> rc = check_interleave_cap(&cxled->cxld, p->interleave_ways,
> @@ -2108,10 +2106,31 @@ static int cxl_region_attach(struct cxl_region *cxlr,
> return -ENXIO;
> }
>
> - if (cxled->cxld.target_type != cxlr->type) {
> - dev_dbg(&cxlr->dev, "%s:%s type mismatch: %d vs %d\n",
> - dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
> - cxled->cxld.target_type, cxlr->type);
> + /*
> + * Verify the device and HDM are capable of the region's flavor before
> + * proceeding. The endpoint decoder's target_type is then inherited
> + * from cxlr->type later in cxl_rr_assign_decoder().
> + */
> + if (cxlr->type == CXL_DECODER_DEVMEM &&
> + cxl_root_decoder_is_bi(cxlrd) && !cxlds->bi) {
> + dev_err(&cxlr->dev, "%s:%s BI not enabled on device\n",
> + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
> + return -ENXIO;
> + }
> +
> + cxlhdm = dev_get_drvdata(&ep_port->dev);
> + if (!cxlhdm)
> + return -ENXIO;
> + if (cxlr->type == CXL_DECODER_HOSTONLYMEM &&
> + cxlhdm->supported_coherency == CXL_HDM_DECODER_COHERENCY_DEV) {
> + dev_warn(&cxlr->dev, "%s:%s HDM is device-coherent only\n",
> + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
> + return -ENXIO;
> + }
> + if (cxlr->type == CXL_DECODER_DEVMEM &&
> + cxlhdm->supported_coherency == CXL_HDM_DECODER_COHERENCY_HOST) {
> + dev_warn(&cxlr->dev, "%s:%s HDM is host-only coherent\n",
> + dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
> return -ENXIO;
> }
>
> @@ -2327,6 +2346,8 @@ __cxl_decoder_detach(struct cxl_region *cxlr,
> .start = 0,
> .end = -1,
> };
> + /* undo cxl_rr_assign_decoder() type inheritance */
> + cxled->cxld.target_type = cxled_default_type(cxled);
>
> get_device(&cxlr->dev);
> return cxlr;
> @@ -2823,6 +2844,7 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
> size_t len, enum cxl_partition_mode mode)
> {
> struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
> + enum cxl_decoder_type target_type;
> struct cxl_region *cxlr;
> int rc, id;
>
> @@ -2834,7 +2856,14 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
> if ((rc = ACQUIRE_ERR(mutex_intr, ®ions_lock)))
> return rc;
>
> - cxlr = __create_region(cxlrd, mode, id, CXL_DECODER_HOSTONLYMEM);
> + /*
> + * The CFMWS dictates endpoint coherency: a BI-restricted Window
> + * produces an HDM-DB region; otherwise HDM-H.
> + */
> + target_type = cxl_root_decoder_is_bi(cxlrd) ?
> + CXL_DECODER_DEVMEM : CXL_DECODER_HOSTONLYMEM;
> +
> + cxlr = __create_region(cxlrd, mode, id, target_type);
> if (IS_ERR(cxlr))
> return PTR_ERR(cxlr);
>
> diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
> index c323c38d0da2..ec2203561446 100644
> --- a/drivers/cxl/cxl.h
> +++ b/drivers/cxl/cxl.h
> @@ -300,6 +300,7 @@ int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport);
> #define CXL_DECODER_F_LOCK BIT(4)
> #define CXL_DECODER_F_ENABLE BIT(5)
> #define CXL_DECODER_F_NORMALIZED_ADDRESSING BIT(6)
> +#define CXL_DECODER_F_BI BIT(7)
> #define CXL_DECODER_F_RESET_MASK (CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK)
>
> enum cxl_decoder_type {
> @@ -826,6 +827,10 @@ static inline int cxl_root_decoder_autoremove(struct device *host,
> {
> return cxl_decoder_autoremove(host, &cxlrd->cxlsd.cxld);
> }
> +static inline bool cxl_root_decoder_is_bi(struct cxl_root_decoder *cxlrd)
> +{
> + return cxlrd->cxlsd.cxld.flags & CXL_DECODER_F_BI;
> +}
> int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint);
>
> /**
next prev parent reply other threads:[~2026-08-04 22:28 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 14:41 [PATCH v7 0/8] cxl: Support Back-Invalidate Davidlohr Bueso
2026-07-28 14:41 ` [PATCH v7 1/8] cxl: Add BI register probing and port initialization Davidlohr Bueso
2026-08-04 21:13 ` Dave Jiang
2026-08-05 0:42 ` Alison Schofield
2026-08-05 10:41 ` Li Ming
2026-08-07 5:38 ` Richard Cheng
2026-07-28 14:41 ` [PATCH v7 2/8] cxl/pci: Add BI topology enable/disable Davidlohr Bueso
2026-07-28 15:16 ` sashiko-bot
2026-08-03 18:55 ` Davidlohr Bueso
2026-08-05 12:49 ` Li Ming
2026-08-05 13:33 ` Li Ming
2026-08-07 6:54 ` Richard Cheng
2026-07-28 14:41 ` [PATCH v7 3/8] cxl/hdm: Add BI coherency support for endpoint decoders Davidlohr Bueso
2026-07-28 15:26 ` sashiko-bot
2026-07-28 18:44 ` Davidlohr Bueso
2026-07-28 14:41 ` [PATCH v7 4/8] cxl: Add HDM-DB region creation Davidlohr Bueso
2026-08-04 22:28 ` Dave Jiang [this message]
2026-08-05 0:11 ` Alison Schofield
2026-08-05 19:10 ` Davidlohr Bueso
2026-08-07 11:50 ` Richard Cheng
2026-07-28 14:41 ` [PATCH v7 5/8] cxl/hdm: Rename decoder coherency flags Davidlohr Bueso
2026-08-05 1:13 ` Alison Schofield
2026-07-28 14:41 ` [PATCH v7 6/8] cxl/region: Log the coherency model at region creation Davidlohr Bueso
2026-08-04 22:51 ` Dave Jiang
2026-07-28 14:41 ` [PATCH v7 7/8] cxl/pci: Split BI capability probe from setup Davidlohr Bueso
2026-08-04 23:07 ` Dave Jiang
2026-07-28 14:41 ` [PATCH v7 8/8] cxl: Allow auto-committed BI hdm decoders Davidlohr Bueso
2026-07-28 15:46 ` sashiko-bot
2026-08-03 19:04 ` Davidlohr Bueso
2026-08-04 23:22 ` Dave Jiang
2026-08-05 0:51 ` Alison Schofield
2026-08-05 20:53 ` Davidlohr Bueso
2026-08-07 12:03 ` Richard Cheng
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=30e839e7-20b7-4d68-8fb7-bf6ee333c2b5@intel.com \
--to=dave.jiang@intel.com \
--cc=alison.schofield@intel.com \
--cc=alucerop@amd.com \
--cc=benjamin.cheatham@amd.com \
--cc=dave@stgolabs.net \
--cc=dongjoo.seo1@samsung.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox