// SPDX-License-Identifier: GPL-2.0-only //Copyright(c) 2021 Intel Corporation. All rights reserved. #include <linux/libnvdimm.h> #include <linux/rculist.h> #include <linux/device.h> #include <linux/export.h> #include <linux/acpi.h> #include <linux/pci.h> #include <cxlmem.h> #include <cxlpci.h> #include "mock.h" static LIST_HEAD(mock); void register_cxl_mock_ops(struct cxl_mock_ops *ops) { list_add_rcu(&ops->list, &mock); } EXPORT_SYMBOL_GPL(register_cxl_mock_ops); DEFINE_STATIC_SRCU(cxl_mock_srcu); void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) { list_del_rcu(&ops->list); synchronize_srcu(&cxl_mock_srcu); } EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); struct cxl_mock_ops *get_cxl_mock_ops(int *index) { *index = srcu_read_lock(&cxl_mock_srcu); return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); } EXPORT_SYMBOL_GPL(get_cxl_mock_ops); void put_cxl_mock_ops(int index) { srcu_read_unlock(&cxl_mock_srcu, index); } EXPORT_SYMBOL_GPL(put_cxl_mock_ops); bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) { struct acpi_device *adev = container_of(fwnode, struct acpi_device, fwnode); int index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); bool retval = false; if (ops) retval = ops->is_mock_adev(adev); if (!retval) retval = is_acpi_device_node(fwnode); put_cxl_mock_ops(index); return retval; } EXPORT_SYMBOL(__wrap_is_acpi_device_node); int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, acpi_tbl_entry_handler_arg handler_arg, void *arg) { int index, rc; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops) rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); else rc = acpi_table_parse_cedt(id, handler_arg, arg); put_cxl_mock_ops(index); return rc; } EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, acpi_string pathname, struct acpi_object_list *arguments, unsigned long long *data) { int index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); acpi_status status; if (ops) status = ops->acpi_evaluate_integer(handle, pathname, arguments, data); else status = acpi_evaluate_integer(handle, pathname, arguments, data); put_cxl_mock_ops(index); return status; } EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) { int index; struct acpi_pci_root *root; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops) root = ops->acpi_pci_find_root(handle); else root = acpi_pci_find_root(handle); put_cxl_mock_ops(index); return root; } EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); struct nvdimm_bus * __wrap_nvdimm_bus_register(struct device *dev, struct nvdimm_bus_descriptor *nd_desc) { int index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_dev(dev->parent->parent)) nd_desc->provider_name = "cxl_test"; put_cxl_mock_ops(index); return nvdimm_bus_register(dev, nd_desc); } EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port, struct cxl_endpoint_dvsec_info *info) { int index; struct cxl_hdm *cxlhdm; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(port->uport_dev)) cxlhdm = ops->devm_cxl_setup_hdm(port, info); else cxlhdm = devm_cxl_setup_hdm(port, info); put_cxl_mock_ops(index); return cxlhdm; } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port) { int rc, index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(port->uport_dev)) rc = ops->devm_cxl_add_passthrough_decoder(port); else rc = devm_cxl_add_passthrough_decoder(port); put_cxl_mock_ops(index); return rc; } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info) { int rc, index; struct cxl_port *port = cxlhdm->port; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(port->uport_dev)) rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info); else rc = devm_cxl_enumerate_decoders(cxlhdm, info); put_cxl_mock_ops(index); return rc; } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) { int rc, index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(port->uport_dev)) rc = ops->devm_cxl_port_enumerate_dports(port); else rc = devm_cxl_port_enumerate_dports(port); put_cxl_mock_ops(index); return rc; } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) { int rc, index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_dev(cxlds->dev)) rc = 0; else rc = cxl_await_media_ready(cxlds); put_cxl_mock_ops(index); return rc; } 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_endpoint_dvsec_info *info) { int rc = 0, index; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_dev(cxlds->dev)) rc = 0; else 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); struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port, struct device *dport_dev, int port_id, resource_size_t rcrb) { int index; struct cxl_dport *dport; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(dport_dev)) { dport = devm_cxl_add_dport(port, dport_dev, port_id, CXL_RESOURCE_NONE); if (!IS_ERR(dport)) { dport->rcrb.base = rcrb; dport->rch = true; } } else dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb); put_cxl_mock_ops(index); return dport; } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL); resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev, struct cxl_dport *dport) { int index; resource_size_t component_reg_phys; struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); if (ops && ops->is_mock_port(dev)) component_reg_phys = CXL_RESOURCE_NONE; else component_reg_phys = cxl_rcd_component_reg_phys(dev, dport); put_cxl_mock_ops(index); return component_reg_phys; } EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(ACPI); MODULE_IMPORT_NS(CXL);