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 #include "../exports.h" 14 15 static LIST_HEAD(mock); 16 17 static struct cxl_dport * 18 redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port, 19 struct device *dport_dev); 20 static int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port); 21 22 void register_cxl_mock_ops(struct cxl_mock_ops *ops) 23 { 24 list_add_rcu(&ops->list, &mock); 25 _devm_cxl_add_dport_by_dev = redirect_devm_cxl_add_dport_by_dev; 26 _devm_cxl_switch_port_decoders_setup = 27 redirect_devm_cxl_switch_port_decoders_setup; 28 } 29 EXPORT_SYMBOL_GPL(register_cxl_mock_ops); 30 31 DEFINE_STATIC_SRCU(cxl_mock_srcu); 32 33 void unregister_cxl_mock_ops(struct cxl_mock_ops *ops) 34 { 35 _devm_cxl_switch_port_decoders_setup = 36 __devm_cxl_switch_port_decoders_setup; 37 _devm_cxl_add_dport_by_dev = __devm_cxl_add_dport_by_dev; 38 list_del_rcu(&ops->list); 39 synchronize_srcu(&cxl_mock_srcu); 40 } 41 EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops); 42 43 struct cxl_mock_ops *get_cxl_mock_ops(int *index) 44 { 45 *index = srcu_read_lock(&cxl_mock_srcu); 46 return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list); 47 } 48 EXPORT_SYMBOL_GPL(get_cxl_mock_ops); 49 50 void put_cxl_mock_ops(int index) 51 { 52 srcu_read_unlock(&cxl_mock_srcu, index); 53 } 54 EXPORT_SYMBOL_GPL(put_cxl_mock_ops); 55 56 bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode) 57 { 58 struct acpi_device *adev = 59 container_of(fwnode, struct acpi_device, fwnode); 60 int index; 61 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 62 bool retval = false; 63 64 if (ops) 65 retval = ops->is_mock_adev(adev); 66 67 if (!retval) 68 retval = is_acpi_device_node(fwnode); 69 70 put_cxl_mock_ops(index); 71 return retval; 72 } 73 EXPORT_SYMBOL(__wrap_is_acpi_device_node); 74 75 int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, 76 acpi_tbl_entry_handler_arg handler_arg, 77 void *arg) 78 { 79 int index, rc; 80 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 81 82 if (ops) 83 rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); 84 else 85 rc = acpi_table_parse_cedt(id, handler_arg, arg); 86 87 put_cxl_mock_ops(index); 88 89 return rc; 90 } 91 EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, "ACPI"); 92 93 acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle, 94 acpi_string pathname, 95 struct acpi_object_list *arguments, 96 unsigned long long *data) 97 { 98 int index; 99 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 100 acpi_status status; 101 102 if (ops) 103 status = ops->acpi_evaluate_integer(handle, pathname, arguments, 104 data); 105 else 106 status = acpi_evaluate_integer(handle, pathname, arguments, 107 data); 108 put_cxl_mock_ops(index); 109 110 return status; 111 } 112 EXPORT_SYMBOL(__wrap_acpi_evaluate_integer); 113 114 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 115 { 116 int index; 117 struct acpi_pci_root *root; 118 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 119 120 if (ops) 121 root = ops->acpi_pci_find_root(handle); 122 else 123 root = acpi_pci_find_root(handle); 124 125 put_cxl_mock_ops(index); 126 127 return root; 128 } 129 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 130 131 struct nvdimm_bus * 132 __wrap_nvdimm_bus_register(struct device *dev, 133 struct nvdimm_bus_descriptor *nd_desc) 134 { 135 int index; 136 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 137 138 if (ops && ops->is_mock_dev(dev->parent->parent)) 139 nd_desc->provider_name = "cxl_test"; 140 put_cxl_mock_ops(index); 141 142 return nvdimm_bus_register(dev, nd_desc); 143 } 144 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 145 146 int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port) 147 { 148 int rc, index; 149 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 150 151 if (ops && ops->is_mock_port(port->uport_dev)) 152 rc = ops->devm_cxl_switch_port_decoders_setup(port); 153 else 154 rc = __devm_cxl_switch_port_decoders_setup(port); 155 put_cxl_mock_ops(index); 156 157 return rc; 158 } 159 160 int __wrap_devm_cxl_endpoint_decoders_setup(struct cxl_port *port) 161 { 162 int rc, index; 163 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 164 165 if (ops && ops->is_mock_port(port->uport_dev)) 166 rc = ops->devm_cxl_endpoint_decoders_setup(port); 167 else 168 rc = devm_cxl_endpoint_decoders_setup(port); 169 put_cxl_mock_ops(index); 170 171 return rc; 172 } 173 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_endpoint_decoders_setup, "CXL"); 174 175 int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) 176 { 177 int rc, index; 178 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 179 180 if (ops && ops->is_mock_port(port->uport_dev)) 181 rc = ops->devm_cxl_port_enumerate_dports(port); 182 else 183 rc = devm_cxl_port_enumerate_dports(port); 184 put_cxl_mock_ops(index); 185 186 return rc; 187 } 188 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, "CXL"); 189 190 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 191 { 192 int rc, index; 193 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 194 195 if (ops && ops->is_mock_dev(cxlds->dev)) 196 rc = 0; 197 else 198 rc = cxl_await_media_ready(cxlds); 199 put_cxl_mock_ops(index); 200 201 return rc; 202 } 203 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, "CXL"); 204 205 struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port, 206 struct device *dport_dev, 207 int port_id, 208 resource_size_t rcrb) 209 { 210 int index; 211 struct cxl_dport *dport; 212 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 213 214 if (ops && ops->is_mock_port(dport_dev)) { 215 dport = devm_cxl_add_dport(port, dport_dev, port_id, 216 CXL_RESOURCE_NONE); 217 if (!IS_ERR(dport)) { 218 dport->rcrb.base = rcrb; 219 dport->rch = true; 220 } 221 } else 222 dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb); 223 put_cxl_mock_ops(index); 224 225 return dport; 226 } 227 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, "CXL"); 228 229 resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev, 230 struct cxl_dport *dport) 231 { 232 int index; 233 resource_size_t component_reg_phys; 234 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 235 236 if (ops && ops->is_mock_port(dev)) 237 component_reg_phys = CXL_RESOURCE_NONE; 238 else 239 component_reg_phys = cxl_rcd_component_reg_phys(dev, dport); 240 put_cxl_mock_ops(index); 241 242 return component_reg_phys; 243 } 244 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, "CXL"); 245 246 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port) 247 { 248 int index; 249 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 250 struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); 251 252 if (ops && ops->is_mock_dev(cxlmd->dev.parent)) 253 ops->cxl_endpoint_parse_cdat(port); 254 else 255 cxl_endpoint_parse_cdat(port); 256 put_cxl_mock_ops(index); 257 } 258 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL"); 259 260 void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host) 261 { 262 int index; 263 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 264 265 if (!ops || !ops->is_mock_port(dport->dport_dev)) 266 cxl_dport_init_ras_reporting(dport, host); 267 268 put_cxl_mock_ops(index); 269 } 270 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL"); 271 272 struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port, 273 struct device *dport_dev) 274 { 275 int index; 276 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 277 struct cxl_dport *dport; 278 279 if (ops && ops->is_mock_port(port->uport_dev)) 280 dport = ops->devm_cxl_add_dport_by_dev(port, dport_dev); 281 else 282 dport = __devm_cxl_add_dport_by_dev(port, dport_dev); 283 put_cxl_mock_ops(index); 284 285 return dport; 286 } 287 288 MODULE_LICENSE("GPL v2"); 289 MODULE_DESCRIPTION("cxl_test: emulation module"); 290 MODULE_IMPORT_NS("ACPI"); 291 MODULE_IMPORT_NS("CXL"); 292