From: Anisa Su <anisa.su887@gmail.com>
To: linux-cxl@vger.kernel.org
Cc: alison.schofield@intel.com, jic23@kernel.org,
dave.jiang@intel.com, gourry@gourry.net, icheng@nvidia.com,
ming.li@zohomail.com, vishal.l.verma@intel.com,
dave@stgolabs.net, benjamin.cheatham@amd.com,
Ira Weiny <iweiny@kernel.org>, Anisa Su <anisa.su@samsung.com>,
Wonjae Lee <wj28.lee@samsung.com>,
Junhee Park <jh9934.park@samsung.com>,
Heesoo Kim <habil.kim@samsung.com>
Subject: [RESEND PATCH v13 2/8] cxl/mem: Read dynamic capacity configuration from the device
Date: Tue, 8 Sep 2026 03:15:06 -0700 [thread overview]
Message-ID: <20260908102124.2231730-4-anisa.su@samsung.com> (raw)
In-Reply-To: <20260908102124.2231730-2-anisa.su@samsung.com>
From: Ira Weiny <iweiny@kernel.org>
Devices which support Dynamic Capacity (DC) are configured
via mailbox commands. CXL r4.0 section 9.13.3 requires the host to issue
the Get DC Configuration command in order to properly configure DCDs.
Implement the DC mailbox commands as specified in CXL 4.0 section
8.2.10.9.9 (opcodes 48XXh) to read and store the DCD configuration
information. Disable DCD if an invalid configuration is found.
Linux has no support for more than one dynamic capacity partition. Read
all the partitions the device reports but validate only the first, and
configure it as 'dynamic ram 1'.
The specification requires that volatile capacity starts at DPA 0 and pmem
starts at the DPA immediately following it, but DC partitions only need
to be 256MB aligned according to CXL r4.0 section 8.2.10.9.9.1 Table 8-347.
So a device could leave a gap between ram/pmem (static) capacity and its first
DC partition, or between one DC partition and the next.
However, Linux follows the precedent set by PMEM/RAM partitions and requires the
first DC partition to begin at the DPA immediately following static
capacity.
Based on an original patch by Navneet Singh.
Signed-off-by: Ira Weiny <iweiny@kernel.org>
Signed-off-by: Anisa Su <anisa.su@samsung.com>
Tested-by: Wonjae Lee <wj28.lee@samsung.com>
Tested-by: Junhee Park <jh9934.park@samsung.com>
Tested-by: Heesoo Kim <habil.kim@samsung.com>
---
Changes:
1. mbox.c: validate only the first DC partition. Other partitions are read
to make it easier to add support for additional partitions but not
checked. Richard/Alison
2. mbox.c: rework the cxl_dc_check() validation. Run the checks in
dependency order -- block size, decode length, length, base -- so the
block size is validated before IS_ALIGNED() uses it as an alignment,
and give each failure its own message naming the field that is wrong.
Drop the block size alignment requirement on the region base; CXL
r4.0 Table 8-347 requires the base to be 256M aligned and states the
block size alignment for extent start DPAs, not for the base.
Reported by Alison.
3. mbox.c: range check the number of available DC partitions reported by
the device. CXL r4.0 Table 8-346 requires a DCD to report between 1
and 8 regions, but the count was used unchecked as the read loop
bound, so an out of range value failed later as "Invalid num of
dynamic capacity partitions". Reported by Alison.
4. mbox.c/pci.c: cxl_configure_dcd() returns an error instead of void,
and cxl_pci_probe() decides what to do with it. Failure to read the
DC configuration is now reported rather than silently swallowed;
-EINVAL for a partition overlapping static capacity, -EOPNOTSUPP for
the gap Linux does not support, and the mailbox error propagated
otherwise. cxl_disable_dcd() moves to the caller so the function
reports and the caller sets policy. Probe still continues without
DCD rather than failing the memdev, which would cost the device its
static capacity too. Reported by Jonathan Cameron.
5. mbox.c: check the block size is a power of 2 in 64 bits.
is_power_of_2() takes an unsigned long, so on a 32 bit build blk_size
was truncated to its low 32 bits and a value such as 0x100000040 --
non-zero and a multiple of 40h -- passed validation. CXL_BUS only
depends on PCI, so this builds on 32 bit. Reported by Sashiko.
---
drivers/cxl/core/hdm.c | 2 +
drivers/cxl/core/mbox.c | 235 ++++++++++++++++++++++++++++++++++++++
drivers/cxl/core/memdev.c | 37 ++++++
drivers/cxl/cxlmem.h | 55 +++++++++
drivers/cxl/pci.c | 6 +
include/cxl/cxl.h | 3 +-
6 files changed, 337 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 0c80b76a5f9b..0ef076c08ed2 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -446,6 +446,8 @@ static const char *cxl_mode_name(enum cxl_partition_mode mode)
return "ram";
case CXL_PARTMODE_PMEM:
return "pmem";
+ case CXL_PARTMODE_DYNAMIC_RAM_1:
+ return "dynamic_ram_1";
default:
return "";
};
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 199bb986d674..a484e23b2b3a 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1349,6 +1349,241 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
return -EBUSY;
}
+/*
+ * A partition unavailable for Dynamic Capacity reports zeros for decode_length,
+ * length, and block_size.
+ */
+static bool cxl_dc_partition_unavailable(struct cxl_dc_partition *dev_part)
+{
+ return !le64_to_cpu(dev_part->decode_length) &&
+ !le64_to_cpu(dev_part->length) &&
+ !le64_to_cpu(dev_part->block_size);
+}
+
+static int cxl_dc_check(struct device *dev, struct cxl_dc_partition_info *part,
+ struct cxl_dc_partition *dev_part)
+{
+ u64 blk_size = le64_to_cpu(dev_part->block_size);
+ u64 len = le64_to_cpu(dev_part->length);
+
+ /*
+ * Not an error; leave the entry empty. A partially zeroed partition
+ * is rejected by the checks below. CXL r4.0 Table 8-347.
+ */
+ if (cxl_dc_partition_unavailable(dev_part)) {
+ *part = (struct cxl_dc_partition_info) { };
+ dev_dbg(dev, "Partition 0 unavailable for DC\n");
+ return 0;
+ }
+
+ *part = (struct cxl_dc_partition_info) {
+ .start = le64_to_cpu(dev_part->base),
+ .size = le64_to_cpu(dev_part->decode_length) * CXL_CAPACITY_MULTIPLIER,
+ };
+
+ /*
+ * Block size is a power of 2 and a multiple of 40h. is_power_of_2()
+ * takes an unsigned long, which truncates blk_size on 32 bit.
+ */
+ if (blk_size == 0 || (blk_size & (blk_size - 1)) ||
+ blk_size % CXL_DCD_BLOCK_LINE_SIZE) {
+ dev_err(dev, "DC partition 0 invalid block size %#llx\n", blk_size);
+ return -EINVAL;
+ }
+
+ if (part->size == 0) {
+ dev_err(dev, "DC partition 0 zero decode length\n");
+ return -EINVAL;
+ }
+
+ if (len == 0) {
+ dev_err(dev, "DC partition 0 zero length\n");
+ return -EINVAL;
+ }
+
+ if (len > part->size) {
+ dev_err(dev, "DC partition 0 length %#llx exceeds decode length %#llx\n",
+ len, part->size);
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(len, blk_size)) {
+ dev_err(dev, "DC partition 0 length %#llx not a multiple of block size %#llx\n",
+ len, blk_size);
+ return -EINVAL;
+ }
+
+ if (!IS_ALIGNED(part->start, SZ_256M)) {
+ dev_err(dev, "DC partition 0 base %#llx not aligned to 256M\n",
+ part->start);
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "DC partition 0 start %#llx size %#llx blk_size: %#llx\n",
+ part->start, part->size, blk_size);
+
+ return 0;
+}
+
+/* Returns the number of partitions in dc_resp or -ERRNO */
+static int cxl_get_dc_config(struct cxl_mailbox *mbox, u8 start_partition,
+ u8 partition_count,
+ struct cxl_mbox_get_dc_config_out *dc_resp,
+ size_t dc_resp_size)
+{
+ struct cxl_mbox_get_dc_config_in get_dc = (struct cxl_mbox_get_dc_config_in) {
+ .partition_count = partition_count,
+ .start_partition_index = start_partition,
+ };
+ struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_DC_CONFIG,
+ .payload_in = &get_dc,
+ .size_in = sizeof(get_dc),
+ .size_out = dc_resp_size,
+ .payload_out = dc_resp,
+ /* The device must return at least the fixed header */
+ .min_out = sizeof(*dc_resp),
+ };
+ size_t expected_sz;
+ int rc;
+
+ rc = cxl_internal_send_cmd(mbox, &mbox_cmd);
+ if (rc < 0)
+ return rc;
+
+ /* A DCD reports between 1 and 8 partitions */
+ if (dc_resp->avail_partition_count == 0 ||
+ dc_resp->avail_partition_count > CXL_MAX_DC_PARTITIONS) {
+ dev_err(mbox->host,
+ "Device reported %u available DC partitions, expected 1 to %u\n",
+ dc_resp->avail_partition_count, CXL_MAX_DC_PARTITIONS);
+ return -EIO;
+ }
+
+ if (dc_resp->partitions_returned > partition_count) {
+ dev_err(mbox->host, "Device returned %u partitions, requested %u\n",
+ dc_resp->partitions_returned, partition_count);
+ return -EIO;
+ }
+
+ /*
+ * The payload carries trailing extent/tag count fields after the
+ * partition array (CXL r4.0 Table 8-346) which the driver ignores, so
+ * the response is at least, not exactly, expected_sz.
+ */
+ expected_sz = struct_size(dc_resp, partition,
+ dc_resp->partitions_returned);
+
+ if (mbox_cmd.size_out < expected_sz) {
+ dev_err(mbox->host,
+ "Payload size %zu less than expected %zu for %u partitions\n",
+ mbox_cmd.size_out,
+ expected_sz,
+ dc_resp->partitions_returned);
+ return -EIO;
+ }
+
+ dev_dbg(mbox->host, "Read %d/%d DC partitions\n",
+ dc_resp->partitions_returned, dc_resp->avail_partition_count);
+ return dc_resp->partitions_returned;
+}
+
+/**
+ * cxl_dev_dc_identify() - Reads the dynamic capacity information from the
+ * device.
+ * @mbox: Mailbox to query
+ * @dc_info: The dynamic partition information to return
+ *
+ * Read every partition the device reports, but validate only the first:
+ * Linux maps partition 0 and nothing else, so a defect in capacity the
+ * driver never touches is not a reason to refuse the device dynamic
+ * capacity. The remaining entries of @partitions are left unset.
+ *
+ * Return: 0 if identify was executed successfully, -ERRNO on error.
+ * on error only dc_info is left unchanged.
+ */
+int cxl_dev_dc_identify(struct cxl_mailbox *mbox,
+ struct cxl_dc_partition_info *dc_info)
+{
+ struct cxl_dc_partition_info partitions[CXL_MAX_DC_PARTITIONS] = { };
+ struct cxl_mbox_get_dc_config_out *dc_resp __free(kfree) = NULL;
+ struct device *dev = mbox->host;
+ u8 start_partition;
+ u8 num_partitions;
+ u8 partition_count;
+ size_t dc_resp_size;
+
+ /*
+ * Bound requested number of partitions by mailbox payload size. The
+ * 256 byte spec minimum, verified in cxl_pci_setup_mailbox(), keeps
+ * the subtraction below from underflowing.
+ */
+ partition_count = min_t(size_t, CXL_MAX_DC_PARTITIONS,
+ (mbox->payload_size - sizeof(*dc_resp) -
+ sizeof(struct cxl_mbox_get_dc_config_tail)) /
+ sizeof(struct cxl_dc_partition));
+ dc_resp_size = struct_size(dc_resp, partition, partition_count) +
+ sizeof(struct cxl_mbox_get_dc_config_tail);
+
+ dc_resp = kmalloc(dc_resp_size, GFP_KERNEL);
+ if (!dc_resp)
+ return -ENOMEM;
+
+ start_partition = 0;
+ num_partitions = 0;
+ do {
+ int returned, rc;
+
+ returned = cxl_get_dc_config(mbox, start_partition,
+ partition_count, dc_resp,
+ dc_resp_size);
+ if (returned < 0) {
+ dev_err(dev, "Failed to get DC config: %d\n", returned);
+ return returned;
+ }
+
+ if (returned == 0) {
+ dev_err(dev,
+ "Device reported %u partitions available but returned none at index %u\n",
+ dc_resp->avail_partition_count, start_partition);
+ return -EIO;
+ }
+
+ /*
+ * Only partition 0 is mapped, so it is the only one checked.
+ * The rest are read to complete the enumeration and dropped.
+ */
+ if (start_partition == 0) {
+ rc = cxl_dc_check(dev, &partitions[0],
+ &dc_resp->partition[0]);
+ if (rc)
+ return rc;
+ }
+
+ num_partitions += returned;
+
+ if (num_partitions > CXL_MAX_DC_PARTITIONS) {
+ dev_err(dev, "Invalid num of dynamic capacity partitions %d\n",
+ num_partitions);
+ return -EINVAL;
+ }
+
+ start_partition = num_partitions;
+
+ } while (num_partitions < dc_resp->avail_partition_count);
+
+ /* Linux only supports the 1st partition; nothing to do if it is unavailable */
+ if (partitions[0].size == 0)
+ return -ENODEV;
+
+ *dc_info = partitions[0];
+ dev_dbg(dev, "Returning partition 0 %#llx size %#llx\n",
+ dc_info->start, dc_info->size);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_dev_dc_identify, "CXL");
+
int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count)
{
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index b3419df586b9..fdd6b395dcdf 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -643,6 +643,43 @@ int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
}
EXPORT_SYMBOL_NS_GPL(cxl_mem_dpa_fetch, "CXL");
+int cxl_configure_dcd(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
+{
+ struct cxl_dc_partition_info dc_info = { };
+ struct device *dev = mds->cxlds.dev;
+ int rc;
+
+ rc = cxl_dev_dc_identify(&mds->cxlds.cxl_mbox, &dc_info);
+ if (rc) {
+ dev_warn(dev,
+ "Failed to read Dynamic Capacity config: %d\n", rc);
+ return rc;
+ }
+
+ if (dc_info.start < info->size) {
+ dev_err(dev,
+ "DC partition 0 base %#llx overlaps static capacity ending at %#llx\n",
+ dc_info.start, info->size);
+ return -EINVAL;
+ }
+
+ /* A gap between static capacity and the DC partition is not supported */
+ if (dc_info.start > info->size) {
+ dev_warn(dev,
+ "DC partition 0 base %#llx leaves a gap from static capacity ending at %#llx\n",
+ dc_info.start, info->size);
+ return -EOPNOTSUPP;
+ }
+
+ info->size += dc_info.size;
+ dev_dbg(dev, "Adding dynamic ram partition 1; %#llx size %#llx\n",
+ dc_info.start, dc_info.size);
+ add_part(info, dc_info.start, dc_info.size, CXL_PARTMODE_DYNAMIC_RAM_1);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_configure_dcd, "CXL");
+
/**
* cxl_set_capacity: initialize dpa by a driver without a mailbox.
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 0c8e23276dc6..4fac65dbb808 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -407,6 +407,8 @@ struct cxl_security_state {
struct kernfs_node *sanitize_node;
};
+#define CXL_MAX_DC_PARTITIONS 8
+
static inline resource_size_t cxl_pmem_size(struct cxl_dev_state *cxlds)
{
/*
@@ -689,6 +691,39 @@ struct cxl_mbox_set_shutdown_state_in {
u8 state;
} __packed;
+/* See CXL r4.0 Table 8-345 get dynamic capacity config Input Payload */
+struct cxl_mbox_get_dc_config_in {
+ u8 partition_count;
+ u8 start_partition_index;
+} __packed;
+
+/* See CXL r4.0 Table 8-346 get dynamic capacity config Output Payload */
+struct cxl_mbox_get_dc_config_out {
+ u8 avail_partition_count;
+ u8 partitions_returned;
+ u8 rsvd[6];
+ /* See CXL r4.0 Table 8-347 */
+ struct cxl_dc_partition {
+ __le64 base;
+ __le64 decode_length;
+ __le64 length;
+ __le64 block_size;
+ __le32 dsmad_handle;
+ u8 flags;
+ u8 rsvd[3];
+ } __packed partition[] __counted_by(partitions_returned);
+ /* Trailing extent/tag count fields unused */
+} __packed;
+
+/* Trailing counts; cannot be a member after the flex array above */
+struct cxl_mbox_get_dc_config_tail {
+ __le32 num_extents_supported;
+ __le32 num_extents_available;
+ __le32 num_tags_supported;
+ __le32 num_tags_available;
+} __packed;
+#define CXL_DCD_BLOCK_LINE_SIZE 0x40
+
/* Set Timestamp CXL 3.0 Spec 8.2.9.4.2 */
struct cxl_mbox_set_timestamp_in {
__le64 timestamp;
@@ -812,9 +847,18 @@ enum {
int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox,
struct cxl_mbox_cmd *cmd);
int cxl_dev_state_identify(struct cxl_memdev_state *mds);
+
+struct cxl_dc_partition_info {
+ u64 start;
+ u64 size;
+};
+
+int cxl_dev_dc_identify(struct cxl_mailbox *mbox,
+ struct cxl_dc_partition_info *dc_info);
int cxl_await_media_ready(struct cxl_dev_state *cxlds);
int cxl_enumerate_cmds(struct cxl_memdev_state *mds);
int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info);
+int cxl_configure_dcd(struct cxl_memdev_state *mds, struct cxl_dpa_info *info);
struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev, u64 serial,
u16 dvsec);
void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
@@ -828,6 +872,17 @@ void cxl_event_trace_record(struct cxl_memdev *cxlmd,
const uuid_t *uuid, union cxl_event *evt);
int cxl_get_dirty_count(struct cxl_memdev_state *mds, u32 *count);
int cxl_arm_dirty_shutdown(struct cxl_memdev_state *mds);
+
+static inline bool cxl_dcd_supported(struct cxl_memdev_state *mds)
+{
+ return mds->dcd_supported;
+}
+
+static inline void cxl_disable_dcd(struct cxl_memdev_state *mds)
+{
+ mds->dcd_supported = false;
+}
+
int cxl_set_timestamp(struct cxl_memdev_state *mds);
int cxl_poison_state_init(struct cxl_memdev_state *mds);
int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index c7c91e8dc51d..2fe9db4b3d86 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -868,6 +868,12 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
+ if (cxl_dcd_supported(mds)) {
+ rc = cxl_configure_dcd(mds, &range_info);
+ if (rc)
+ cxl_disable_dcd(mds);
+ }
+
rc = cxl_dpa_setup(cxlds, &range_info);
if (rc)
return rc;
diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
index 802b143de83d..4ef9511fbbdd 100644
--- a/include/cxl/cxl.h
+++ b/include/cxl/cxl.h
@@ -133,6 +133,7 @@ struct cxl_dpa_perf {
enum cxl_partition_mode {
CXL_PARTMODE_RAM,
CXL_PARTMODE_PMEM,
+ CXL_PARTMODE_DYNAMIC_RAM_1,
};
/**
@@ -147,7 +148,7 @@ struct cxl_dpa_partition {
enum cxl_partition_mode mode;
};
-#define CXL_NR_PARTITIONS_MAX 2
+#define CXL_NR_PARTITIONS_MAX 3
/**
* struct cxl_dev_state - The driver device state
--
2.43.0
next prev parent reply other threads:[~2026-09-08 10:22 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 10:15 [RESEND PATCH v13 0/8] DCD Prep Series Anisa Su
2026-09-08 10:15 ` [RESEND PATCH v13 1/8] cxl/mbox: Flag support for Dynamic Capacity Devices (DCD) Anisa Su
2026-09-08 15:39 ` dave
2026-09-08 18:45 ` Jonathan Cameron
2026-09-08 10:15 ` Anisa Su [this message]
2026-09-08 15:59 ` [RESEND PATCH v13 2/8] cxl/mem: Read dynamic capacity configuration from the device Davidlohr Bueso
2026-09-08 20:43 ` Jonathan Cameron
2026-09-10 23:56 ` Anisa Su
2026-09-11 0:53 ` Jonathan Cameron
2026-09-11 16:38 ` Anisa Su
2026-09-08 10:15 ` [RESEND PATCH v13 3/8] cxl/cdat: Gather DSMAS data for DCD partitions Anisa Su
2026-09-08 20:52 ` Jonathan Cameron
2026-09-11 0:02 ` Anisa Su
2026-09-11 0:56 ` Jonathan Cameron
2026-09-11 16:37 ` Anisa Su
2026-09-08 10:15 ` [RESEND PATCH v13 4/8] cxl/events: Split event msgnum configuration from irq setup Anisa Su
2026-09-08 16:37 ` Davidlohr Bueso
2026-09-08 10:15 ` [RESEND PATCH v13 5/8] cxl/pci: Factor out interrupt policy check Anisa Su
2026-09-08 17:17 ` Davidlohr Bueso
2026-09-08 10:15 ` [RESEND PATCH v13 6/8] cxl/mem: Configure dynamic capacity interrupts Anisa Su
2026-09-08 10:43 ` sashiko-bot
2026-09-11 21:10 ` Anisa Su
2026-09-12 0:09 ` Gregory Price
2026-09-08 22:14 ` Jonathan Cameron
2026-09-11 18:21 ` Anisa Su
2026-09-08 10:15 ` [RESEND PATCH v13 7/8] cxl/core: Enforce partition order/simplify partition calls Anisa Su
2026-09-08 10:15 ` [RESEND PATCH v13 8/8] Documentation/cxl: Document DPA partition layout and ordering rules Anisa Su
2026-09-08 22:17 ` Jonathan Cameron
2026-09-11 20:39 ` Anisa Su
2026-09-09 15:19 ` Davidlohr Bueso
2026-09-11 20:38 ` Anisa Su
2026-09-11 20:50 ` Davidlohr Bueso
2026-09-12 0:20 ` Gregory Price
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=20260908102124.2231730-4-anisa.su@samsung.com \
--to=anisa.su887@gmail.com \
--cc=alison.schofield@intel.com \
--cc=anisa.su@samsung.com \
--cc=benjamin.cheatham@amd.com \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=gourry@gourry.net \
--cc=habil.kim@samsung.com \
--cc=icheng@nvidia.com \
--cc=iweiny@kernel.org \
--cc=jh9934.park@samsung.com \
--cc=jic23@kernel.org \
--cc=linux-cxl@vger.kernel.org \
--cc=ming.li@zohomail.com \
--cc=vishal.l.verma@intel.com \
--cc=wj28.lee@samsung.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