|
@@ -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);
|
|
|
|