Skip to content

Commit 3d8f7cc

Browse files
committed
tools/testing/cxl: Define a fixed volatile configuration to parse
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 <[email protected]> Reviewed-by: Vishal Verma <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/167602000547.1924368.11613151863880268868.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent a32320b commit 3d8f7cc

File tree

6 files changed

+146
-14
lines changed

6 files changed

+146
-14
lines changed

drivers/cxl/core/core.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
5757
resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
5858
extern struct rw_semaphore cxl_dpa_rwsem;
5959

60-
bool is_switch_decoder(struct device *dev);
61-
struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
62-
6360
int cxl_memdev_init(void);
6461
void cxl_memdev_exit(void);
6562
void cxl_mbox_init(void);

drivers/cxl/core/hdm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
279279
return 0;
280280
}
281281

282-
static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
282+
int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
283283
resource_size_t base, resource_size_t len,
284284
resource_size_t skipped)
285285
{
@@ -295,6 +295,7 @@ static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
295295

296296
return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled);
297297
}
298+
EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, CXL);
298299

299300
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled)
300301
{

drivers/cxl/core/port.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ bool is_switch_decoder(struct device *dev)
458458
{
459459
return is_root_decoder(dev) || dev->type == &cxl_decoder_switch_type;
460460
}
461+
EXPORT_SYMBOL_NS_GPL(is_switch_decoder, CXL);
461462

462463
struct cxl_decoder *to_cxl_decoder(struct device *dev)
463464
{
@@ -485,6 +486,7 @@ struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
485486
return NULL;
486487
return container_of(dev, struct cxl_switch_decoder, cxld.dev);
487488
}
489+
EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, CXL);
488490

489491
static void cxl_ep_release(struct cxl_ep *ep)
490492
{

drivers/cxl/cxl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,8 +653,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
653653

654654
struct cxl_decoder *to_cxl_decoder(struct device *dev);
655655
struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
656+
struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
656657
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
657658
bool is_root_decoder(struct device *dev);
659+
bool is_switch_decoder(struct device *dev);
658660
bool is_endpoint_decoder(struct device *dev);
659661
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
660662
unsigned int nr_targets,

drivers/cxl/cxlmem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
8181
}
8282

8383
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
84+
int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
85+
resource_size_t base, resource_size_t len,
86+
resource_size_t skipped);
8487

8588
static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
8689
struct cxl_memdev *cxlmd)

tools/testing/cxl/test/cxl.c

Lines changed: 137 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,142 @@ static int mock_decoder_reset(struct cxl_decoder *cxld)
703703
return 0;
704704
}
705705

