From: Ankit Agrawal <ankita@nvidia.com>
To: <linux-cxl@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<linux-kernel@vger.kernel.org>
Cc: <dave@stgolabs.net>, <jic23@kernel.org>, <dave.jiang@intel.com>,
<alison.schofield@intel.com>, <vishal.l.verma@intel.com>,
<jgg@nvidia.com>, <aneesh.kumar@kernel.org>, <aik@amd.com>,
<yilun.xu@linux.intel.com>, <iweiny@kernel.org>,
<ming.li@zohomail.com>, <icheng@nvidia.com>,
<bhelgaas@google.com>, <smadhavan@nvidia.com>,
<ankita@nvidia.com>, <ilpo.jarvinen@linux.intel.com>,
<Smita.KoralahalliChannabasappa@amd.com>,
<andriy.shevchenko@linux.intel.com>, <linux-coco@lists.linux.dev>,
<terry.bowman@amd.com>, <nik.borisov@suse.com>,
<brads@mainlining.org>, <lukas@wunner.de>, <rrichter@amd.com>,
<gourry@gourry.net>
Subject: [RFC PATCH v2 2/5] PCI/CXL: Populate and insert/remove pdev->coh_resource[]
Date: Thu, 5 Nov 2026 15:29:06 +0000 [thread overview]
Message-ID: <20261105152909.53452-3-ankita@nvidia.com> (raw)
In-Reply-To: <20261105152909.53452-1-ankita@nvidia.com>
On systems with precommitted HDM decoders, the firmware programs
the decoders before any software runs. This range also stays constant
over the runs.
Snapshot precommitted CXL HDM decoder ranges into a new
pdev->coh_resource[] array, so later code has a known-good source for
a device coherent (CXL) windows without re-scanning decoder
registers.
Only decoders that are enabled and locked are recorded, since an
unlocked decoder can be reprogrammed and leave the snapshot stale.
Zero-sized decoders are skipped. Decoders found to use Normalized
Addressing (a DPA rather than an HPA) are dropped later, once the flag is
known in a follow-up patch.
Signed-off-by: Ankit Agrawal <ankita@nvidia.com>
---
drivers/cxl/core/resource.c | 60 ++++++++++++++++++++++++++++++++++++-
include/linux/pci.h | 14 +++++++++
2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/resource.c b/drivers/cxl/core/resource.c
index 3422139ae3ab..d837f8e952a9 100644
--- a/drivers/cxl/core/resource.c
+++ b/drivers/cxl/core/resource.c
@@ -404,6 +404,54 @@ static struct cxl_hdm_info *cxl_pci_hdm_read_info(struct pci_dev *pdev,
return ERR_PTR(pcibios_err_to_errno(rc));
}
+/*
+ * Snapshot committed decoders into pdev->coh_resource[] which is called
+ * once per pdev before any driver can bind, so a populated entry is
+ * always firmware-committed and not driver-committed.
+ *
+ * Insert each entry into iomem_resource for /proc/iomem visibility and
+ * conflict detection.
+ */
+static void cxl_populate_coh_resource(struct pci_dev *pdev,
+ struct cxl_hdm_info *info)
+{
+ int count = min(info->decoder_count, PCI_CXL_MAX_COHERENT_RANGES);
+
+ for (int i = 0; i < count; i++) {
+ struct cxl_decoder_config *config = &info->settings[i].config;
+ struct resource *res = &pdev->coh_resource[i];
+ struct resource *conflict;
+ u64 size = range_len(&config->hpa_range);
+
+ /*
+ * Only a decoder that is both enabled and locked has a fixed
+ * mapping that won't change under the snapshot. Also skip a
+ * zero-sized decoder, whose resource end would wrap.
+ */
+ if ((config->flags &
+ (CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK)) !=
+ (CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK) ||
+ !size)
+ continue;
+
+ *res = DEFINE_RES_NAMED_DESC(config->hpa_range.start, size,
+ "CXL coherent memory",
+ IORESOURCE_MEM, IORES_DESC_NONE);
+
+ conflict = insert_resource_conflict(&iomem_resource, res);
+ if (conflict) {
+ pci_warn(pdev,
+ "CXL coherent range: decoder%d %pR conflicts with %s %pR, leaving unpopulated\n",
+ i, res, conflict->name, conflict);
+ memset(res, 0, sizeof(*res));
+ continue;
+ }
+
+ pci_info(pdev, "CXL coherent range: decoder%d precommitted, populated %pR\n",
+ i, res);
+ }
+}
+
static int __pci_cxl_hdm_cache_init(struct pci_dev *pdev)
{
struct cxl_register_map map = { };
@@ -442,8 +490,10 @@ static int __pci_cxl_hdm_cache_init(struct pci_dev *pdev)
struct cxl_hdm_info *info __free(kfree) = read_info;
guard(rwsem_write)(&cxl_rwsem.dpa);
/* Another initializer may have published while we read MMIO. */
- if (!pdev->hdm)
+ if (!pdev->hdm) {
+ cxl_populate_coh_resource(pdev, info);
pdev->hdm = no_free_ptr(info);
+ }
return 0;
}
@@ -466,6 +516,14 @@ void pci_cxl_hdm_cache_release(struct pci_dev *pdev)
info = pdev->hdm;
/* Unpublish before freeing so subsequent readers cannot use stale state. */
pdev->hdm = NULL;
+
+ for (int i = 0; i < PCI_CXL_MAX_COHERENT_RANGES; i++) {
+ struct resource *res = &pdev->coh_resource[i];
+
+ if (res->parent)
+ remove_resource(res);
+ }
+
kfree(info);
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0d24fc65c049..ad7917895f4c 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -148,6 +148,13 @@ enum {
DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES,
};
+/*
+ * Max CXL HDM decoders tracked per endpoint in pci_dev->coh_resource[].
+ * CXL 3.1 spec section 8.2.4.20.1 - CXL HDM Decoder Capability Register,
+ * mention a max of 10 decoders for a CXL device.
+ */
+#define PCI_CXL_MAX_COHERENT_RANGES 10
+
/**
* enum pci_interrupt_pin - PCI INTx interrupt values
* @PCI_INTERRUPT_UNKNOWN: Unknown or unassigned interrupt
@@ -573,6 +580,13 @@ struct pci_dev {
#endif
#ifdef CONFIG_CXL_RESET
struct cxl_hdm_info *hdm; /* CXL HDM decoder state */
+ /*
+ * Precommitted CXL HDM decoder coherent ranges, snapshotted before
+ * any driver binds. One entry per decoder index. Only written by
+ * pci_cxl_hdm_cache_init()/_release(), outside any bound driver's
+ * read window.
+ */
+ struct resource coh_resource[PCI_CXL_MAX_COHERENT_RANGES];
#endif
#ifdef CONFIG_PCI_NPEM
struct npem *npem; /* Native PCIe Enclosure Management */
--
2.53.0
next prev parent reply other threads:[~2026-11-05 15:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 15:29 [RFC PATCH v2 0/5] PCI/TSM: Resolve TDISP coherent (CXL) ranges from precommitted HDM decoders Ankit Agrawal
2026-11-05 15:29 ` [RFC PATCH v2 1/5] PCI/TSM: Create MMIO descriptors via TDISP Report Ankit Agrawal
2026-11-05 15:29 ` Ankit Agrawal [this message]
2026-11-05 15:29 ` [RFC PATCH v2 3/5] PCI/TSM: Derive the coherent-range IPA from CXL Ankit Agrawal
2026-11-06 10:06 ` Richard Cheng
2026-11-06 12:16 ` Ankit Agrawal
2026-11-06 12:38 ` Ankit Agrawal
2026-11-06 14:26 ` Jason Gunthorpe
2026-11-05 15:29 ` [RFC PATCH v2 4/5] PCI/TSM: Support multiple coherent ranges via coh_idx Ankit Agrawal
2026-11-05 15:29 ` [RFC PATCH v2 5/5] cxl: Invalidate cached coherent range when Normalized Addressing is detected Ankit Agrawal
2026-11-06 10:19 ` Richard Cheng
2026-11-06 12:22 ` Ankit Agrawal
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=20261105152909.53452-3-ankita@nvidia.com \
--to=ankita@nvidia.com \
--cc=Smita.KoralahalliChannabasappa@amd.com \
--cc=aik@amd.com \
--cc=alison.schofield@intel.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=aneesh.kumar@kernel.org \
--cc=bhelgaas@google.com \
--cc=brads@mainlining.org \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=gourry@gourry.net \
--cc=icheng@nvidia.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=iweiny@kernel.org \
--cc=jgg@nvidia.com \
--cc=jic23@kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=ming.li@zohomail.com \
--cc=nik.borisov@suse.com \
--cc=rrichter@amd.com \
--cc=smadhavan@nvidia.com \
--cc=terry.bowman@amd.com \
--cc=vishal.l.verma@intel.com \
--cc=yilun.xu@linux.intel.com \
/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.