cxl/pci: Refactor cxl_hdm_decode_init()
authorDave Jiang <dave.jiang@intel.com>
Tue, 14 Feb 2023 19:41:19 +0000 (11:41 -0800)
committerDan Williams <dan.j.williams@intel.com>
Tue, 14 Feb 2023 23:45:21 +0000 (15:45 -0800)
With the previous refactoring of DVSEC range registers out of
cxl_hdm_decode_init(), it basically becomes a skeleton function. Squash
__cxl_hdm_decode_init() with cxl_hdm_decode_init() to simplify the code.
cxl_hdm_decode_init() now returns more error codes than just -EBUSY.

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

index 948fa3724a0f8bd74510c9b027f1c19fc066ec14..d0b25481bdce9dded76f0793310293f7fb45ffe5 100644 (file)
@@ -259,80 +259,6 @@ static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
        return devm_add_action_or_reset(host, disable_hdm, cxlhdm);
 }
 
-static bool __cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
-                                 struct cxl_hdm *cxlhdm,
-                                 struct cxl_endpoint_dvsec_info *info)
-{
-       void __iomem *hdm = cxlhdm->regs.hdm_decoder;
-       struct cxl_port *port = cxlhdm->port;
-       struct device *dev = cxlds->dev;
-       struct cxl_port *root;
-       int i, rc, allowed;
-       u32 global_ctrl;
-
-       global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
-
-       /*
-        * If the HDM Decoder Capability is already enabled then assume
-        * that some other agent like platform firmware set it up.
-        */
-       if (global_ctrl & CXL_HDM_DECODER_ENABLE) {
-               rc = devm_cxl_enable_mem(&port->dev, cxlds);
-               if (rc)
-                       return false;
-               return true;
-       }
-
-       root = to_cxl_port(port->dev.parent);
-       while (!is_cxl_root(root) && is_cxl_port(root->dev.parent))
-               root = to_cxl_port(root->dev.parent);
-       if (!is_cxl_root(root)) {
-               dev_err(dev, "Failed to acquire root port for HDM enable\n");
-               return false;
-       }
-
-       for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) {
-               struct device *cxld_dev;
-
-               cxld_dev = device_find_child(&root->dev, &info->dvsec_range[i],
-                                            dvsec_range_allowed);
-               if (!cxld_dev) {
-                       dev_dbg(dev, "DVSEC Range%d denied by platform\n", i);
-                       continue;
-               }
-               dev_dbg(dev, "DVSEC Range%d allowed by platform\n", i);
-               put_device(cxld_dev);
-               allowed++;
-       }
-
-       if (!allowed) {
-               cxl_set_mem_enable(cxlds, 0);
-               info->mem_enabled = 0;
-       }
-
-       /*
-        * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
-        * [High,Low] when HDM operation is enabled the range register values
-        * are ignored by the device, but the spec also recommends matching the
-        * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
-        * are expected even though Linux does not require or maintain that
-        * match. If at least one DVSEC range is enabled and allowed, skip HDM
-        * Decoder Capability Enable.
-        */
-       if (info->mem_enabled)
-               return false;
-
-       rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
-       if (rc)
-               return false;
-
-       rc = devm_cxl_enable_mem(&port->dev, cxlds);
-       if (rc)
-               return false;
-
-       return true;
-}
-
 int cxl_dvsec_rr_decode(struct device *dev, int d,
                        struct cxl_endpoint_dvsec_info *info)
 {
@@ -447,19 +373,66 @@ EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL);
 int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
                        struct cxl_endpoint_dvsec_info *info)
 {
+       void __iomem *hdm = cxlhdm->regs.hdm_decoder;
+       struct cxl_port *port = cxlhdm->port;
        struct device *dev = cxlds->dev;
+       struct cxl_port *root;
+       int i, rc, allowed;
+       u32 global_ctrl;
+
+       global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
 
        /*
-        * If DVSEC ranges are being used instead of HDM decoder registers there
-        * is no use in trying to manage those.
+        * If the HDM Decoder Capability is already enabled then assume
+        * that some other agent like platform firmware set it up.
         */
-       if (!__cxl_hdm_decode_init(cxlds, cxlhdm, info)) {
-               dev_err(dev,
-                       "Legacy range registers configuration prevents HDM operation.\n");
-               return -EBUSY;
+       if (global_ctrl & CXL_HDM_DECODER_ENABLE)
+               return devm_cxl_enable_mem(&port->dev, cxlds);
+
+       root = to_cxl_port(port->dev.parent);
+       while (!is_cxl_root(root) && is_cxl_port(root->dev.parent))
+               root = to_cxl_port(root->dev.parent);
+       if (!is_cxl_root(root)) {
+               dev_err(dev, "Failed to acquire root port for HDM enable\n");
+               return -ENODEV;
        }
 
-       return 0;
+       for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) {
+               struct device *cxld_dev;
+
+               cxld_dev = device_find_child(&root->dev, &info->dvsec_range[i],
+                                            dvsec_range_allowed);
+               if (!cxld_dev) {
+                       dev_dbg(dev, "DVSEC Range%d denied by platform\n", i);
+                       continue;
+               }
+               dev_dbg(dev, "DVSEC Range%d allowed by platform\n", i);
+               put_device(cxld_dev);
+               allowed++;
+       }
+
+       if (!allowed) {
+               cxl_set_mem_enable(cxlds, 0);
+               info->mem_enabled = 0;
+       }
+
+       /*
+        * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
+        * [High,Low] when HDM operation is enabled the range register values
+        * are ignored by the device, but the spec also recommends matching the
+        * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
+        * are expected even though Linux does not require or maintain that
+        * match. If at least one DVSEC range is enabled and allowed, skip HDM
+        * Decoder Capability Enable.
+        */
+       if (info->mem_enabled)
+               return -EBUSY;
+
+       rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
+       if (rc)
+               return rc;
+
+       return devm_cxl_enable_mem(&port->dev, cxlds);
 }
 EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL);