xref: /openbmc/linux/tools/testing/cxl/test/mock.c (revision 6e10e219)
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 "mock.h"
11 
12 static LIST_HEAD(mock);
13 
14 void register_cxl_mock_ops(struct cxl_mock_ops *ops)
15 {
16 	list_add_rcu(&ops->list, &mock);
17 }
18 EXPORT_SYMBOL_GPL(register_cxl_mock_ops);
19 
20 static DEFINE_SRCU(cxl_mock_srcu);
21 
22 void unregister_cxl_mock_ops(struct cxl_mock_ops *ops)
23 {
24 	list_del_rcu(&ops->list);
25 	synchronize_srcu(&cxl_mock_srcu);
26 }
27 EXPORT_SYMBOL_GPL(unregister_cxl_mock_ops);
28 
29 struct cxl_mock_ops *get_cxl_mock_ops(int *index)
30 {
31 	*index = srcu_read_lock(&cxl_mock_srcu);
32 	return list_first_or_null_rcu(&mock, struct cxl_mock_ops, list);
33 }
34 EXPORT_SYMBOL_GPL(get_cxl_mock_ops);
35 
36 void put_cxl_mock_ops(int index)
37 {
38 	srcu_read_unlock(&cxl_mock_srcu, index);
39 }
40 EXPORT_SYMBOL_GPL(put_cxl_mock_ops);
41 
42 bool __wrap_is_acpi_device_node(const struct fwnode_handle *fwnode)
43 {
44 	struct acpi_device *adev =
45 		container_of(fwnode, struct acpi_device, fwnode);
46 	int index;
47 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
48 	bool retval = false;
49 
50 	if (ops)
51 		retval = ops->is_mock_adev(adev);
52 
53 	if (!retval)
54 		retval = is_acpi_device_node(fwnode);
55 
56 	put_cxl_mock_ops(index);
57 	return retval;
58 }
59 EXPORT_SYMBOL(__wrap_is_acpi_device_node);
60 
61 int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,
62 				 acpi_tbl_entry_handler_arg handler_arg,
63 				 void *arg)
64 {
65 	int index, rc;
66 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
67 
68 	if (ops)
69 		rc = ops->acpi_table_parse_cedt(id, handler_arg, arg);
70 	else
71 		rc = acpi_table_parse_cedt(id, handler_arg, arg);
72 
73 	put_cxl_mock_ops(index);
74 
75 	return rc;
76 }
77 EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI);
78 
79 acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle,
80 					 acpi_string pathname,
81 					 struct acpi_object_list *arguments,
82 					 unsigned long long *data)
83 {
84 	int index;
85 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
86 	acpi_status status;
87 
88 	if (ops)
89 		status = ops->acpi_evaluate_integer(handle, pathname, arguments,
90 						    data);
91 	else
92 		status = acpi_evaluate_integer(handle, pathname, arguments,
93 					       data);
94 	put_cxl_mock_ops(index);
95 
96 	return status;
97 }
98 EXPORT_SYMBOL(__wrap_acpi_evaluate_integer);
99 
100 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle)
101 {
102 	int index;
103 	struct acpi_pci_root *root;
104 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
105 
106 	if (ops)
107 		root = ops->acpi_pci_find_root(handle);
108 	else
109 		root = acpi_pci_find_root(handle);
110 
111 	put_cxl_mock_ops(index);
112 
113 	return root;
114 }
115 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
116 
117 void __wrap_pci_walk_bus(struct pci_bus *bus,
118 			 int (*cb)(struct pci_dev *, void *), void *userdata)
119 {
120 	int index;
121 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
122 
123 	if (ops && ops->is_mock_bus(bus)) {
124 		int rc, i;
125 
126 		/*
127 		 * Simulate 2 root ports per host-bridge and no
128 		 * depth recursion.
129 		 */
130 		for (i = 0; i < 2; i++) {
131 			rc = cb((struct pci_dev *) ops->mock_port(bus, i),
132 				userdata);
133 			if (rc)
134 				break;
135 		}
136 	} else
137 		pci_walk_bus(bus, cb, userdata);
138 
139 	put_cxl_mock_ops(index);
140 }
141 EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus);
142 
143 struct nvdimm_bus *
144 __wrap_nvdimm_bus_register(struct device *dev,
145 			   struct nvdimm_bus_descriptor *nd_desc)
146 {
147 	int index;
148 	struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
149 
150 	if (ops && ops->is_mock_dev(dev->parent->parent))
151 		nd_desc->provider_name = "cxl_test";
152 	put_cxl_mock_ops(index);
153 
154 	return nvdimm_bus_register(dev, nd_desc);
155 }
156 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
157 
158 MODULE_LICENSE("GPL v2");
159 MODULE_IMPORT_NS(ACPI);
160