xref: /linux/tools/testing/cxl/test/mock.c (revision 5797d10ea4fade7df0f920c368cad07f705afc63)
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 
register_cxl_mock_ops(struct cxl_mock_ops * ops)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 
unregister_cxl_mock_ops(struct cxl_mock_ops * ops)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 
get_cxl_mock_ops(int * index)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 
put_cxl_mock_ops(int index)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 
__wrap_is_acpi_device_node(const struct fwnode_handle * fwnode)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 
__wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,acpi_tbl_entry_handler_arg handler_arg,void * arg)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 
__wrap_acpi_evaluate_integer(acpi_handle handle,acpi_string pathname,struct acpi_object_list * arguments,unsigned long long * data)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 
__wrap_hmat_get_extended_linear_cache_size(struct resource * backing_res,int nid,resource_size_t * cache_size)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 
__wrap_acpi_pci_find_root(acpi_handle handle)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 *
__wrap_nvdimm_bus_register(struct device * dev,struct nvdimm_bus_descriptor * nd_desc)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 
redirect_devm_cxl_switch_port_decoders_setup(struct cxl_port * port)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 
__wrap_devm_cxl_endpoint_decoders_setup(struct cxl_port * port)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 
__wrap_cxl_await_media_ready(struct cxl_dev_state * cxlds)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 
__wrap_devm_cxl_add_rch_dport(struct cxl_port * port,struct device * dport_dev,int port_id,resource_size_t rcrb)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 
__wrap_cxl_endpoint_parse_cdat(struct cxl_port * port)234 void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
235 {
236 	int index;
237 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
238 	struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
239 
240 	if (ops && ops->is_mock_dev(cxlmd->dev.parent))
241 		ops->cxl_endpoint_parse_cdat(port);
242 	else
243 		cxl_endpoint_parse_cdat(port);
244 	put_cxl_mock_ops(index);
245 }
246 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
247 
__wrap_cxl_dport_init_ras_reporting(struct cxl_dport * dport,struct device * host)248 void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
249 {
250 	int index;
251 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
252 
253 	if (!ops || !ops->is_mock_port(dport->dport_dev))
254 		cxl_dport_init_ras_reporting(dport, host);
255 
256 	put_cxl_mock_ops(index);
257 }
258 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL");
259 
redirect_devm_cxl_add_dport_by_dev(struct cxl_port * port,struct device * dport_dev)260 struct cxl_dport *redirect_devm_cxl_add_dport_by_dev(struct cxl_port *port,
261 						     struct device *dport_dev)
262 {
263 	int index;
264 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
265 	struct cxl_dport *dport;
266 
267 	if (ops && ops->is_mock_port(port->uport_dev))
268 		dport = ops->devm_cxl_add_dport_by_dev(port, dport_dev);
269 	else
270 		dport = __devm_cxl_add_dport_by_dev(port, dport_dev);
271 	put_cxl_mock_ops(index);
272 
273 	return dport;
274 }
275 
276 MODULE_LICENSE("GPL v2");
277 MODULE_DESCRIPTION("cxl_test: emulation module");
278 MODULE_IMPORT_NS("ACPI");
279 MODULE_IMPORT_NS("CXL");
280