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 <cxlmem.h> 11 #include <cxlpci.h> 12 #include "mock.h" 13 14 static LIST_HEAD(mock); 15 16 void register_cxl_mock_ops(struct cxl_mock_ops *ops) 17 { 18 list_add_rcu(&ops->list, &mock); 19 } 20 EXPORT_SYMBOL_GPL(register_cxl_mock_ops); 21 22 static DEFINE_SRCU(cxl_mock_srcu); 23 24 void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 25 { 26 list_del_rcu(&ops->list); 27 synchronize_srcu(&cxl_mock_srcu); 28 } 29 EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 30 31 struct cxl_mock_ops *get_cxl_mock_ops(int *index) 32 { 33 *index = srcu_read_lock(&cxl_mock_srcu); 34 return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); 35 } 36 EXPORT_SYMBOL_GPL(get_cxl_mock_ops); 37 38 void put_cxl_mock_ops(int index) 39 { 40 srcu_read_unlock(&cxl_mock_srcu, index); 41 } 42 EXPORT_SYMBOL_GPL(put_cxl_mock_ops); 43 44 bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) 45 { 46 struct acpi_device *adev = 47 container_of(fwnode, struct acpi_device, fwnode); 48 int index; 49 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 50 bool retval = false; 51 52 if (ops) 53 retval = ops->is_mock_adev(adev); 54 55 if (!retval) 56 retval = is_acpi_device_node(fwnode); 57 58 put_cxl_mock_ops(index); 59 return retval; 60 } 61 EXPORT_SYMBOL(__wrap_is_acpi_device_node); 62 63 int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, 64 acpi_tbl_entry_handler_arg handler_arg, 65 void *arg) 66 { 67 int index, rc; 68 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 69 70 if (ops) 71 rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); 72 else 73 rc = acpi_table_parse_cedt(id, handler_arg, arg); 74 75 put_cxl_mock_ops(index); 76 77 return rc; 78 } 79 EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); 80 81 acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 82 acpi_string pathname, 83 struct acpi_object_list *arguments, 84 unsigned long long *data) 85 { 86 int index; 87 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 88 acpi_status status; 89 90 if (ops) 91 status = ops->acpi_evaluate_integer(handle, pathname, arguments, 92 data); 93 else 94 status = acpi_evaluate_integer(handle, pathname, arguments, 95 data); 96 put_cxl_mock_ops(index); 97 98 return status; 99 } 100 EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 101 102 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 103 { 104 int index; 105 struct acpi_pci_root *root; 106 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 107 108 if (ops) 109 root = ops->acpi_pci_find_root(handle); 110 else 111 root = acpi_pci_find_root(handle); 112 113 put_cxl_mock_ops(index); 114 115 return root; 116 } 117 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 118 119 struct nvdimm_bus * 120 __wrap_nvdimm_bus_register(struct device *dev, 121 struct nvdimm_bus_descriptor *nd_desc) 122 { 123 int index; 124 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 125 126 if (ops && ops->is_mock_dev(dev->parent->parent)) 127 nd_desc->provider_name = "cxl_test"; 128 put_cxl_mock_ops(index); 129 130 return nvdimm_bus_register(dev, nd_desc); 131 } 132 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 133 134 struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port) 135 { 136 int index; 137 struct cxl_hdm *cxlhdm; 138 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 139 140 if (ops && ops->is_mock_port(port->uport)) 141 cxlhdm = ops->devm_cxl_setup_hdm(port); 142 else 143 cxlhdm = devm_cxl_setup_hdm(port); 144 put_cxl_mock_ops(index); 145 146 return cxlhdm; 147 } 148 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); 149 150 int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port) 151 { 152 int rc, index; 153 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 154 155 if (ops && ops->is_mock_port(port->uport)) 156 rc = ops->devm_cxl_add_passthrough_decoder(port); 157 else 158 rc = devm_cxl_add_passthrough_decoder(port); 159 put_cxl_mock_ops(index); 160 161 return rc; 162 } 163 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); 164 165 int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) 166 { 167 int rc, index; 168 struct cxl_port *port = cxlhdm->port; 169 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 170 171 if (ops && ops->is_mock_port(port->uport)) 172 rc = ops->devm_cxl_enumerate_decoders(cxlhdm); 173 else 174 rc = devm_cxl_enumerate_decoders(cxlhdm); 175 put_cxl_mock_ops(index); 176 177 return rc; 178 } 179 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); 180 181 int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) 182 { 183 int rc, index; 184 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 185 186 if (ops && ops->is_mock_port(port->uport)) 187 rc = ops->devm_cxl_port_enumerate_dports(port); 188 else 189 rc = devm_cxl_port_enumerate_dports(port); 190 put_cxl_mock_ops(index); 191 192 return rc; 193 } 194 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); 195 196 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 197 { 198 int rc, index; 199 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 200 201 if (ops && ops->is_mock_dev(cxlds->dev)) 202 rc = 0; 203 else 204 rc = cxl_await_media_ready(cxlds); 205 put_cxl_mock_ops(index); 206 207 return rc; 208 } 209 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); 210 211 int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, 212 struct cxl_hdm *cxlhdm) 213 { 214 int rc = 0, index; 215 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 216 217 if (ops && ops->is_mock_dev(cxlds->dev)) 218 rc = 0; 219 else 220 rc = cxl_hdm_decode_init(cxlds, cxlhdm); 221 put_cxl_mock_ops(index); 222 223 return rc; 224 } 225 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); 226 227 MODULE_LICENSE("GPL v2"); 228 MODULE_IMPORT_NS(ACPI); 229 MODULE_IMPORT_NS(CXL); 230