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 14static LIST_HEAD(mock); 15 16void register_cxl_mock_ops(struct cxl_mock_ops *ops) 17{ 18 list_add_rcu(&ops->list, &mock); 19} 20EXPORT_SYMBOL_GPL(register_cxl_mock_ops); 21 22DEFINE_STATIC_SRCU(cxl_mock_srcu); 23 24void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 25{ 26 list_del_rcu(&ops->list); 27 synchronize_srcu(&cxl_mock_srcu); 28} 29EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 30 31struct 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} 36EXPORT_SYMBOL_GPL(get_cxl_mock_ops); 37 38void put_cxl_mock_ops(int index) 39{ 40 srcu_read_unlock(&cxl_mock_srcu, index); 41} 42EXPORT_SYMBOL_GPL(put_cxl_mock_ops); 43 44bool __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} 61EXPORT_SYMBOL(__wrap_is_acpi_device_node); 62 63int __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} 79EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); 80 81acpi_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} 100EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 101 102struct 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} 117EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 118 119struct 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} 132EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 133 134struct 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} 150EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); 151 152int __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} 165EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); 166 167int __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} 182EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); 183 184int __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} 197EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); 198 199int __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} 212EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); 213 214int __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} 229EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); 230 231int __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} 245EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL); 246 247struct 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} 269EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL); 270 271resource_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} 286EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL); 287 288MODULE_LICENSE("GPL v2"); 289MODULE_IMPORT_NS(ACPI); 290MODULE_IMPORT_NS(CXL); 291