From: Anisa Su <anisa.su887@gmail.com>
To: linux-cxl@vger.kernel.org
Cc: nvdimm@lists.linux.dev, linux-kernel@vger.kernel.org,
Dave Jiang <dave.jiang@intel.com>,
Alison Schofield <alison.schofield@intel.com>,
Jonathan Cameron <jic23@kernel.org>,
Davidlohr Bueso <dave@stgolabs.net>,
Ira Weiny <iweiny@kernel.org>,
Vishal Verma <vishal.l.verma@intel.com>,
Fan Ni <nifan.cxl@gmail.com>, Li Ming <ming.li@zohomail.com>,
Benjamin Cheatham <benjamin.cheatham@amd.com>,
Gregory Price <gourry@gourry.net>,
Richard Cheng <icheng@nvidia.com>,
Anisa Su <anisa.su@samsung.com>
Subject: [PATCH v1 09/14] cxl/mem: Enforce tag-group semantics
Date: Thu, 5 Nov 2026 08:02:33 +0900 [thread overview]
Message-ID: <20261104230445.66625-10-anisa.su@samsung.com> (raw)
In-Reply-To: <20261104230445.66625-1-anisa.su@samsung.com>
The previous commits added validation for individual extents. Add
two group-level checks to cxl_validate_group():
- Sequence integrity (cxl_check_group_seq): sharability is taken from
the group's DC partition attribute (cxl_group_is_shareable).
For a sharable partition, extents have a shared_extn_seq number,
which must be 0..n-1 for a tag. Any gaps or duplicate values are an
error.
The field is reserved for non-sharable extents, and
cxl_validate_extent() rejects a non-zero value there when the group
is realized. Therefore, cxl_check_group_seq only applies to
sharable groups.
- cxl_check_group_partition: verify tagged allocations
don't span DC partitions.
Each check drops the whole group on violation.
Tag uniqueness checks land in a subsequent commit.
Based on patches by John Groves.
Co-developed-by: John Groves <John@Groves.net>
Signed-off-by: John Groves <John@Groves.net>
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>
---
drivers/cxl/core/mbox.c | 138 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 133 insertions(+), 5 deletions(-)
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index a605ffc4c64f..a1d3e04a1e1b 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -1452,6 +1452,119 @@ static void extract_tag_group(struct list_head *pending,
}
}
+/*
+ * Validate shared_extn_seq across a tag group from a sharable partition,
+ * already sorted ascending. Per CXL r4.0 Table 8-230 the device stamps
+ * each extent of an n-extent sharable allocation with a unique value in
+ * 0..n-1, so the sorted group must be exactly 0, 1, ..., n-1. A gap,
+ * duplicate, or out-of-range value is a device firmware bug.
+ *
+ * Non-sharable extents must carry 0 here, which cxl_validate_extent()
+ * enforces per extent when the group is realized, so only sharable
+ * groups are checked; sharability comes from the partition, not the
+ * seq value.
+ */
+static int cxl_check_group_seq(struct device *dev,
+ const uuid_t *tag,
+ const struct list_head *group,
+ bool shareable)
+{
+ struct cxl_extent_list_node *pos;
+ u16 expected = 0;
+
+ if (!shareable)
+ return 0;
+
+ list_for_each_entry(pos, group, list) {
+ u16 s = le16_to_cpu(pos->extent->shared_extn_seq);
+
+ if (s != expected) {
+ dev_warn_ratelimited(dev,
+ "Tag %pUb: sharable shared_extn_seq must be dense 0..n-1: expected %u got %u (firmware bug)\n",
+ tag, expected, s);
+ return -EINVAL;
+ }
+ expected++;
+ }
+ return 0;
+}
+
+/*
+ * A tag group's sharability is a property of the DC partition holding its
+ * extents (cxl_check_group_partition() separately enforces that the group
+ * does not span partitions). Resolve it from the first extent; an empty
+ * group or an extent outside any DC partition is treated as non-sharable.
+ */
+static bool cxl_group_is_shareable(struct cxl_memdev_state *mds,
+ const struct list_head *group)
+{
+ const struct cxl_dpa_partition *part;
+ struct cxl_extent_list_node *first;
+ struct cxl_extent *extent;
+ struct range ext_range;
+
+ if (list_empty(group))
+ return false;
+
+ first = list_first_entry(group, struct cxl_extent_list_node, list);
+ extent = first->extent;
+ ext_range = (struct range) {
+ .start = le64_to_cpu(extent->start_dpa),
+ .end = le64_to_cpu(extent->start_dpa) +
+ le64_to_cpu(extent->length) - 1,
+ };
+ part = cxl_extent_dc_partition(mds, extent, &ext_range);
+ return part && part->shareable;
+}
+
+/*
+ * For tagged groups, reject allocations that span DC partitions. A tag
+ * is an allocation identity; the partition's CDAT DSMAS entry is what
+ * tells the host which attributes (sharable, writable, coherency)
+ * apply. Untagged groups are skipped — the spec does not define a
+ * cross-chain identity for them.
+ */
+static int cxl_check_group_partition(struct cxl_memdev_state *mds,
+ const uuid_t *tag,
+ const struct list_head *group)
+{
+ struct device *dev = mds->cxlds.dev;
+ const struct cxl_dpa_partition *first_part = NULL;
+ u64 first_dpa = 0;
+ struct cxl_extent_list_node *pos;
+
+ if (uuid_is_null(tag) || list_empty(group))
+ return 0;
+
+ list_for_each_entry(pos, group, list) {
+ struct cxl_extent *extent = pos->extent;
+ struct range ext_range = (struct range) {
+ .start = le64_to_cpu(extent->start_dpa),
+ .end = le64_to_cpu(extent->start_dpa) +
+ le64_to_cpu(extent->length) - 1,
+ };
+ const struct cxl_dpa_partition *part;
+
+ part = cxl_extent_dc_partition(mds, extent, &ext_range);
+ if (!part)
+ return -ENXIO;
+
+ if (!first_part) {
+ first_part = part;
+ first_dpa = ext_range.start;
+ continue;
+ }
+
+ if (part != first_part) {
+ dev_warn_ratelimited(dev,
+ "Tag %pUb: extents span DC partitions (DPA:%#llx and DPA:%#llx), firmware bug\n",
+ tag, first_dpa, ext_range.start);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
/*
* Realize a tag @group: assign each extent its dax-side @seq_num and add it
* via cxl_add_extent(), then online the resulting tag group. Returns the
@@ -1460,7 +1573,7 @@ static void extract_tag_group(struct list_head *pending,
* the caller to drop.
*/
static int cxl_realize_group(struct cxl_memdev_state *mds, const uuid_t *tag,
- struct list_head *group)
+ struct list_head *group, bool shareable)
{
struct device *dev = mds->cxlds.dev;
struct cxl_extent_list_node *pos;
@@ -1475,7 +1588,12 @@ static int cxl_realize_group(struct cxl_memdev_state *mds, const uuid_t *tag,
/* Each extent gets a dense dax-side seq_num, 0..n-1 */
seq_num = -1;
list_for_each_entry(pos, group, list) {
- seq_num++;
+ /* Sharable: device-assigned dense 0..n-1; otherwise by arrival */
+ if (shareable)
+ seq_num = le16_to_cpu(pos->extent->shared_extn_seq);
+ else
+ seq_num++;
+
rc = cxl_add_extent(mds, pos->extent, seq_num);
if (rc < 0) {
dev_dbg(dev,
@@ -1517,11 +1635,19 @@ static int cxl_realize_group(struct cxl_memdev_state *mds, const uuid_t *tag,
* added, or a negative errno if it must be dropped.
*/
static int cxl_validate_group(struct cxl_memdev_state *mds, const uuid_t *tag,
- struct list_head *group)
+ struct list_head *group, bool shareable)
{
struct device *dev = mds->cxlds.dev;
struct cxl_extent_list_node *pos;
+ /* Sequence-number integrity */
+ if (cxl_check_group_seq(dev, tag, group, shareable))
+ return -EINVAL;
+
+ /* Partition equality (skipped for null UUID) */
+ if (cxl_check_group_partition(mds, tag, group))
+ return -EINVAL;
+
/* Alignment gate — drop the group if any member fails */
list_for_each_entry(pos, group, list) {
if (!cxl_extent_dcd_aligned(pos->extent)) {
@@ -1559,6 +1685,7 @@ static int cxl_add_pending(struct cxl_memdev_state *mds,
while (!list_empty(pending)) {
struct cxl_extent_list_node *first;
LIST_HEAD(group);
+ bool shareable;
uuid_t tag;
int cnt;
@@ -1581,13 +1708,14 @@ static int cxl_add_pending(struct cxl_memdev_state *mds,
* the stable sort maintains arrival order.
*/
list_sort(NULL, &group, extent_seq_compare);
+ shareable = cxl_group_is_shareable(mds, &group);
- if (cxl_validate_group(mds, &tag, &group)) {
+ if (cxl_validate_group(mds, &tag, &group, shareable)) {
drop_extent_group(&group);
continue;
}
- cnt = cxl_realize_group(mds, &tag, &group);
+ cnt = cxl_realize_group(mds, &tag, &group, shareable);
if (cnt < 0) {
drop_extent_group(&group);
continue;
--
2.43.0
next prev parent reply other threads:[~2026-11-04 23:03 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 23:02 [PATCH v1 00/14] DCD CXL Series: Dynamic Capacity extent handling Anisa Su
2026-11-04 23:02 ` [PATCH v1 01/14] cxl/core: Return endpoint decoder information from region search Anisa Su
2026-11-04 23:02 ` [PATCH v1 02/14] cxl/port: Add dynamic capacity options to endpoint decoder mode Anisa Su
2026-11-04 23:02 ` [PATCH v1 03/14] cxl/region: Add dynamic DAX region support Anisa Su
2026-11-04 23:02 ` [PATCH v1 04/14] cxl/mem: Introduce DC event handlers Anisa Su
2026-11-04 23:02 ` [PATCH v1 05/14] cxl/mem: Add 20 second timeout for stalled DC event chains Anisa Su
2026-11-04 23:02 ` [PATCH v1 06/14] cxl/extent: Handle DC Add Capacity events Anisa Su
2026-11-04 23:02 ` [PATCH v1 07/14] cxl/mem: Drop misaligned DCD extent groups Anisa Su
2026-11-04 23:02 ` [PATCH v1 08/14] cxl/extent: Validate DC extent partition Anisa Su
2026-11-04 23:02 ` Anisa Su [this message]
2026-11-04 23:02 ` [PATCH v1 10/14] cxl/extent: Enforce cross-region tag uniqueness Anisa Su
2026-11-04 23:02 ` [PATCH v1 11/14] cxl/extent: Handle DC Release Capacity events Anisa Su
2026-11-04 23:02 ` [PATCH v1 12/14] cxl/region: Read existing extents on region creation Anisa Su
2026-11-04 23:02 ` [PATCH v1 13/14] cxl/mem: Trace Dynamic capacity Event Record Anisa Su
2026-11-04 23:02 ` [PATCH v1 14/14] Documentation/cxl: Document DCD extent handling Anisa Su
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=20261104230445.66625-10-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=icheng@nvidia.com \
--cc=iweiny@kernel.org \
--cc=jic23@kernel.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ming.li@zohomail.com \
--cc=nifan.cxl@gmail.com \
--cc=nvdimm@lists.linux.dev \
--cc=vishal.l.verma@intel.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
all inboxes | Powered by JetHome®