]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cxl/region: Block region delete during region creation
authorDan Williams <djbw@kernel.org>
Tue, 19 May 2026 21:01:54 +0000 (14:01 -0700)
committerDave Jiang <dave.jiang@intel.com>
Fri, 12 Jun 2026 20:47:28 +0000 (13:47 -0700)
Expand the range lock, rename it "regions_lock", to disable region deletion
in the critical period between construct_region() and attach_target(), as
well as the period between device_add() and registering the remove actions.

Otherwise, userspace can confuse the kernel. It can violate the assumption
the region stays registered through the completion of cxl_add_to_region().
It can violate the assumption that devm_add_action_or_reset() is working
with a live 'struct cxl_region'.

It is ok for the region to disappear outside of those windows as that
mirrors device hotplug flows where the proper locks are held.

Fixes: a32320b71f08 ("cxl/region: Add region autodiscovery")
Signed-off-by: Dan Williams <djbw@kernel.org>
Reviewed-by: Alejandro Lucero <alucerop@amd.com>
Tested-by: ALejandro Lucero <alucerop@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/20260519210158.1499795-2-djbw@kernel.org
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
drivers/cxl/core/port.c
drivers/cxl/core/region.c
drivers/cxl/cxl.h

index c5aacd7054f1d245d8334d6397530da44ce5130e..6e7a70d51cfe4dd18c503f9e9e1168e5b93eeffa 100644 (file)
@@ -2016,7 +2016,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
                return ERR_PTR(rc);
        }
 
-       mutex_init(&cxlrd->range_lock);
+       mutex_init(&cxlrd->regions_lock);
 
        cxld = &cxlsd->cxld;
        cxld->dev.type = &cxl_decoder_root_type;
index e50dc716d4e820df278840814eed91483c461cd8..b5601e89e302eecf8b4b923d838b8ad9d478c7a5 100644 (file)
@@ -2779,6 +2779,10 @@ static ssize_t create_region_store(struct device *dev, const char *buf,
        if (rc != 1)
                return -EINVAL;
 
+       ACQUIRE(mutex_intr, regions_lock)(&cxlrd->regions_lock);
+       if ((rc = ACQUIRE_ERR(mutex_intr, &regions_lock)))
+               return rc;
+
        cxlr = __create_region(cxlrd, mode, id, CXL_DECODER_HOSTONLYMEM);
        if (IS_ERR(cxlr))
                return PTR_ERR(cxlr);
@@ -2838,6 +2842,11 @@ static ssize_t delete_region_store(struct device *dev,
        struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(dev);
        struct cxl_port *port = to_cxl_port(dev->parent);
        struct cxl_region *cxlr;
+       int rc;
+
+       ACQUIRE(mutex_intr, regions_lock)(&cxlrd->regions_lock);
+       if ((rc = ACQUIRE_ERR(mutex_intr, &regions_lock)))
+               return rc;
 
        cxlr = cxl_find_region_by_name(cxlrd, buf);
        if (IS_ERR(cxlr))
@@ -3776,12 +3785,11 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled)
         * for the HPA range, one does the construction and the others
         * add to that.
         */
-       mutex_lock(&cxlrd->range_lock);
+       guard(mutex)(&cxlrd->regions_lock);
        struct cxl_region *cxlr __free(put_cxl_region) =
                cxl_find_region_by_range(cxlrd, &ctx.hpa_range);
        if (!cxlr)
                cxlr = construct_region(cxlrd, &ctx);
-       mutex_unlock(&cxlrd->range_lock);
 
        rc = PTR_ERR_OR_ZERO(cxlr);
        if (rc)
index 1297594beaec31f1e49a8ae05dbcca00e267111b..3900a0778571d449ef54ea4b3bba2ce3c3a15143 100644 (file)
@@ -359,7 +359,7 @@ struct cxl_rd_ops {
  * @cache_size: extended linear cache size if exists, otherwise zero.
  * @region_id: region id for next region provisioning event
  * @platform_data: platform specific configuration data
- * @range_lock: sync region autodiscovery by address range
+ * @regions_lock: sync region discovery, construction, and deletion
  * @qos_class: QoS performance class cookie
  * @ops: CXL root decoder operations
  * @cxlsd: base cxl switch decoder
@@ -369,7 +369,7 @@ struct cxl_root_decoder {
        resource_size_t cache_size;
        atomic_t region_id;
        void *platform_data;
-       struct mutex range_lock;
+       struct mutex regions_lock;
        int qos_class;
        struct cxl_rd_ops ops;
        struct cxl_switch_decoder cxlsd;