cxl/port: Export cxl_dvsec_rr_decode() to cxl_port
authorDave Jiang <dave.jiang@intel.com>
Tue, 14 Feb 2023 19:41:13 +0000 (11:41 -0800)
committerDan Williams <dan.j.williams@intel.com>
Tue, 14 Feb 2023 23:45:21 +0000 (15:45 -0800)
Call cxl_dvsec_rr_decode() in the beginning of cxl_port_probe() and
preserve the decoded information in a local
'struct cxl_endpoint_dvsec_info'. This info can be passed to various
functions later on in order to support the HDM decoder emulation.
The invocation of cxl_dvsec_rr_decode() in cxl_hdm_decode_init() is
removed and a pointer to the 'struct cxl_endpoint_dvsec_info' is passed
in.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/167640367377.935665.2848747799651019676.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/pci.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
drivers/cxl/cxlpci.h
drivers/cxl/port.c
tools/testing/cxl/Kbuild
tools/testing/cxl/test/mock.c

index 52bf6b4..948fa37 100644 (file)
@@ -333,8 +333,8 @@ static bool __cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
        return true;
 }
 
-static int cxl_dvsec_rr_decode(struct device *dev, int d,
-                              struct cxl_endpoint_dvsec_info *info)
+int cxl_dvsec_rr_decode(struct device *dev, int d,
+                       struct cxl_endpoint_dvsec_info *info)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        int hdm_count, rc, i, ranges = 0;
@@ -434,30 +434,26 @@ static int cxl_dvsec_rr_decode(struct device *dev, int d,
 
        return 0;
 }
+EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL);
 
 /**
  * cxl_hdm_decode_init() - Setup HDM decoding for the endpoint
  * @cxlds: Device state
  * @cxlhdm: Mapped HDM decoder Capability
+ * @info: Cached DVSEC range registers info
  *
  * Try to enable the endpoint's HDM Decoder Capability
  */
-int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm)
+int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
+                       struct cxl_endpoint_dvsec_info *info)
 {
-       struct cxl_endpoint_dvsec_info info = { 0 };
        struct device *dev = cxlds->dev;
-       int d = cxlds->cxl_dvsec;
-       int rc;
-
-       rc = cxl_dvsec_rr_decode(dev, d, &info);
-       if (rc < 0)
-               return rc;
 
        /*
         * If DVSEC ranges are being used instead of HDM decoder registers there
         * is no use in trying to manage those.
         */
-       if (!__cxl_hdm_decode_init(cxlds, cxlhdm, &info)) {
+       if (!__cxl_hdm_decode_init(cxlds, cxlhdm, info)) {
                dev_err(dev,
                        "Legacy range registers configuration prevents HDM operation.\n");
                return -EBUSY;
index 1b1cf45..fc01ce9 100644 (file)
@@ -630,10 +630,24 @@ int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map);
 int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld);
 int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint);
 
+/**
+ * struct cxl_endpoint_dvsec_info - Cached DVSEC info
+ * @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE
+ * @ranges: Number of active HDM ranges this device uses.
+ * @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE
+ */
+struct cxl_endpoint_dvsec_info {
+       bool mem_enabled;
+       int ranges;
+       struct range dvsec_range[2];
+};
+
 struct cxl_hdm;
 struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port);
 int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm);
 int devm_cxl_add_passthrough_decoder(struct cxl_port *port);
+int cxl_dvsec_rr_decode(struct device *dev, int dvsec,
+                       struct cxl_endpoint_dvsec_info *info);
 
 bool is_cxl_region(struct device *dev);
 
index ab13800..187a310 100644 (file)
@@ -182,18 +182,6 @@ static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd)
 #define CXL_CAPACITY_MULTIPLIER SZ_256M
 
 /**
- * struct cxl_endpoint_dvsec_info - Cached DVSEC info
- * @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE
- * @ranges: Number of active HDM ranges this device uses.
- * @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE
- */
-struct cxl_endpoint_dvsec_info {
-       bool mem_enabled;
-       int ranges;
-       struct range dvsec_range[2];
-};
-
-/**
  * struct cxl_dev_state - The driver device state
  *
  * cxl_dev_state represents the CXL driver/device state.  It provides an
index 9209097..430e233 100644 (file)
@@ -64,6 +64,7 @@ enum cxl_regloc_type {
 
 int devm_cxl_port_enumerate_dports(struct cxl_port *port);
 struct cxl_dev_state;
-int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm);
+int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
+                       struct cxl_endpoint_dvsec_info *info);
 void read_cdat_data(struct cxl_port *port);
 #endif /* __CXL_PCI_H__ */
