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 int __wrap_hmat_get_extended_linear_cache_size(struct resource *backing_res, 103 int nid, 104 resource_size_t *cache_size) 105 { 106 int index, rc; 107 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 108 109 if (ops) 110 rc = ops->hmat_get_extended_linear_cache_size(backing_res, nid, 111 cache_size); 112 else 113 rc = hmat_get_extended_linear_cache_size(backing_res, nid, 114 cache_size); 115 116 put_cxl_mock_ops(index); 117 118 return rc; 119 } 120 EXPORT_SYMBOL_GPL(__wrap_hmat_get_extended_linear_cache_size); 121 122 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle) 123 { 124 int index; 125 struct acpi_pci_root *root; 126 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 127 128 if (ops) 129 root = ops->acpi_pci_find_root(handle); 130 else 131 root = acpi_pci_find_root(handle); 132 133 put_cxl_mock_ops(index); 134 135 return root; 136 } 137 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root); 138 139 struct nvdimm_bus * 140 __wrap_nvdimm_bus_register(struct device *dev, 141 struct nvdimm_bus_descriptor *nd_desc) 142 { 143 int index; 144 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 145 146 if (ops && ops->is_mock_dev(dev->parent->parent)) 147 nd_desc->provider_name = "cxl_test"; 148 put_cxl_mock_ops(index); 149 150 return nvdimm_bus_register(dev, nd_desc); 151 } 152 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 153 154 int __wrap_devm_cxl_switch_port_decoders_setup(struct cxl_port *port) 155 { 156 int rc, index; 157 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 158 159 if (ops && ops->is_mock_port(port->uport_dev)) 160 rc = ops->devm_cxl_switch_port_decoders_setup(port); 161 else 162 rc = devm_cxl_switch_port_decoders_setup(port); 163 put_cxl_mock_ops(index); 164 165 return rc; 166 } 167 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_switch_port_decoders_setup, "CXL"); 168 169 int __wrap_devm_cxl_endpoint_decoders_setup(struct cxl_port *port) 170 { 171 int rc, index; 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_endpoint_decoders_setup(port); 176 else 177 rc = devm_cxl_endpoint_decoders_setup(port); 178 put_cxl_mock_ops(index); 179 180 return rc; 181 } 182 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_endpoint_decoders_setup, "CXL"); 183 184 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) 185 { 186 int rc, index; 187 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 188 189 if (ops && ops->is_mock_dev(cxlds->dev)) 190 rc = 0; 191 else 192 rc = cxl_await_media_ready(cxlds); 193 put_cxl_mock_ops(index); 194 195 return rc; 196 } 197 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, "CXL"); 198 199 struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port, 200 struct device *dport_dev, 201 int port_id, 202 resource_size_t rcrb) 203 { 204 int index; 205 struct cxl_dport *dport; 206 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 207 208 if (ops && ops->is_mock_port(dport_dev)) { 209 dport = devm_cxl_add_dport(port, dport_dev, port_id, 210 CXL_RESOURCE_NONE); 211 if (!IS_ERR(dport)) { 212 dport->rcrb.base = rcrb; 213 dport->rch = true; 214 } 215 } else 216 dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb); 217 put_cxl_mock_ops(index); 218 219 return dport; 220 } 221 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, "CXL"); 222 223 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port) 224 { 225 int index; 226 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 227 struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); 228 229 if (ops && ops->is_mock_dev(cxlmd->dev.parent)) 230 ops->cxl_endpoint_parse_cdat(port); 231 else 232 cxl_endpoint_parse_cdat(port); 233 put_cxl_mock_ops(index); 234 } 235 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL"); 236 237 struct cxl_dport *__wrap_devm_cxl_add_dport_by_dev(struct cxl_port *port, 238 struct device *dport_dev) 239 { 240 int index; 241 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 242 struct cxl_dport *dport; 243 244 if (ops && ops->is_mock_port(port->uport_dev)) 245 dport = ops->devm_cxl_add_dport_by_dev(port, dport_dev); 246 else 247 dport = devm_cxl_add_dport_by_dev(port, dport_dev); 248 put_cxl_mock_ops(index); 249 250 return dport; 251 } 252 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_dport_by_dev, "CXL"); 253 254 MODULE_LICENSE("GPL v2"); 255 MODULE_DESCRIPTION("cxl_test: emulation module"); 256 MODULE_IMPORT_NS("ACPI"); 257 MODULE_IMPORT_NS("CXL"); 258