• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Link physical devices with ACPI devices support
4  *
5  * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com>
6  * Copyright (c) 2005 Intel Corp.
7  */
8 
9 #define pr_fmt(fmt) "ACPI: " fmt
10 
11 #include <linux/acpi_iort.h>
12 #include <linux/export.h>
13 #include <linux/init.h>
14 #include <linux/list.h>
15 #include <linux/device.h>
16 #include <linux/slab.h>
17 #include <linux/rwsem.h>
18 #include <linux/acpi.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/platform_device.h>
21 
22 #include "internal.h"
23 
24 static LIST_HEAD(bus_type_list);
25 static DECLARE_RWSEM(bus_type_sem);
26 
27 #define PHYSICAL_NODE_STRING "physical_node"
28 #define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10)
29 
register_acpi_bus_type(struct acpi_bus_type * type)30 int register_acpi_bus_type(struct acpi_bus_type *type)
31 {
32 	if (acpi_disabled)
33 		return -ENODEV;
34 	if (type && type->match && type->find_companion) {
35 		down_write(&bus_type_sem);
36 		list_add_tail(&type->list, &bus_type_list);
37 		up_write(&bus_type_sem);
38 		pr_info("bus type %s registered\n", type->name);
39 		return 0;
40 	}
41 	return -ENODEV;
42 }
43 EXPORT_SYMBOL_GPL(register_acpi_bus_type);
44 
unregister_acpi_bus_type(struct acpi_bus_type * type)45 int unregister_acpi_bus_type(struct acpi_bus_type *type)
46 {
47 	if (acpi_disabled)
48 		return 0;
49 	if (type) {
50 		down_write(&bus_type_sem);
51 		list_del_init(&type->list);
52 		up_write(&bus_type_sem);
53 		pr_info("bus type %s unregistered\n", type->name);
54 		return 0;
55 	}
56 	return -ENODEV;
57 }
58 EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
59 
acpi_get_bus_type(struct device * dev)60 static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
61 {
62 	struct acpi_bus_type *tmp, *ret = NULL;
63 
64 	down_read(&bus_type_sem);
65 	list_for_each_entry(tmp, &bus_type_list, list) {
66 		if (tmp->match(dev)) {
67 			ret = tmp;
68 			break;
69 		}
70 	}
71 	up_read(&bus_type_sem);
72 	return ret;
73 }
74 
75 #define FIND_CHILD_MIN_SCORE	1
76 #define FIND_CHILD_MAX_SCORE	2
77 
find_child_checks(struct acpi_device * adev,bool check_children)78 static int find_child_checks(struct acpi_device *adev, bool check_children)
79 {
80 	bool sta_present = true;
81 	unsigned long long sta;
82 	acpi_status status;
83 
84 	status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
85 	if (status == AE_NOT_FOUND)
86 		sta_present = false;
87 	else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
88 		return -ENODEV;
89 
90 	if (check_children && list_empty(&adev->children))
91 		return -ENODEV;
92 
93 	/*
94 	 * If the device has a _HID returning a valid ACPI/PNP device ID, it is
95 	 * better to make it look less attractive here, so that the other device
96 	 * with the same _ADR value (that may not have a valid device ID) can be
97 	 * matched going forward.  [This means a second spec violation in a row,
98 	 * so whatever we do here is best effort anyway.]
99 	 */
100 	return sta_present && !adev->pnp.type.platform_id ?
101 			FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
102 }
103 
acpi_find_child_device(struct acpi_device * parent,u64 address,bool check_children)104 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
105 					   u64 address, bool check_children)
106 {
107 	struct acpi_device *adev, *ret = NULL;
108 	int ret_score = 0;
109 
110 	if (!parent)
111 		return NULL;
112 
113 	list_for_each_entry(adev, &parent->children, node) {
114 		unsigned long long addr;
115 		acpi_status status;
116 		int score;
117 
118 		status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR,
119 					       NULL, &addr);
120 		if (ACPI_FAILURE(status) || addr != address)
121 			continue;
122 
123 		if (!ret) {
124 			/* This is the first matching object.  Save it. */
125 			ret = adev;
126 			continue;
127 		}
128 		/*
129 		 * There is more than one matching device object with the same
130 		 * _ADR value.  That really is unexpected, so we are kind of
131 		 * beyond the scope of the spec here.  We have to choose which
132 		 * one to return, though.
133 		 *
134 		 * First, check if the previously found object is good enough
135 		 * and return it if so.  Second, do the same for the object that
136 		 * we've just found.
137 		 */
138 		if (!ret_score) {
139 			ret_score = find_child_checks(ret, check_children);
140 			if (ret_score == FIND_CHILD_MAX_SCORE)
141 				return ret;
142 		}
143 		score = find_child_checks(adev, check_children);
144 		if (score == FIND_CHILD_MAX_SCORE) {
145 			return adev;
146 		} else if (score > ret_score) {
147 			ret = adev;
148 			ret_score = score;
149 		}
150 	}
151 	return ret;
152 }
153 EXPORT_SYMBOL_GPL(acpi_find_child_device);
154 
acpi_physnode_link_name(char * buf,unsigned int node_id)155 static void acpi_physnode_link_name(char *buf, unsigned int node_id)
156 {
157 	if (node_id > 0)
158 		snprintf(buf, PHYSICAL_NODE_NAME_SIZE,
159 			 PHYSICAL_NODE_STRING "%u", node_id);
160 	else
161 		strcpy(buf, PHYSICAL_NODE_STRING);
162 }
163 
acpi_bind_one(struct device * dev,struct acpi_device * acpi_dev)164 int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
165 {
166 	struct acpi_device_physical_node *physical_node, *pn;
167 	char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
168 	struct list_head *physnode_list;
169 	unsigned int node_id;
170 	int retval = -EINVAL;
171 
172 	if (has_acpi_companion(dev)) {
173 		if (acpi_dev) {
174 			dev_warn(dev, "ACPI companion already set\n");
175 			return -EINVAL;
176 		} else {
177 			acpi_dev = ACPI_COMPANION(dev);
178 		}
179 	}
180 	if (!acpi_dev)
181 		return -EINVAL;
182 
183 	acpi_dev_get(acpi_dev);
184 	get_device(dev);
185 	physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
186 	if (!physical_node) {
187 		retval = -ENOMEM;
188 		goto err;
189 	}
190 
191 	mutex_lock(&acpi_dev->physical_node_lock);
192 
193 	/*
194 	 * Keep the list sorted by node_id so that the IDs of removed nodes can
195 	 * be recycled easily.
196 	 */
197 	physnode_list = &acpi_dev->physical_node_list;
198 	node_id = 0;
199 	list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
200 		/* Sanity check. */
201 		if (pn->dev == dev) {
202 			mutex_unlock(&acpi_dev->physical_node_lock);
203 
204 			dev_warn(dev, "Already associated with ACPI node\n");
205 			kfree(physical_node);
206 			if (ACPI_COMPANION(dev) != acpi_dev)
207 				goto err;
208 
209 			put_device(dev);
210 			acpi_dev_put(acpi_dev);
211 			return 0;
212 		}
213 		if (pn->node_id == node_id) {
214 			physnode_list = &pn->node;
215 			node_id++;
216 		}
217 	}
218 
219 	physical_node->node_id = node_id;
220 	physical_node->dev = dev;
221 	list_add(&physical_node->node, physnode_list);
222 	acpi_dev->physical_node_count++;
223 
224 	if (!has_acpi_companion(dev))
225 		ACPI_COMPANION_SET(dev, acpi_dev);
226 
227 	acpi_physnode_link_name(physical_node_name, node_id);
228 	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
229 				   physical_node_name);
230 	if (retval)
231 		dev_err(&acpi_dev->dev, "Failed to create link %s (%d)\n",
232 			physical_node_name, retval);
233 
234 	retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
235 				   "firmware_node");
236 	if (retval)
237 		dev_err(dev, "Failed to create link firmware_node (%d)\n",
238 			retval);
239 
240 	mutex_unlock(&acpi_dev->physical_node_lock);
241 
242 	if (acpi_dev->wakeup.flags.valid)
243 		device_set_wakeup_capable(dev, true);
244 
245 	return 0;
246 
247  err:
248 	ACPI_COMPANION_SET(dev, NULL);
249 	put_device(dev);
250 	acpi_dev_put(acpi_dev);
251 	return retval;
252 }
253 EXPORT_SYMBOL_GPL(acpi_bind_one);
254 
acpi_unbind_one(struct device * dev)255 int acpi_unbind_one(struct device *dev)
256 {
257 	struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
258 	struct acpi_device_physical_node *entry;
259 
260 	if (!acpi_dev)
261 		return 0;
262 
263 	mutex_lock(&acpi_dev->physical_node_lock);
264 
265 	list_for_each_entry(entry, &acpi_dev->physical_node_list, node)
266 		if (entry->dev == dev) {
267 			char physnode_name[PHYSICAL_NODE_NAME_SIZE];
268 
269 			list_del(&entry->node);
270 			acpi_dev->physical_node_count--;
271 
272 			acpi_physnode_link_name(physnode_name, entry->node_id);
273 			sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
274 			sysfs_remove_link(&dev->kobj, "firmware_node");
275 			ACPI_COMPANION_SET(dev, NULL);
276 			/* Drop references taken by acpi_bind_one(). */
277 			put_device(dev);
278 			acpi_dev_put(acpi_dev);
279 			kfree(entry);
280 			break;
281 		}
282 
283 	mutex_unlock(&acpi_dev->physical_node_lock);
284 	return 0;
285 }
286 EXPORT_SYMBOL_GPL(acpi_unbind_one);
287 
acpi_device_notify(struct device * dev)288 void acpi_device_notify(struct device *dev)
289 {
290 	struct acpi_bus_type *type = acpi_get_bus_type(dev);
291 	struct acpi_device *adev;
292 	int ret;
293 
294 	ret = acpi_bind_one(dev, NULL);
295 	if (ret) {
296 		if (!type)
297 			goto err;
298 
299 		adev = type->find_companion(dev);
300 		if (!adev) {
301 			dev_dbg(dev, "ACPI companion not found\n");
302 			goto err;
303 		}
304 		ret = acpi_bind_one(dev, adev);
305 		if (ret)
306 			goto err;
307 	}
308 	adev = ACPI_COMPANION(dev);
309 
310 	if (dev_is_platform(dev))
311 		acpi_configure_pmsi_domain(dev);
312 
313 	if (type && type->setup)
314 		type->setup(dev);
315 	else if (adev->handler && adev->handler->bind)
316 		adev->handler->bind(dev);
317 
318 	acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n",
319 			  dev_name(dev));
320 
321 	return;
322 
323 err:
324 	dev_dbg(dev, "No ACPI support\n");
325 }
326 
acpi_device_notify_remove(struct device * dev)327 void acpi_device_notify_remove(struct device *dev)
328 {
329 	struct acpi_device *adev = ACPI_COMPANION(dev);
330 	struct acpi_bus_type *type;
331 
332 	if (!adev)
333 		return;
334 
335 	type = acpi_get_bus_type(dev);
336 	if (type && type->cleanup)
337 		type->cleanup(dev);
338 	else if (adev->handler && adev->handler->unbind)
339 		adev->handler->unbind(dev);
340 
341 	acpi_unbind_one(dev);
342 }
343