]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tools/testing/cxl: Define a fixed volatile configuration to parse
authorDan Williams <dan.j.williams@intel.com>
Fri, 10 Feb 2023 09:06:45 +0000 (01:06 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 28 Nov 2023 17:07:17 +0000 (17:07 +0000)
[ Upstream commit 3d8f7ccaa611a743ae3a1e6f605346993d37c513 ]

Take two endpoints attached to the first switch on the first host-bridge
in the cxl_test topology and define a pre-initialized region. This is a
x2 interleave underneath a x1 CXL Window.

$ modprobe cxl_test
$ # cxl list -Ru
{
  "region":"region3",
  "resource":"0xf010000000",
  "size":"512.00 MiB (536.87 MB)",
  "interleave_ways":2,
  "interleave_granularity":4096,
  "decode_state":"commit"
}

Tested-by: Fan Ni <fan.ni@samsung.com>
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/167602000547.1924368.11613151863880268868.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Stable-dep-of: 98a04c7aced2 ("cxl/region: Fix x1 root-decoder granularity calculations")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/cxl/core/core.h
drivers/cxl/core/hdm.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
tools/testing/cxl/test/cxl.c

index 8c04672dca5637f3de8149397c4f3494287a13d6..cbee2340f1bcefbacdf03172f23a6863176df318 100644 (file)
@@ -56,9 +56,6 @@ resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
 resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
 extern struct rw_semaphore cxl_dpa_rwsem;
 
-bool is_switch_decoder(struct device *dev);
-struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
-
 int cxl_memdev_init(void);
 void cxl_memdev_exit(void);
 void cxl_mbox_init(void);
index 5aa0726aafe6f7329dc8619a2e6cb42bf80d4112..8c1db4e1b816de1aa5789487143a70ffeb80e220 100644 (file)
@@ -276,7 +276,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
        return 0;
 }
 
-static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
+int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
                                resource_size_t base, resource_size_t len,
                                resource_size_t skipped)
 {
@@ -292,6 +292,7 @@ static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
 
        return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled);
 }
+EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, CXL);
 
 resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled)
 {
index 585c2b43c7c7f39080e5b8a01e3caf28c2f08bb7..9de8336d76379cd2ca5355a86c2b2456bf56b02f 100644 (file)
@@ -455,6 +455,7 @@ bool is_switch_decoder(struct device *dev)
 {
        return is_root_decoder(dev) || dev->type == &cxl_decoder_switch_type;
 }
+EXPORT_SYMBOL_NS_GPL(is_switch_decoder, CXL);
 
 struct cxl_decoder *to_cxl_decoder(struct device *dev)
 {
@@ -482,6 +483,7 @@ struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
                return NULL;
        return container_of(dev, struct cxl_switch_decoder, cxld.dev);
 }
+EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, CXL);
 
 static void cxl_ep_release(struct cxl_ep *ep)
 {
index 8787ef1e64047c88f112f814656b4ff6cb177d53..7750ccb7652db8b64da824de00b0cd0a808a0504 100644 (file)
@@ -575,8 +575,10 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
 
 struct cxl_decoder *to_cxl_decoder(struct device *dev);
 struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
+struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
 struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
 bool is_root_decoder(struct device *dev);
+bool is_switch_decoder(struct device *dev);
 bool is_endpoint_decoder(struct device *dev);
 struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
                                                unsigned int nr_targets);
index 7e50b4e93ee5355089a9d548561fa0144e9ee615..b58a5b782e5dcc086bf5d5c6504c1a8c9f4bfb2a 100644 (file)
@@ -75,6 +75,9 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
 }
 
 struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
+int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
+                        resource_size_t base, resource_size_t len,
+                        resource_size_t skipped);
 
 static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
                                         struct cxl_memdev *cxlmd)
index 7edce12fd2ce58515b3214b5143d35bad9d4d92c..c43bb6774f4db49b3318c226bbc178692c61b863 100644 (file)
@@ -551,6 +551,142 @@ static int mock_decoder_reset(struct cxl_decoder *cxld)
        return 0;
 }
 
