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 #include <linux/export.h> 10 #include <linux/init.h> 11 #include <linux/list.h> 12 #include <linux/device.h> 13 #include <linux/slab.h> 14 #include <linux/rwsem.h> 15 #include <linux/acpi.h> 16 #include <linux/dma-mapping.h> 17 18 #include "internal.h" 19 20 #define ACPI_GLUE_DEBUG 0 21 #if ACPI_GLUE_DEBUG 22 #define DBG(fmt, ...) \ 23 printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__) 24 #else 25 #define DBG(fmt, ...) \ 26 do { \ 27 if (0) \ 28 printk(KERN_DEBUG PREFIX fmt, ##__VA_ARGS__); \ 29 } while (0) 30 #endif 31 static LIST_HEAD(bus_type_list); 32 static DECLARE_RWSEM(bus_type_sem); 33 34 #define PHYSICAL_NODE_STRING "physical_node" 35 #define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10) 36 37 int register_acpi_bus_type(struct acpi_bus_type *type) 38 { 39 if (acpi_disabled) 40 return -ENODEV; 41 if (type && type->match && type->find_companion) { 42 down_write(&bus_type_sem); 43 list_add_tail(&type->list, &bus_type_list); 44 up_write(&bus_type_sem); 45 printk(KERN_INFO PREFIX "bus type %s registered\n", type->name); 46 return 0; 47 } 48 return -ENODEV; 49 } 50 EXPORT_SYMBOL_GPL(register_acpi_bus_type); 51 52 int unregister_acpi_bus_type(struct acpi_bus_type *type) 53 { 54 if (acpi_disabled) 55 return 0; 56 if (type) { 57 down_write(&bus_type_sem); 58 list_del_init(&type->list); 59 up_write(&bus_type_sem); 60 printk(KERN_INFO PREFIX "bus type %s unregistered\n", 61 type->name); 62 return 0; 63 } 64 return -ENODEV; 65 } 66 EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); 67 68 static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) 69 { 70 struct acpi_bus_type *tmp, *ret = NULL; 71 72 down_read(&bus_type_sem); 73 list_for_each_entry(tmp, &bus_type_list, list) { 74 if (tmp->match(dev)) { 75 ret = tmp; 76 break; 77 } 78 } 79 up_read(&bus_type_sem); 80 return ret; 81 } 82 83 #define FIND_CHILD_MIN_SCORE 1 84 #define FIND_CHILD_MAX_SCORE 2 85 86 static int find_child_checks(struct acpi_device *adev, bool check_children) 87 { 88 bool sta_present = true; 89 unsigned long long sta; 90 acpi_status status; 91 92 status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); 93 if (status == AE_NOT_FOUND) 94 sta_present = false; 95 else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) 96 return -ENODEV; 97 98 if (check_children && list_empty(&adev->children)) 99 return -ENODEV; 100 101 return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; 102 } 103 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 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 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 bool coherent; 172 173 if (has_acpi_companion(dev)) { 174 if (acpi_dev) { 175 dev_warn(dev, "ACPI companion already set\n"); 176 return -EINVAL; 177 } else { 178 acpi_dev = ACPI_COMPANION(dev); 179 } 180 } 181 if (!acpi_dev) 182 return -EINVAL; 183 184 get_device(&acpi_dev->dev); 185 get_device(dev); 186 physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL); 187 if (!physical_node) { 188 retval = -ENOMEM; 189 goto err; 190 } 191 192 mutex_lock(&acpi_dev->physical_node_lock); 193 194 /* 195 * Keep the list sorted by node_id so that the IDs of removed nodes can 196 * be recycled easily. 197 */ 198 physnode_list = &acpi_dev->physical_node_list; 199 node_id = 0; 200 list_for_each_entry(pn, &acpi_dev->physical_node_list, node) { 201 /* Sanity check. */ 202 if (pn->dev == dev) { 203 mutex_unlock(&acpi_dev->physical_node_lock); 204 205 dev_warn(dev, "Already associated with ACPI node\n"); 206 kfree(physical_node); 207 if (ACPI_COMPANION(dev) != acpi_dev) 208 goto err; 209 210 put_device(dev); 211 put_device(&acpi_dev->dev); 212 return 0; 213 } 214 if (pn->node_id == node_id) { 215 physnode_list = &pn->node; 216 node_id++; 217 } 218 } 219 220 physical_node->node_id = node_id; 221 physical_node->dev = dev; 222 list_add(&physical_node->node, physnode_list); 223 acpi_dev->physical_node_count++; 224 225 if (!has_acpi_companion(dev)) 226 ACPI_COMPANION_SET(dev, acpi_dev); 227 228 if (acpi_check_dma(acpi_dev, &coherent)) 229 arch_setup_dma_ops(dev, 0, 0, NULL, coherent); 230 231 acpi_physnode_link_name(physical_node_name, node_id); 232 retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, 233 physical_node_name); 234 if (retval) 235 dev_err(&acpi_dev->dev, "Failed to create link %s (%d)\n", 236 physical_node_name, retval); 237 238 retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, 239 "firmware_node"); 240 if (retval) 241 dev_err(dev, "Failed to create link firmware_node (%d)\n", 242 retval); 243 244 mutex_unlock(&acpi_dev->physical_node_lock); 245 246 if (acpi_dev->wakeup.flags.valid) 247 device_set_wakeup_capable(dev, true); 248 249 return 0; 250 251 err: 252 ACPI_COMPANION_SET(dev, NULL); 253 put_device(dev); 254 put_device(&acpi_dev->dev); 255 return retval; 256 } 257 EXPORT_SYMBOL_GPL(acpi_bind_one); 258 259 int acpi_unbind_one(struct device *dev) 260 { 261 struct acpi_device *acpi_dev = ACPI_COMPANION(dev); 262 struct acpi_device_physical_node *entry; 263 264 if (!acpi_dev) 265 return 0; 266 267 mutex_lock(&acpi_dev->physical_node_lock); 268 269 list_for_each_entry(entry, &acpi_dev->physical_node_list, node) 270 if (entry->dev == dev) { 271 char physnode_name[PHYSICAL_NODE_NAME_SIZE]; 272 273 list_del(&entry->node); 274 acpi_dev->physical_node_count--; 275 276 acpi_physnode_link_name(physnode_name, entry->node_id); 277 sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name); 278 sysfs_remove_link(&dev->kobj, "firmware_node"); 279 ACPI_COMPANION_SET(dev, NULL); 280 /* Drop references taken by acpi_bind_one(). */ 281 put_device(dev); 282 put_device(&acpi_dev->dev); 283 kfree(entry); 284 break; 285 } 286 287 mutex_unlock(&acpi_dev->physical_node_lock); 288 return 0; 289 } 290 EXPORT_SYMBOL_GPL(acpi_unbind_one); 291 292 static int acpi_platform_notify(struct device *dev) 293 { 294 struct acpi_bus_type *type = acpi_get_bus_type(dev); 295 struct acpi_device *adev; 296 int ret; 297 298 ret = acpi_bind_one(dev, NULL); 299 if (ret && type) { 300 struct acpi_device *adev; 301 302 adev = type->find_companion(dev); 303 if (!adev) { 304 DBG("Unable to get handle for %s\n", dev_name(dev)); 305 ret = -ENODEV; 306 goto out; 307 } 308 ret = acpi_bind_one(dev, adev); 309 if (ret) 310 goto out; 311 } 312 adev = ACPI_COMPANION(dev); 313 if (!adev) 314 goto out; 315 316 if (type && type->setup) 317 type->setup(dev); 318 else if (adev->handler && adev->handler->bind) 319 adev->handler->bind(dev); 320 321 out: 322 #if ACPI_GLUE_DEBUG 323 if (!ret) { 324 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 325 326 acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); 327 DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); 328 kfree(buffer.pointer); 329 } else 330 DBG("Device %s -> No ACPI support\n", dev_name(dev)); 331 #endif 332 333 return ret; 334 } 335 336 static int acpi_platform_notify_remove(struct device *dev) 337 { 338 struct acpi_device *adev = ACPI_COMPANION(dev); 339 struct acpi_bus_type *type; 340 341 if (!adev) 342 return 0; 343 344 type = acpi_get_bus_type(dev); 345 if (type && type->cleanup) 346 type->cleanup(dev); 347 else if (adev->handler && adev->handler->unbind) 348 adev->handler->unbind(dev); 349 350 acpi_unbind_one(dev); 351 return 0; 352 } 353 354 int __init init_acpi_device_notify(void) 355 { 356 if (platform_notify || platform_notify_remove) { 357 printk(KERN_ERR PREFIX "Can't use platform_notify\n"); 358 return 0; 359 } 360 platform_notify = acpi_platform_notify; 361 platform_notify_remove = acpi_platform_notify_remove; 362 return 0; 363 } 364