From: Dave Jiang <dave.jiang@intel.com>
To: Srirangan Madhavan <smadhavan@nvidia.com>,
Alison Schofield <alison.schofield@intel.com>,
Bjorn Helgaas <bhelgaas@google.com>,
Davidlohr Bueso <dave@stgolabs.net>,
Jonathan Cameron <jic23@kernel.org>,
Vishal Verma <vishal.l.verma@intel.com>,
linux-cxl@vger.kernel.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: Alex Williamson <alex.williamson@redhat.com>,
vsethi@nvidia.com, alwilliamson@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
Subject: Re: [PATCH v10 04/12] cxl: Cache decoder settings on PCI devices
Date: Fri, 21 Aug 2026 15:12:53 -0700 [thread overview]
Message-ID: <8d26e993-1c04-4609-be0d-f26449c490cf@intel.com> (raw)
In-Reply-To: <20260804192958.1823952-5-smadhavan@nvidia.com>
On 8/4/26 12:29 PM, Srirangan Madhavan wrote:
> Add CXL core plumbing to refresh a PCI device HDM decoder cache when
> decoders are enumerated, committed, or reset. PCI reset paths can use
> this snapshot to restore HDM programming without walking CXL topology
> during reset recovery.
>
> The cache is populated by PCI-side discovery in a follow-on patch. Until
> then, the CXL core update path is a no-op when no PCI HDM cache is
> present.
>
> Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
> ---
> drivers/cxl/core/hdm.c | 114 ++++++++++++++++++++++++++++++++++++++++-
> include/cxl/cxl.h | 12 +++++
> include/linux/pci.h | 6 +++
> 3 files changed, 131 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 6e132b4f092b..ec988e7b7c0c 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -84,6 +84,110 @@ static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
> cxlhdm->iw_cap_mask |= BIT(16);
> }
>
> +static int cxl_pci_hdm_info_match(struct pci_dev *pdev, int decoder_count,
> + bool *present)
Maybe this should just return a bool based on match.
bool cxl_pci_hdm_decoder_count_match()?
> +{
> + struct cxl_hdm_info *info;
> + int rc = 0;
> +
> + *present = false;
> + down_read(&cxl_rwsem.dpa);
> + info = pdev->hdm;
> + if (info) {
> + *present = true;
> + if (info->decoder_count != decoder_count) {
> + pci_warn(pdev,
> + "CXL HDM cache decoder count mismatch: cached=%d hdm=%d\n",
> + info->decoder_count, decoder_count);
> + rc = -ENXIO;
> + }
> + }
> + up_read(&cxl_rwsem.dpa);
> +
> + return rc;
> +}
> +
> +static int cxl_pci_setup_hdm_info(struct cxl_hdm *cxlhdm)
I'm not sure if this function name makes sense. Nothing is being setup here. I think the above function should just be __cxl_pci_hdm_decoder_count_match() and this function can just be cxl_pci_hdm_decoder_count_match(). Or just collpase the two into a single function.
> +{
> + struct pci_dev *pdev __free(pci_dev_put) =
> + cxl_port_get_uport_pci_dev(cxlhdm->port);
> + bool present;
> +
> + if (!pdev)
> + return 0;
> +
> + return cxl_pci_hdm_info_match(pdev, cxlhdm->decoder_count, &present);
> +}
> +
> +static u64 cxl_switch_target_list(struct cxl_switch_decoder *cxlsd)
cxl_switch_get_target_list()
> +{
> + struct cxl_decoder *cxld = &cxlsd->cxld;
> + u64 targets = 0;
> + int ways = min(cxld->interleave_ways, cxlsd->nr_targets);
> +
> + /* target_map[] holds the raw list before target[] is resolved. */
> + for (int i = 0; i < ways && i < 8; i++) {
> + u8 port_id;
> +
> + if (cxlsd->target[i])
> + port_id = cxlsd->target[i]->port_id;
> + else
> + port_id = cxld->target_map[i];
> +
> + targets |= (u64)port_id << (i * 8);
> + }
> +
> + return targets;
> +}
> +
> +static void cxl_decoder_snapshot(struct cxl_decoder *cxld,
> + struct cxl_decoder_settings *settings)
> +{
Probably a good idea to add
lockdep_assert_held_write(&cxl_rwsem.dpa);
> + *settings = (struct cxl_decoder_settings) {
> + .id = cxld->id,
> + .hpa_range = cxld->hpa_range,
> + .interleave_ways = cxld->interleave_ways,
> + .interleave_granularity = cxld->interleave_granularity,
> + .target_type = cxld->target_type,
> + .flags = cxld->flags,
> + };
> +
> + if (is_endpoint_decoder(&cxld->dev)) {
> + struct cxl_endpoint_decoder *cxled =
> + to_cxl_endpoint_decoder(&cxld->dev);
> +
> + settings->target_or_skip = cxled->skip;
> + } else if (is_switch_decoder(&cxld->dev)) {
> + struct cxl_switch_decoder *cxlsd =
> + to_cxl_switch_decoder(&cxld->dev);
> +
> + settings->target_or_skip = cxl_switch_target_list(cxlsd);
> + }
> +}
> +
> +static void cxl_hdm_info_set_decoder(struct cxl_hdm *cxlhdm,
> + struct cxl_decoder *cxld)
cxl_hdm_cache(or save)_decoder_info()?
> +{
> + struct pci_dev *pdev __free(pci_dev_put) =
> + cxl_port_get_uport_pci_dev(cxlhdm->port);
> + struct cxl_hdm_info *info;
> +
> + if (!pdev)
> + return;
> +
> + guard(rwsem_write)(&cxl_rwsem.dpa);
> + info = pdev->hdm;
> + if (!info || cxld->id >= info->decoder_count)
> + return;
> +
> + if (cxld->flags & CXL_DECODER_F_ENABLE)
> + cxl_decoder_snapshot(cxld, &info->settings[cxld->id]);
> + else
> + info->settings[cxld->id] = (struct cxl_decoder_settings) {
> + .id = cxld->id,
> + };
Use {} for if/else since the else part is multi-lines. Although given that you have to set the id either way, maybe have a helper function cxl_decoder_settings_init() that does it so you don't need the else branch.
DJ
> +}
> +
> static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
> {
> struct cxl_hdm *cxlhdm;
> @@ -767,6 +871,7 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
> }
> port->commit_end++;
> cxld->flags |= CXL_DECODER_F_ENABLE;
> + cxl_hdm_info_set_decoder(cxlhdm, cxld);
>
> return 0;
> }
> @@ -839,6 +944,7 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld)
> writel(0, hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id));
>
> cxld->flags &= ~CXL_DECODER_F_ENABLE;
> + cxl_hdm_info_set_decoder(cxlhdm, cxld);
>
> /* Userspace is now responsible for reconfiguring this decoder */
> if (is_endpoint_decoder(&cxld->dev)) {
> @@ -1058,11 +1164,16 @@ static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
> struct cxl_port *port = cxlhdm->port;
> int i;
> u64 dpa_base = 0;
> + int rc;
>
> cxl_settle_decoders(cxlhdm);
>
> + rc = cxl_pci_setup_hdm_info(cxlhdm);
> + if (rc)
> + return rc;
> +
> for (i = 0; i < cxlhdm->decoder_count; i++) {
> - int rc, target_count = cxlhdm->target_count;
> + int target_count = cxlhdm->target_count;
> struct cxl_decoder *cxld;
>
> if (is_cxl_endpoint(port)) {
> @@ -1097,6 +1208,7 @@ static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
> put_device(&cxld->dev);
> return rc;
> }
> + cxl_hdm_info_set_decoder(cxlhdm, cxld);
> rc = add_hdm_decoder(port, cxld);
> if (rc) {
> dev_warn(&port->dev,
> diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
> index 85e895d9b31c..703285966946 100644
> --- a/include/cxl/cxl.h
> +++ b/include/cxl/cxl.h
> @@ -133,6 +133,18 @@ struct cxl_regs {
> );
> };
>
> +#define CXL_HDM_DECODER_MAX_COUNT 32
> +
> +/**
> + * struct cxl_hdm_info - PCI device HDM decoder programming cache
> + * @decoder_count: number of decoder settings entries
> + * @settings: cached per-decoder programming state
> + */
> +struct cxl_hdm_info {
> + int decoder_count;
> + struct cxl_decoder_settings settings[CXL_HDM_DECODER_MAX_COUNT];
> +};
> +
> struct cxl_reg_map {
> bool valid;
> int id;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 64b308b6e61c..a8e5cec96bae 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -335,6 +335,9 @@ struct pcie_link_state;
> struct pci_sriov;
> struct pci_p2pdma;
> struct rcec_ea;
> +#ifdef CONFIG_CXL_HDM
> +struct cxl_hdm_info;
> +#endif
>
> /* struct pci_dev - describes a PCI device
> *
> @@ -562,6 +565,9 @@ struct pci_dev {
> #ifdef CONFIG_PCI_DOE
> struct xarray doe_mbs; /* Data Object Exchange mailboxes */
> #endif
> +#ifdef CONFIG_CXL_HDM
> + struct cxl_hdm_info *hdm; /* CXL HDM decoder reset state */
> +#endif
> #ifdef CONFIG_PCI_NPEM
> struct npem *npem; /* Native PCIe Enclosure Management */
> #endif
next prev parent reply other threads:[~2026-08-21 22:12 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 19:29 [PATCH v10 00/12] PCI/CXL: Add CXL reset support for Type 2 devices Srirangan Madhavan
2026-08-04 19:29 ` [PATCH v10 01/12] cxl: Move HDM decoder programming helpers Srirangan Madhavan
2026-08-04 19:46 ` sashiko-bot
2026-08-05 2:13 ` Alison Schofield
2026-08-20 21:13 ` Dave Jiang
2026-08-24 7:11 ` Li Ming
2026-08-24 7:19 ` Li Ming
2026-08-04 19:29 ` [PATCH v10 02/12] cxl: Pass decoder settings to HDM commit helpers Srirangan Madhavan
2026-08-04 19:49 ` sashiko-bot
2026-08-20 22:21 ` Dave Jiang
2026-08-24 7:33 ` Li Ming
2026-08-04 19:29 ` [PATCH v10 03/12] cxl: Share HDM decoder decode logic Srirangan Madhavan
2026-08-04 19:45 ` sashiko-bot
2026-08-20 23:25 ` Dave Jiang
2026-08-04 19:29 ` [PATCH v10 04/12] cxl: Cache decoder settings on PCI devices Srirangan Madhavan
2026-08-04 19:40 ` sashiko-bot
2026-08-21 22:12 ` Dave Jiang [this message]
2026-08-24 7:53 ` Li Ming
2026-08-04 19:29 ` [PATCH v10 05/12] cxl: Cache endpoint decoder settings during PCI enumeration Srirangan Madhavan
2026-08-04 19:51 ` sashiko-bot
2026-08-05 2:28 ` Alison Schofield
2026-08-17 5:30 ` Richard Cheng
2026-08-21 23:33 ` Dave Jiang
2026-08-25 6:58 ` Li Ming
2026-08-04 19:29 ` [PATCH v10 06/12] cxl: Add CXL Device Reset helper Srirangan Madhavan
2026-08-04 19:42 ` sashiko-bot
2026-08-24 22:24 ` Dave Jiang
2026-08-04 19:29 ` [PATCH v10 07/12] cxl: Validate HDM ranges before CXL reset Srirangan Madhavan
2026-08-04 19:38 ` sashiko-bot
2026-08-04 19:29 ` [PATCH v10 08/12] cxl: Reject CXL Reset on multifunction devices Srirangan Madhavan
2026-08-04 19:40 ` sashiko-bot
2026-08-04 19:29 ` [PATCH v10 09/12] cxl: Restore CXL HDM state after PCI reset Srirangan Madhavan
2026-08-04 19:44 ` sashiko-bot
2026-08-17 7:12 ` Richard Cheng
2026-08-04 19:29 ` [PATCH v10 10/12] PCI/CXL: Expose CXL Reset as a PCI reset method Srirangan Madhavan
2026-08-04 20:00 ` sashiko-bot
2026-08-04 19:29 ` [PATCH v10 11/12] Documentation/ABI: Document CXL Reset " Srirangan Madhavan
2026-08-04 19:41 ` sashiko-bot
2026-08-04 19:29 ` [PATCH v10 12/12] PCI/CXL: Restore HDM state after CXL bus reset Srirangan Madhavan
2026-08-04 19:59 ` sashiko-bot
2026-08-13 9:35 ` [PATCH v10 00/12] PCI/CXL: Add CXL reset support for Type 2 devices Alejandro Lucero Palau
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=8d26e993-1c04-4609-be0d-f26449c490cf@intel.com \
--to=dave.jiang@intel.com \
--cc=alex.williamson@redhat.com \
--cc=alison.schofield@intel.com \
--cc=alwilliamson@nvidia.com \
--cc=bhelgaas@google.com \
--cc=dave@stgolabs.net \
--cc=icheng@nvidia.com \
--cc=jan@nvidia.com \
--cc=jic23@kernel.org \
--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=smadhavan@nvidia.com \
--cc=vaslot@nvidia.com \
--cc=vishal.l.verma@intel.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 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.