Merge branch 'pm-cpuidle'
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / glue.c
index 408f6b2a5fa8ee5c6578cd9e555a8386e112e370..94672297e1b1bc6f3b482b3e0985cda28786ee10 100644 (file)
@@ -173,6 +173,15 @@ acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
 }
 EXPORT_SYMBOL_GPL(acpi_find_child);
 
+static void acpi_physnode_link_name(char *buf, unsigned int node_id)
+{
+       if (node_id > 0)
+               snprintf(buf, PHYSICAL_NODE_NAME_SIZE,
+                        PHYSICAL_NODE_STRING "%u", node_id);
+       else
+               strcpy(buf, PHYSICAL_NODE_STRING);
+}
+
 int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
        struct acpi_device *acpi_dev;
@@ -216,8 +225,15 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
                /* Sanity check. */
                if (pn->dev == dev) {
+                       mutex_unlock(&acpi_dev->physical_node_lock);
+
                        dev_warn(dev, "Already associated with ACPI node\n");
-                       goto err_free;
+                       kfree(physical_node);
+                       if (ACPI_HANDLE(dev) != handle)
+                               goto err;
+
+                       put_device(dev);
+                       return 0;
                }
                if (pn->node_id == node_id) {
                        physnode_list = &pn->node;
@@ -230,20 +246,23 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        list_add(&physical_node->node, physnode_list);
        acpi_dev->physical_node_count++;
 
-       mutex_unlock(&acpi_dev->physical_node_lock);
-
        if (!ACPI_HANDLE(dev))
                ACPI_HANDLE_SET(dev, acpi_dev->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);
+       acpi_physnode_link_name(physical_node_name, node_id);
        retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
-                       physical_node_name);
+                                  physical_node_name);
+       if (retval)
+               dev_err(&acpi_dev->dev, "Failed to create link %s (%d)\n",
+                       physical_node_name, retval);
+
        retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
-               "firmware_node");
+                                  "firmware_node");
+       if (retval)
+               dev_err(dev, "Failed to create link firmware_node (%d)\n",
+                       retval);
+
+       mutex_unlock(&acpi_dev->physical_node_lock);
 
        if (acpi_dev->wakeup.flags.valid)
                device_set_wakeup_capable(dev, true);
@@ -254,11 +273,6 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        ACPI_HANDLE_SET(dev, NULL);
        put_device(dev);
        return retval;
-
- err_free:
-       mutex_unlock(&acpi_dev->physical_node_lock);
-       kfree(physical_node);
-       goto err;
 }
 EXPORT_SYMBOL_GPL(acpi_bind_one);
 
@@ -267,48 +281,37 @@ 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 (!ACPI_HANDLE(dev))
                return 0;
 
        status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
-       if (ACPI_FAILURE(status))
-               goto err;
+       if (ACPI_FAILURE(status)) {
+               dev_err(dev, "Oops, ACPI handle corrupt in %s()\n", __func__);
+               return -EINVAL;
+       }
 
        mutex_lock(&acpi_dev->physical_node_lock);
-       list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
-               char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
 
-               entry = list_entry(node, struct acpi_device_physical_node,
-                       node);
-               if (entry->dev != dev)
-                       continue;
+       list_for_each_entry(entry, &acpi_dev->physical_node_list, node)
+               if (entry->dev == dev) {
+                       char physnode_name[PHYSICAL_NODE_NAME_SIZE];
 
-               list_del(node);
+                       list_del(&entry->node);
+                       acpi_dev->physical_node_count--;
 
-               acpi_dev->physical_node_count--;
+                       acpi_physnode_link_name(physnode_name, entry->node_id);
+                       sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
+                       sysfs_remove_link(&dev->kobj, "firmware_node");
+                       ACPI_HANDLE_SET(dev, NULL);
+                       /* acpi_bind_one() increase refcnt by one. */
+                       put_device(dev);
+                       kfree(entry);
+                       break;
+               }
 
-               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");
-               ACPI_HANDLE_SET(dev, NULL);
-               /* acpi_bind_one increase refcnt by one */
-               put_device(dev);
-               kfree(entry);
-       }
        mutex_unlock(&acpi_dev->physical_node_lock);
-
        return 0;
-
-err:
-       dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
-       return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(acpi_unbind_one);