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