1*67dcdd4dSDan Williams // SPDX-License-Identifier: GPL-2.0-only 2*67dcdd4dSDan Williams //Copyright(c) 2021 Intel Corporation. All rights reserved. 3*67dcdd4dSDan Williams 4*67dcdd4dSDan Williams #include <linux/libnvdimm.h> 5*67dcdd4dSDan Williams #include <linux/rculist.h> 6*67dcdd4dSDan Williams #include <linux/device.h> 7*67dcdd4dSDan Williams #include <linux/export.h> 8*67dcdd4dSDan Williams #include <linux/acpi.h> 9*67dcdd4dSDan Williams #include <linux/pci.h> 10*67dcdd4dSDan Williams #include "mock.h" 11*67dcdd4dSDan Williams 12*67dcdd4dSDan Williams static LIST_HEAD(mock); 13*67dcdd4dSDan Williams 14*67dcdd4dSDan Williams void register_cxl_mock_ops(struct cxl_mock_ops *ops) 15*67dcdd4dSDan Williams { 16*67dcdd4dSDan Williams list_add_rcu(&ops->list, &mock); 17*67dcdd4dSDan Williams } 18*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(register_cxl_mock_ops); 19*67dcdd4dSDan Williams 20*67dcdd4dSDan Williams static DEFINE_SRCU(cxl_mock_srcu); 21*67dcdd4dSDan Williams 22*67dcdd4dSDan Williams void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 23*67dcdd4dSDan Williams { 24*67dcdd4dSDan Williams list_del_rcu(&ops->list); 25*67dcdd4dSDan Williams synchronize_srcu(&cxl_mock_srcu); 26*67dcdd4dSDan Williams } 27*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 28*67dcdd4dSDan Williams 29*67dcdd4dSDan Williams struct cxl_mock_ops *get_cxl_mock_ops(int *index) 30*67dcdd4dSDan Williams { 31*67dcdd4dSDan Williams *index = srcu_read_lock(&cxl_mock_srcu); 32*67dcdd4dSDan Williams return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); 33*67dcdd4dSDan Williams } 34*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(get_cxl_mock_ops); 35*67dcdd4dSDan Williams 36*67dcdd4dSDan Williams void put_cxl_mock_ops(int index) 37*67dcdd4dSDan Williams { 38*67dcdd4dSDan Williams srcu_read_unlock(&cxl_mock_srcu, index); 39*67dcdd4dSDan Williams } 40*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(put_cxl_mock_ops); 41*67dcdd4dSDan Williams 42*67dcdd4dSDan Williams bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) 43*67dcdd4dSDan Williams { 44*67dcdd4dSDan Williams struct acpi_device *adev = 45*67dcdd4dSDan Williams container_of(fwnode, struct acpi_device, fwnode); 46*67dcdd4dSDan Williams int index; 47*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 48*67dcdd4dSDan Williams bool retval = false; 49*67dcdd4dSDan Williams 50*67dcdd4dSDan Williams if (ops) 51*67dcdd4dSDan Williams retval = ops->is_mock_adev(adev); 52*67dcdd4dSDan Williams 53*67dcdd4dSDan Williams if (!retval) 54*67dcdd4dSDan Williams retval = is_acpi_device_node(fwnode); 55*67dcdd4dSDan Williams 56*67dcdd4dSDan Williams put_cxl_mock_ops(index); 57*67dcdd4dSDan Williams return retval; 58*67dcdd4dSDan Williams } 59*67dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_is_acpi_device_node); 60*67dcdd4dSDan Williams 61*67dcdd4dSDan Williams acpi_status __wrap_acpi_get_table(char *signature, u32 instance, 62*67dcdd4dSDan Williams struct acpi_table_header **out_table) 63*67dcdd4dSDan Williams { 64*67dcdd4dSDan Williams int index; 65*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 66*67dcdd4dSDan Williams acpi_status status; 67*67dcdd4dSDan Williams 68*67dcdd4dSDan Williams if (ops) 69*67dcdd4dSDan Williams status = ops->acpi_get_table(signature, instance, out_table); 70*67dcdd4dSDan Williams else 71*67dcdd4dSDan Williams status = acpi_get_table(signature, instance, out_table); 72*67dcdd4dSDan Williams 73*67dcdd4dSDan Williams put_cxl_mock_ops(index); 74*67dcdd4dSDan Williams 75*67dcdd4dSDan Williams return status; 76*67dcdd4dSDan Williams } 77*67dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_get_table); 78*67dcdd4dSDan Williams 79*67dcdd4dSDan Williams void __wrap_acpi_put_table(struct acpi_table_header *table) 80*67dcdd4dSDan Williams { 81*67dcdd4dSDan Williams int index; 82*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 83*67dcdd4dSDan Williams 84*67dcdd4dSDan Williams if (ops) 85*67dcdd4dSDan Williams ops->acpi_put_table(table); 86*67dcdd4dSDan Williams else 87*67dcdd4dSDan Williams acpi_put_table(table); 88*67dcdd4dSDan Williams put_cxl_mock_ops(index); 89*67dcdd4dSDan Williams } 90*67dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_put_table); 91*67dcdd4dSDan Williams 92*67dcdd4dSDan Williams acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 93*67dcdd4dSDan Williams acpi_string pathname, 94*67dcdd4dSDan Williams struct acpi_object_list *arguments, 95*67dcdd4dSDan Williams unsigned long long *data) 96*67dcdd4dSDan Williams { 97*67dcdd4dSDan Williams int index; 98*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 99*67dcdd4dSDan Williams acpi_status status; 100*67dcdd4dSDan Williams 101*67dcdd4dSDan Williams if (ops) 102*67dcdd4dSDan Williams status = ops->acpi_evaluate_integer(handle, pathname, arguments, 103*67dcdd4dSDan Williams data); 104*67dcdd4dSDan Williams else 105*67dcdd4dSDan Williams status = acpi_evaluate_integer(handle, pathname, arguments, 106*67dcdd4dSDan Williams data); 107*67dcdd4dSDan Williams put_cxl_mock_ops(index); 108*67dcdd4dSDan Williams 109*67dcdd4dSDan Williams return status; 110*67dcdd4dSDan Williams } 111*67dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 112*67dcdd4dSDan Williams 113*67dcdd4dSDan Williams struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 114*67dcdd4dSDan Williams { 115*67dcdd4dSDan Williams int index; 116*67dcdd4dSDan Williams struct acpi_pci_root *root; 117*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 118*67dcdd4dSDan Williams 119*67dcdd4dSDan Williams if (ops) 120*67dcdd4dSDan Williams root = ops->acpi_pci_find_root(handle); 121*67dcdd4dSDan Williams else 122*67dcdd4dSDan Williams root = acpi_pci_find_root(handle); 123*67dcdd4dSDan Williams 124*67dcdd4dSDan Williams put_cxl_mock_ops(index); 125*67dcdd4dSDan Williams 126*67dcdd4dSDan Williams return root; 127*67dcdd4dSDan Williams } 128*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 129*67dcdd4dSDan Williams 130*67dcdd4dSDan Williams void __wrap_pci_walk_bus(struct pci_bus *bus, 131*67dcdd4dSDan Williams int (*cb)(struct pci_dev *, void *), void *userdata) 132*67dcdd4dSDan Williams { 133*67dcdd4dSDan Williams int index; 134*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 135*67dcdd4dSDan Williams 136*67dcdd4dSDan Williams if (ops && ops->is_mock_bus(bus)) { 137*67dcdd4dSDan Williams int rc, i; 138*67dcdd4dSDan Williams 139*67dcdd4dSDan Williams /* 140*67dcdd4dSDan Williams * Simulate 2 root ports per host-bridge and no 141*67dcdd4dSDan Williams * depth recursion. 142*67dcdd4dSDan Williams */ 143*67dcdd4dSDan Williams for (i = 0; i < 2; i++) { 144*67dcdd4dSDan Williams rc = cb((struct pci_dev *) ops->mock_port(bus, i), 145*67dcdd4dSDan Williams userdata); 146*67dcdd4dSDan Williams if (rc) 147*67dcdd4dSDan Williams break; 148*67dcdd4dSDan Williams } 149*67dcdd4dSDan Williams } else 150*67dcdd4dSDan Williams pci_walk_bus(bus, cb, userdata); 151*67dcdd4dSDan Williams 152*67dcdd4dSDan Williams put_cxl_mock_ops(index); 153*67dcdd4dSDan Williams } 154*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus); 155*67dcdd4dSDan Williams 156*67dcdd4dSDan Williams struct nvdimm_bus * 157*67dcdd4dSDan Williams __wrap_nvdimm_bus_register(struct device *dev, 158*67dcdd4dSDan Williams struct nvdimm_bus_descriptor *nd_desc) 159*67dcdd4dSDan Williams { 160*67dcdd4dSDan Williams int index; 161*67dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 162*67dcdd4dSDan Williams 163*67dcdd4dSDan Williams if (ops && ops->is_mock_dev(dev->parent->parent)) 164*67dcdd4dSDan Williams nd_desc->provider_name = "cxl_test"; 165*67dcdd4dSDan Williams put_cxl_mock_ops(index); 166*67dcdd4dSDan Williams 167*67dcdd4dSDan Williams return nvdimm_bus_register(dev, nd_desc); 168*67dcdd4dSDan Williams } 169*67dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 170*67dcdd4dSDan Williams 171*67dcdd4dSDan Williams MODULE_LICENSE("GPL v2"); 172