+static void default_mock_decoder(struct cxl_decoder *cxld)
+{
+       cxld->hpa_range = (struct range){
+               .start = 0,
+               .end = -1,
+       };
+
+       cxld->interleave_ways = 1;
+       cxld->interleave_granularity = 256;
+       cxld->target_type = CXL_DECODER_EXPANDER;
+       cxld->commit = mock_decoder_commit;
+       cxld->reset = mock_decoder_reset;
+}
+
+static int first_decoder(struct device *dev, void *data)
+{
+       struct cxl_decoder *cxld;
+
+       if (!is_switch_decoder(dev))
+               return 0;
+       cxld = to_cxl_decoder(dev);
+       if (cxld->id == 0)
+               return 1;
+       return 0;
+}
+
+static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
+{
+       struct acpi_cedt_cfmws *window = mock_cfmws[0];
+       struct platform_device *pdev = NULL;
+       struct cxl_endpoint_decoder *cxled;
+       struct cxl_switch_decoder *cxlsd;
+       struct cxl_port *port, *iter;
+       const int size = SZ_512M;
+       struct cxl_memdev *cxlmd;
+       struct cxl_dport *dport;
+       struct device *dev;
+       bool hb0 = false;
+       u64 base;
+       int i;
+
+       if (is_endpoint_decoder(&cxld->dev)) {
+               cxled = to_cxl_endpoint_decoder(&cxld->dev);
+               cxlmd = cxled_to_memdev(cxled);
+               WARN_ON(!dev_is_platform(cxlmd->dev.parent));
+               pdev = to_platform_device(cxlmd->dev.parent);
+
+               /* check is endpoint is attach to host-bridge0 */
+               port = cxled_to_port(cxled);
+               do {
+                       if (port->uport == &cxl_host_bridge[0]->dev) {
+                               hb0 = true;
+                               break;
+                       }
+                       if (is_cxl_port(port->dev.parent))
+                               port = to_cxl_port(port->dev.parent);
+                       else
+                               port = NULL;
+               } while (port);
+               port = cxled_to_port(cxled);
+       }
+
+       /*
+        * The first decoder on the first 2 devices on the first switch
+        * attached to host-bridge0 mock a fake / static RAM region. All
+        * other decoders are default disabled. Given the round robin
+        * assignment those devices are named cxl_mem.0, and cxl_mem.4.
+        *
+        * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
+        */
+       if (!hb0 || pdev->id % 4 || pdev->id > 4 || cxld->id > 0) {
+               default_mock_decoder(cxld);
+               return;
+       }
+
+       base = window->base_hpa;
+       cxld->hpa_range = (struct range) {
+               .start = base,
+               .end = base + size - 1,
+       };
+
+       cxld->interleave_ways = 2;
+       eig_to_granularity(window->granularity, &cxld->interleave_granularity);
+       cxld->target_type = CXL_DECODER_EXPANDER;
+       cxld->flags = CXL_DECODER_F_ENABLE;
+       cxled->state = CXL_DECODER_STATE_AUTO;
+       port->commit_end = cxld->id;
+       devm_cxl_dpa_reserve(cxled, 0, size / cxld->interleave_ways, 0);
+       cxld->commit = mock_decoder_commit;
+       cxld->reset = mock_decoder_reset;
+
+       /*
+        * Now that endpoint decoder is set up, walk up the hierarchy
+        * and setup the switch and root port decoders targeting @cxlmd.
+        */
+       iter = port;
+       for (i = 0; i < 2; i++) {
+               dport = iter->parent_dport;
+               iter = dport->port;
+               dev = device_find_child(&iter->dev, NULL, first_decoder);
+               /*
+                * Ancestor ports are guaranteed to be enumerated before
+                * @port, and all ports have at least one decoder.
+                */
+               if (WARN_ON(!dev))
+                       continue;
+               cxlsd = to_cxl_switch_decoder(dev);
+               if (i == 0) {
+                       /* put cxl_mem.4 second in the decode order */
+                       if (pdev->id == 4)
+                               cxlsd->target[1] = dport;
+                       else
+                               cxlsd->target[0] = dport;
+               } else
+                       cxlsd->target[0] = dport;
+               cxld = &cxlsd->cxld;
+               cxld->target_type = CXL_DECODER_EXPANDER;
+               cxld->flags = CXL_DECODER_F_ENABLE;
+               iter->commit_end = 0;
+               /*
+                * Switch targets 2 endpoints, while host bridge targets
+                * one root port
+                */
+               if (i == 0)
+                       cxld->interleave_ways = 2;
+               else
+                       cxld->interleave_ways = 1;
+               cxld->interleave_granularity = 256;
+               cxld->hpa_range = (struct range) {
+                       .start = base,
+                       .end = base + size - 1,
+               };
+               put_device(dev);
+       }
+}
+
 static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
 {
        struct cxl_port *port = cxlhdm->port;
@@ -596,16 +732,7 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
                        cxld = &cxled->cxld;
                }
 
-               cxld->hpa_range = (struct range) {
-                       .start = 0,
-                       .end = -1,
-               };
-
-               cxld->interleave_ways = min_not_zero(target_count, 1);
-               cxld->interleave_granularity = SZ_4K;
-               cxld->target_type = CXL_DECODER_EXPANDER;
-               cxld->commit = mock_decoder_commit;
-               cxld->reset = mock_decoder_reset;
+               mock_init_hdm_decoder(cxld);
 
                if (target_count) {
                        rc = device_for_each_child(port->uport, &ctx,