xref: /linux/tools/testing/cxl/test/mock.c (revision d104e3d17f7bfc505281f57f8c1a5589fca6ffe4)
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