706+
static void default_mock_decoder(struct cxl_decoder *cxld)
707+
{
708+
cxld->hpa_range = (struct range){
709+
.start = 0,
710+
.end = -1,
711+
};
712+
713+
cxld->interleave_ways = 1;
714+
cxld->interleave_granularity = 256;
715+
cxld->target_type = CXL_DECODER_EXPANDER;
716+
cxld->commit = mock_decoder_commit;
717+
cxld->reset = mock_decoder_reset;
718+
}
719+
720+
static int first_decoder(struct device *dev, void *data)
721+
{
722+
struct cxl_decoder *cxld;
723+
724+
if (!is_switch_decoder(dev))
725+
return 0;
726+
cxld = to_cxl_decoder(dev);
727+
if (cxld->id == 0)
728+
return 1;
729+
return 0;
730+
}
731+
732+
static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
733+
{
734+
struct acpi_cedt_cfmws *window = mock_cfmws[0];
735+
struct platform_device *pdev = NULL;
736+
struct cxl_endpoint_decoder *cxled;
737+
struct cxl_switch_decoder *cxlsd;
738+
struct cxl_port *port, *iter;
739+
const int size = SZ_512M;
740+
struct cxl_memdev *cxlmd;
741+
struct cxl_dport *dport;
742+
struct device *dev;
743+
bool hb0 = false;
744+
u64 base;
745+
int i;
746+
747+
if (is_endpoint_decoder(&cxld->dev)) {
748+
cxled = to_cxl_endpoint_decoder(&cxld->dev);
749+
cxlmd = cxled_to_memdev(cxled);
750+
WARN_ON(!dev_is_platform(cxlmd->dev.parent));
751+
pdev = to_platform_device(cxlmd->dev.parent);
752+
753+
/* check is endpoint is attach to host-bridge0 */
754+
port = cxled_to_port(cxled);
755+
do {
756+
if (port->uport == &cxl_host_bridge[0]->dev) {
757+
hb0 = true;
758+
break;
759+
}
760+
if (is_cxl_port(port->dev.parent))
761+
port = to_cxl_port(port->dev.parent);
762+
else
763+
port = NULL;
764+
} while (port);
765+
port = cxled_to_port(cxled);
766+
}
767+
768+
/*
769+
* The first decoder on the first 2 devices on the first switch
770+
* attached to host-bridge0 mock a fake / static RAM region. All
771+
* other decoders are default disabled. Given the round robin
772+
* assignment those devices are named cxl_mem.0, and cxl_mem.4.
773+
*
774+
* See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
775+
*/
776+
if (!hb0 || pdev->id % 4 || pdev->id > 4 || cxld->id > 0) {
777+
default_mock_decoder(cxld);
778+
return;
779+
}
780+
781+
base = window->base_hpa;
782+
cxld->hpa_range = (struct range) {
783+
.start = base,
784+
.end = base + size - 1,
785+
};
786+
787+
cxld->interleave_ways = 2;
788+
eig_to_granularity(window->granularity, &cxld->interleave_granularity);
789+
cxld->target_type = CXL_DECODER_EXPANDER;
790+
cxld->flags = CXL_DECODER_F_ENABLE;
791+
cxled->state = CXL_DECODER_STATE_AUTO;
792+
port->commit_end = cxld->id;
793+
devm_cxl_dpa_reserve(cxled, 0, size / cxld->interleave_ways, 0);
794+
cxld->commit = mock_decoder_commit;
795+
cxld->reset = mock_decoder_reset;
796+
797+
/*
798+
* Now that endpoint decoder is set up, walk up the hierarchy
799+
* and setup the switch and root port decoders targeting @cxlmd.
800+
*/
801+
iter = port;
802+
for (i = 0; i < 2; i++) {
803+
dport = iter->parent_dport;
804+
iter = dport->port;
805+
dev = device_find_child(&iter->dev, NULL, first_decoder);
806+
/*
807+
* Ancestor ports are guaranteed to be enumerated before
808+
* @port, and all ports have at least one decoder.
809+
*/
810+
if (WARN_ON(!dev))
811+
continue;
812+
cxlsd = to_cxl_switch_decoder(dev);
813+
if (i == 0) {
814+
/* put cxl_mem.4 second in the decode order */
815+
if (pdev->id == 4)
816+
cxlsd->target[1] = dport;
817+
else
818+
cxlsd->target[0] = dport;
819+
} else
820+
cxlsd->target[0] = dport;
821+
cxld = &cxlsd->cxld;
822+
cxld->target_type = CXL_DECODER_EXPANDER;
823+
cxld->flags = CXL_DECODER_F_ENABLE;
824+
iter->commit_end = 0;
825+
/*
826+
* Switch targets 2 endpoints, while host bridge targets
827+
* one root port
828+
*/
829+
if (i == 0)
830+
cxld->interleave_ways = 2;
831+
else
832+
cxld->interleave_ways = 1;
833+
cxld->interleave_granularity = 256;
834+
cxld->hpa_range = (struct range) {
835+
.start = base,
836+
.end = base + size - 1,
837+
};
838+
put_device(dev);
839+
}
840+
}
841+
706842
static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
707843
{
708844
struct cxl_port *port = cxlhdm->port;
@@ -748,16 +884,7 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
748884
cxld = &cxled->cxld;
749885
}
750886

751-
cxld->hpa_range = (struct range) {
752-
.start = 0,
753-
.end = -1,
754-
};
755-
756-
cxld->interleave_ways = min_not_zero(target_count, 1);
757-
cxld->interleave_granularity = SZ_4K;
758-
cxld->target_type = CXL_DECODER_EXPANDER;
759-
cxld->commit = mock_decoder_commit;
760-
cxld->reset = mock_decoder_reset;
887+
mock_init_hdm_decoder(cxld);
761888

762889
if (target_count) {
763890
rc = device_for_each_child(port->uport, &ctx,

0 commit comments

Comments
 (0)