index 5453771..9e09728 100644 (file)
@@ -32,12 +32,21 @@ static void schedule_detach(void *cxlmd)
 
 static int cxl_port_probe(struct device *dev)
 {
+       struct cxl_endpoint_dvsec_info info = { 0 };
        struct cxl_port *port = to_cxl_port(dev);
+       bool is_ep = is_cxl_endpoint(port);
+       struct cxl_dev_state *cxlds;
+       struct cxl_memdev *cxlmd;
        struct cxl_hdm *cxlhdm;
        int rc;
 
-
-       if (!is_cxl_endpoint(port)) {
+       if (is_ep) {
+               cxlmd = to_cxl_memdev(port->uport);
+               cxlds = cxlmd->cxlds;
+               rc = cxl_dvsec_rr_decode(cxlds->dev, cxlds->cxl_dvsec, &info);
+               if (rc < 0)
+                       return rc;
+       } else {
                rc = devm_cxl_port_enumerate_dports(port);
                if (rc < 0)
                        return rc;
@@ -49,10 +58,7 @@ static int cxl_port_probe(struct device *dev)
        if (IS_ERR(cxlhdm))
                return PTR_ERR(cxlhdm);
 
-       if (is_cxl_endpoint(port)) {
-               struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
-               struct cxl_dev_state *cxlds = cxlmd->cxlds;
-
+       if (is_ep) {
                /* Cache the data early to ensure is_visible() works */
                read_cdat_data(port);
 
@@ -61,7 +67,7 @@ static int cxl_port_probe(struct device *dev)
                if (rc)
                        return rc;
 
-               rc = cxl_hdm_decode_init(cxlds, cxlhdm);
+               rc = cxl_hdm_decode_init(cxlds, cxlhdm, &info);
                if (rc)
                        return rc;
 
index 0805f08..012149a 100644 (file)
@@ -10,6 +10,7 @@ ldflags-y += --wrap=devm_cxl_add_passthrough_decoder
 ldflags-y += --wrap=devm_cxl_enumerate_decoders
 ldflags-y += --wrap=cxl_await_media_ready
 ldflags-y += --wrap=cxl_hdm_decode_init
+ldflags-y += --wrap=cxl_dvsec_rr_decode
 ldflags-y += --wrap=cxl_rcrb_to_component
 
 DRIVERS := ../../../drivers
index 5dface0..2a13f47 100644 (file)
@@ -209,7 +209,8 @@ int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL);
 
 int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
-                              struct cxl_hdm *cxlhdm)
+                              struct cxl_hdm *cxlhdm,
+                              struct cxl_endpoint_dvsec_info *info)
 {
        int rc = 0, index;
        struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
@@ -217,13 +218,29 @@ int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
        if (ops && ops->is_mock_dev(cxlds->dev))
                rc = 0;
        else
-               rc = cxl_hdm_decode_init(cxlds, cxlhdm);
+               rc = cxl_hdm_decode_init(cxlds, cxlhdm, info);
        put_cxl_mock_ops(index);
 
        return rc;
 }
 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL);
 
+int __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec,
+                              struct cxl_endpoint_dvsec_info *info)
+{
+       int rc = 0, index;
+       struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
+
+       if (ops && ops->is_mock_dev(dev))
+               rc = 0;
+       else
+               rc = cxl_dvsec_rr_decode(dev, dvsec, info);
+       put_cxl_mock_ops(index);
+
+       return rc;
+}
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL);
+
 resource_size_t __wrap_cxl_rcrb_to_component(struct device *dev,
                                             resource_size_t rcrb,
                                             enum cxl_rcrb which)