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