167dcdd4dSDan Williams // SPDX-License-Identifier: GPL-2.0-only 267dcdd4dSDan Williams //Copyright(c) 2021 Intel Corporation. All rights reserved. 367dcdd4dSDan Williams 467dcdd4dSDan Williams #include <linux/libnvdimm.h> 567dcdd4dSDan Williams #include <linux/rculist.h> 667dcdd4dSDan Williams #include <linux/device.h> 767dcdd4dSDan Williams #include <linux/export.h> 867dcdd4dSDan Williams #include <linux/acpi.h> 967dcdd4dSDan Williams #include <linux/pci.h> 1067dcdd4dSDan Williams #include "mock.h" 1167dcdd4dSDan Williams 1267dcdd4dSDan Williams static LIST_HEAD(mock); 1367dcdd4dSDan Williams 1467dcdd4dSDan Williams void register_cxl_mock_ops(struct cxl_mock_ops *ops) 1567dcdd4dSDan Williams { 1667dcdd4dSDan Williams list_add_rcu(&ops->list, &mock); 1767dcdd4dSDan Williams } 1867dcdd4dSDan Williams EXPORT_SYMBOL_GPL(register_cxl_mock_ops); 1967dcdd4dSDan Williams 2067dcdd4dSDan Williams static DEFINE_SRCU(cxl_mock_srcu); 2167dcdd4dSDan Williams 2267dcdd4dSDan Williams void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 2367dcdd4dSDan Williams { 2467dcdd4dSDan Williams list_del_rcu(&ops->list); 2567dcdd4dSDan Williams synchronize_srcu(&cxl_mock_srcu); 2667dcdd4dSDan Williams } 2767dcdd4dSDan Williams EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 2867dcdd4dSDan Williams 2967dcdd4dSDan Williams struct cxl_mock_ops *get_cxl_mock_ops(int *index) 3067dcdd4dSDan Williams { 3167dcdd4dSDan Williams *index = srcu_read_lock(&cxl_mock_srcu); 3267dcdd4dSDan Williams return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); 3367dcdd4dSDan Williams } 3467dcdd4dSDan Williams EXPORT_SYMBOL_GPL(get_cxl_mock_ops); 3567dcdd4dSDan Williams 3667dcdd4dSDan Williams void put_cxl_mock_ops(int index) 3767dcdd4dSDan Williams { 3867dcdd4dSDan Williams srcu_read_unlock(&cxl_mock_srcu, index); 3967dcdd4dSDan Williams } 4067dcdd4dSDan Williams EXPORT_SYMBOL_GPL(put_cxl_mock_ops); 4167dcdd4dSDan Williams 4267dcdd4dSDan Williams bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) 4367dcdd4dSDan Williams { 4467dcdd4dSDan Williams struct acpi_device *adev = 4567dcdd4dSDan Williams container_of(fwnode, struct acpi_device, fwnode); 4667dcdd4dSDan Williams int index; 4767dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 4867dcdd4dSDan Williams bool retval = false; 4967dcdd4dSDan Williams 5067dcdd4dSDan Williams if (ops) 5167dcdd4dSDan Williams retval = ops->is_mock_adev(adev); 5267dcdd4dSDan Williams 5367dcdd4dSDan Williams if (!retval) 5467dcdd4dSDan Williams retval = is_acpi_device_node(fwnode); 5567dcdd4dSDan Williams 5667dcdd4dSDan Williams put_cxl_mock_ops(index); 5767dcdd4dSDan Williams return retval; 5867dcdd4dSDan Williams } 5967dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_is_acpi_device_node); 6067dcdd4dSDan Williams 61*814dff9aSDan Williams int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, 62*814dff9aSDan Williams acpi_tbl_entry_handler_arg handler_arg, 63*814dff9aSDan Williams void *arg) 6467dcdd4dSDan Williams { 65*814dff9aSDan Williams int index, rc; 6667dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 6767dcdd4dSDan Williams 6867dcdd4dSDan Williams if (ops) 69*814dff9aSDan Williams rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); 7067dcdd4dSDan Williams else 71*814dff9aSDan Williams rc = acpi_table_parse_cedt(id, handler_arg, arg); 72*814dff9aSDan Williams 7367dcdd4dSDan Williams put_cxl_mock_ops(index); 74*814dff9aSDan Williams 75*814dff9aSDan Williams return rc; 7667dcdd4dSDan Williams } 77*814dff9aSDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); 7867dcdd4dSDan Williams 7967dcdd4dSDan Williams acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 8067dcdd4dSDan Williams acpi_string pathname, 8167dcdd4dSDan Williams struct acpi_object_list *arguments, 8267dcdd4dSDan Williams unsigned long long *data) 8367dcdd4dSDan Williams { 8467dcdd4dSDan Williams int index; 8567dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 8667dcdd4dSDan Williams acpi_status status; 8767dcdd4dSDan Williams 8867dcdd4dSDan Williams if (ops) 8967dcdd4dSDan Williams status = ops->acpi_evaluate_integer(handle, pathname, arguments, 9067dcdd4dSDan Williams data); 9167dcdd4dSDan Williams else 9267dcdd4dSDan Williams status = acpi_evaluate_integer(handle, pathname, arguments, 9367dcdd4dSDan Williams data); 9467dcdd4dSDan Williams put_cxl_mock_ops(index); 9567dcdd4dSDan Williams 9667dcdd4dSDan Williams return status; 9767dcdd4dSDan Williams } 9867dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 9967dcdd4dSDan Williams 10067dcdd4dSDan Williams struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 10167dcdd4dSDan Williams { 10267dcdd4dSDan Williams int index; 10367dcdd4dSDan Williams struct acpi_pci_root *root; 10467dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 10567dcdd4dSDan Williams 10667dcdd4dSDan Williams if (ops) 10767dcdd4dSDan Williams root = ops->acpi_pci_find_root(handle); 10867dcdd4dSDan Williams else 10967dcdd4dSDan Williams root = acpi_pci_find_root(handle); 11067dcdd4dSDan Williams 11167dcdd4dSDan Williams put_cxl_mock_ops(index); 11267dcdd4dSDan Williams 11367dcdd4dSDan Williams return root; 11467dcdd4dSDan Williams } 11567dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 11667dcdd4dSDan Williams 11767dcdd4dSDan Williams void __wrap_pci_walk_bus(struct pci_bus *bus, 11867dcdd4dSDan Williams int (*cb)(struct pci_dev *, void *), void *userdata) 11967dcdd4dSDan Williams { 12067dcdd4dSDan Williams int index; 12167dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 12267dcdd4dSDan Williams 12367dcdd4dSDan Williams if (ops && ops->is_mock_bus(bus)) { 12467dcdd4dSDan Williams int rc, i; 12567dcdd4dSDan Williams 12667dcdd4dSDan Williams /* 12767dcdd4dSDan Williams * Simulate 2 root ports per host-bridge and no 12867dcdd4dSDan Williams * depth recursion. 12967dcdd4dSDan Williams */ 13067dcdd4dSDan Williams for (i = 0; i < 2; i++) { 13167dcdd4dSDan Williams rc = cb((struct pci_dev *) ops->mock_port(bus, i), 13267dcdd4dSDan Williams userdata); 13367dcdd4dSDan Williams if (rc) 13467dcdd4dSDan Williams break; 13567dcdd4dSDan Williams } 13667dcdd4dSDan Williams } else 13767dcdd4dSDan Williams pci_walk_bus(bus, cb, userdata); 13867dcdd4dSDan Williams 13967dcdd4dSDan Williams put_cxl_mock_ops(index); 14067dcdd4dSDan Williams } 14167dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus); 14267dcdd4dSDan Williams 14367dcdd4dSDan Williams struct nvdimm_bus * 14467dcdd4dSDan Williams __wrap_nvdimm_bus_register(struct device *dev, 14567dcdd4dSDan Williams struct nvdimm_bus_descriptor *nd_desc) 14667dcdd4dSDan Williams { 14767dcdd4dSDan Williams int index; 14867dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 14967dcdd4dSDan Williams 15067dcdd4dSDan Williams if (ops && ops->is_mock_dev(dev->parent->parent)) 15167dcdd4dSDan Williams nd_desc->provider_name = "cxl_test"; 15267dcdd4dSDan Williams put_cxl_mock_ops(index); 15367dcdd4dSDan Williams 15467dcdd4dSDan Williams return nvdimm_bus_register(dev, nd_desc); 15567dcdd4dSDan Williams } 15667dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 15767dcdd4dSDan Williams 15867dcdd4dSDan Williams MODULE_LICENSE("GPL v2"); 159*814dff9aSDan Williams MODULE_IMPORT_NS(ACPI); 160