All of lore.kernel.org
 help / color / mirror / Atom feed
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


      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.