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