From: Ben Cheatham <Benjamin.Cheatham@amd.com>
To: <linux-cxl@vger.kernel.org>
Cc: <benjamin.cheatham@amd.com>
Subject: [PATCH 17/17] cxl/core: Add cache device cache management attributes
Date: Tue, 11 Nov 2025 15:40:32 -0600 [thread overview]
Message-ID: <20251111214032.8188-18-Benjamin.Cheatham@amd.com> (raw)
In-Reply-To: <20251111214032.8188-1-Benjamin.Cheatham@amd.com>
Add functions to cxl/core/pci.c to manage the cache of a CXL.cache
enabled endpoint. Add these new functions to sysfs attributes for
userspace accessibility.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
Documentation/ABI/testing/sysfs-bus-cxl | 31 +++++++++
drivers/cxl/core/cachedev.c | 89 +++++++++++++++++++++++++
drivers/cxl/core/pci.c | 85 +++++++++++++++++++++++
drivers/cxl/cxlcache.h | 13 ++++
drivers/cxl/cxlpci.h | 6 ++
5 files changed, 224 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-cxl b/Documentation/ABI/testing/sysfs-bus-cxl
index 6b4e8c7a963d..b7293a09dc93 100644
--- a/Documentation/ABI/testing/sysfs-bus-cxl
+++ b/Documentation/ABI/testing/sysfs-bus-cxl
@@ -615,3 +615,34 @@ Description:
The count is persistent across power loss and wraps back to 0
upon overflow. If this file is not present, the device does not
have the necessary support for dirty tracking.
+
+What: /sys/bus/cxl/devices/cacheX/cache_disable
+Date: Dec, 2025
+KernelVersion: v6.19
+Contact: linux-cxl@vger.kernel.org
+Description:
+ (RW) Reading this attribute returns whether the CXL cache of this
+ device is currently disabled. Writing a '1' to this attribute disables
+ the CXL cache of the device.
+
+What: /sys/bus/cxl/devices/cacheX/cache_invalid
+Date: Dec, 2025
+KernelVersion: v6.19
+Contact: linux-cxl@vger.kernel.org
+Description:
+ (RO) Whether the CXL cache of this device is currently invalid. Reading
+ this attribute while caching is enabled will always return 0. See the
+ "cache_disable" attribute for disabling caching.
+
+What: /sys/bus/cxl/devices/cacheX/initiate_wbinvd
+Date: Dec, 2025
+KernelVersion: v6.19
+Contact: linux-cxl@vger.kernel.org
+Description:
+ (WO) Writes to this attribute initiate an attempt to writeback and
+ invalidate this device's CXL cache. Writing to this attribute while
+ caching is enabled will result in a failure, see the "cache_disable"
+ attribute for disabling caching. The writeback and invalidate may take
+ some time to finish depending on the device. The result of this
+ operation can be found by reading the "cache_invalid" attribute of the
+ device.
diff --git a/drivers/cxl/core/cachedev.c b/drivers/cxl/core/cachedev.c
index d8bf18ec0579..2a6a3e4f6a17 100644
--- a/drivers/cxl/core/cachedev.c
+++ b/drivers/cxl/core/cachedev.c
@@ -6,6 +6,7 @@
#include "cxlpci.h"
#include "../cxlcache.h"
+#include "../cxlpci.h"
#include "private.h"
static DEFINE_IDA(cxl_cachedev_ida);
@@ -110,9 +111,97 @@ static struct attribute_group cxl_cachedev_cache_attribute_group = {
.is_visible = cxl_cachedev_cache_visible,
};
+static ssize_t cache_disable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct cxl_cachedev *cxlcd = to_cxl_cachedev(dev);
+ struct cxl_dev_state *cxlds = cxlcd->cxlds;
+ bool disable;
+ int rc;
+
+ rc = kstrtobool(buf, &disable);
+ if (rc)
+ return rc;
+
+ rc = cxl_accel_set_cache_disable(cxlds, disable);
+ if (rc < 0)
+ return rc;
+
+ return n;
+}
+
+static ssize_t cache_disable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxl_cachedev *cxlcd = to_cxl_cachedev(dev);
+ struct cxl_dev_state *cxlds = cxlcd->cxlds;
+
+ return sysfs_emit(buf, "%d\n", cxl_accel_caching_disabled(cxlds));
+}
+static DEVICE_ATTR_RW(cache_disable);
+
+static ssize_t cache_invalid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cxl_cachedev *cxlcd = to_cxl_cachedev(dev);
+ struct cxl_dev_state *cxlds = cxlcd->cxlds;
+
+ return sysfs_emit(buf, "%d\n", cxl_accel_cache_invalid(cxlds));
+}
+static DEVICE_ATTR_RO(cache_invalid);
+
+static ssize_t init_wbinvd_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t n)
+{
+ struct cxl_cachedev *cxlcd = to_cxl_cachedev(dev);
+ struct cxl_dev_state *cxlds = cxlcd->cxlds;
+ int rc;
+
+ rc = cxl_accel_initiate_wbinvd(cxlds);
+ return rc ? rc : n;
+}
+static DEVICE_ATTR_WO(init_wbinvd);
+
+static struct attribute *cxl_cachedev_mgmt_attributes[] = {
+ &dev_attr_cache_disable.attr,
+ &dev_attr_cache_invalid.attr,
+ &dev_attr_init_wbinvd.attr,
+ NULL
+};
+
+static umode_t cxl_cachedev_mgmt_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct cxl_cachedev *cxlcd = to_cxl_cachedev(dev);
+ struct cxl_dev_state *cxlds = cxlcd->cxlds;
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ u16 cap;
+ int rc;
+
+ rc = pci_read_config_word(pdev, cxlds->cxl_dvsec + CXL_DVSEC_CAP_OFFSET,
+ &cap);
+ if (rc)
+ return 0;
+
+ if (!(cap & CXL_DVSEC_WBINVD_CAPABLE) &&
+ a == &dev_attr_init_wbinvd.attr)
+ return 0;
+
+ return a->mode;
+}
+
+static struct attribute_group cxl_cachedev_mgmt_attribute_group = {
+ .attrs = cxl_cachedev_mgmt_attributes,
+ .is_visible = cxl_cachedev_mgmt_visible,
+};
+
static const struct attribute_group *cxl_cachedev_attribute_groups[] = {
&cxl_cachedev_attribute_group,
&cxl_cachedev_cache_attribute_group,
+ &cxl_cachedev_mgmt_attribute_group,
NULL
};
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 27c74e90ade5..a1bd7778aaff 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -1313,3 +1313,88 @@ int cxl_accel_read_cache_info(struct cxl_dev_state *cxlds, bool hdmd)
return 0;
}
EXPORT_SYMBOL_NS_GPL(cxl_accel_read_cache_info, "CXL");
+
+bool cxl_accel_caching_disabled(struct cxl_dev_state *cxlds)
+{
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ int dvsec, rc;
+ u16 ctrl2;
+
+ if (!dev_is_pci(cxlds->dev))
+ return false;
+
+ dvsec = cxlds->cxl_dvsec;
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET, &ctrl2);
+ if (rc)
+ return false;
+
+ return FIELD_GET(CXL_DVSEC_DISABLE_CACHING, ctrl2);
+}
+
+int cxl_accel_set_cache_disable(struct cxl_dev_state *cxlds, bool disable)
+{
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ int dvsec, rc;
+ u16 ctrl2;
+
+ if (!dev_is_pci(cxlds->dev))
+ return -EINVAL;
+
+ guard(device)(cxlds->dev);
+ dvsec = cxlds->cxl_dvsec;
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET, &ctrl2);
+ if (rc)
+ return rc;
+
+ if (FIELD_GET(CXL_DVSEC_DISABLE_CACHING, ctrl2) == disable)
+ return 1;
+
+ ctrl2 &= ~CXL_DVSEC_DISABLE_CACHING;
+ ctrl2 |= FIELD_PREP(CXL_DVSEC_DISABLE_CACHING, disable);
+ return pci_write_config_word(pdev, dvsec + CXL_DVSEC_DISABLE_CACHING,
+ ctrl2);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_accel_set_cache_disable, "CXL");
+
+int cxl_accel_initiate_wbinvd(struct cxl_dev_state *cxlds)
+{
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ int dvsec, rc;
+ u16 ctrl2;
+
+ if (!dev_is_pci(cxlds->dev))
+ return -EINVAL;
+
+ guard(device)(cxlds->dev);
+ if (cxl_accel_caching_disabled(cxlds) != 1)
+ return -EBUSY;
+
+ dvsec = cxlds->cxl_dvsec;
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET, &ctrl2);
+ if (rc)
+ return rc;
+
+ ctrl2 |= CXL_DVSEC_INIT_WBINVD;
+ return pci_write_config_word(pdev, dvsec + CXL_DVSEC_CTRL2_OFFSET,
+ ctrl2);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_accel_initiate_wbinvd, "CXL");
+
+bool cxl_accel_cache_invalid(struct cxl_dev_state *cxlds)
+{
+ struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+ int dvsec, rc;
+ u16 stat2;
+
+ if (!dev_is_pci(cxlds->dev))
+ return false;
+
+ guard(device)(cxlds->dev);
+ dvsec = cxlds->cxl_dvsec;
+ rc = pci_read_config_word(pdev, dvsec + CXL_DVSEC_STAT2_OFFSET, &stat2);
+ if (rc)
+ return false;
+
+ return FIELD_GET(CXL_DVSEC_CACHE_INVALID, stat2);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_accel_cache_invalid, "CXL");
diff --git a/drivers/cxl/cxlcache.h b/drivers/cxl/cxlcache.h
index fe9e44fda641..b62c5269507c 100644
--- a/drivers/cxl/cxlcache.h
+++ b/drivers/cxl/cxlcache.h
@@ -32,4 +32,17 @@ int cxl_accel_read_cache_info(struct cxl_dev_state *cxlds, bool hdmd);
struct cxl_cachedev *devm_cxl_add_cachedev(struct device *host,
struct cxl_dev_state *cxlds);
bool cxl_cachedev_is_type2(struct cxl_cachedev *cxlcd);
+
+int devm_cxl_snoop_filter_alloc(u32 gid, struct cxl_dev_state *cxlds);
+
+int devm_cxl_port_program_cache_idrt(struct cxl_port *port,
+ struct cxl_dport *dport,
+ struct cxl_cachedev *cxlcd);
+int cxl_dport_program_cache_idd(struct cxl_dport *dport,
+ struct cxl_cachedev *cxlcd);
+
+int cxl_accel_set_cache_disable(struct cxl_dev_state *cxlds, bool disable);
+bool cxl_accel_caching_disabled(struct cxl_dev_state *cxlds);
+bool cxl_accel_cache_invalid(struct cxl_dev_state *cxlds);
+int cxl_accel_initiate_wbinvd(struct cxl_dev_state *cxlds);
#endif
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index 18230e4f677c..a63bba3ab348 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -20,8 +20,14 @@
#define CXL_DVSEC_CACHE_CAPABLE BIT(0)
#define CXL_DVSEC_MEM_CAPABLE BIT(2)
#define CXL_DVSEC_HDM_COUNT_MASK GENMASK(5, 4)
+#define CXL_DVSEC_WBINVD_CAPABLE BIT(6)
#define CXL_DVSEC_CTRL_OFFSET 0xC
#define CXL_DVSEC_MEM_ENABLE BIT(2)
+#define CXL_DVSEC_CTRL2_OFFSET 0x10
+#define CXL_DVSEC_DISABLE_CACHING BIT(0)
+#define CXL_DVSEC_INIT_WBINVD BIT(1)
+#define CXL_DVSEC_STAT2_OFFSET 0x12
+#define CXL_DVSEC_CACHE_INVALID BIT(0)
#define CXL_DVSEC_CAP2_OFFSET 0x16
#define CXL_DVSEC_CACHE_UNIT_MASK GENMASK(3, 0)
#define CXL_DVSEC_CACHE_SIZE_MASK GENMASK(15, 8)
--
2.51.1
prev parent reply other threads:[~2025-11-11 21:44 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-11 21:40 [RFC v2 PATCH 00/17] Initial CXL.cache device support Ben Cheatham
2025-11-11 21:40 ` [PATCH 01/17] cxl/port: Arrange for always synchronous endpoint attach Ben Cheatham
2025-11-17 15:56 ` Jonathan Cameron
2025-11-11 21:40 ` [PATCH 02/17] cxl: Move struct cxl_dev_state definition Ben Cheatham
2025-11-11 21:40 ` [PATCH 03/17] cxl/core: Add function for getting CXL cache info Ben Cheatham
2025-12-17 16:09 ` Jonathan Cameron
2025-12-17 18:01 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 04/17] cxl/core: Add CXL.cache device struct Ben Cheatham
2025-12-17 16:14 ` Jonathan Cameron
2025-11-11 21:40 ` [PATCH 05/17] cxl/cache: Add cxl_cache driver Ben Cheatham
2025-12-17 16:17 ` Jonathan Cameron
2025-12-17 18:01 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 06/17] cxl: Replace cxl_mem_find_port() with cxl_dev_find_port() Ben Cheatham
2025-12-17 16:18 ` Jonathan Cameron
2025-12-17 18:01 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 07/17] cxl: Change cxl_ep_load() to use struct device * parameter Ben Cheatham
2025-11-11 21:40 ` [PATCH 08/17] cxl/core: Update devm_cxl_enumerate_ports() Ben Cheatham
2025-11-11 21:40 ` [PATCH 09/17] cxl/port: Split endpoint port probe on device type Ben Cheatham
2025-11-11 21:40 ` [PATCH 10/17] cxl/cache, mem: Prevent RAS register mapping race Ben Cheatham
2025-12-17 16:23 ` Jonathan Cameron
2025-12-17 18:02 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 11/17] cxl/core, port: Update devm_cxl_add_endpoint() Ben Cheatham
2025-11-11 21:40 ` [PATCH 12/17] cxl/core: Add CXL snoop filter setup and allocation Ben Cheatham
2025-12-17 16:35 ` Jonathan Cameron
2025-12-17 18:02 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 13/17] cxl/core: Add cache id verification Ben Cheatham
2025-12-22 13:47 ` Jonathan Cameron
2026-01-05 21:16 ` Cheatham, Benjamin
2025-11-11 21:40 ` [PATCH 14/17] cxl/port: Add cache id programming Ben Cheatham
2025-11-11 21:40 ` [PATCH 15/17] cxl/port: Bypass cache id for singleton cache devices Ben Cheatham
2025-11-11 21:40 ` [PATCH 16/17] cxl/core: Add cache device attributes Ben Cheatham
2025-12-17 16:12 ` Jonathan Cameron
2025-12-17 18:02 ` Cheatham, Benjamin
2025-11-11 21:40 ` Ben Cheatham [this message]
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=20251111214032.8188-18-Benjamin.Cheatham@amd.com \
--to=benjamin.cheatham@amd.com \
--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 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.