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
register_cxl_mock_ops(struct cxl_mock_ops * ops)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
unregister_cxl_mock_ops(struct cxl_mock_ops * ops)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
get_cxl_mock_ops(int * index)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
put_cxl_mock_ops(int index)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
__wrap_is_acpi_device_node(const struct fwnode_handle * fwnode)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
__wrap_acpi_get_table(char * signature,u32 instance,struct acpi_table_header ** out_table)61 acpi_status __wrap_acpi_get_table(char *signature, u32 instance,
62 struct acpi_table_header **out_table)
63 {
64 int index;
65 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
66 acpi_status status;
67
68 if (ops)
69 status = ops->acpi_get_table(signature, instance, out_table);
70 else
71 status = acpi_get_table(signature, instance, out_table);
72
73 put_cxl_mock_ops(index);
74
75 return status;
76 }
77 EXPORT_SYMBOL(__wrap_acpi_get_table);
78
__wrap_acpi_put_table(struct acpi_table_header * table)79 void __wrap_acpi_put_table(struct acpi_table_header *table)
80 {
81 int index;
82 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
83
84 if (ops)
85 ops->acpi_put_table(table);
86 else
87 acpi_put_table(table);
88 put_cxl_mock_ops(index);
89 }
90 EXPORT_SYMBOL(__wrap_acpi_put_table);
91
__wrap_acpi_evaluate_integer(acpi_handle handle,acpi_string pathname,struct acpi_object_list * arguments,unsigned long long * data)92 acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle,
93 acpi_string pathname,
94 struct acpi_object_list *arguments,
95 unsigned long long *data)
96 {
97 int index;
98 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
99 acpi_status status;
100
101 if (ops)
102 status = ops->acpi_evaluate_integer(handle, pathname, arguments,
103 data);
104 else
105 status = acpi_evaluate_integer(handle, pathname, arguments,
106 data);
107 put_cxl_mock_ops(index);
108
109 return status;
110 }
111 EXPORT_SYMBOL(__wrap_acpi_evaluate_integer);
112
__wrap_acpi_pci_find_root(acpi_handle handle)113 struct acpi_pci_root *__wrap_acpi_pci_find_root(acpi_handle handle)
114 {
115 int index;
116 struct acpi_pci_root *root;
117 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
118
119 if (ops)
120 root = ops->acpi_pci_find_root(handle);
121 else
122 root = acpi_pci_find_root(handle);
123
124 put_cxl_mock_ops(index);
125
126 return root;
127 }
128 EXPORT_SYMBOL_GPL(__wrap_acpi_pci_find_root);
129
__wrap_pci_walk_bus(struct pci_bus * bus,int (* cb)(struct pci_dev *,void *),void * userdata)130 void __wrap_pci_walk_bus(struct pci_bus *bus,
131 int (*cb)(struct pci_dev *, void *), void *userdata)
132 {
133 int index;
134 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
135
136 if (ops && ops->is_mock_bus(bus)) {
137 int rc, i;
138
139 /*
140 * Simulate 2 root ports per host-bridge and no
141 * depth recursion.
142 */
143 for (i = 0; i < 2; i++) {
144 rc = cb((struct pci_dev *) ops->mock_port(bus, i),
145 userdata);
146 if (rc)
147 break;
148 }
149 } else
150 pci_walk_bus(bus, cb, userdata);
151
152 put_cxl_mock_ops(index);
153 }
154 EXPORT_SYMBOL_GPL(__wrap_pci_walk_bus);
155
156 struct nvdimm_bus *
__wrap_nvdimm_bus_register(struct device * dev,struct nvdimm_bus_descriptor * nd_desc)157 __wrap_nvdimm_bus_register(struct device *dev,
158 struct nvdimm_bus_descriptor *nd_desc)
159 {
160 int index;
161 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
162
163 if (ops && ops->is_mock_dev(dev->parent->parent))
164 nd_desc->provider_name = "cxl_test";
165 put_cxl_mock_ops(index);
166
167 return nvdimm_bus_register(dev, nd_desc);
168 }
169 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register);
170
171 MODULE_LICENSE("GPL v2");
172