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 DEFINE_STATIC_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 struct cxl_endpoint_dvsec_info *info) 136 137 { 138 int index; 139 struct cxl_hdm *cxlhdm; 140 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 141 142 if (ops && ops->is_mock_port(port->uport_dev)) 143 cxlhdm = ops->devm_cxl_setup_hdm(port, info); 144 else 145 cxlhdm = devm_cxl_setup_hdm(port, info); 146 put_cxl_mock_ops(index); 147 148 return cxlhdm; 149 } 150 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); 151 152 int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port) 153 { 154 int rc, index; 155 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 156 157 if (ops && ops->is_mock_port(port->uport_dev)) 158 rc = ops->devm_cxl_add_passthrough_decoder(port); 159 else 160 rc = devm_cxl_add_passthrough_decoder(port); 161 put_cxl_mock_ops(index); 162 163 return rc; 164 } 165 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); 166 167 int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 168 struct cxl_endpoint_dvsec_info *info) 169 { 170 int rc, index; 171 struct cxl_port *port = cxlhdm->port; 172 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 173 174 if (ops && ops->is_mock_port(port->uport_dev)) 175 rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info); 176 else 177 rc = devm_cxl_enumerate_decoders(cxlhdm, info); 178 put_cxl_mock_ops(index); 179 180 return rc; 181 } 182 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); 183 184 int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) 185 { 186 int rc, index; 187 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 188 189 if (ops && ops->is_mock_port(port->uport_dev)) 190 rc = ops->devm_cxl_port_enumerate_dports(port); 191 else 192 rc = devm_cxl_port_enumerate_dports(port); 193 put_cxl_mock_ops(index); 194 195 return rc; 196 } 197 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); 198 199 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 200 { 201 int rc, index; 202 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 203 204 if (ops && ops->is_mock_dev(cxlds->dev)) 205 rc = 0; 206 else 207 rc = cxl_await_media_ready(cxlds); 208 put_cxl_mock_ops(index); 209 210 return rc; 211 } 212 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); 213 214 int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, 215 struct cxl_hdm *cxlhdm, 216 struct cxl_endpoint_dvsec_info *info) 217 { 218 int rc = 0, index; 219 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 220 221 if (ops && ops->is_mock_dev(cxlds->dev)) 222 rc = 0; 223 else 224 rc = cxl_hdm_decode_init(cxlds, cxlhdm, info); 225 put_cxl_mock_ops(index); 226 227 return rc; 228 } 229 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); 230 231 int __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec, 232 struct cxl_endpoint_dvsec_info *info) 233 { 234 int rc = 0, index; 235 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 236 237 if (ops && ops->is_mock_dev(dev)) 238 rc = 0; 239 else 240 rc = cxl_dvsec_rr_decode(dev, dvsec, info); 241 put_cxl_mock_ops(index); 242 243 return rc; 244 } 245 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL); 246 247 struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port, 248 struct device *dport_dev, 249 int port_id, 250 resource_size_t rcrb) 251 { 252 int index; 253 struct cxl_dport *dport; 254 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 255 256 if (ops && ops->is_mock_port(dport_dev)) { 257 dport = devm_cxl_add_dport(port, dport_dev, port_id, 258 CXL_RESOURCE_NONE); 259 if (!IS_ERR(dport)) { 260 dport->rcrb.base = rcrb; 261 dport->rch = true; 262 } 263 } else 264 dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb); 265 put_cxl_mock_ops(index); 266 267 return dport; 268 } 269 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL); 270 271 resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev, 272 struct cxl_dport *dport) 273 { 274 int index; 275 resource_size_t component_reg_phys; 276 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 277 278 if (ops && ops->is_mock_port(dev)) 279 component_reg_phys = CXL_RESOURCE_NONE; 280 else 281 component_reg_phys = cxl_rcd_component_reg_phys(dev, dport); 282 put_cxl_mock_ops(index); 283 284 return component_reg_phys; 285 } 286 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL); 287 288 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port) 289 { 290 int index; 291 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 292 struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); 293 294 if (ops && ops->is_mock_dev(cxlmd->dev.parent)) 295 ops->cxl_endpoint_parse_cdat(port); 296 else 297 cxl_endpoint_parse_cdat(port); 298 put_cxl_mock_ops(index); 299 } 300 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, CXL); 301 302 void __wrap_cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport) 303 { 304 int index; 305 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 306 307 if (!ops || !ops->is_mock_port(dport->dport_dev)) 308 cxl_setup_parent_dport(host, dport); 309 310 put_cxl_mock_ops(index); 311 } 312 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_setup_parent_dport, CXL); 313 314 MODULE_LICENSE("GPL v2"); 315 MODULE_IMPORT_NS(ACPI); 316 MODULE_IMPORT_NS(CXL); 317