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