cxl_region_determine_granularity() rejects any user-supplied granularity
that does not exactly match the root decoder's granularity, making it
impossible to create mixed-granularity regions from userspace even when
the kernel driver accepts them.

Relax the check to allow region_gran <= root_gran. The kernel validates
constraints at region-commit time so this function only needs to reject
the one arrangement it can determine is always wrong: a region
granularity greater than the root decoder's granularity.

Update the cxl-create-region man page to document the new behavior.

Signed-off-by: Alison Schofield <[email protected]>
---
 Documentation/cxl/cxl-create-region.txt | 13 ++++++++-----
 cxl/region.c                            | 13 +++++++------
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/Documentation/cxl/cxl-create-region.txt 
b/Documentation/cxl/cxl-create-region.txt
index b244af60b8a6..d2ff47ec2a18 100644
--- a/Documentation/cxl/cxl-create-region.txt
+++ b/Documentation/cxl/cxl-create-region.txt
@@ -93,11 +93,14 @@ include::bus-option.txt[]
 
 -g::
 --granularity=::
-       The interleave granularity for the new region. Must match the selected
-       root decoder's (if provided) granularity. If the root decoder is
-       interleaved across more than one host-bridge then this value must match
-       that granularity. Otherwise, for non-interleaved decode windows, any
-       granularity can be specified as long as all devices support that 
setting.
+       The interleave granularity for the new region. If the root decoder is
+       interleaved across more than one host bridge, the region granularity
+       must be less than or equal to the root decoder granularity. A region
+       granularity less than root creates a mixed-granularity configuration
+       where the root interleaves at a coarser granularity and subordinate
+       switches interleave at the finer region granularity. For
+       non-interleaved root decoders, any granularity can be specified as
+       long as all devices support that setting.
 
 -d::
 --decoder=::
diff --git a/cxl/region.c b/cxl/region.c
index 85d4d9bb54f2..fbc7272b9a84 100644
--- a/cxl/region.c
+++ b/cxl/region.c
@@ -632,15 +632,16 @@ static int cxl_region_determine_granularity(struct 
cxl_region *region,
                return p->granularity;
 
        /*
-        * For ways > 1, only allow the same granularity as the selected
-        * root decoder
+        * For ways > 1, allow any region granularity up to and including the
+        * root decoder granularity. A finer region granularity produces a
+        * mixed-granularity configuration and a coarser one is always invalid.
         */
-       if (p->granularity == granularity)
-               return granularity;
+       if (p->granularity <= granularity)
+               return p->granularity;
 
        log_err(&rl,
-               "%s: For an x%d root, only root decoder granularity (%d) 
permitted\n",
-               devname, ways, granularity);
+               "%s: region granularity (%d) cannot exceed root decoder 
granularity (%d)\n",
+               devname, p->granularity, granularity);
        return -EINVAL;
 }
 

base-commit: bbd403a03fa2a1551c1a10bbf78f32027c718758
-- 
2.37.3


Reply via email to