xref: /openbmc/linux/tools/testing/cxl/test/mock.c (revision 814dff9a)
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>
1067dcdd4dSDan Williams #include "mock.h"
1167dcdd4dSDan Williams 
1267dcdd4dSDan Williams static LIST_HEAD(mock);
1367dcdd4dSDan Williams 
1467dcdd4dSDan Williams void register_cxl_mock_ops(struct cxl_mock_ops *ops)
1567dcdd4dSDan Williams {
1667dcdd4dSDan Williams 	list_add_rcu(&ops->list, &mock);
1767dcdd4dSDan Williams }
1867dcdd4dSDan Williams EXPORT_SYMBOL_GPL(register_cxl_mock_ops);
1967dcdd4dSDan Williams 
2067dcdd4dSDan Williams static DEFINE_SRCU(cxl_mock_srcu);
2167dcdd4dSDan Williams 
2267dcdd4dSDan Williams void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
2367dcdd4dSDan Williams {
2467dcdd4dSDan Williams 	list_del_rcu(&ops->list);
2567dcdd4dSDan Williams 	synchronize_srcu(&cxl_mock_srcu);
2667dcdd4dSDan Williams }
2767dcdd4dSDan Williams EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops);
2867dcdd4dSDan Williams 
2967dcdd4dSDan Williams struct cxl_mock_ops *get_cxl_mock_ops(int *index)
3067dcdd4dSDan Williams {
3167dcdd4dSDan Williams 	*index = srcu_read_lock(&cxl_mock_srcu);
3267dcdd4dSDan Williams 	return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list);
3367dcdd4dSDan Williams }
3467dcdd4dSDan Williams EXPORT_SYMBOL_GPL(get_cxl_mock_ops);
3567dcdd4dSDan Williams 
3667dcdd4dSDan Williams void put_cxl_mock_ops(int index)
3767dcdd4dSDan Williams {
3867dcdd4dSDan Williams 	srcu_read_unlock(&cxl_mock_srcu, index);
3967dcdd4dSDan Williams }
4067dcdd4dSDan Williams EXPORT_SYMBOL_GPL(put_cxl_mock_ops);
4167dcdd4dSDan Williams 
4267dcdd4dSDan Williams bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode)
4367dcdd4dSDan Williams {
4467dcdd4dSDan Williams 	struct acpi_device *adev =
4567dcdd4dSDan Williams 		container_of(fwnode, struct acpi_device, fwnode);
4667dcdd4dSDan Williams 	int index;
4767dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
4867dcdd4dSDan Williams 	bool retval = false;
4967dcdd4dSDan Williams 
5067dcdd4dSDan Williams 	if (ops)
5167dcdd4dSDan Williams 		retval = ops->is_mock_adev(adev);
5267dcdd4dSDan Williams 
5367dcdd4dSDan Williams 	if (!retval)
5467dcdd4dSDan Williams 		retval = is_acpi_device_node(fwnode);
5567dcdd4dSDan Williams 
5667dcdd4dSDan Williams 	put_cxl_mock_ops(index);
5767dcdd4dSDan Williams 	return retval;
5867dcdd4dSDan Williams }
5967dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_is_acpi_device_node);
6067dcdd4dSDan Williams 
61*814dff9aSDan Williams int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,
62*814dff9aSDan Williams 				 acpi_tbl_entry_handler_arg handler_arg,
63*814dff9aSDan Williams 				 void *arg)
6467dcdd4dSDan Williams {
65*814dff9aSDan Williams 	int index, rc;
6667dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
6767dcdd4dSDan Williams 
6867dcdd4dSDan Williams 	if (ops)
69*814dff9aSDan Williams 		rc = ops->acpi_table_parse_cedt(id, handler_arg, arg);
7067dcdd4dSDan Williams 	else
71*814dff9aSDan Williams 		rc = acpi_table_parse_cedt(id, handler_arg, arg);
72*814dff9aSDan Williams 
7367dcdd4dSDan Williams 	put_cxl_mock_ops(index);
74*814dff9aSDan Williams 
75*814dff9aSDan Williams 	return rc;
7667dcdd4dSDan Williams }
77*814dff9aSDan Williams EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI);
7867dcdd4dSDan Williams 
7967dcdd4dSDan Williams acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle,
8067dcdd4dSDan Williams 					 acpi_string pathname,
8167dcdd4dSDan Williams 					 struct acpi_object_list *arguments,
8267dcdd4dSDan Williams 					 unsigned long long *data)
8367dcdd4dSDan Williams {
8467dcdd4dSDan Williams 	int index;
8567dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
8667dcdd4dSDan Williams 	acpi_status status;
8767dcdd4dSDan Williams 
8867dcdd4dSDan Williams 	if (ops)
8967dcdd4dSDan Williams 		status = ops->acpi_evaluate_integer(handle, pathname, arguments,
9067dcdd4dSDan Williams 						    data);
9167dcdd4dSDan Williams 	else
9267dcdd4dSDan Williams 		status = acpi_evaluate_integer(handle, pathname, arguments,
9367dcdd4dSDan Williams 					       data);
9467dcdd4dSDan Williams 	put_cxl_mock_ops(index);
9567dcdd4dSDan Williams 
9667dcdd4dSDan Williams 	return status;
9767dcdd4dSDan Williams }
9867dcdd4dSDan Williams EXPORT_SYMBOL(__wrap_acpi_evaluate_integer);
9967dcdd4dSDan Williams 
10067dcdd4dSDan Williams struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle)
10167dcdd4dSDan Williams {
10267dcdd4dSDan Williams 	int index;
10367dcdd4dSDan Williams 	struct acpi_pci_root *root;
10467dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
10567dcdd4dSDan Williams 
10667dcdd4dSDan Williams 	if (ops)
10767dcdd4dSDan Williams 		root = ops->acpi_pci_find_root(handle);
10867dcdd4dSDan Williams 	else
10967dcdd4dSDan Williams 		root = acpi_pci_find_root(handle);
11067dcdd4dSDan Williams 
11167dcdd4dSDan Williams 	put_cxl_mock_ops(index);
11267dcdd4dSDan Williams 
11367dcdd4dSDan Williams 	return root;
11467dcdd4dSDan Williams }
11567dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
11667dcdd4dSDan Williams 
11767dcdd4dSDan Williams void __wrap_pci_walk_bus(struct pci_bus *bus,
11867dcdd4dSDan Williams 			 int (*cb)(struct pci_dev *, void *), void *userdata)
11967dcdd4dSDan Williams {
12067dcdd4dSDan Williams 	int index;
12167dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
12267dcdd4dSDan Williams 
12367dcdd4dSDan Williams 	if (ops && ops->is_mock_bus(bus)) {
12467dcdd4dSDan Williams 		int rc, i;
12567dcdd4dSDan Williams 
12667dcdd4dSDan Williams 		/*
12767dcdd4dSDan Williams 		 * Simulate 2 root ports per host-bridge and no
12867dcdd4dSDan Williams 		 * depth recursion.
12967dcdd4dSDan Williams 		 */
13067dcdd4dSDan Williams 		for (i = 0; i < 2; i++) {
13167dcdd4dSDan Williams 			rc = cb((struct pci_dev *) ops->mock_port(bus, i),
13267dcdd4dSDan Williams 				userdata);
13367dcdd4dSDan Williams 			if (rc)
13467dcdd4dSDan Williams 				break;
13567dcdd4dSDan Williams 		}
13667dcdd4dSDan Williams 	} else
13767dcdd4dSDan Williams 		pci_walk_bus(bus, cb, userdata);
13867dcdd4dSDan Williams 
13967dcdd4dSDan Williams 	put_cxl_mock_ops(index);
14067dcdd4dSDan Williams }
14167dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus);
14267dcdd4dSDan Williams 
14367dcdd4dSDan Williams struct nvdimm_bus *
14467dcdd4dSDan Williams __wrap_nvdimm_bus_register(struct device *dev,
14567dcdd4dSDan Williams 			   struct nvdimm_bus_descriptor *nd_desc)
14667dcdd4dSDan Williams {
14767dcdd4dSDan Williams 	int index;
14867dcdd4dSDan Williams 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
14967dcdd4dSDan Williams 
15067dcdd4dSDan Williams 	if (ops && ops->is_mock_dev(dev->parent->parent))
15167dcdd4dSDan Williams 		nd_desc->provider_name = "cxl_test";
15267dcdd4dSDan Williams 	put_cxl_mock_ops(index);
15367dcdd4dSDan Williams 
15467dcdd4dSDan Williams 	return nvdimm_bus_register(dev, nd_desc);
15567dcdd4dSDan Williams }
15667dcdd4dSDan Williams EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
15767dcdd4dSDan Williams 
15867dcdd4dSDan Williams MODULE_LICENSE("GPL v2");
159*814dff9aSDan Williams MODULE_IMPORT_NS(ACPI);
160