Linux CXL
 help / color / mirror / Atom feed
From: Ben Cheatham <Benjamin.Cheatham@amd.com>
To: <linux-cxl@vger.kernel.org>, <dave@stgolabs.net>,
	<jic23@kernel.org>, <dave.jiang@intel.com>,
	<alison.schofield@intel.com>
Cc: <linux-iommu@vger.kernel.org>, <benjamin.cheatham@amd.com>,
	<terry.bowman@amd.com>, <robert.richter@amd.com>
Subject: [PATCH 10/15] cxl/core: Add Cache ID allocation
Date: Wed, 23 Sep 2026 12:33:37 -0500	[thread overview]
Message-ID: <20260923173342.5584-11-Benjamin.Cheatham@amd.com> (raw)
In-Reply-To: <20260923173342.5584-1-Benjamin.Cheatham@amd.com>

Add allocation and programming of CXL cache ids for struct
cxl_cachedevs as part of cxl_cache::probe(). Programming only occurs
when system firmware has not already programmed an id and the device is
*not* using HDM-D flows. Cache id allocation for HDM-D devices will be
added in a later commit ("cxl/core": Add support for HDM-D cache id
programming").

Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
 drivers/cxl/cache.c      |  21 ++-
 drivers/cxl/core/cache.c | 337 ++++++++++++++++++++++++++++++++++++++-
 drivers/cxl/cxl.h        |  10 ++
 drivers/cxl/cxlcache.h   |   2 +
 4 files changed, 359 insertions(+), 11 deletions(-)

diff --git a/drivers/cxl/cache.c b/drivers/cxl/cache.c
index 6c098010149a..0fc8f413c638 100644
--- a/drivers/cxl/cache.c
+++ b/drivers/cxl/cache.c
@@ -124,6 +124,7 @@ static void deprogram_cache_id(void *_cxlcd)
 		return;
 
 	guard(device)(&hb->dev);
+	cxl_cachedev_deprogram_cache_id(cxlcd);
 	cxl_free_cache_id(cxlcd);
 }
 
@@ -152,20 +153,26 @@ static int program_cache_id(struct cxl_cachedev *cxlcd)
 		return num_cachedevs > 1 ? -ENXIO : 0;
 
 	rc = cxl_cachedev_validate_cache_id(cxlcd);
-	if (rc && num_cachedevs > 1) {
+	if (!rc)
+		return cxl_allocate_cache_id(cxlcd);
+
+	if (cxlcd->cxlds->hdmd) {
 		dev_err(dev,
-			"Cache id not programmed with other CXL.cache devices present: %d\n",
-			rc);
-		return rc;
-	} else if (rc) {
-		cxlcd->cache_id = 0;
+			"Cache id programming not supported for HDM-D devices\n");
+		return -ENXIO;
 	}
 
 	rc = cxl_allocate_cache_id(cxlcd);
 	if (rc)
 		return rc;
 
-	return 0;
+	rc = cxl_cachedev_program_cache_id(cxlcd);
+	if (rc) {
+		dev_err(dev, "Failed to program cache id: %d\n", rc);
+		cxl_free_cache_id(cxlcd);
+	}
+
+	return rc;
 }
 
 /**
diff --git a/drivers/cxl/core/cache.c b/drivers/cxl/core/cache.c
index be570d3dc609..9c6c8ea713ef 100644
--- a/drivers/cxl/core/cache.c
+++ b/drivers/cxl/core/cache.c
@@ -1,11 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (C) Advanced Micro Device, Inc. */
 
+#include <linux/iopoll.h>
 #include <linux/pci.h>
 #include <cxlcache.h>
 
 #include "cxlpci.h"
 
+#define CXL_CACHE_ID_COMMIT_MAXTMO_US (5 * USEC_PER_SEC)
+#define CACHE_DECODER_MAX_CACHE_ID (15)
+
 int cxl_port_map_cache_id_rt(struct cxl_port *port)
 {
 	struct cxl_register_map *map = &port->reg_map;
@@ -112,6 +116,260 @@ static int cache_idrt_entry_valid(struct cxl_port *port, int id)
 	return FIELD_GET(CXL_CACHE_ID_RT_TARGETN_VALID, entry);
 }
 
