Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cxl/core: Generalize dport enumeration in the core

The core houses infrastructure for decoder resources. A CXL port's
dports are more closely related to decoder infrastructure than topology
enumeration. Implement generic PCI based dport enumeration in the core,
i.e. arrange for existing root port enumeration from cxl_acpi to share
code with switch port enumeration which just amounts to a small
difference in a pci_walk_bus() invocation once the appropriate 'struct
pci_bus' has been retrieved.

Set the convention that decoder objects are registered after all dports
are enumerated. This enables userspace to know when the CXL core is
finished establishing 'dportX' links underneath the 'portX' object.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/164368114191.354031.5270501846455462665.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+238 -238
+8 -59
drivers/cxl/acpi.c
··· 130 130 return 0; 131 131 } 132 132 133 - __mock int match_add_root_ports(struct pci_dev *pdev, void *data) 134 - { 135 - resource_size_t creg = CXL_RESOURCE_NONE; 136 - struct cxl_walk_context *ctx = data; 137 - struct pci_bus *root_bus = ctx->root; 138 - struct cxl_port *port = ctx->port; 139 - int type = pci_pcie_type(pdev); 140 - struct device *dev = ctx->dev; 141 - struct cxl_register_map map; 142 - u32 lnkcap, port_num; 143 - int rc; 144 - 145 - if (pdev->bus != root_bus) 146 - return 0; 147 - if (!pci_is_pcie(pdev)) 148 - return 0; 149 - if (type != PCI_EXP_TYPE_ROOT_PORT) 150 - return 0; 151 - if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP, 152 - &lnkcap) != PCIBIOS_SUCCESSFUL) 153 - return 0; 154 - 155 - /* The driver doesn't rely on component registers for Root Ports yet. */ 156 - rc = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map); 157 - if (!rc) 158 - dev_info(&pdev->dev, "No component register block found\n"); 159 - 160 - creg = cxl_regmap_to_base(pdev, &map); 161 - 162 - port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); 163 - rc = cxl_add_dport(port, &pdev->dev, port_num, creg); 164 - if (rc) { 165 - ctx->error = rc; 166 - return rc; 167 - } 168 - ctx->count++; 169 - 170 - dev_dbg(dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev)); 171 - 172 - return 0; 173 - } 174 - 175 133 static struct cxl_dport *find_dport_by_dev(struct cxl_port *port, struct device *dev) 176 134 { 177 135 struct cxl_dport *dport; ··· 168 210 struct device *host = root_port->dev.parent; 169 211 struct acpi_device *bridge = to_cxl_host_bridge(host, match); 170 212 struct acpi_pci_root *pci_root; 171 - struct cxl_walk_context ctx; 172 213 int single_port_map[1], rc; 173 214 struct cxl_decoder *cxld; 174 215 struct cxl_dport *dport; ··· 197 240 return PTR_ERR(port); 198 241 dev_dbg(host, "%s: add: %s\n", dev_name(match), dev_name(&port->dev)); 199 242 200 - ctx = (struct cxl_walk_context){ 201 - .dev = host, 202 - .root = pci_root->bus, 203 - .port = port, 204 - }; 205 - pci_walk_bus(pci_root->bus, match_add_root_ports, &ctx); 206 - 207 - if (ctx.count == 0) 208 - return -ENODEV; 209 - if (ctx.error) 210 - return ctx.error; 211 - if (ctx.count > 1) 243 + rc = devm_cxl_port_enumerate_dports(host, port); 244 + if (rc < 0) 245 + return rc; 246 + if (rc > 1) 212 247 return 0; 213 248 214 249 /* TODO: Scan CHBCR for HDM Decoder resources */ ··· 260 311 261 312 static int add_host_bridge_dport(struct device *match, void *arg) 262 313 { 263 - int rc; 264 314 acpi_status status; 265 315 unsigned long long uid; 316 + struct cxl_dport *dport; 266 317 struct cxl_chbs_context ctx; 267 318 struct cxl_port *root_port = arg; 268 319 struct device *host = root_port->dev.parent; ··· 292 343 } 293 344 294 345 cxl_device_lock(&root_port->dev); 295 - rc = cxl_add_dport(root_port, match, uid, ctx.chbcr); 346 + dport = devm_cxl_add_dport(host, root_port, match, uid, ctx.chbcr); 296 347 cxl_device_unlock(&root_port->dev); 297 - if (rc) { 348 + if (IS_ERR(dport)) { 298 349 dev_err(host, "failed to add downstream port: %s\n", 299 350 dev_name(match)); 300 - return rc; 351 + return PTR_ERR(dport); 301 352 } 302 353 dev_dbg(host, "add dport%llu: %s\n", uid, dev_name(match)); 303 354 return 0;
+1
drivers/cxl/core/Makefile
··· 7 7 cxl_core-y += regs.o 8 8 cxl_core-y += memdev.o 9 9 cxl_core-y += mbox.o 10 + cxl_core-y += pci.o
+101
drivers/cxl/core/pci.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2021 Intel Corporation. All rights reserved. */ 3 + #include <linux/device.h> 4 + #include <linux/pci.h> 5 + #include <cxlpci.h> 6 + #include <cxl.h> 7 + #include "core.h" 8 + 9 + /** 10 + * DOC: cxl core pci 11 + * 12 + * Compute Express Link protocols are layered on top of PCIe. CXL core provides 13 + * a set of helpers for CXL interactions which occur via PCIe. 14 + */ 15 + 16 + struct cxl_walk_context { 17 + struct pci_bus *bus; 18 + struct device *host; 19 + struct cxl_port *port; 20 + int type; 21 + int error; 22 + int count; 23 + }; 24 + 25 + static int match_add_dports(struct pci_dev *pdev, void *data) 26 + { 27 + struct cxl_walk_context *ctx = data; 28 + struct cxl_port *port = ctx->port; 29 + int type = pci_pcie_type(pdev); 30 + struct cxl_register_map map; 31 + struct cxl_dport *dport; 32 + u32 lnkcap, port_num; 33 + int rc; 34 + 35 + if (pdev->bus != ctx->bus) 36 + return 0; 37 + if (!pci_is_pcie(pdev)) 38 + return 0; 39 + if (type != ctx->type) 40 + return 0; 41 + if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP, 42 + &lnkcap)) 43 + return 0; 44 + 45 + rc = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map); 46 + if (rc) 47 + dev_dbg(&port->dev, "failed to find component registers\n"); 48 + 49 + port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); 50 + cxl_device_lock(&port->dev); 51 + dport = devm_cxl_add_dport(ctx->host, port, &pdev->dev, port_num, 52 + cxl_regmap_to_base(pdev, &map)); 53 + cxl_device_unlock(&port->dev); 54 + if (IS_ERR(dport)) { 55 + ctx->error = PTR_ERR(dport); 56 + return PTR_ERR(dport); 57 + } 58 + ctx->count++; 59 + 60 + dev_dbg(&port->dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev)); 61 + 62 + return 0; 63 + } 64 + 65 + /** 66 + * devm_cxl_port_enumerate_dports - enumerate downstream ports of the upstream port 67 + * @host: devm context 68 + * @port: cxl_port whose ->uport is the upstream of dports to be enumerated 69 + * 70 + * Returns a positive number of dports enumerated or a negative error 71 + * code. 72 + */ 73 + int devm_cxl_port_enumerate_dports(struct device *host, struct cxl_port *port) 74 + { 75 + struct pci_bus *bus = cxl_port_to_pci_bus(port); 76 + struct cxl_walk_context ctx; 77 + int type; 78 + 79 + if (!bus) 80 + return -ENXIO; 81 + 82 + if (pci_is_root_bus(bus)) 83 + type = PCI_EXP_TYPE_ROOT_PORT; 84 + else 85 + type = PCI_EXP_TYPE_DOWNSTREAM; 86 + 87 + ctx = (struct cxl_walk_context) { 88 + .host = host, 89 + .port = port, 90 + .bus = bus, 91 + .type = type, 92 + }; 93 + pci_walk_bus(bus, match_add_dports, &ctx); 94 + 95 + if (ctx.count == 0) 96 + return -ENODEV; 97 + if (ctx.error) 98 + return ctx.error; 99 + return ctx.count; 100 + } 101 + EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL);
+52 -39
drivers/cxl/core/port.c
··· 243 243 } 244 244 EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL); 245 245 246 - static void cxl_dport_release(struct cxl_dport *dport) 247 - { 248 - list_del(&dport->list); 249 - put_device(dport->dport); 250 - kfree(dport); 251 - } 252 - 253 246 static void cxl_port_release(struct device *dev) 254 247 { 255 248 struct cxl_port *port = to_cxl_port(dev); 256 - struct cxl_dport *dport, *_d; 257 249 258 - cxl_device_lock(dev); 259 - list_for_each_entry_safe(dport, _d, &port->dports, list) 260 - cxl_dport_release(dport); 261 - cxl_device_unlock(dev); 262 250 ida_free(&cxl_port_ida, port->id); 263 251 kfree(port); 264 252 } ··· 280 292 static void unregister_port(void *_port) 281 293 { 282 294 struct cxl_port *port = _port; 283 - struct cxl_dport *dport; 284 295 285 - cxl_device_lock(&port->dev); 286 - list_for_each_entry(dport, &port->dports, list) { 287 - char link_name[CXL_TARGET_STRLEN]; 288 - 289 - if (snprintf(link_name, CXL_TARGET_STRLEN, "dport%d", 290 - dport->port_id) >= CXL_TARGET_STRLEN) 291 - continue; 292 - sysfs_remove_link(&port->dev.kobj, link_name); 293 - } 294 - cxl_device_unlock(&port->dev); 295 296 device_unregister(&port->dev); 296 297 } 297 298 ··· 509 532 return dup ? -EEXIST : 0; 510 533 } 511 534 535 + static void cxl_dport_remove(void *data) 536 + { 537 + struct cxl_dport *dport = data; 538 + struct cxl_port *port = dport->port; 539 + 540 + put_device(dport->dport); 541 + cxl_device_lock(&port->dev); 542 + list_del(&dport->list); 543 + cxl_device_unlock(&port->dev); 544 + } 545 + 546 + static void cxl_dport_unlink(void *data) 547 + { 548 + struct cxl_dport *dport = data; 549 + struct cxl_port *port = dport->port; 550 + char link_name[CXL_TARGET_STRLEN]; 551 + 552 + sprintf(link_name, "dport%d", dport->port_id); 553 + sysfs_remove_link(&port->dev.kobj, link_name); 554 + } 555 + 512 556 /** 513 - * cxl_add_dport - append downstream port data to a cxl_port 557 + * devm_cxl_add_dport - append downstream port data to a cxl_port 558 + * @host: devm context for allocations 514 559 * @port: the cxl_port that references this dport 515 560 * @dport_dev: firmware or PCI device representing the dport 516 561 * @port_id: identifier for this dport in a decoder's target list 517 562 * @component_reg_phys: optional location of CXL component registers 518 563 * 519 - * Note that all allocations and links are undone by cxl_port deletion 520 - * and release. 564 + * Note that dports are appended to the devm release action's of the 565 + * either the port's host (for root ports), or the port itself (for 566 + * switch ports) 521 567 */ 522 - int cxl_add_dport(struct cxl_port *port, struct device *dport_dev, int port_id, 523 - resource_size_t component_reg_phys) 568 + struct cxl_dport *devm_cxl_add_dport(struct device *host, struct cxl_port *port, 569 + struct device *dport_dev, int port_id, 570 + resource_size_t component_reg_phys) 524 571 { 525 572 char link_name[CXL_TARGET_STRLEN]; 526 573 struct cxl_dport *dport; 527 574 int rc; 528 575 576 + if (!host->driver) { 577 + dev_WARN_ONCE(&port->dev, 1, "dport:%s bad devm context\n", 578 + dev_name(dport_dev)); 579 + return ERR_PTR(-ENXIO); 580 + } 581 + 529 582 if (snprintf(link_name, CXL_TARGET_STRLEN, "dport%d", port_id) >= 530 583 CXL_TARGET_STRLEN) 531 - return -EINVAL; 584 + return ERR_PTR(-EINVAL); 532 585 533 - dport = kzalloc(sizeof(*dport), GFP_KERNEL); 586 + dport = devm_kzalloc(host, sizeof(*dport), GFP_KERNEL); 534 587 if (!dport) 535 - return -ENOMEM; 588 + return ERR_PTR(-ENOMEM); 536 589 537 590 INIT_LIST_HEAD(&dport->list); 538 - dport->dport = get_device(dport_dev); 591 + dport->dport = dport_dev; 539 592 dport->port_id = port_id; 540 593 dport->component_reg_phys = component_reg_phys; 541 594 dport->port = port; 542 595 543 596 rc = add_dport(port, dport); 544 597 if (rc) 545 - goto err; 598 + return ERR_PTR(rc); 599 + 600 + get_device(dport_dev); 601 + rc = devm_add_action_or_reset(host, cxl_dport_remove, dport); 602 + if (rc) 603 + return ERR_PTR(rc); 546 604 547 605 rc = sysfs_create_link(&port->dev.kobj, &dport_dev->kobj, link_name); 548 606 if (rc) 549 - goto err; 607 + return ERR_PTR(rc); 550 608 551 - return 0; 552 - err: 553 - cxl_dport_release(dport); 554 - return rc; 609 + rc = devm_add_action_or_reset(host, cxl_dport_unlink, dport); 610 + if (rc) 611 + return ERR_PTR(rc); 612 + 613 + return dport; 555 614 } 556 - EXPORT_SYMBOL_NS_GPL(cxl_add_dport, CXL); 615 + EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL); 557 616 558 617 static int decoder_populate_targets(struct cxl_decoder *cxld, 559 618 struct cxl_port *port, int *target_map)
+4 -12
drivers/cxl/cxl.h
··· 236 236 struct nvdimm *nvdimm; 237 237 }; 238 238 239 - struct cxl_walk_context { 240 - struct device *dev; 241 - struct pci_bus *root; 242 - struct cxl_port *port; 243 - int error; 244 - int count; 245 - }; 246 - 247 239 /** 248 240 * struct cxl_port - logical collection of upstream port devices and 249 241 * downstream port devices to construct a CXL memory ··· 287 295 288 296 bool is_cxl_port(struct device *dev); 289 297 struct cxl_port *to_cxl_port(struct device *dev); 298 + struct pci_bus; 290 299 int devm_cxl_register_pci_bus(struct device *host, struct device *uport, 291 300 struct pci_bus *bus); 292 301 struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port); 293 302 struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, 294 303 resource_size_t component_reg_phys, 295 304 struct cxl_port *parent_port); 296 - 297 - int cxl_add_dport(struct cxl_port *port, struct device *dport, int port_id, 298 - resource_size_t component_reg_phys); 299 305 struct cxl_port *find_cxl_root(struct device *dev); 300 - 306 + struct cxl_dport *devm_cxl_add_dport(struct device *host, struct cxl_port *port, 307 + struct device *dport, int port_id, 308 + resource_size_t component_reg_phys); 301 309 struct cxl_decoder *to_cxl_decoder(struct device *dev); 302 310 bool is_root_decoder(struct device *dev); 303 311 bool is_cxl_decoder(struct device *dev);
+1
drivers/cxl/cxlpci.h
··· 57 57 return pci_resource_start(pdev, map->barno) + map->block_offset; 58 58 } 59 59 60 + int devm_cxl_port_enumerate_dports(struct device *host, struct cxl_port *port); 60 61 #endif /* __CXL_PCI_H__ */
+2 -1
tools/testing/cxl/Kbuild
··· 3 3 ldflags-y += --wrap=is_acpi_device_node 4 4 ldflags-y += --wrap=acpi_evaluate_integer 5 5 ldflags-y += --wrap=acpi_pci_find_root 6 - ldflags-y += --wrap=pci_walk_bus 7 6 ldflags-y += --wrap=nvdimm_bus_register 7 + ldflags-y += --wrap=devm_cxl_port_enumerate_dports 8 8 9 9 DRIVERS := ../../../drivers 10 10 CXL_SRC := $(DRIVERS)/cxl ··· 30 30 cxl_core-y += $(CXL_CORE_SRC)/regs.o 31 31 cxl_core-y += $(CXL_CORE_SRC)/memdev.o 32 32 cxl_core-y += $(CXL_CORE_SRC)/mbox.o 33 + cxl_core-y += $(CXL_CORE_SRC)/pci.o 33 34 cxl_core-y += config_check.o 34 35 35 36 obj-m += test/
-78
tools/testing/cxl/mock_acpi.c
··· 4 4 #include <linux/platform_device.h> 5 5 #include <linux/device.h> 6 6 #include <linux/acpi.h> 7 - #include <linux/pci.h> 8 7 #include <cxl.h> 9 8 #include "test/mock.h" 10 9 ··· 32 33 out: 33 34 put_cxl_mock_ops(index); 34 35 return found; 35 - } 36 - 37 - static int match_add_root_port(struct pci_dev *pdev, void *data) 38 - { 39 - struct cxl_walk_context *ctx = data; 40 - struct pci_bus *root_bus = ctx->root; 41 - struct cxl_port *port = ctx->port; 42 - int type = pci_pcie_type(pdev); 43 - struct device *dev = ctx->dev; 44 - u32 lnkcap, port_num; 45 - int rc; 46 - 47 - if (pdev->bus != root_bus) 48 - return 0; 49 - if (!pci_is_pcie(pdev)) 50 - return 0; 51 - if (type != PCI_EXP_TYPE_ROOT_PORT) 52 - return 0; 53 - if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP, 54 - &lnkcap) != PCIBIOS_SUCCESSFUL) 55 - return 0; 56 - 57 - /* TODO walk DVSEC to find component register base */ 58 - port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap); 59 - cxl_device_lock(&port->dev); 60 - rc = cxl_add_dport(port, &pdev->dev, port_num, CXL_RESOURCE_NONE); 61 - cxl_device_unlock(&port->dev); 62 - if (rc) { 63 - dev_err(dev, "failed to add dport: %s (%d)\n", 64 - dev_name(&pdev->dev), rc); 65 - ctx->error = rc; 66 - return rc; 67 - } 68 - ctx->count++; 69 - 70 - dev_dbg(dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev)); 71 - 72 - return 0; 73 - } 74 - 75 - static int mock_add_root_port(struct platform_device *pdev, void *data) 76 - { 77 - struct cxl_walk_context *ctx = data; 78 - struct cxl_port *port = ctx->port; 79 - struct device *dev = ctx->dev; 80 - int rc; 81 - 82 - cxl_device_lock(&port->dev); 83 - rc = cxl_add_dport(port, &pdev->dev, pdev->id, CXL_RESOURCE_NONE); 84 - cxl_device_unlock(&port->dev); 85 - if (rc) { 86 - dev_err(dev, "failed to add dport: %s (%d)\n", 87 - dev_name(&pdev->dev), rc); 88 - ctx->error = rc; 89 - return rc; 90 - } 91 - ctx->count++; 92 - 93 - dev_dbg(dev, "add dport%d: %s\n", pdev->id, dev_name(&pdev->dev)); 94 - 95 - return 0; 96 - } 97 - 98 - int match_add_root_ports(struct pci_dev *dev, void *data) 99 - { 100 - int index, rc; 101 - struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 102 - struct platform_device *pdev = (struct platform_device *) dev; 103 - 104 - if (ops && ops->is_mock_port(pdev)) 105 - rc = mock_add_root_port(pdev, data); 106 - else 107 - rc = match_add_root_port(dev, data); 108 - 109 - put_cxl_mock_ops(index); 110 - 111 - return rc; 112 36 }
+46 -21
tools/testing/cxl/test/cxl.c
··· 317 317 for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) 318 318 if (dev == &cxl_host_bridge[i]->dev) 319 319 return true; 320 + return false; 321 + } 322 + 323 + static bool is_mock_port(struct device *dev) 324 + { 325 + int i; 326 + 327 + if (is_mock_bridge(dev)) 328 + return true; 329 + 330 + for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) 331 + if (dev == &cxl_root_port[i]->dev) 332 + return true; 320 333 321 334 return false; 322 335 } ··· 379 366 }, 380 367 }; 381 368 382 - static struct platform_device *mock_cxl_root_port(struct pci_bus *bus, int index) 383 - { 384 - int i; 385 - 386 - for (i = 0; i < ARRAY_SIZE(mock_pci_bus); i++) 387 - if (bus == &mock_pci_bus[i]) 388 - return cxl_root_port[index + i * NR_CXL_ROOT_PORTS]; 389 - return NULL; 390 - } 391 - 392 - static bool is_mock_port(struct platform_device *pdev) 393 - { 394 - int i; 395 - 396 - for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) 397 - if (pdev == cxl_root_port[i]) 398 - return true; 399 - return false; 400 - } 401 - 402 369 static bool is_mock_bus(struct pci_bus *bus) 403 370 { 404 371 int i; ··· 398 405 return &mock_pci_root[host_bridge_index(adev)]; 399 406 } 400 407 408 + static int mock_cxl_port_enumerate_dports(struct device *host, 409 + struct cxl_port *port) 410 + { 411 + struct device *dev = &port->dev; 412 + int i; 413 + 414 + for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) { 415 + struct platform_device *pdev = cxl_root_port[i]; 416 + struct cxl_dport *dport; 417 + 418 + if (pdev->dev.parent != port->uport) 419 + continue; 420 + 421 + cxl_device_lock(&port->dev); 422 + dport = devm_cxl_add_dport(host, port, &pdev->dev, pdev->id, 423 + CXL_RESOURCE_NONE); 424 + cxl_device_unlock(&port->dev); 425 + 426 + if (IS_ERR(dport)) { 427 + dev_err(dev, "failed to add dport: %s (%ld)\n", 428 + dev_name(&pdev->dev), PTR_ERR(dport)); 429 + return PTR_ERR(dport); 430 + } 431 + 432 + dev_dbg(dev, "add dport%d: %s\n", pdev->id, 433 + dev_name(&pdev->dev)); 434 + } 435 + 436 + return 0; 437 + } 438 + 401 439 static struct cxl_mock_ops cxl_mock_ops = { 402 440 .is_mock_adev = is_mock_adev, 403 441 .is_mock_bridge = is_mock_bridge, 404 442 .is_mock_bus = is_mock_bus, 405 443 .is_mock_port = is_mock_port, 406 444 .is_mock_dev = is_mock_dev, 407 - .mock_port = mock_cxl_root_port, 408 445 .acpi_table_parse_cedt = mock_acpi_table_parse_cedt, 409 446 .acpi_evaluate_integer = mock_acpi_evaluate_integer, 410 447 .acpi_pci_find_root = mock_acpi_pci_find_root, 448 + .devm_cxl_port_enumerate_dports = mock_cxl_port_enumerate_dports, 411 449 .list = LIST_HEAD_INIT(cxl_mock_ops.list), 412 450 }; 413 451 ··· 622 598 module_exit(cxl_test_exit); 623 599 MODULE_LICENSE("GPL v2"); 624 600 MODULE_IMPORT_NS(ACPI); 601 + MODULE_IMPORT_NS(CXL);
+19 -26
tools/testing/cxl/test/mock.c
··· 7 7 #include <linux/export.h> 8 8 #include <linux/acpi.h> 9 9 #include <linux/pci.h> 10 + #include <cxlmem.h> 11 + #include <cxlpci.h> 10 12 #include "mock.h" 11 13 12 14 static LIST_HEAD(mock); ··· 116 114 } 117 115 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 118 116 119 - void __wrap_pci_walk_bus(struct pci_bus *bus, 120 - int (*cb)(struct pci_dev *, void *), void *userdata) 121 - { 122 - int index; 123 - struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 124 - 125 - if (ops && ops->is_mock_bus(bus)) { 126 - int rc, i; 127 - 128 - /* 129 - * Simulate 2 root ports per host-bridge and no 130 - * depth recursion. 131 - */ 132 - for (i = 0; i < 2; i++) { 133 - rc = cb((struct pci_dev *) ops->mock_port(bus, i), 134 - userdata); 135 - if (rc) 136 - break; 137 - } 138 - } else 139 - pci_walk_bus(bus, cb, userdata); 140 - 141 - put_cxl_mock_ops(index); 142 - } 143 - EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus); 144 - 145 117 struct nvdimm_bus * 146 118 __wrap_nvdimm_bus_register(struct device *dev, 147 119 struct nvdimm_bus_descriptor *nd_desc) ··· 131 155 } 132 156 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 133 157 158 + int __wrap_devm_cxl_port_enumerate_dports(struct device *host, 159 + struct cxl_port *port) 160 + { 161 + int rc, index; 162 + struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 163 + 164 + if (ops && ops->is_mock_port(port->uport)) 165 + rc = ops->devm_cxl_port_enumerate_dports(host, port); 166 + else 167 + rc = devm_cxl_port_enumerate_dports(host, port); 168 + put_cxl_mock_ops(index); 169 + 170 + return rc; 171 + } 172 + EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); 173 + 134 174 MODULE_LICENSE("GPL v2"); 135 175 MODULE_IMPORT_NS(ACPI); 176 + MODULE_IMPORT_NS(CXL);
+4 -2
tools/testing/cxl/test/mock.h
··· 2 2 3 3 #include <linux/list.h> 4 4 #include <linux/acpi.h> 5 + #include <cxl.h> 5 6 6 7 struct cxl_mock_ops { 7 8 struct list_head list; ··· 16 15 struct acpi_object_list *arguments, 17 16 unsigned long long *data); 18 17 struct acpi_pci_root *(*acpi_pci_find_root)(acpi_handle handle); 19 - struct platform_device *(*mock_port)(struct pci_bus *bus, int index); 20 18 bool (*is_mock_bus)(struct pci_bus *bus); 21 - bool (*is_mock_port)(struct platform_device *pdev); 19 + bool (*is_mock_port)(struct device *dev); 22 20 bool (*is_mock_dev)(struct device *dev); 21 + int (*devm_cxl_port_enumerate_dports)(struct device *host, 22 + struct cxl_port *port); 23 23 }; 24 24 25 25 void register_cxl_mock_ops(struct cxl_mock_ops *ops);