162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci//Copyright(c) 2021 Intel Corporation. All rights reserved. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/libnvdimm.h> 562306a36Sopenharmony_ci#include <linux/rculist.h> 662306a36Sopenharmony_ci#include <linux/device.h> 762306a36Sopenharmony_ci#include <linux/export.h> 862306a36Sopenharmony_ci#include <linux/acpi.h> 962306a36Sopenharmony_ci#include <linux/pci.h> 1062306a36Sopenharmony_ci#include <cxlmem.h> 1162306a36Sopenharmony_ci#include <cxlpci.h> 1262306a36Sopenharmony_ci#include "mock.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic LIST_HEAD(mock); 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_civoid register_cxl_mock_ops(struct cxl_mock_ops *ops) 1762306a36Sopenharmony_ci{ 1862306a36Sopenharmony_ci list_add_rcu(&ops->list, &mock); 1962306a36Sopenharmony_ci} 2062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(register_cxl_mock_ops); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciDEFINE_STATIC_SRCU(cxl_mock_srcu); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci list_del_rcu(&ops->list); 2762306a36Sopenharmony_ci synchronize_srcu(&cxl_mock_srcu); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistruct cxl_mock_ops *get_cxl_mock_ops(int *index) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci *index = srcu_read_lock(&cxl_mock_srcu); 3462306a36Sopenharmony_ci return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(get_cxl_mock_ops); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_civoid put_cxl_mock_ops(int index) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci srcu_read_unlock(&cxl_mock_srcu, index); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(put_cxl_mock_ops); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cibool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci struct acpi_device *adev = 4762306a36Sopenharmony_ci container_of(fwnode, struct acpi_device, fwnode); 4862306a36Sopenharmony_ci int index; 4962306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 5062306a36Sopenharmony_ci bool retval = false; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (ops) 5362306a36Sopenharmony_ci retval = ops->is_mock_adev(adev); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (!retval) 5662306a36Sopenharmony_ci retval = is_acpi_device_node(fwnode); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci put_cxl_mock_ops(index); 5962306a36Sopenharmony_ci return retval; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ciEXPORT_SYMBOL(__wrap_is_acpi_device_node); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciint __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, 6462306a36Sopenharmony_ci acpi_tbl_entry_handler_arg handler_arg, 6562306a36Sopenharmony_ci void *arg) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci int index, rc; 6862306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (ops) 7162306a36Sopenharmony_ci rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); 7262306a36Sopenharmony_ci else 7362306a36Sopenharmony_ci rc = acpi_table_parse_cedt(id, handler_arg, arg); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci put_cxl_mock_ops(index); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return rc; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciacpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 8262306a36Sopenharmony_ci acpi_string pathname, 8362306a36Sopenharmony_ci struct acpi_object_list *arguments, 8462306a36Sopenharmony_ci unsigned long long *data) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci int index; 8762306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 8862306a36Sopenharmony_ci acpi_status status; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (ops) 9162306a36Sopenharmony_ci status = ops->acpi_evaluate_integer(handle, pathname, arguments, 9262306a36Sopenharmony_ci data); 9362306a36Sopenharmony_ci else 9462306a36Sopenharmony_ci status = acpi_evaluate_integer(handle, pathname, arguments, 9562306a36Sopenharmony_ci data); 9662306a36Sopenharmony_ci put_cxl_mock_ops(index); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci return status; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ciEXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci int index; 10562306a36Sopenharmony_ci struct acpi_pci_root *root; 10662306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (ops) 10962306a36Sopenharmony_ci root = ops->acpi_pci_find_root(handle); 11062306a36Sopenharmony_ci else 11162306a36Sopenharmony_ci root = acpi_pci_find_root(handle); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci put_cxl_mock_ops(index); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci return root; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistruct nvdimm_bus * 12062306a36Sopenharmony_ci__wrap_nvdimm_bus_register(struct device *dev, 12162306a36Sopenharmony_ci struct nvdimm_bus_descriptor *nd_desc) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci int index; 12462306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (ops && ops->is_mock_dev(dev->parent->parent)) 12762306a36Sopenharmony_ci nd_desc->provider_name = "cxl_test"; 12862306a36Sopenharmony_ci put_cxl_mock_ops(index); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return nvdimm_bus_register(dev, nd_desc); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistruct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port, 13562306a36Sopenharmony_ci struct cxl_endpoint_dvsec_info *info) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int index; 13962306a36Sopenharmony_ci struct cxl_hdm *cxlhdm; 14062306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (ops && ops->is_mock_port(port->uport_dev)) 14362306a36Sopenharmony_ci cxlhdm = ops->devm_cxl_setup_hdm(port, info); 14462306a36Sopenharmony_ci else 14562306a36Sopenharmony_ci cxlhdm = devm_cxl_setup_hdm(port, info); 14662306a36Sopenharmony_ci put_cxl_mock_ops(index); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci return cxlhdm; 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciint __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci int rc, index; 15562306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (ops && ops->is_mock_port(port->uport_dev)) 15862306a36Sopenharmony_ci rc = ops->devm_cxl_add_passthrough_decoder(port); 15962306a36Sopenharmony_ci else 16062306a36Sopenharmony_ci rc = devm_cxl_add_passthrough_decoder(port); 16162306a36Sopenharmony_ci put_cxl_mock_ops(index); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return rc; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciint __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 16862306a36Sopenharmony_ci struct cxl_endpoint_dvsec_info *info) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci int rc, index; 17162306a36Sopenharmony_ci struct cxl_port *port = cxlhdm->port; 17262306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (ops && ops->is_mock_port(port->uport_dev)) 17562306a36Sopenharmony_ci rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info); 17662306a36Sopenharmony_ci else 17762306a36Sopenharmony_ci rc = devm_cxl_enumerate_decoders(cxlhdm, info); 17862306a36Sopenharmony_ci put_cxl_mock_ops(index); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return rc; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciint __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci int rc, index; 18762306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (ops && ops->is_mock_port(port->uport_dev)) 19062306a36Sopenharmony_ci rc = ops->devm_cxl_port_enumerate_dports(port); 19162306a36Sopenharmony_ci else 19262306a36Sopenharmony_ci rc = devm_cxl_port_enumerate_dports(port); 19362306a36Sopenharmony_ci put_cxl_mock_ops(index); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci return rc; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciint __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci int rc, index; 20262306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (ops && ops->is_mock_dev(cxlds->dev)) 20562306a36Sopenharmony_ci rc = 0; 20662306a36Sopenharmony_ci else 20762306a36Sopenharmony_ci rc = cxl_await_media_ready(cxlds); 20862306a36Sopenharmony_ci put_cxl_mock_ops(index); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return rc; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciint __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, 21562306a36Sopenharmony_ci struct cxl_hdm *cxlhdm, 21662306a36Sopenharmony_ci struct cxl_endpoint_dvsec_info *info) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci int rc = 0, index; 21962306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (ops && ops->is_mock_dev(cxlds->dev)) 22262306a36Sopenharmony_ci rc = 0; 22362306a36Sopenharmony_ci else 22462306a36Sopenharmony_ci rc = cxl_hdm_decode_init(cxlds, cxlhdm, info); 22562306a36Sopenharmony_ci put_cxl_mock_ops(index); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci return rc; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciint __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec, 23262306a36Sopenharmony_ci struct cxl_endpoint_dvsec_info *info) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci int rc = 0, index; 23562306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (ops && ops->is_mock_dev(dev)) 23862306a36Sopenharmony_ci rc = 0; 23962306a36Sopenharmony_ci else 24062306a36Sopenharmony_ci rc = cxl_dvsec_rr_decode(dev, dvsec, info); 24162306a36Sopenharmony_ci put_cxl_mock_ops(index); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return rc; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistruct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port, 24862306a36Sopenharmony_ci struct device *dport_dev, 24962306a36Sopenharmony_ci int port_id, 25062306a36Sopenharmony_ci resource_size_t rcrb) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci int index; 25362306a36Sopenharmony_ci struct cxl_dport *dport; 25462306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (ops && ops->is_mock_port(dport_dev)) { 25762306a36Sopenharmony_ci dport = devm_cxl_add_dport(port, dport_dev, port_id, 25862306a36Sopenharmony_ci CXL_RESOURCE_NONE); 25962306a36Sopenharmony_ci if (!IS_ERR(dport)) { 26062306a36Sopenharmony_ci dport->rcrb.base = rcrb; 26162306a36Sopenharmony_ci dport->rch = true; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci } else 26462306a36Sopenharmony_ci dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb); 26562306a36Sopenharmony_ci put_cxl_mock_ops(index); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return dport; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciresource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev, 27262306a36Sopenharmony_ci struct cxl_dport *dport) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci int index; 27562306a36Sopenharmony_ci resource_size_t component_reg_phys; 27662306a36Sopenharmony_ci struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (ops && ops->is_mock_port(dev)) 27962306a36Sopenharmony_ci component_reg_phys = CXL_RESOURCE_NONE; 28062306a36Sopenharmony_ci else 28162306a36Sopenharmony_ci component_reg_phys = cxl_rcd_component_reg_phys(dev, dport); 28262306a36Sopenharmony_ci put_cxl_mock_ops(index); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return component_reg_phys; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 28962306a36Sopenharmony_ciMODULE_IMPORT_NS(ACPI); 29062306a36Sopenharmony_ciMODULE_IMPORT_NS(CXL); 291