167dcdd4dSDan Williams // SPDX-License-Identifier: GPL-2.0-only
267dcdd4dSDan Williams //Copyright(c) 2021 Intel Corporation. All rights reserved.
367dcdd4dSDan Williams
467dcdd4dSDan Williams #include <linux/libnvdimm.h>
567dcdd4dSDan Williams #include <linux/rculist.h>
667dcdd4dSDan Williams #include <linux/device.h>
767dcdd4dSDan Williams #include <linux/export.h>
867dcdd4dSDan Williams #include <linux/acpi.h>
967dcdd4dSDan Williams #include <linux/pci.h>
1098d2d3a2SDan Williams #include <cxlmem.h>
1198d2d3a2SDan Williams #include <cxlpci.h>
1267dcdd4dSDan Williams #include "mock.h"
1367dcdd4dSDan Williams
1467dcdd4dSDan Williams static LIST_HEAD(mock);
1567dcdd4dSDan Williams
register_cxl_mock_ops(struct cxl_mock_ops * ops)1667dcdd4dSDan Williams void register_cxl_mock_ops(struct cxl_mock_ops *ops)
1767dcdd4dSDan Williams {
1867dcdd4dSDan Williams list_add_rcu(&ops->list, &mock);
1967dcdd4dSDan Williams }
2067dcdd4dSDan Williams EXPORT_SYMBOL_GPL(register_cxl_mock_ops);
2167dcdd4dSDan Williams
22270205beSDan Williams DEFINE_STATIC_SRCU(cxl_mock_srcu);
2367dcdd4dSDan Williams
unregister_cxl_mock_ops(struct cxl_mock_ops * ops)2467dcdd4dSDan Williams void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
2567dcdd4dSDan Williams {
2667dcdd4dSDan Williams list_del_rcu(&ops->list);
2767dcdd4dSDan Williams synchronize_srcu(&cxl_mock_srcu);
2867dcdd4dSDan Williams }
2967dcdd4dSDan Williams EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops);
3067dcdd4dSDan Williams
get_cxl_mock_ops(int * index)3167dcdd4dSDan Williams struct cxl_mock_ops *get_cxl_mock_ops(int *index)
3267dcdd4dSDan Williams {
3367dcdd4dSDan Williams *index = srcu_read_lock(&cxl_mock_srcu);
3467dcdd4dSDan Williams return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list);
3567dcdd4dSDan Williams }
3667dcdd4dSDan Williams EXPORT_SYMBOL_GPL(get_cxl_mock_ops);
3767dcdd4dSDan Williams
put_cxl_mock_ops(int index)3867dcdd4dSDan Williams void put_cxl_mock_ops(int index)
3967dcdd4dSDan Williams {
4067dcdd4dSDan Williams srcu_read_unlock(&cxl_mock_srcu, index);
4167dcdd4dSDan Williams }
4267dcdd4dSDan Williams EXPORT_SYMBOL_GPL(put_cxl_mock_ops);
4367dcdd4dSDan Williams
__wrap_is_acpi_device_node(const struct fwnode_handle * fwnode)4467dcdd4dSDan Williams bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode)
4567dcdd4dSDan Williams {
4667dcdd4dSDan Williams struct acpi_device *adev =
4767dcdd4dSDan Williams container_of(fwnode, struct acpi_device, fwnode);
4867dcdd4dSDan Williams int index;
4967dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
5067dcdd4dSDan Williams bool retval = false;
5167dcdd4dSDan Williams
5267dcdd4dSDan Williams if (ops)
5367dcdd4dSDan Williams retval = ops->is_mock_adev(adev);
5467dcdd4dSDan Williams
5567dcdd4dSDan Williams if (!retval)
5667dcdd4dSDan Williams retval = is_acpi_device_node(fwnode);
5767dcdd4dSDan Williams
5867dcdd4dSDan Williams put_cxl_mock_ops(index);
5967dcdd4dSDan Williams return retval;
6067dcdd4dSDan Williams }
6167dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_is_acpi_device_node);
6267dcdd4dSDan Williams
__wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,acpi_tbl_entry_handler_arg handler_arg,void * arg)63814dff9aSDan Williams int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,
64814dff9aSDan Williams acpi_tbl_entry_handler_arg handler_arg,
65814dff9aSDan Williams void *arg)
6667dcdd4dSDan Williams {
67814dff9aSDan Williams int index, rc;
6867dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
6967dcdd4dSDan Williams
7067dcdd4dSDan Williams if (ops)
71814dff9aSDan Williams rc = ops->acpi_table_parse_cedt(id, handler_arg, arg);
7267dcdd4dSDan Williams else
73814dff9aSDan Williams rc = acpi_table_parse_cedt(id, handler_arg, arg);
74814dff9aSDan Williams
7567dcdd4dSDan Williams put_cxl_mock_ops(index);
76814dff9aSDan Williams
77814dff9aSDan Williams return rc;
7867dcdd4dSDan Williams }
79814dff9aSDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI);
8067dcdd4dSDan Williams
__wrap_acpi_evaluate_integer(acpi_handle handle,acpi_string pathname,struct acpi_object_list * arguments,unsigned long long * data)8167dcdd4dSDan Williams acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle,
8267dcdd4dSDan Williams acpi_string pathname,
8367dcdd4dSDan Williams struct acpi_object_list *arguments,
8467dcdd4dSDan Williams unsigned long long *data)
8567dcdd4dSDan Williams {
8667dcdd4dSDan Williams int index;
8767dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
8867dcdd4dSDan Williams acpi_status status;
8967dcdd4dSDan Williams
9067dcdd4dSDan Williams if (ops)
9167dcdd4dSDan Williams status = ops->acpi_evaluate_integer(handle, pathname, arguments,
9267dcdd4dSDan Williams data);
9367dcdd4dSDan Williams else
9467dcdd4dSDan Williams status = acpi_evaluate_integer(handle, pathname, arguments,
9567dcdd4dSDan Williams data);
9667dcdd4dSDan Williams put_cxl_mock_ops(index);
9767dcdd4dSDan Williams
9867dcdd4dSDan Williams return status;
9967dcdd4dSDan Williams }
10067dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_evaluate_integer);
10167dcdd4dSDan Williams
__wrap_acpi_pci_find_root(acpi_handle handle)10267dcdd4dSDan Williams struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle)
10367dcdd4dSDan Williams {
10467dcdd4dSDan Williams int index;
10567dcdd4dSDan Williams struct acpi_pci_root *root;
10667dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
10767dcdd4dSDan Williams
10867dcdd4dSDan Williams if (ops)
10967dcdd4dSDan Williams root = ops->acpi_pci_find_root(handle);
11067dcdd4dSDan Williams else
11167dcdd4dSDan Williams root = acpi_pci_find_root(handle);
11267dcdd4dSDan Williams
11367dcdd4dSDan Williams put_cxl_mock_ops(index);
11467dcdd4dSDan Williams
11567dcdd4dSDan Williams return root;
11667dcdd4dSDan Williams }
11767dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
11867dcdd4dSDan Williams
11967dcdd4dSDan Williams struct nvdimm_bus *
__wrap_nvdimm_bus_register(struct device * dev,struct nvdimm_bus_descriptor * nd_desc)12067dcdd4dSDan Williams __wrap_nvdimm_bus_register(struct device *dev,
12167dcdd4dSDan Williams struct nvdimm_bus_descriptor *nd_desc)
12267dcdd4dSDan Williams {
12367dcdd4dSDan Williams int index;
12467dcdd4dSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
12567dcdd4dSDan Williams
12667dcdd4dSDan Williams if (ops && ops->is_mock_dev(dev->parent->parent))
12767dcdd4dSDan Williams nd_desc->provider_name = "cxl_test";
12867dcdd4dSDan Williams put_cxl_mock_ops(index);
12967dcdd4dSDan Williams
13067dcdd4dSDan Williams return nvdimm_bus_register(dev, nd_desc);
13167dcdd4dSDan Williams }
13267dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
13367dcdd4dSDan Williams
__wrap_devm_cxl_setup_hdm(struct cxl_port * port,struct cxl_endpoint_dvsec_info * info)1344474ce56SDave Jiang struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port,
1354474ce56SDave Jiang struct cxl_endpoint_dvsec_info *info)
1364474ce56SDave Jiang
137d17d0540SDan Williams {
138d17d0540SDan Williams int index;
139d17d0540SDan Williams struct cxl_hdm *cxlhdm;
140d17d0540SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
141d17d0540SDan Williams
142d17d0540SDan Williams if (ops && ops->is_mock_port(port->uport_dev))
1434474ce56SDave Jiang cxlhdm = ops->devm_cxl_setup_hdm(port, info);
144d17d0540SDan Williams else
1454474ce56SDave Jiang cxlhdm = devm_cxl_setup_hdm(port, info);
146d17d0540SDan Williams put_cxl_mock_ops(index);
147d17d0540SDan Williams
148d17d0540SDan Williams return cxlhdm;
149d17d0540SDan Williams }
150d17d0540SDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL);
151d17d0540SDan Williams
__wrap_devm_cxl_add_passthrough_decoder(struct cxl_port * port)152*eb0764b8SDan Williams int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
153*eb0764b8SDan Williams {
154*eb0764b8SDan Williams int rc, index;
155*eb0764b8SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
156*eb0764b8SDan Williams
157*eb0764b8SDan Williams if (ops && ops->is_mock_port(port->uport_dev))
158*eb0764b8SDan Williams rc = ops->devm_cxl_add_passthrough_decoder(port);
159*eb0764b8SDan Williams else
160*eb0764b8SDan Williams rc = devm_cxl_add_passthrough_decoder(port);
161*eb0764b8SDan Williams put_cxl_mock_ops(index);
162*eb0764b8SDan Williams
163*eb0764b8SDan Williams return rc;
164*eb0764b8SDan Williams }
165*eb0764b8SDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL);
166*eb0764b8SDan Williams
__wrap_devm_cxl_enumerate_decoders(struct cxl_hdm * cxlhdm,struct cxl_endpoint_dvsec_info * info)167664bf115SDan Williams int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
168d17d0540SDan Williams struct cxl_endpoint_dvsec_info *info)
169d17d0540SDan Williams {
170d17d0540SDan Williams int rc, index;
171d17d0540SDan Williams struct cxl_port *port = cxlhdm->port;
172d17d0540SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
173664bf115SDan Williams
174d17d0540SDan Williams if (ops && ops->is_mock_port(port->uport_dev))
175664bf115SDan Williams rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info);
176d17d0540SDan Williams else
177d17d0540SDan Williams rc = devm_cxl_enumerate_decoders(cxlhdm, info);
178d17d0540SDan Williams put_cxl_mock_ops(index);
179d17d0540SDan Williams
180d17d0540SDan Williams return rc;
181d17d0540SDan Williams }
182b777e9beSDave Jiang EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL);
183b777e9beSDave Jiang
__wrap_devm_cxl_port_enumerate_dports(struct cxl_port * port)184d17d0540SDan Williams int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port)
185d17d0540SDan Williams {
186d17d0540SDan Williams int rc, index;
187d17d0540SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
188d17d0540SDan Williams
189d17d0540SDan Williams if (ops && ops->is_mock_port(port->uport_dev))
190b777e9beSDave Jiang rc = ops->devm_cxl_port_enumerate_dports(port);
191d17d0540SDan Williams else
192b777e9beSDave Jiang rc = devm_cxl_port_enumerate_dports(port);
193d17d0540SDan Williams put_cxl_mock_ops(index);
194d17d0540SDan Williams
195d17d0540SDan Williams return rc;
196d17d0540SDan Williams }
197d17d0540SDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL);
198d17d0540SDan Williams
__wrap_cxl_await_media_ready(struct cxl_dev_state * cxlds)199664bf115SDan Williams int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
20098d2d3a2SDan Williams {
20198d2d3a2SDan Williams int rc, index;
20298d2d3a2SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
20398d2d3a2SDan Williams
20498d2d3a2SDan Williams if (ops && ops->is_mock_dev(cxlds->dev))
205664bf115SDan Williams rc = 0;
20698d2d3a2SDan Williams else
207664bf115SDan Williams rc = cxl_await_media_ready(cxlds);
20898d2d3a2SDan Williams put_cxl_mock_ops(index);
20998d2d3a2SDan Williams
21098d2d3a2SDan Williams return rc;
21198d2d3a2SDan Williams }
21298d2d3a2SDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL);
21398d2d3a2SDan Williams
__wrap_cxl_hdm_decode_init(struct cxl_dev_state * cxlds,struct cxl_hdm * cxlhdm,struct cxl_endpoint_dvsec_info * info)2142e4ba0ecSDan Williams int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
2152e4ba0ecSDan Williams struct cxl_hdm *cxlhdm,
2162e4ba0ecSDan Williams struct cxl_endpoint_dvsec_info *info)
2172e4ba0ecSDan Williams {
2182e4ba0ecSDan Williams int rc = 0, index;
2192e4ba0ecSDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
2202e4ba0ecSDan Williams
2212e4ba0ecSDan Williams if (ops && ops->is_mock_dev(cxlds->dev))
2222e4ba0ecSDan Williams rc = 0;
2232e4ba0ecSDan Williams else
2242e4ba0ecSDan Williams rc = cxl_hdm_decode_init(cxlds, cxlhdm, info);
2252e4ba0ecSDan Williams put_cxl_mock_ops(index);
2262e4ba0ecSDan Williams
2272e4ba0ecSDan Williams return rc;
2282e4ba0ecSDan Williams }
229863fdccdSDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL);
23059c3368bSDave Jiang
__wrap_cxl_dvsec_rr_decode(struct device * dev,int dvsec,struct cxl_endpoint_dvsec_info * info)23159c3368bSDave Jiang int __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec,
23214d78874SDan Williams struct cxl_endpoint_dvsec_info *info)
23314d78874SDan Williams {
23414d78874SDan Williams int rc = 0, index;
23514d78874SDan Williams struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
236863fdccdSDan Williams
237863fdccdSDan Williams if (ops && ops->is_mock_dev(dev))
238863fdccdSDan Williams rc = 0;
23959c3368bSDave Jiang else
24014d78874SDan Williams rc = cxl_dvsec_rr_decode(dev, dvsec, info);
24114d78874SDan Williams put_cxl_mock_ops(index);
24214d78874SDan Williams
24314d78874SDan Williams return rc;
244a12562bbSDan Williams }
24514d78874SDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL);
24659c3368bSDave Jiang
__wrap_devm_cxl_add_rch_dport(struct cxl_port * port,struct device * dport_dev,int port_id,resource_size_t rcrb)24759c3368bSDave Jiang struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port,
24859c3368bSDave Jiang struct device *dport_dev,
24959c3368bSDave Jiang int port_id,
25059c3368bSDave Jiang resource_size_t rcrb)
25159c3368bSDave Jiang {
25259c3368bSDave Jiang int index;
25359c3368bSDave Jiang struct cxl_dport *dport;
25459c3368bSDave Jiang struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
25559c3368bSDave Jiang
25659c3368bSDave Jiang if (ops && ops->is_mock_port(dport_dev)) {
25759c3368bSDave Jiang dport = devm_cxl_add_dport(port, dport_dev, port_id,
25859c3368bSDave Jiang CXL_RESOURCE_NONE);
25959c3368bSDave Jiang if (!IS_ERR(dport)) {
26059c3368bSDave Jiang dport->rcrb.base = rcrb;
26159c3368bSDave Jiang dport->rch = true;
262d5b1a271SRobert Richter }
263d5b1a271SRobert Richter } else
264d5b1a271SRobert Richter dport = devm_cxl_add_rch_dport(port, dport_dev, port_id, rcrb);
265d5b1a271SRobert Richter put_cxl_mock_ops(index);
266d5b1a271SRobert Richter
267d5b1a271SRobert Richter return dport;
268d5b1a271SRobert Richter }
269d5b1a271SRobert Richter EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL);
270d5b1a271SRobert Richter
__wrap_cxl_rcd_component_reg_phys(struct device * dev,struct cxl_dport * dport)271d5b1a271SRobert Richter resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev,
272d5b1a271SRobert Richter struct cxl_dport *dport)
273d5b1a271SRobert Richter {
274d5b1a271SRobert Richter int index;
275d5b1a271SRobert Richter resource_size_t component_reg_phys;
276d5b1a271SRobert Richter struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
277d5b1a271SRobert Richter
278d5b1a271SRobert Richter if (ops && ops->is_mock_port(dev))
279d5b1a271SRobert Richter component_reg_phys = CXL_RESOURCE_NONE;
280d5b1a271SRobert Richter else
28167dcdd4dSDan Williams component_reg_phys = cxl_rcd_component_reg_phys(dev, dport);
282814dff9aSDan Williams put_cxl_mock_ops(index);
28398d2d3a2SDan Williams
284 return component_reg_phys;
285 }
286 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL);
287
288 MODULE_LICENSE("GPL v2");
289 MODULE_IMPORT_NS(ACPI);
290 MODULE_IMPORT_NS(CXL);
291