Commit | Line | Data |
---|---|---|
67dcdd4d DW |
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> | |
98d2d3a2 DW |
10 | #include <cxlmem.h> |
11 | #include <cxlpci.h> | |
67dcdd4d DW |
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 | ||
270205be | 22 | DEFINE_STATIC_SRCU(cxl_mock_srcu); |
67dcdd4d DW |
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 | ||
814dff9a DW |
63 | int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id, |
64 | acpi_tbl_entry_handler_arg handler_arg, | |
65 | void *arg) | |
67dcdd4d | 66 | { |
814dff9a | 67 | int index, rc; |
67dcdd4d | 68 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); |
67dcdd4d DW |
69 | |
70 | if (ops) | |
814dff9a | 71 | rc = ops->acpi_table_parse_cedt(id, handler_arg, arg); |
67dcdd4d | 72 | else |
814dff9a | 73 | rc = acpi_table_parse_cedt(id, handler_arg, arg); |
67dcdd4d DW |
74 | |
75 | put_cxl_mock_ops(index); | |
76 | ||
814dff9a | 77 | return rc; |
67dcdd4d | 78 | } |
814dff9a | 79 | EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI); |
67dcdd4d DW |
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 | ||
67dcdd4d DW |
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 | ||
4474ce56 DJ |
134 | struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port, |
135 | struct cxl_endpoint_dvsec_info *info) | |
136 | ||
d17d0540 DW |
137 | { |
138 | int index; | |
139 | struct cxl_hdm *cxlhdm; | |
140 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); | |
141 | ||
7481653d | 142 | if (ops && ops->is_mock_port(port->uport_dev)) |
4474ce56 | 143 | cxlhdm = ops->devm_cxl_setup_hdm(port, info); |
d17d0540 | 144 | else |
4474ce56 | 145 | cxlhdm = devm_cxl_setup_hdm(port, info); |
d17d0540 DW |
146 | put_cxl_mock_ops(index); |
147 | ||
148 | return cxlhdm; | |
149 | } | |
150 | EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL); | |
151 | ||
664bf115 | 152 | int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port) |
d17d0540 DW |
153 | { |
154 | int rc, index; | |
155 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); | |
156 | ||
7481653d | 157 | if (ops && ops->is_mock_port(port->uport_dev)) |
664bf115 | 158 | rc = ops->devm_cxl_add_passthrough_decoder(port); |
d17d0540 | 159 | else |
664bf115 | 160 | rc = devm_cxl_add_passthrough_decoder(port); |
d17d0540 DW |
161 | put_cxl_mock_ops(index); |
162 | ||
163 | return rc; | |
164 | } | |
165 | EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); | |
166 | ||
b777e9be DJ |
167 | int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, |
168 | struct cxl_endpoint_dvsec_info *info) | |
d17d0540 DW |
169 | { |
170 | int rc, index; | |
171 | struct cxl_port *port = cxlhdm->port; | |
172 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); | |
173 | ||
7481653d | 174 | if (ops && ops->is_mock_port(port->uport_dev)) |
b777e9be | 175 | rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info); |
d17d0540 | 176 | else |
b777e9be | 177 | rc = devm_cxl_enumerate_decoders(cxlhdm, info); |
d17d0540 DW |
178 | put_cxl_mock_ops(index); |
179 | ||
180 | return rc; | |
181 | } | |
182 | EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL); | |
183 | ||
664bf115 | 184 | int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) |
98d2d3a2 DW |
185 | { |
186 | int rc, index; | |
187 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); | |
188 | ||
7481653d | 189 | if (ops && ops->is_mock_port(port->uport_dev)) |
664bf115 | 190 | rc = ops->devm_cxl_port_enumerate_dports(port); |
98d2d3a2 | 191 | else |
664bf115 | 192 | rc = devm_cxl_port_enumerate_dports(port); |
98d2d3a2 DW |
193 | put_cxl_mock_ops(index); |
194 | ||
195 | return rc; | |
196 | } | |
197 | EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); | |
198 | ||
2e4ba0ec DW |
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 | ||
863fdccd | 214 | int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, |
59c3368b DJ |
215 | struct cxl_hdm *cxlhdm, |
216 | struct cxl_endpoint_dvsec_info *info) | |
14d78874 DW |
217 | { |
218 | int rc = 0, index; | |
219 | struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); | |
220 | ||
863fdccd DW |
221 | if (ops && ops->is_mock_dev(cxlds->dev)) |
222 | rc = 0; | |
223 | else | |
59c3368b | 224 | rc = cxl_hdm_decode_init(cxlds, cxlhdm, info); |
14d78874 DW |
225 | put_cxl_mock_ops(index); |
226 | ||
227 | return rc; | |
228 | } | |
a12562bb | 229 | EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); |
14d78874 | 230 | |
59c3368b DJ |
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 | ||
eb4663b0 RR |
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); | |
06193378 DW |
259 | if (!IS_ERR(dport)) { |
260 | dport->rcrb.base = rcrb; | |
eb4663b0 | 261 | dport->rch = true; |
06193378 | 262 | } |
eb4663b0 RR |
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) | |
d5b1a271 RR |
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)) | |
eb4663b0 | 279 | component_reg_phys = CXL_RESOURCE_NONE; |
d5b1a271 | 280 | else |
eb4663b0 | 281 | component_reg_phys = cxl_rcd_component_reg_phys(dev, dport); |
d5b1a271 RR |
282 | put_cxl_mock_ops(index); |
283 | ||
284 | return component_reg_phys; | |
285 | } | |
eb4663b0 | 286 | EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL); |
d5b1a271 | 287 | |
117132ed DJ |
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 | ||
67dcdd4d | 302 | MODULE_LICENSE("GPL v2"); |
814dff9a | 303 | MODULE_IMPORT_NS(ACPI); |
98d2d3a2 | 304 | MODULE_IMPORT_NS(CXL); |