Re: [PATCH v11 02/31] cxl/mem: Read dynamic capacity configuration from the device
Anisa Su <[email protected]> Tue, 14 Jul 2026 23:26:53 -0700
| Newsgroups | dev.linux.lists.nvdimm,dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-cxl |
|---|---|
| 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