]> git.itanic.dy.fi Git - linux-stable/commitdiff
cxl/hdm: Default CXL_DEVTYPE_DEVMEM decoders to CXL_DECODER_DEVMEM
authorDan Williams <dan.j.williams@intel.com>
Thu, 15 Jun 2023 01:30:19 +0000 (18:30 -0700)
committerDan Williams <dan.j.williams@intel.com>
Sun, 25 Jun 2023 21:31:08 +0000 (14:31 -0700)
In preparation for device-memory region creation, arrange for decoders
of CXL_DEVTYPE_DEVMEM memdevs to default to CXL_DECODER_DEVMEM for their
target type.

Revisit this if a device ever shows up that wants to offer mixed HDM-H
(Host-Only Memory) and HDM-DB support, or an CXL_DEVTYPE_DEVMEM device
that supports HDM-H.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/168679261945.3436160.11673393474107374595.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/hdm.c
drivers/cxl/cxl.h

index 79170de13d898b844009ecf7b6dbb066001bc5db..715c1f10373923038f150178f131dece12d35ff7 100644 (file)
@@ -572,7 +572,7 @@ static void cxld_set_type(struct cxl_decoder *cxld, u32 *ctrl)
 {
        u32p_replace_bits(ctrl,
                          !!(cxld->target_type == CXL_DECODER_HOSTONLYMEM),
-                         CXL_HDM_DECODER0_CTRL_TYPE);
+                         CXL_HDM_DECODER0_CTRL_HOSTONLY);
 }
 
 static int cxlsd_set_targets(struct cxl_switch_decoder *cxlsd, u64 *tgt)
@@ -794,8 +794,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                            int *target_map, void __iomem *hdm, int which,
                            u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
 {
+       struct cxl_endpoint_decoder *cxled = NULL;
        u64 size, base, skip, dpa_size, lo, hi;
-       struct cxl_endpoint_decoder *cxled;
        bool committed;
        u32 remainder;
        int i, rc;
@@ -828,6 +828,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                return -ENXIO;
        }
 
+       if (info)
+               cxled = to_cxl_endpoint_decoder(&cxld->dev);
        cxld->hpa_range = (struct range) {
                .start = base,
                .end = base + size - 1,
@@ -838,7 +840,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                cxld->flags |= CXL_DECODER_F_ENABLE;
                if (ctrl & CXL_HDM_DECODER0_CTRL_LOCK)
                        cxld->flags |= CXL_DECODER_F_LOCK;
-               if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl))
+               if (FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl))
                        cxld->target_type = CXL_DECODER_HOSTONLYMEM;
                else
                        cxld->target_type = CXL_DECODER_DEVMEM;
@@ -857,12 +859,28 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                }
                port->commit_end = cxld->id;
        } else {
-               /* unless / until type-2 drivers arrive, assume type-3 */
-               if (FIELD_GET(CXL_HDM_DECODER0_CTRL_TYPE, ctrl) == 0) {
-                       ctrl |= CXL_HDM_DECODER0_CTRL_TYPE;
+               if (cxled) {
+                       struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+                       struct cxl_dev_state *cxlds = cxlmd->cxlds;
+
+                       /*
+                        * Default by devtype until a device arrives that needs
+                        * more precision.
+                        */
+                       if (cxlds->type == CXL_DEVTYPE_CLASSMEM)
+                               cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+                       else
+                               cxld->target_type = CXL_DECODER_DEVMEM;
+               } else {
+                       /* To be overridden by region type at commit time */
+                       cxld->target_type = CXL_DECODER_HOSTONLYMEM;
+               }
+
+               if (!FIELD_GET(CXL_HDM_DECODER0_CTRL_HOSTONLY, ctrl) &&
+                   cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
+                       ctrl |= CXL_HDM_DECODER0_CTRL_HOSTONLY;
                        writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
                }
-               cxld->target_type = CXL_DECODER_HOSTONLYMEM;
        }
        rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
                          &cxld->interleave_ways);
@@ -881,7 +899,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
                cxld->interleave_ways, cxld->interleave_granularity);
 
-       if (!info) {
+       if (!cxled) {
                lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
                hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
                target_list.value = (hi << 32) + lo;
@@ -904,7 +922,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
        lo = readl(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
        hi = readl(hdm + CXL_HDM_DECODER0_SKIP_HIGH(which));
        skip = (hi << 32) + lo;
-       cxled = to_cxl_endpoint_decoder(&cxld->dev);
        rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
        if (rc) {
                dev_err(&port->dev,
index ae0965ac8c5a5f23064e9db2aeb0d6a1f1d5bce9..f309b1387858bf37dcb0cc6ef5348f84ef2b2419 100644 (file)
@@ -56,7 +56,7 @@
 #define   CXL_HDM_DECODER0_CTRL_COMMIT BIT(9)
 #define   CXL_HDM_DECODER0_CTRL_COMMITTED BIT(10)
 #define   CXL_HDM_DECODER0_CTRL_COMMIT_ERROR BIT(11)
-#define   CXL_HDM_DECODER0_CTRL_TYPE BIT(12)
+#define   CXL_HDM_DECODER0_CTRL_HOSTONLY BIT(12)
 #define CXL_HDM_DECODER0_TL_LOW(i) (0x20 * (i) + 0x24)
 #define CXL_HDM_DECODER0_TL_HIGH(i) (0x20 * (i) + 0x28)
 #define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i)