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