xref: /linux/tools/testing/cxl/test/mock.c (revision 6efc0ab3b05de0d7bab8ec0597214e4788251071)
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 struct 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 }
117 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
118 
119 struct 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 }
132 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
133 
134 struct 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 }
150 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL);
151 
152 int __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 }
165 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL);
166 
167 int __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 }
182 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL);
183 
184 int __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 }
197 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL);
198 
199 int __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 }
212 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL);
213 
214 int __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 }
229 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL);
230 
231 int __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 }
245 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL);
246 
247 struct 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 }
269 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL);
270 
271 resource_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 }
286 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL);
287 
288 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
289 {
290 	int index;
291 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
292 	struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
293 
294 	if (ops && ops->is_mock_dev(cxlmd->dev.parent))
295 		ops->cxl_endpoint_parse_cdat(port);
296 	else
297 		cxl_endpoint_parse_cdat(port);
298 	put_cxl_mock_ops(index);
299 }
300 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, CXL);
301 
302 void __wrap_cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport)
303 {
304 	int index;
305 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
306 
307 	if (!ops || !ops->is_mock_port(dport->dport_dev))
308 		cxl_setup_parent_dport(host, dport);
309 
310 	put_cxl_mock_ops(index);
311 }
312 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_setup_parent_dport, CXL);
313 
314 MODULE_LICENSE("GPL v2");
315 MODULE_IMPORT_NS(ACPI);
316 MODULE_IMPORT_NS(CXL);
317