+static unsigned long __cxl_cid_get_timeout_us(struct device *dev,
+					      unsigned int scale,
+					      unsigned int base)
+{
+	static const unsigned long scale_tbl[] = {
+		1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+	};
+
+	if (scale >= ARRAY_SIZE(scale_tbl) || !base) {
+		dev_dbg(dev,
+			"Invalid Cache ID commit timeout: scale=%u base=%u\n",
+			scale, base);
+		return CXL_CACHE_ID_COMMIT_MAXTMO_US;
+	}
+
+	return scale_tbl[scale] * base;
+}
+
+static int __cxl_cid_wait_commit(struct device *dev, void __iomem *status_reg,
+				 u32 commit_bit, u32 err_bit,
+				 unsigned int scale, unsigned int base)
+{
+	unsigned long tmo_us, poll_us;
+	ktime_t start;
+	u32 status;
+	int rc;
+
+	tmo_us = min_t(unsigned long, CXL_CACHE_ID_COMMIT_MAXTMO_US,
+		       __cxl_cid_get_timeout_us(dev, scale, base));
+	poll_us = max_t(unsigned long, tmo_us / 10, 1); /* ~10% */
+	start = ktime_get();
+
+	rc = readx_poll_timeout(readl, status_reg, status,
+				status & (commit_bit | err_bit), poll_us,
+				tmo_us);
+	if (rc) {
+		dev_err(dev, "Cache ID commit timed out\n");
+		return rc;
+	}
+
+	if (status & err_bit) {
+		dev_err(dev, "Cache ID commit rejected by hardware\n");
+		return -EIO;
+	}
+
+	dev_dbg(dev, "Cache ID commit took %lluus\n",
+		ktime_to_us(ktime_sub(ktime_get(), start)));
+	return 0;
+}
+
+static int cxl_cid_commit_decoder(struct cxl_dport *dport)
+{
+	void __iomem *ciddc = dport->regs.ciddc;
+	u32 cap, ctrl, status;
+	u8 scale, base;
+	int rc;
+
+	cap = readl(ciddc + CXL_CACHE_ID_DC_CAP_OFFSET);
+	if (!FIELD_GET(CXL_CACHE_ID_DC_CAP_COMMIT_REQ, cap))
+		return 0;
+
+	status = readl(ciddc + CXL_CACHE_ID_DC_STATUS_OFFSET);
+	scale = FIELD_GET(CXL_CACHE_ID_DC_STATUS_TM_SCALE, status);
+	base = FIELD_GET(CXL_CACHE_ID_DC_STATUS_TM_BASE, status);
+
+	ctrl = readl(ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+	if (FIELD_GET(CXL_CACHE_ID_DC_CTRL_COMMIT, ctrl)) {
+		ctrl &= ~CXL_CACHE_ID_DC_CTRL_COMMIT;
+		writel(ctrl, ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+	}
+
+	ctrl |= CXL_CACHE_ID_DC_CTRL_COMMIT;
+	writel(ctrl, ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+
+	rc = __cxl_cid_wait_commit(dport->dport_dev,
+				   ciddc + CXL_CACHE_ID_DC_STATUS_OFFSET,
+				   CXL_CACHE_ID_DC_STATUS_COMMITTED,
+				   CXL_CACHE_ID_DC_STATUS_COMMIT_ERR, scale,
+				   base);
+	if (rc) {
+		ctrl &= ~CXL_CACHE_ID_DC_CTRL_COMMIT;
+		writel(ctrl, ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+	}
+
+	return rc;
+}
+
+static int cxl_cid_program_decoder(struct cxl_dport *dport, int cid,
+				   bool endpoint)
+{
+	void __iomem *ciddc = dport->regs.ciddc;
+	u32 ctrl;
+
+	if (!ciddc)
+		return -EINVAL;
+
+	ctrl = readl(ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+
+	/*
+	 * The decoder may have been programmed before, so we zero out
+	 * all the fields before writing to them
+	 */
+	ctrl &= ~(CXL_CACHE_ID_DC_CTRL_ASGN_ID | CXL_CACHE_ID_DC_CTRL_FWD_ID);
+	if (endpoint) {
+		ctrl |= CXL_CACHE_ID_DC_CTRL_ASGN_ID;
+	} else {
+		ctrl |= CXL_CACHE_ID_DC_CTRL_FWD_ID;
+	}
+
+	FIELD_MODIFY(CXL_CACHE_ID_DC_CTRL_LOCAL_ID, &ctrl, cid);
+	writel(ctrl, ciddc + CXL_CACHE_ID_DC_CTRL_OFFSET);
+
+	return cxl_cid_commit_decoder(dport);
+}
+
+static int cxl_cid_commit_table(struct cxl_port *port)
+{
+	void __iomem *cidrt = port->regs.cidrt;
+	u32 cap, ctrl, status;
+	u8 scale, base;
+	int rc;
+
+	cap = readl(cidrt + CXL_CACHE_ID_RT_CAP_OFFSET);
+	if (!FIELD_GET(CXL_CACHE_ID_RT_CAP_COMMIT_REQ, cap))
+		return 0;
+
+	status = readl(cidrt + CXL_CACHE_ID_RT_STATUS_OFFSET);
+	scale = FIELD_GET(CXL_CACHE_ID_RT_STATUS_TM_SCALE, status);
+	base = FIELD_GET(CXL_CACHE_ID_RT_STATUS_TM_BASE, status);
+
+	ctrl = readl(cidrt + CXL_CACHE_ID_RT_CTRL_OFFSET);
+	if (FIELD_GET(CXL_CACHE_ID_RT_CTRL_COMMIT, ctrl)) {
+		ctrl &= ~CXL_CACHE_ID_RT_CTRL_COMMIT;
+		writel(ctrl, cidrt + CXL_CACHE_ID_RT_CTRL_OFFSET);
+	}
+
+	ctrl |= CXL_CACHE_ID_RT_CTRL_COMMIT;
+	writel(ctrl, cidrt + CXL_CACHE_ID_RT_CTRL_OFFSET);
+
+	rc = __cxl_cid_wait_commit(&port->dev,
+				   cidrt + CXL_CACHE_ID_RT_STATUS_OFFSET,
+				   CXL_CACHE_ID_RT_STATUS_COMMITTED,
+				   CXL_CACHE_ID_RT_STATUS_COMMIT_ERR, scale,
+				   base);
+	if (rc) {
+		ctrl &= ~CXL_CACHE_ID_RT_CTRL_COMMIT;
+		writel(ctrl, cidrt + CXL_CACHE_ID_RT_CTRL_OFFSET);
+	}
+
+	return rc;
+}
+
+static int cxl_cid_program_table_entry(struct cxl_port *port, int cid,
+				       unsigned int dport_id)
+{
+	void __iomem *cidrt = port->regs.cidrt;
+	u8 target_cnt, portn;
+	u16 target_n;
+	u32 cap;
+
+	if (!cidrt)
+		return -EINVAL;
+
+	cap = readl(cidrt + CXL_CACHE_ID_RT_CAP_OFFSET);
+	target_cnt = FIELD_GET(CXL_CACHE_ID_RT_CAP_TARGET_CNT, cap);
+
+	/* Shouldn't be possible, but better to be safe */
+	if (cid >= target_cnt) {
+		dev_err(&port->dev,
+			"Tried to allocate cache ID (%d) larger than table size (%d)\n",
+			cid, target_cnt);
+		return -EINVAL;
+	}
+
+	target_n = readw(cidrt + CXL_CACHE_ID_RT_TARGETN_OFFSET(cid));
+	if (FIELD_GET(CXL_CACHE_ID_RT_TARGETN_VALID, target_n)) {
+		portn = FIELD_GET(CXL_CACHE_ID_RT_TARGETN_PORTN, target_n);
+		return dport_id == portn ? 0 : -EINVAL;
+	}
+
+	target_n = CXL_CACHE_ID_RT_TARGETN_VALID;
+	target_n |= FIELD_PREP(CXL_CACHE_ID_RT_TARGETN_PORTN, dport_id);
+	writew(target_n, cidrt + CXL_CACHE_ID_RT_TARGETN_OFFSET(cid));
+
+	return cxl_cid_commit_table(port);
+}
+
+static void cxl_cid_invalidate_table_entry(struct cxl_port *port, int cid)
+{
+	void __iomem *cidrt = port->regs.cidrt;
+	u8 target_cnt;
+	u16 target_n;
+	u32 cap;
+	int rc;
+
+	if (!cidrt)
+		return;
+
+	cap = readl(cidrt + CXL_CACHE_ID_RT_CAP_OFFSET);
+	target_cnt = FIELD_GET(CXL_CACHE_ID_RT_CAP_TARGET_CNT, cap);
+
+	/* Shouldn't be possible, but better to be safe */
+	if (cid >= target_cnt) {
+		dev_err(&port->dev,
+			"Tried to free cache ID (%d) larger than table size (%d)\n",
+			cid, target_cnt);
+		return;
+	}
+
+	target_n = readw(cidrt + CXL_CACHE_ID_RT_TARGETN_OFFSET(cid));
+	if (!FIELD_GET(CXL_CACHE_ID_RT_TARGETN_VALID, target_n))
+		return;
+
+	target_n &= ~CXL_CACHE_ID_RT_TARGETN_VALID;
+	writew(target_n, cidrt + CXL_CACHE_ID_RT_TARGETN_OFFSET(cid));
+
+	rc = cxl_cid_commit_table(port);
+	if (rc)
+		dev_warn(
+			&port->dev,
+			"Failed to commit invalidation of cache id table entry %d: %d\n",
+			cid, rc);
+}
+
+static int get_max_cid(struct cxl_port *endpoint)
+{
+	struct cxl_port *port = parent_port_of(endpoint);
+	void __iomem *cidrt;
+	u32 cap;
+	u8 cnt;
+
+	if (!port)
+		return -EINVAL;
+
+	while (!is_cxl_root(port) && !is_cxl_root(parent_port_of(port)))
+		port = parent_port_of(port);
+
+	cidrt = port->regs.cidrt;
+	if (!cidrt)
+		return -EINVAL;
+
+	cap = readl(cidrt + CXL_CACHE_ID_RT_CAP_OFFSET);
+	cnt = FIELD_GET(CXL_CACHE_ID_RT_CAP_TARGET_CNT, cap);
+	if (cnt == 0)
+		return 0;
+
+	/*
+	 * Cache id decoders have 4 bits for the cache id, while target count
+	 * is a 5 bit long field. Limit cache ids to the maximum value allowed
+	 * by cache id decoders.
+	 */
+	return min(CACHE_DECODER_MAX_CACHE_ID, cnt - 1);
+}
+
 static struct ida *find_cache_id_ida(struct cxl_port *port)
 {
 	struct cxl_port *parent = parent_port_of(port);
@@ -130,15 +388,26 @@ static struct ida *find_cache_id_ida(struct cxl_port *port)
 int cxl_allocate_cache_id(struct cxl_cachedev *cxlcd)
 {
 	struct ida *ida = find_cache_id_ida(cxlcd->endpoint);
-	int id;
+	int min, max, id;
 
 	if (!ida)
 		return -ENOSPC;
 
-	id = ida_alloc_range(ida, cxlcd->cache_id, cxlcd->cache_id, GFP_KERNEL);
-	if (id != cxlcd->cache_id)
+	max = get_max_cid(cxlcd->endpoint);
+	if (max < 0 || cxlcd->cache_id > max)
 		return -EINVAL;
 
+	if (cxlcd->cache_id == CXL_CACHE_ID_NO_ID) {
+		min = 0;
+	} else {
+		min = max = cxlcd->cache_id;
+	}
+
+	id = ida_alloc_range(ida, min, max, GFP_KERNEL);
+	if (id < 0)
+		return id;
+
+	cxlcd->cache_id = id;
 	return 0;
 }
 EXPORT_SYMBOL_FOR_MODULES(cxl_allocate_cache_id, "cxl_cache");
@@ -196,4 +465,64 @@ int cxl_cachedev_validate_cache_id(struct cxl_cachedev *cxlcd)
 	return 0;
 }
 EXPORT_SYMBOL_FOR_MODULES(cxl_cachedev_validate_cache_id, "cxl_cache");
->>>>>>> conflict 1 of 1 ends
+
+static void __deprogram_cache_id(struct cxl_cachedev *cxlcd,
+				 struct cxl_port *stop)
+{
+	struct cxl_port *iter = cxlcd->endpoint->parent_dport->port;
+
+	/*
+	 * Leave cache id decoders programmed; the table entry being invalidated
+	 * should be enough
+	 */
+	while (!is_cxl_root(iter)) {
+		cxl_cid_invalidate_table_entry(iter, cxlcd->cache_id);
+
+		if (iter == stop)
+			return;
+
+		iter = parent_port_of(iter);
+	}
+}
+
+int cxl_cachedev_program_cache_id(struct cxl_cachedev *cxlcd)
+{
+	struct cxl_dport *dport = cxlcd->endpoint->parent_dport;
+	struct cxl_port *port = dport->port;
+	bool endpoint = true;
+	int rc;
+
+	while (!is_cxl_root(port)) {
+		rc = cxl_cid_program_decoder(dport, cxlcd->cache_id,
+					     endpoint);
+		if (rc)
+			goto err;
+
+		rc = cxl_cid_program_table_entry(port, cxlcd->cache_id,
+						 dport->port_id);
+		if (rc)
+			goto err;
+
+		endpoint = false;
+		dport = port->parent_dport;
+		port = dport->port;
+	}
+
+	return 0;
+
+err:
+	__deprogram_cache_id(cxlcd, port);
+	return rc;
+}
+EXPORT_SYMBOL_FOR_MODULES(cxl_cachedev_program_cache_id, "cxl_cache");
+
+void cxl_cachedev_deprogram_cache_id(struct cxl_cachedev *cxlcd)
+{
+	struct cxl_root *root = find_cxl_root(cxlcd->endpoint);
+
+	if (!root)
+		return;
+
+	__deprogram_cache_id(cxlcd, &root->port);
+}
+EXPORT_SYMBOL_FOR_MODULES(cxl_cachedev_deprogram_cache_id, "cxl_cache");
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index ed6b56a269ee..4cdc26dbdb6a 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -230,10 +230,16 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
 #define CXL_CACHE_ID_RT_CAP_OFFSET 0x0
 #define   CXL_CACHE_ID_RT_CAP_TARGET_CNT GENMASK(4, 0)
 #define   CXL_CACHE_ID_RT_CAP_COMMIT_REQ BIT(16)
+#define CXL_CACHE_ID_RT_CTRL_OFFSET 0x4
+#define   CXL_CACHE_ID_RT_CTRL_COMMIT BIT(0)
 #define CXL_CACHE_ID_RT_STATUS_OFFSET 0x8
 #define   CXL_CACHE_ID_RT_STATUS_COMMITTED BIT(0)
+#define   CXL_CACHE_ID_RT_STATUS_COMMIT_ERR BIT(1)
+#define   CXL_CACHE_ID_RT_STATUS_TM_SCALE GENMASK(11, 8)
+#define   CXL_CACHE_ID_RT_STATUS_TM_BASE GENMASK(15, 12)
 #define CXL_CACHE_ID_RT_TARGETN_OFFSET(n) (0x10 + (2 * (n)))
 #define   CXL_CACHE_ID_RT_TARGETN_VALID BIT(0)
+#define   CXL_CACHE_ID_RT_TARGETN_PORTN GENMASK(15, 8)
 
 /* CXL 4.0 8.2.4.29.1 CXL Cache ID Decoder Capability Structure */
 #define CXL_CACHE_ID_DC_CAP_OFFSET 0x0
@@ -242,10 +248,14 @@ static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
 #define   CXL_CACHE_ID_DC_CTRL_FWD_ID BIT(0)
 #define   CXL_CACHE_ID_DC_CTRL_ASGN_ID BIT(1)
 #define   CXL_CACHE_ID_DC_CTRL_HDMD_PRESENT BIT(2)
+#define   CXL_CACHE_ID_DC_CTRL_COMMIT BIT(3)
 #define   CXL_CACHE_ID_DC_CTRL_HDMD_ID GENMASK(11, 8)
 #define   CXL_CACHE_ID_DC_CTRL_LOCAL_ID GENMASK(19, 16)
 #define CXL_CACHE_ID_DC_STATUS_OFFSET 0x8
 #define   CXL_CACHE_ID_DC_STATUS_COMMITTED BIT(0)
+#define   CXL_CACHE_ID_DC_STATUS_COMMIT_ERR BIT(1)
+#define   CXL_CACHE_ID_DC_STATUS_TM_SCALE GENMASK(11, 8)
+#define   CXL_CACHE_ID_DC_STATUS_TM_BASE GENMASK(15, 12)
 #define CXL_CACHE_ID_DC_CAPABILITY_LENGTH 0xC
 
 void cxl_probe_component_regs(struct device *dev, void __iomem *base,
diff --git a/drivers/cxl/cxlcache.h b/drivers/cxl/cxlcache.h
index 1e4a1e61ad7b..72d58eded292 100644
--- a/drivers/cxl/cxlcache.h
+++ b/drivers/cxl/cxlcache.h
@@ -45,4 +45,6 @@ bool cxl_cache_id_supported(struct cxl_cachedev *cxlcd);
 int cxl_allocate_cache_id(struct cxl_cachedev *cxlcd);
 void cxl_free_cache_id(struct cxl_cachedev *cxlcd);
 int cxl_cachedev_validate_cache_id(struct cxl_cachedev *cxlcd);
+int cxl_cachedev_program_cache_id(struct cxl_cachedev *cxlcd);
+void cxl_cachedev_deprogram_cache_id(struct cxl_cachedev *cxlcd);
 #endif
-- 
2.53.0


  parent reply	other threads:[~2026-09-23 17:34 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23 17:33 [PATCH 00/15] Add initial CXL.cache support Ben Cheatham
2026-09-23 17:33 ` [PATCH 01/15] cxl/core: Add CXL.cache device struct Ben Cheatham
2026-09-23 17:41   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 02/15] cxl/cache: Add cxl_cache driver Ben Cheatham
2026-09-23 17:49   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 03/15] cxl/core: Change cxl_ep_load() to use device pointer parameter Ben Cheatham
2026-09-23 17:33 ` [PATCH 04/15] cxl/core: Update devm_cxl_enumerate_ports() for cxl_cachedevs Ben Cheatham
2026-09-23 17:33 ` [PATCH 05/15] cxl/port: Split endpoint port probe on device type Ben Cheatham
2026-09-23 17:46   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 06/15] cxl/core: Update devm_cxl_add_endpoint() for cxl_cachedevs Ben Cheatham
2026-09-23 17:51   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 07/15] cxl/cache: Verify port hierarchy has CXL.cache enabled Ben Cheatham
2026-09-23 17:33 ` [PATCH 08/15] cxl/core, cache: Add Cache ID register probing and init Ben Cheatham
2026-09-23 17:46   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 09/15] cxl/core: Add Cache ID verification Ben Cheatham
2026-09-23 17:49   ` sashiko-bot
2026-09-23 17:33 ` Ben Cheatham [this message]
2026-09-23 17:49   ` [PATCH 10/15] cxl/core: Add Cache ID allocation sashiko-bot
2026-09-23 17:33 ` [PATCH 11/15] cxl/core: Add support for HDM-D cache id programming Ben Cheatham
2026-09-23 17:51   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 12/15] cxl/cache: Add snoop filter creation and set up Ben Cheatham
2026-09-23 17:50   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 13/15] cxl/cache: Add snoop filter allocation Ben Cheatham
2026-09-23 17:58   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 14/15] iommu, cxl: Configure IOMMU for CXL.cache Ben Cheatham
2026-09-23 17:57   ` sashiko-bot
2026-09-23 17:33 ` [PATCH 15/15] cxl/cache: Enable CXL.cache on successful probe Ben Cheatham
2026-09-23 17:35 ` [PATCH 00/15] Add initial CXL.cache support Cheatham, Benjamin

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=20260923173342.5584-11-Benjamin.Cheatham@amd.com \
    --to=benjamin.cheatham@amd.com \
    --cc=alison.schofield@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=jic23@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-iommu@vger.kernel.org \
    --cc=robert.richter@amd.com \
    --cc=terry.bowman@amd.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