From: <smadhavan@nvidia.com>
To: <dave@stgolabs.net>, <jonathan.cameron@huawei.com>,
<dave.jiang@intel.com>, <alison.schofield@intel.com>,
<vishal.l.verma@intel.com>, <ira.weiny@intel.com>,
<dan.j.williams@intel.com>, <bhelgaas@google.com>,
<ming.li@zohomail.com>, <rrichter@amd.com>,
<Smita.KoralahalliChannabasappa@amd.com>,
<huaisheng.ye@intel.com>, <linux-cxl@vger.kernel.org>,
<linux-pci@vger.kernel.org>
Cc: <smadhavan@nvidia.com>, <vaslot@nvidia.com>, <vsethi@nvidia.com>,
<sdonthineni@nvidia.com>, <vidyas@nvidia.com>, <mochs@nvidia.com>,
<jsequeira@nvidia.com>
Subject: [PATCH v3 8/10] cxl: add DVSEC config save/restore
Date: Fri, 16 Jan 2026 01:41:44 +0000 [thread overview]
Message-ID: <20260116014146.2149236-9-smadhavan@nvidia.com> (raw)
In-Reply-To: <20260116014146.2149236-1-smadhavan@nvidia.com>
From: Srirangan Madhavan <smadhavan@nvidia.com>
Save and restore CXL DVSEC control registers across reset with
CONFIG_LOCK handling so RWL fields are preserved when locked. This
maintains device policy and capability state across cxl_reset while
avoiding writes to locked fields.
Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
---
drivers/cxl/pci.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++
include/cxl/pci.h | 15 +++++++
2 files changed, 122 insertions(+)
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index 5d2bb4431de3..9a9fab60f1e8 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -1161,6 +1161,113 @@ static int cxl_region_flush_host_cpu_caches(struct device *dev, void *data)
return 0;
}
+/*
+ * CXL DVSEC register save/restore
+ */
+static int cxl_save_dvsec_state(struct pci_dev *pdev,
+ struct cxl_type2_saved_state *state, int dvsec)
+{
+ int rc;
+
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL_OFFSET,
+ &state->dvsec_ctrl);
+ if (rc)
+ return rc;
+
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET,
+ &state->dvsec_ctrl2);
+ return rc;
+}
+
+static int cxl_restore_dvsec_state(struct pci_dev *pdev,
+ const struct cxl_type2_saved_state *state,
+ int dvsec, bool config_locked)
+{
+ int rc;
+ u16 val_to_restore;
+
+ if (config_locked) {
+ u16 current_val;
+
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL_OFFSET,
+ ¤t_val);
+ if (rc)
+ return rc;
+
+ val_to_restore = (current_val & CXL_DVSEC_CTRL_RWL_MASK) |
+ (state->dvsec_ctrl & ~CXL_DVSEC_CTRL_RWL_MASK);
+ } else {
+ val_to_restore = state->dvsec_ctrl;
+ }
+
+ rc = pci_write_config_word(pdev, dvsec + CXL_DVSEC_CTRL_OFFSET,
+ val_to_restore);
+ if (rc)
+ return rc;
+
+ rc = pci_write_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET,
+ state->dvsec_ctrl2);
+ return rc;
+}
+
+/**
+ * cxl_config_save_state - Save CXL configuration state
+ * @pdev: PCI device
+ * @state: Structure to store saved state
+ *
+ * Saves CXL DVSEC state before reset.
+ */
+int cxl_config_save_state(struct pci_dev *pdev,
+ struct cxl_type2_saved_state *state)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ int dvsec;
+
+ if (!cxlds || !state)
+ return -EINVAL;
+
+ memset(state, 0, sizeof(*state));
+
+ dvsec = cxlds->cxl_dvsec;
+ if (!dvsec)
+ return -ENODEV;
+
+ return cxl_save_dvsec_state(pdev, state, dvsec);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_config_save_state, "CXL");
+
+/**
+ * cxl_config_restore_state - Restore CXL configuration state
+ * @pdev: PCI device
+ * @state: Previously saved state
+ *
+ * Restores CXL DVSEC state after reset.
+ */
+int cxl_config_restore_state(struct pci_dev *pdev,
+ const struct cxl_type2_saved_state *state)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ bool config_locked;
+ int rc, dvsec;
+ u16 lock_reg;
+
+ if (!cxlds || !state)
+ return -EINVAL;
+
+ dvsec = cxlds->cxl_dvsec;
+ if (!dvsec)
+ return -ENODEV;
+
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_LOCK_OFFSET, &lock_reg);
+ if (rc)
+ return rc;
+
+ config_locked = !!(lock_reg & CXL_DVSEC_LOCK_CONFIG_LOCK);
+
+ return cxl_restore_dvsec_state(pdev, state, dvsec, config_locked);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_config_restore_state, "CXL");
+
static int cxl_check_region_driver_bound(struct device *dev, void *data)
{
struct cxl_decoder *cxld = to_cxl_decoder(dev);
diff --git a/include/cxl/pci.h b/include/cxl/pci.h
index 71d8de5de948..2c629ded73cc 100644
--- a/include/cxl/pci.h
+++ b/include/cxl/pci.h
@@ -4,6 +4,18 @@
#ifndef __CXL_ACCEL_PCI_H
#define __CXL_ACCEL_PCI_H
+/* CXL Type 2 device state for save/restore across reset */
+struct cxl_type2_saved_state {
+ /* DVSEC registers */
+ u16 dvsec_ctrl;
+ u16 dvsec_ctrl2;
+};
+
+int cxl_config_save_state(struct pci_dev *pdev,
+ struct cxl_type2_saved_state *state);
+int cxl_config_restore_state(struct pci_dev *pdev,
+ const struct cxl_type2_saved_state *state);
+
/*
* See section 8.1 Configuration Space Registers in the CXL 2.0
* Specification. Names are taken straight from the specification with "CXL" and
@@ -23,6 +35,7 @@
#define CXL_DVSEC_CXL_RST_MEM_CLR_CAPABLE BIT(11)
#define CXL_DVSEC_CTRL_OFFSET 0xC
#define CXL_DVSEC_MEM_ENABLE BIT(2)
+#define CXL_DVSEC_CTRL_RWL_MASK 0x5FED
#define CXL_DVSEC_CTRL2_OFFSET 0x10
#define CXL_DVSEC_DISABLE_CACHING BIT(0)
#define CXL_DVSEC_INIT_CACHE_WBI BIT(1)
@@ -32,6 +45,8 @@
#define CXL_DVSEC_CACHE_INVALID BIT(0)
#define CXL_DVSEC_CXL_RST_COMPLETE BIT(1)
#define CXL_DVSEC_CXL_RESET_ERR BIT(2)
+#define CXL_DVSEC_LOCK_OFFSET 0x14
+#define CXL_DVSEC_LOCK_CONFIG_LOCK BIT(0)
#define CXL_DVSEC_RANGE_SIZE_HIGH(i) (0x18 + ((i) * 0x10))
#define CXL_DVSEC_RANGE_SIZE_LOW(i) (0x1C + ((i) * 0x10))
#define CXL_DVSEC_MEM_INFO_VALID BIT(0)
--
2.34.1
next prev parent reply other threads:[~2026-01-16 1:42 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-16 1:41 [PATCH v3 0/10] CXL reset support for Type 2 devices smadhavan
2026-01-16 1:41 ` [PATCH v3 1/10] cxl: move DVSEC defines to cxl pci header smadhavan
2026-01-16 1:41 ` [PATCH v3 2/10] PCI: switch CXL port DVSEC defines smadhavan
2026-01-16 1:41 ` [PATCH v3 3/10] cxl: add type 2 helper and reset DVSEC bits smadhavan
2026-01-16 1:41 ` [PATCH v3 4/10] PCI: add CXL reset method smadhavan
2026-01-17 13:56 ` kernel test robot
2026-01-17 14:28 ` kernel test robot
2026-01-16 1:41 ` [PATCH v3 5/10] cxl: add reset prepare and region teardown smadhavan
2026-01-16 1:41 ` [PATCH v3 6/10] PCI: wire CXL reset prepare/cleanup smadhavan
2026-01-16 1:41 ` [PATCH v3 7/10] cxl: add host cache flush and multi-function reset smadhavan
2026-01-16 1:41 ` smadhavan [this message]
2026-01-16 1:41 ` [PATCH v3 9/10] PCI: save/restore CXL config around reset smadhavan
2026-01-16 1:41 ` [PATCH v3 10/10] cxl: add HDM decoder and IDE save/restore smadhavan
2026-01-18 22:29 ` [PATCH v3 0/10] CXL reset support for Type 2 devices Alison Schofield
2026-01-20 22:33 ` Srirangan Madhavan
[not found] ` <CY5PR12MB6226EE35D88E6F4442572D1CC389A@CY5PR12MB6226.namprd12.prod.outlook.com>
2026-01-21 0:30 ` Alison Schofield
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=20260116014146.2149236-9-smadhavan@nvidia.com \
--to=smadhavan@nvidia.com \
--cc=Smita.KoralahalliChannabasappa@amd.com \
--cc=alison.schofield@intel.com \
--cc=bhelgaas@google.com \
--cc=dan.j.williams@intel.com \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=huaisheng.ye@intel.com \
--cc=ira.weiny@intel.com \
--cc=jonathan.cameron@huawei.com \
--cc=jsequeira@nvidia.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=ming.li@zohomail.com \
--cc=mochs@nvidia.com \
--cc=rrichter@amd.com \
--cc=sdonthineni@nvidia.com \
--cc=vaslot@nvidia.com \
--cc=vidyas@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.