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
next prev 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 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.