Re: [PATCH v11 02/31] cxl/mem: Read dynamic capacity configuration from the device

Anisa Su <[email protected]>
Newsgroups org.kernel.vger.linux-cxl,dev.linux.lists.nvdimm,dev.linux.lists.sashiko-reviews
Message-ID <[email protected]>
On Thu, Jun 25, 2026 at 06:16:36PM +0000, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
> - [High] Mailbox payload size statically requests too many partitions, failing initialization on devices with small mailboxes.

fine... I fixed it but I find it unlikely for a DCD to have the minimum 256B
mailbox size

> - [High] Incorrect unit conversion of DC partition decode_length causes severe integer overflow.

false pos
explained below

> - [High] Logic Error in DPA Skip Check mathematically guarantees failure, breaking DCD on all devices.
false pos
explained below

> - [Medium] Valid CXL devices configured with 0 Dynamic Capacity partitions are erroneously treated as having an I/O error.

false pos. Partition info is only requested if mds->dcd_supported, which is set
to true if the device supports the full set of DCD commands. If the
device supports the commands and has 0 partitions that is an error.

> --
> 
> commit cbb0f735b5888cbb19cb493b31cc330ef3afdadf
> Author: Ira Weiny <[email protected]>
> 
> cxl/mem: Read dynamic capacity configuration from the device
> 
> This commit implements the mailbox commands to read Dynamic Capacity
> partition configurations from CXL devices. It validates the partitions
> and configures the first partition as dynamic RAM.
> 
> > diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
> > index 07aba6f0b7194..2932bbd67e550 100644
> > --- a/drivers/cxl/core/mbox.c
> > +++ b/drivers/cxl/core/mbox.c
> > @@ -1347,6 +1347,188 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
> 
> [ ... ]
> 
> > +static int cxl_dc_check(struct device *dev, struct cxl_dc_partition_info *part_array,
> > +			u8 index, struct cxl_dc_partition *dev_part)
> > +{
> > +	u64 blk_size = le64_to_cpu(dev_part->block_size);
> > +	u64 len = le64_to_cpu(dev_part->length);
> > +
> > +	part_array[index].start = le64_to_cpu(dev_part->base);
> > +	part_array[index].size = le64_to_cpu(dev_part->decode_length);
> > +	part_array[index].size *= CXL_CAPACITY_MULTIPLIER;
> 
> [Severity: High]
> Is it correct to multiply decode_length by CXL_CAPACITY_MULTIPLIER here?
> 
it is.

> The CXL specification provides the decode length in bytes, similar to the 
> base and length fields. Multiplying this by 256MB will cause a 64-bit 

r4.0 8.3.10.9.9.1 Table 8-347 "Region Decode Length" The
device-assigned number of bytes of DPA that this region consumes, in
multiples of 256MB"

decode length is provided in multiples of 256B. This conversion is
necessary to get actual # of bytes.

> integer overflow for capacities of 64GB or larger. This overflow can wrap 
> around to a small value, bypassing the later DPA ordering checks and 
> registering a corrupted partition size.
> 
> [ ... ]
> 
> > +/* Returns the number of partitions in dc_resp or -ERRNO */
> > +static int cxl_get_dc_config(struct cxl_mailbox *mbox, u8 start_partition,
> > +			     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 = CXL_MAX_DC_PARTITIONS,
> > +		.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,
> > +		.min_out = 8,
> > +	};
> 
> [ ... ]
> 
> > +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);
> > +	struct device *dev = mbox->host;
> > +	u8 start_partition;
> > +	u8 num_partitions;
> > +	size_t dc_resp_size = struct_size(dc_resp,
> > +					  partition,
> > +					  CXL_MAX_DC_PARTITIONS);
> 
> [Severity: High]
> Can this static size calculation cause initialization failures on devices 
> with small mailboxes?
> 
> The code requests CXL_MAX_DC_PARTITIONS (8 partitions), resulting in an 
> expected response payload size of 328 bytes (an 8-byte header plus 8 
> 40-byte partition entries). However, the CXL specification allows a minimum 
> mailbox payload size of 256 bytes. 
> 
> If a device has a mailbox smaller than 328 bytes, cxl_internal_send_cmd() 
> will unconditionally fail with -E2BIG. Should the requested number of 
> partitions be dynamically bounded by the device's negotiated payload size?
> 
Fixed. # of partitions requested per iteration of the loop
capped to mailbox size.

> > +	dc_resp = kmalloc(dc_resp_size, GFP_KERNEL);
> > +	if (!dc_resp)
> > +		return -ENOMEM;
> > +
> > +	/**
> > +	 * Read and check all partition information for validity and potential
> > +	 * debugging; see debug output in cxl_dc_check()
> > +	 */
> > +	start_partition = 0;
> > +	num_partitions = 0;
> > +	do {
> > +		int rc, i, j;
> > +
> > +		rc = cxl_get_dc_config(mbox, start_partition, dc_resp, dc_resp_size);
> > +		if (rc < 0) {
> > +			dev_err(dev, "Failed to get DC config: %d\n", rc);
> > +			return rc;
> > +		}
> > +
> > +		if (rc == 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;
> > +		}
> 
> [Severity: Medium]
> Does this unintentionally fail on valid devices configured with 0 Dynamic 
> Capacity partitions?
> 
> If a device supports DCD but is configured with zero partitions, 
> avail_partition_count is 0, and cxl_get_dc_config() legitimately returns 0. 
> This path treats it as a hard error and returns -EIO, logging a confusing 
> error message instead of cleanly disabling DCD and proceeding.
> 
> [ ... ]
> 
> > +void cxl_configure_dcd(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
> > +{
> > +	struct cxl_dc_partition_info dc_info = { 0 };
> > +	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);
> > +		cxl_disable_dcd(mds);
> > +		return;
> > +	}
> > +
> > +	/* Skips between pmem and the dynamic partition are not supported */
> > +	if (dc_info.start != info->size) {
> > +		dev_warn(dev,
> > +			 "Dynamic Capacity skip from pmem not supported\n");
> > +		cxl_disable_dcd(mds);
> > +		return;
> > +	}
> 
> [Severity: High]
> Is it intended to compare dc_info.start against info->size here?
> 
> Because cxl_mem_dpa_fetch() initializes info->size to mds->total_bytes, 
> it already includes the dynamic capacity. 

no it doesn't. it only includes ram and pmem partitions.

> This means dc_info.start will 
> always be strictly less than info->size, causing this skip check to falsely 
> fail on every valid device with a DC partition and breaking DCD entirely.
> 
> > +
> > +	info->size += dc_info.size;
> 
> [Severity: High]
> Does this inadvertently double-count the dynamic capacity?
> 
no.

> Since info->size already includes the total device capacity, adding 
> dc_info.size here will inflate the total DPA span incorrectly.
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.