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