]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/glue.c
r8169: remove unused macros.
[~andy/linux] / drivers / acpi / glue.c
index 243ee85e4d2ed02ad29c22435dd4c5437390f6a7..08373086cd7e883edeec356acb102bcac46147cf 100644 (file)
@@ -25,6 +25,8 @@
 static LIST_HEAD(bus_type_list);
 static DECLARE_RWSEM(bus_type_sem);
 
+#define PHYSICAL_NODE_STRING "physical_node"
+
 int register_acpi_bus_type(struct acpi_bus_type *type)
 {
        if (acpi_disabled)
@@ -124,84 +126,120 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address)
 
 EXPORT_SYMBOL(acpi_get_child);
 
-/* Link ACPI devices with physical devices */
-static void acpi_glue_data_handler(acpi_handle handle,
-                                  void *context)
-{
-       /* we provide an empty handler */
-}
-
-/* Note: a success call will increase reference count by one */
-struct device *acpi_get_physical_device(acpi_handle handle)
-{
-       acpi_status status;
-       struct device *dev;
-
-       status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
-       if (ACPI_SUCCESS(status))
-               return get_device(dev);
-       return NULL;
-}
-
-EXPORT_SYMBOL(acpi_get_physical_device);
-
 static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
        struct acpi_device *acpi_dev;
        acpi_status status;
+       struct acpi_device_physical_node *physical_node;
+       char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+       int retval = -EINVAL;
 
        if (dev->archdata.acpi_handle) {
                dev_warn(dev, "Drivers changed 'acpi_handle'\n");
                return -EINVAL;
        }
+
        get_device(dev);
-       status = acpi_attach_data(handle, acpi_glue_data_handler, dev);
-       if (ACPI_FAILURE(status)) {
-               put_device(dev);
-               return -EINVAL;
+       status = acpi_bus_get_device(handle, &acpi_dev);
+       if (ACPI_FAILURE(status))
+               goto err;
+
+       physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
+               GFP_KERNEL);
+       if (!physical_node) {
+               retval = -ENOMEM;
+               goto err;
        }
-       dev->archdata.acpi_handle = handle;
 
-       status = acpi_bus_get_device(handle, &acpi_dev);
-       if (!ACPI_FAILURE(status)) {
-               int ret;
-
-               ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
-                               "firmware_node");
-               ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
-                               "physical_node");
-               if (acpi_dev->wakeup.flags.valid)
-                       device_set_wakeup_capable(dev, true);
+       mutex_lock(&acpi_dev->physical_node_lock);
+       /* allocate physical node id according to physical_node_id_bitmap */
+       physical_node->node_id =
+               find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
+               ACPI_MAX_PHYSICAL_NODE);
+       if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
+               retval = -ENOSPC;
+               mutex_unlock(&acpi_dev->physical_node_lock);
+               kfree(physical_node);
+               goto err;
        }
 
+       set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
+       physical_node->dev = dev;
+       list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
+       acpi_dev->physical_node_count++;
+       mutex_unlock(&acpi_dev->physical_node_lock);
+
+       dev->archdata.acpi_handle = handle;
+
+       if (!physical_node->node_id)
+               strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+       else
+               sprintf(physical_node_name,
+                       "physical_node%d", physical_node->node_id);
+       retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
+                       physical_node_name);
+       retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
+               "firmware_node");
+
+       if (acpi_dev->wakeup.flags.valid)
+               device_set_wakeup_capable(dev, true);
+
        return 0;
+
+ err:
+       put_device(dev);
+       return retval;
 }
 
 static int acpi_unbind_one(struct device *dev)
 {
+       struct acpi_device_physical_node *entry;
+       struct acpi_device *acpi_dev;
+       acpi_status status;
+       struct list_head *node, *next;
+
        if (!dev->archdata.acpi_handle)
                return 0;
-       if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
-               struct acpi_device *acpi_dev;
 
-               /* acpi_get_physical_device increase refcnt by one */
-               put_device(dev);
+       status = acpi_bus_get_device(dev->archdata.acpi_handle,
+               &acpi_dev);
+       if (ACPI_FAILURE(status))
+               goto err;
 
-               if (!acpi_bus_get_device(dev->archdata.acpi_handle,
-                                       &acpi_dev)) {
-                       sysfs_remove_link(&dev->kobj, "firmware_node");
-                       sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
-               }
+       mutex_lock(&acpi_dev->physical_node_lock);
+       list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
+               char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+
+               entry = list_entry(node, struct acpi_device_physical_node,
+                       node);
+               if (entry->dev != dev)
+                       continue;
+
+               list_del(node);
+               clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
 
-               acpi_detach_data(dev->archdata.acpi_handle,
-                                acpi_glue_data_handler);
+               acpi_dev->physical_node_count--;
+
+               if (!entry->node_id)
+                       strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+               else
+                       sprintf(physical_node_name,
+                               "physical_node%d", entry->node_id);
+
+               sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
+               sysfs_remove_link(&dev->kobj, "firmware_node");
                dev->archdata.acpi_handle = NULL;
                /* acpi_bind_one increase refcnt by one */
                put_device(dev);
-       } else {
-               dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+               kfree(entry);
        }
+       mutex_unlock(&acpi_dev->physical_node_lock);
+
        return 0;
+
+err:
+       dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+       return -EINVAL;
 }
 
 static int acpi_platform_notify(struct device *dev)