From: Srirangan Madhavan <smadhavan@nvidia.com>
To: linux-cxl@vger.kernel.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: vsethi@nvidia.com, alwilliamson@nvidia.com,
Dan Williams <danwilliams@nvidia.com>,
Sai Yashwanth Reddy Kancherla <skancherla@nvidia.com>,
Vishal Aslot <vaslot@nvidia.com>,
Manish Honap <mhonap@nvidia.com>, Jiandi An <jan@nvidia.com>,
Richard Cheng <icheng@nvidia.com>,
linux-tegra@vger.kernel.org,
Srirangan Madhavan <smadhavan@nvidia.com>
Subject: [PATCH v6 6/9] cxl/pci: Track memdevs affected by CXL reset
Date: Thu, 28 May 2026 08:31:51 +0000 [thread overview]
Message-ID: <20260528083154.137979-7-smadhavan@nvidia.com> (raw)
In-Reply-To: <20260528083154.137979-1-smadhavan@nvidia.com>
CXL reset is scoped to the CXL.cache/mem function set, so reset
orchestration needs to account for the target memdev and any affected
sibling-function memdevs.
Add reset context tracking for affected memdevs. Collect the memdevs
associated with the target and sibling PCI functions, track which ones
are active, collect their regions, and provide helpers to lock and
revalidate the active memdevs before reset proceeds.
The reset orchestration and CXL.mem restore flow are added separately.
Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
---
drivers/cxl/core/pci.c | 176 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 1dd880f5a333..c755c18c8d84 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -1106,8 +1106,17 @@ cxl_reset_flush_cpu_caches(struct cxl_reset_region_context *ctx)
return 0;
}
+struct cxl_reset_memdev {
+ struct cxl_memdev *cxlmd;
+ bool active;
+ bool locked;
+};
+
struct cxl_reset_context {
struct pci_dev *target;
+ struct cxl_reset_memdev *memdevs;
+ int nr_memdevs;
+ int memdev_capacity;
struct pci_dev **siblings;
int nr_siblings;
int sibling_capacity;
@@ -1237,6 +1246,173 @@ static int cxl_reset_collect_siblings(struct cxl_reset_context *ctx)
return wctx.rc;
}
+static int cxl_reset_match_memdev_by_parent(struct device *dev,
+ const void *parent)
+{
+ return is_cxl_memdev(dev) && dev->parent == parent;
+}
+
+static bool cxl_reset_memdev_active(struct cxl_memdev *cxlmd)
+{
+ return cxlmd->dev.driver && cxlmd->endpoint &&
+ !IS_ERR(cxlmd->endpoint);
+}
+
+static int cxl_reset_collect_pci_memdev(struct cxl_reset_context *ctx,
+ struct pci_dev *pdev)
+{
+ struct cxl_reset_memdev *memdevs;
+ struct cxl_memdev *cxlmd;
+ struct device *dev;
+ int capacity, i;
+
+ dev = bus_find_device(&cxl_bus_type, NULL, &pdev->dev,
+ cxl_reset_match_memdev_by_parent);
+ if (!dev)
+ return 0;
+
+ cxlmd = to_cxl_memdev(dev);
+ for (i = 0; i < ctx->nr_memdevs; i++) {
+ if (ctx->memdevs[i].cxlmd == cxlmd) {
+ put_device(dev);
+ return 0;
+ }
+ }
+
+ if (ctx->nr_memdevs < ctx->memdev_capacity)
+ goto add;
+
+ capacity = ctx->memdev_capacity ? ctx->memdev_capacity * 2 :
+ CXL_RESET_SIBLINGS_INIT;
+ memdevs = krealloc(ctx->memdevs, capacity * sizeof(*memdevs),
+ GFP_KERNEL);
+ if (!memdevs) {
+ put_device(dev);
+ return -ENOMEM;
+ }
+
+ ctx->memdevs = memdevs;
+ ctx->memdev_capacity = capacity;
+
+add:
+ ctx->memdevs[ctx->nr_memdevs++] = (struct cxl_reset_memdev) {
+ .cxlmd = cxlmd,
+ };
+ return 0;
+}
+
+/*
+ * CXL Reset is device scoped for CXL.cache/mem. Use the affected PCI
+ * function set to find memdevs whose regions and endpoint decoder state must
+ * be handled around the reset.
+ */
+static int __maybe_unused cxl_reset_collect_memdevs(struct cxl_reset_context *ctx)
+{
+ int rc, i;
+
+ rc = cxl_reset_collect_pci_memdev(ctx, ctx->target);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < ctx->nr_siblings; i++) {
+ rc = cxl_reset_collect_pci_memdev(ctx, ctx->siblings[i]);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused
+cxl_reset_collect_regions(struct cxl_reset_context *ctx,
+ struct cxl_reset_region_context *region_ctx)
+{
+ int rc, i;
+
+ lockdep_assert_held_write(&cxl_rwsem.region);
+
+ for (i = 0; i < ctx->nr_memdevs; i++) {
+ struct cxl_reset_memdev *rmd = &ctx->memdevs[i];
+ struct cxl_memdev *cxlmd = rmd->cxlmd;
+
+ if (!device_trylock(&cxlmd->dev))
+ return -EAGAIN;
+
+ if (cxl_reset_memdev_active(cxlmd)) {
+ rc = cxl_reset_collect_memdev_regions(region_ctx,
+ cxlmd);
+ if (!rc)
+ rmd->active = true;
+ } else {
+ rc = 0;
+ }
+
+ device_unlock(&cxlmd->dev);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static void cxl_reset_unlock_memdevs(struct cxl_reset_context *ctx)
+{
+ int i;
+
+ for (i = ctx->nr_memdevs - 1; i >= 0; i--) {
+ struct cxl_reset_memdev *rmd = &ctx->memdevs[i];
+
+ if (!rmd->locked)
+ continue;
+
+ device_unlock(&rmd->cxlmd->dev);
+ rmd->locked = false;
+ }
+}
+
+static int __maybe_unused cxl_reset_lock_memdevs(struct cxl_reset_context *ctx)
+{
+ int i;
+
+ lockdep_assert_held_write(&cxl_rwsem.region);
+
+ for (i = 0; i < ctx->nr_memdevs; i++) {
+ struct cxl_reset_memdev *rmd = &ctx->memdevs[i];
+ struct cxl_memdev *cxlmd = rmd->cxlmd;
+
+ if (!rmd->active)
+ continue;
+
+ if (!device_trylock(&cxlmd->dev))
+ goto err;
+
+ rmd->locked = true;
+ if (!cxl_reset_memdev_active(cxlmd)) {
+ cxl_reset_unlock_memdevs(ctx);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+
+err:
+ cxl_reset_unlock_memdevs(ctx);
+ return -EAGAIN;
+}
+
+static void __maybe_unused cxl_reset_put_memdevs(struct cxl_reset_context *ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->nr_memdevs; i++)
+ put_device(&ctx->memdevs[i].cxlmd->dev);
+
+ kfree(ctx->memdevs);
+ ctx->memdevs = NULL;
+ ctx->nr_memdevs = 0;
+ ctx->memdev_capacity = 0;
+}
+
static void cxl_pci_functions_reset_done(struct cxl_reset_context *ctx)
{
int i;
--
2.43.0
next prev parent reply other threads:[~2026-05-28 8:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-28 8:31 [PATCH v6 0/9] cxl: Add cxl_reset sysfs attribute for memdevs Srirangan Madhavan
2026-05-28 8:31 ` [PATCH v6 1/9] cxl/hdm: Add helpers to restore and commit memdev decoders Srirangan Madhavan
2026-05-28 11:06 ` Richard Cheng
2026-05-28 8:31 ` [PATCH v6 2/9] PCI: Export pci_dev_save_and_disable() and pci_dev_restore() Srirangan Madhavan
2026-05-28 8:31 ` [PATCH v6 3/9] cxl: Add reset-idle and cache flush helpers Srirangan Madhavan
2026-05-28 8:31 ` [PATCH v6 4/9] PCI/CXL: Add sibling function coordination for reset Srirangan Madhavan
2026-05-28 11:15 ` Richard Cheng
2026-05-28 8:31 ` [PATCH v6 5/9] cxl/pci: Add CXL DVSEC reset helper Srirangan Madhavan
2026-05-28 8:31 ` Srirangan Madhavan [this message]
2026-05-28 8:31 ` [PATCH v6 7/9] cxl/pci: Orchestrate CXL reset for affected memdevs Srirangan Madhavan
2026-05-28 8:31 ` [PATCH v6 8/9] cxl/memdev: Add cxl_reset sysfs attribute Srirangan Madhavan
2026-05-28 8:31 ` [PATCH v6 9/9] Documentation/ABI: Document CXL memdev cxl_reset Srirangan Madhavan
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=20260528083154.137979-7-smadhavan@nvidia.com \
--to=smadhavan@nvidia.com \
--cc=alwilliamson@nvidia.com \
--cc=danwilliams@nvidia.com \
--cc=icheng@nvidia.com \
--cc=jan@nvidia.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=mhonap@nvidia.com \
--cc=skancherla@nvidia.com \
--cc=vaslot@nvidia.com \
--cc=vsethi@nvidia.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox