Re: [PATCH v18 09/20] cxl: Define a driver interface for HPA free space enumeration
From: Jonathan Cameron <jonathan.cameron@huawei.com>
Date: 2025-09-18 14:35:15
Also in:
linux-cxl
On Thu, 18 Sep 2025 10:17:35 +0100 [off-list ref] wrote:
From: Alejandro Lucero <redacted> CXL region creation involves allocating capacity from Device Physical Address (DPA) and assigning it to decode a given Host Physical Address (HPA). Before determining how much DPA to allocate the amount of available HPA must be determined. Also, not all HPA is created equal, some HPA targets RAM, some targets PMEM, some is prepared for device-memory flows like HDM-D and HDM-DB, and some is HDM-H (host-only). In order to support Type2 CXL devices, wrap all of those concerns into an API that retrieves a root decoder (platform CXL window) that fits the specified constraints and the capacity available for a new region. Add a complementary function for releasing the reference to such root decoder. Based on https://lore.kernel.org/linux-cxl/168592159290.1948938.13522227102445462976.stgit@dwillia2-xfh.jf.intel.com/ (local) Signed-off-by: Alejandro Lucero <redacted> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Either I was half asleep or a few things have snuck in. See below.
+ +/** + * cxl_get_hpa_freespace - find a root decoder with free capacity per constraints + * @endpoint: the endpoint requiring the HPA
The parameter seems to have changed. Make sure to point scripts/kernel-doc at each file to check for stuff like this.
+ * @interleave_ways: number of entries in @host_bridges
+ * @flags: CXL_DECODER_F flags for selecting RAM vs PMEM, and Type2 device
+ * @max_avail_contig: output parameter of max contiguous bytes available in the
+ * returned decoder
+ *
+ * Returns a pointer to a struct cxl_root_decoder
+ *
+ * The return tuple of a 'struct cxl_root_decoder' and 'bytes available given
+ * in (@max_avail_contig))' is a point in time snapshot. If by the time the
+ * caller goes to use this root decoder's capacity the capacity is reduced then
+ * caller needs to loop and retry.
+ *
+ * The returned root decoder has an elevated reference count that needs to be
+ * put with cxl_put_root_decoder(cxlrd).
+ */
+struct cxl_root_decoder *cxl_get_hpa_freespace(struct cxl_memdev *cxlmd,
+ int interleave_ways,
+ unsigned long flags,
+ resource_size_t *max_avail_contig)
+{
+ struct cxl_root *root __free(put_cxl_root) = NULL;Nope to this. See the stuff in cleanup.h on why not.
+ struct cxl_port *endpoint = cxlmd->endpoint;
+ struct cxlrd_max_context ctx = {
+ .host_bridges = &endpoint->host_bridge,
+ .flags = flags,
+ };
+ struct cxl_port *root_port;
+
+ if (!endpoint) {
+ dev_dbg(&cxlmd->dev, "endpoint not linked to memdev\n");
+ return ERR_PTR(-ENXIO);
+ }
+
+ root = find_cxl_root(endpoint);extra space, but should be struct cxl_root *root __free(put_cxl_root) = find_cxl_root(endpoint); anyway.
+ if (!root) {
+ dev_dbg(&endpoint->dev, "endpoint can not be related to a root port\n");
+ return ERR_PTR(-ENXIO);
+ }
+
+ root_port = &root->port;
+ scoped_guard(rwsem_read, &cxl_rwsem.region)
+ device_for_each_child(&root_port->dev, &ctx, find_max_hpa);
+
+ if (!ctx.cxlrd)
+ return ERR_PTR(-ENOMEM);
+
+ *max_avail_contig = ctx.max_hpa;
+ return ctx.cxlrd;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_get_hpa_freespace, "CXL");
+
+/*
+ * TODO: those references released here should avoid the decoder to be
+ * unregistered.That is an ominous sounding TODO for a v18. Perhaps add more on why this is still here.
+ */
+void cxl_put_root_decoder(struct cxl_root_decoder *cxlrd)
+{
+ put_device(cxlrd_dev(cxlrd));
+}
+EXPORT_SYMBOL_NS_GPL(cxl_put_root_decoder, "CXL");