cxl/core/regs: Add @dev to cxl_register_map
[linux-2.6-block.git] / drivers / cxl / core / hdm.c
index 02cc2c38b44baf8ef37c3dd9c4b4d7806181e3bb..5abfa9276dac0e03eeb61222b5ba3d3545d5c834 100644 (file)
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
-#include <linux/io-64-nonatomic-hi-lo.h>
 #include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/delay.h>
@@ -86,6 +85,7 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
                                struct cxl_component_regs *regs)
 {
        struct cxl_register_map map = {
+               .dev = &port->dev,
                .resource = port->component_reg_phys,
                .base = crb,
                .max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
@@ -93,12 +93,12 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
 
        cxl_probe_component_regs(&port->dev, crb, &map.component_map);
        if (!map.component_map.hdm_decoder.valid) {
-               dev_err(&port->dev, "HDM decoder registers invalid\n");
-               return -ENXIO;
+               dev_dbg(&port->dev, "HDM decoder registers not implemented\n");
+               /* unique error code to indicate no HDM decoder capability */
+               return -ENODEV;
        }
 
-       return cxl_map_component_regs(&port->dev, regs, &map,
-                                     BIT(CXL_CM_CAP_CAP_ID_HDM));
+       return cxl_map_component_regs(&map, regs, BIT(CXL_CM_CAP_CAP_ID_HDM));
 }
 
 static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
@@ -130,6 +130,14 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
         */
        for (i = 0; i < cxlhdm->decoder_count; i++) {
                ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
+               dev_dbg(&info->port->dev,
+                       "decoder%d.%d: committed: %ld base: %#x_%.8x size: %#x_%.8x\n",
+                       info->port->id, i,
+                       FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl),
+                       readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(i)),
+                       readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(i)),
+                       readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(i)),
+                       readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(i)));
                if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
                        return false;
        }
@@ -269,8 +277,11 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
 
        lockdep_assert_held_write(&cxl_dpa_rwsem);
 
-       if (!len)
-               goto success;
+       if (!len) {
+               dev_warn(dev, "decoder%d.%d: empty reservation attempted\n",
+                        port->id, cxled->cxld.id);
+               return -EINVAL;
+       }
 
        if (cxled->dpa_res) {
                dev_dbg(dev, "decoder%d.%d: existing allocation %pr assigned\n",
@@ -323,7 +334,6 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
                cxled->mode = CXL_DECODER_MIXED;
        }
 
-success:
        port->hdm_end++;
        get_device(&cxled->cxld.dev);
        return 0;
@@ -783,8 +793,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)
 {
+       u64 size, base, skip, dpa_size, lo, hi;
        struct cxl_endpoint_decoder *cxled;
-       u64 size, base, skip, dpa_size;
        bool committed;
        u32 remainder;
        int i, rc;
@@ -799,8 +809,12 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                                                        which, info);
 
        ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
-       base = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which));
-       size = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which));
+       lo = readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which));
+       hi = readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(which));
+       base = (hi << 32) + lo;
+       lo = readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(which));
+       hi = readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(which));
+       size = (hi << 32) + lo;
        committed = !!(ctrl & CXL_HDM_DECODER0_CTRL_COMMITTED);
        cxld->commit = cxl_decoder_commit;
        cxld->reset = cxl_decoder_reset;
@@ -833,6 +847,13 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                                 port->id, cxld->id);
                        return -ENXIO;
                }
+
+               if (size == 0) {
+                       dev_warn(&port->dev,
+                                "decoder%d.%d: Committed with zero size\n",
+                                port->id, cxld->id);
+                       return -ENXIO;
+               }
                port->commit_end = cxld->id;
        } else {
                /* unless / until type-2 drivers arrive, assume type-3 */
@@ -855,9 +876,14 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
        if (rc)
                return rc;
 
+       dev_dbg(&port->dev, "decoder%d.%d: range: %#llx-%#llx iw: %d ig: %d\n",
+               port->id, cxld->id, cxld->hpa_range.start, cxld->hpa_range.end,
+               cxld->interleave_ways, cxld->interleave_granularity);
+
        if (!info) {
-               target_list.value =
-                       ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which));
+               lo = readl(hdm + CXL_HDM_DECODER0_TL_LOW(which));
+               hi = readl(hdm + CXL_HDM_DECODER0_TL_HIGH(which));
+               target_list.value = (hi << 32) + lo;
                for (i = 0; i < cxld->interleave_ways; i++)
                        target_map[i] = target_list.target_id[i];
 
@@ -874,7 +900,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                        port->id, cxld->id, size, cxld->interleave_ways);
                return -ENXIO;
        }
-       skip = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
+       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) {