xref: /linux/tools/testing/cxl/test/mock.c (revision 7ec9db66cc552f2f8a6779c16d01a2a01eccedde)
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 int __wrap_hmat_get_extended_linear_cache_size(struct resource *backing_res,
115 					       int nid,
116 					       resource_size_t *cache_size)
117 {
118 	int index, rc;
119 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
120 
121 	if (ops)
122 		rc = ops->hmat_get_extended_linear_cache_size(backing_res, nid,
123 							      cache_size);
124 	else
125 		rc = hmat_get_extended_linear_cache_size(backing_res, nid,
126 							 cache_size);
127 
128 	put_cxl_mock_ops(index);
129 
130 	return rc;
131 }
132 EXPORT_SYMBOL_GPL(__wrap_hmat_get_extended_linear_cache_size);
133 
134 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle)
135 {
136 	int index;
137 	struct acpi_pci_root *root;
138 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
139 
140 	if (ops)
141 		root = ops->acpi_pci_find_root(handle);
142 	else
143 		root = acpi_pci_find_root(handle);
144 
145 	put_cxl_mock_ops(index);
146 
147 	return root;
148 }
149 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
150 
151 struct nvdimm_bus *
152 __wrap_nvdimm_bus_register(struct device *dev,
153 			   struct nvdimm_bus_descriptor *nd_desc)
154 {
155 	int index;
156 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
157 
158 	if (ops && ops->is_mock_dev(dev->parent->parent))
159 		nd_desc->provider_name = "cxl_test";
160 	put_cxl_mock_ops(index);
161 
162 	return nvdimm_bus_register(dev, nd_desc);
163 }
164 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
165 
166 int redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port *port)
167 {
168 	int rc, index;
169 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
170 
171 	if (ops && ops->is_mock_port(port->uport_dev))
172 		rc = ops->devm_cxl_switch_port_decoders_setup(port);
173 	else
174 		rc = __devm_cxl_switch_port_decoders_setup(port);
175 	put_cxl_mock_ops(index);
176 
177 	return rc;
178 }
179 
180 int __wrap_devm_cxl_endpoint_decoders_setup(struct cxl_port *port)
181 {
182 	int rc, index;
183 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
184 
185 	if (ops && ops->is_mock_port(port->uport_dev))
186 		rc = ops->devm_cxl_endpoint_decoders_setup(port);
187 	else
188 		rc = devm_cxl_endpoint_decoders_setup(port);
189 	put_cxl_mock_ops(index);
190 
191 	return rc;
192 }
193 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_endpoint_decoders_setup, "CXL");
194 
195 int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
196 {
197 	int rc, index;
198 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
199 
200 	if (ops && ops->is_mock_dev(cxlds->dev))
201 		rc = 0;
202 	else
203 		rc = cxl_await_media_ready(cxlds);
204 	put_cxl_mock_ops(index);
205 
206 	return rc;
207 }
208 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, "CXL");
209 
210 struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port,
211 						struct device *dport_dev,
212 						int port_id,
213 						resource_size_t rcrb)
214 {
215 	int index;
216 	struct cxl_dport *dport;
217 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
218 
219 	if (ops && ops->is_mock_port(dport_dev)) {
220 		dport = devm_cxl_add_dport(port, dport_dev, port_id,
221 					   CXL_RESOURCE_NONE);
222 		if (!IS_ERR(dport)) {
223 			dport->rcrb.base = rcrb;
224 			dport->rch = true;
225 		}
226 	} else
227 		dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb);
228 	put_cxl_mock_ops(index);
229 
230 	return dport;
231 }
232 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, "CXL");
233 
234 resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev,
235 						  struct cxl_dport *dport)
236 {
237 	int index;
238 	resource_size_t component_reg_phys;
239 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
240 
241 	if (ops && ops->is_mock_port(dev))
242 		component_reg_phys = CXL_RESOURCE_NONE;
243 	else
244 		component_reg_phys = cxl_rcd_component_reg_phys(dev, dport);
245 	put_cxl_mock_ops(index);
246 
247 	return component_reg_phys;
248 }
249 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, "CXL");
250 
251 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
252 {
253 	int index;
254 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
255 	struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
256 
257 	if (ops && ops->is_mock_dev(cxlmd->dev.parent))
258 		ops->cxl_endpoint_parse_cdat(port);
259 	else
260 		cxl_endpoint_parse_cdat(port);
261 	put_cxl_mock_ops(index);
262 }
263 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
264 
265 void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
266 {
267 	int index;
268 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
269 
270 	if (!ops || !ops->is_mock_port(dport->dport_dev))
271 		cxl_dport_init_ras_reporting(dport, host);
272 
273 	put_cxl_mock_ops(index);
274 }
275 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL");
276 
277 struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
278 						     struct device *dport_dev)
279 {
280 	int index;
281 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
282 	struct cxl_dport *dport;
283 
284 	if (ops && ops->is_mock_port(port->uport_dev))
285 		dport = ops->devm_cxl_add_dport_by_dev(port, dport_dev);
286 	else
287 		dport = __devm_cxl_add_dport_by_dev(port, dport_dev);
288 	put_cxl_mock_ops(index);
289 
290 	return dport;
291 }
292 
293 MODULE_LICENSE("GPL v2");
294 MODULE_DESCRIPTION("cxl_test: emulation module");
295 MODULE_IMPORT_NS("ACPI");
296 MODULE_IMPORT_NS("CXL");
297