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 int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, 62 acpi_tbl_entry_handler_arg handler_arg, 63 void *arg) 64 { 65 int index, rc; 66 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 67 68 if (ops) 69 rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); 70 else 71 rc = acpi_table_parse_cedt(id, handler_arg, arg); 72 73 put_cxl_mock_ops(index); 74 75 return rc; 76 } 77 EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); 78 79 acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 80 acpi_string pathname, 81 struct acpi_object_list *arguments, 82 unsigned long long *data) 83 { 84 int index; 85 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 86 acpi_status status; 87 88 if (ops) 89 status = ops->acpi_evaluate_integer(handle, pathname, arguments, 90 data); 91 else 92 status = acpi_evaluate_integer(handle, pathname, arguments, 93 data); 94 put_cxl_mock_ops(index); 95 96 return status; 97 } 98 EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 99 100 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 101 { 102 int index; 103 struct acpi_pci_root *root; 104 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 105 106 if (ops) 107 root = ops->acpi_pci_find_root(handle); 108 else 109 root = acpi_pci_find_root(handle); 110 111 put_cxl_mock_ops(index); 112 113 return root; 114 } 115 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 116 117 void __wrap_pci_walk_bus(struct pci_bus *bus, 118 int (*cb)(struct pci_dev *, void *), void *userdata) 119 { 120 int index; 121 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 122 123 if (ops && ops->is_mock_bus(bus)) { 124 int rc, i; 125 126 /* 127 * Simulate 2 root ports per host-bridge and no 128 * depth recursion. 129 */ 130 for (i = 0; i < 2; i++) { 131 rc = cb((struct pci_dev *) ops->mock_port(bus, i), 132 userdata); 133 if (rc) 134 break; 135 } 136 } else 137 pci_walk_bus(bus, cb, userdata); 138 139 put_cxl_mock_ops(index); 140 } 141 EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus); 142 143 struct nvdimm_bus * 144 __wrap_nvdimm_bus_register(struct device *dev, 145 struct nvdimm_bus_descriptor *nd_desc) 146 { 147 int index; 148 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 149 150 if (ops && ops->is_mock_dev(dev->parent->parent)) 151 nd_desc->provider_name = "cxl_test"; 152 put_cxl_mock_ops(index); 153 154 return nvdimm_bus_register(dev, nd_desc); 155 } 156 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 157 158 MODULE_LICENSE("GPL v2"); 159 MODULE_IMPORT_NS(ACPI); 160