Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / acpi / scan.c
index b99e624..6ad4656 100644 (file)
@@ -175,6 +175,16 @@ acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *bu
 }
 static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
 
+#ifdef CONFIG_PCI_GUESTDEV
+static ssize_t
+acpi_device_uid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+       return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+#endif
+
 static ssize_t
 acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -217,6 +227,13 @@ static int acpi_device_setup_files(struct acpi_device *dev)
                        goto end;
        }
 
+#ifdef CONFIG_PCI_GUESTDEV
+       if(dev->pnp.unique_id) {
+               result = device_create_file(&dev->dev, &dev_attr_uid);
+               if(result)
+                       goto end;
+       }
+#endif
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
@@ -280,6 +297,9 @@ static void acpi_free_ids(struct acpi_device *device)
                kfree(id->id);
                kfree(id);
        }
+#ifdef CONFIG_PCI_GUESTDEV
+       kfree(device->pnp.unique_id);
+#endif
 }
 
 static void acpi_device_release(struct device *dev)
@@ -797,7 +817,6 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
        acpi_status status;
        acpi_event_status event_status;
 
-       device->wakeup.run_wake_count = 0;
        device->wakeup.flags.notifier_present = 0;
 
        /* Power button, Lid switch always enable wakeup */
@@ -870,7 +889,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
        /*
         * Enumerate supported power management states
         */
-       for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
+       for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
                struct acpi_device_power_state *ps = &device->power.states[i];
                char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
 
@@ -881,7 +900,6 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
                        int j;
 
                        device->power.flags.power_resources = 1;
-                       ps->flags.valid = 1;
                        for (j = 0; j < ps->resources.count; j++)
                                acpi_bus_add_power_resource(ps->resources.handles[j]);
                }
@@ -889,13 +907,15 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
                /* Evaluate "_PSx" to see if we can do explicit sets */
                object_name[2] = 'S';
                status = acpi_get_handle(device->handle, object_name, &handle);
-               if (ACPI_SUCCESS(status)) {
+               if (ACPI_SUCCESS(status))
                        ps->flags.explicit_set = 1;
-                       ps->flags.valid = 1;
-               }
 
-               /* State is valid if we have some power control */
-               if (ps->resources.count || ps->flags.explicit_set)
+               /*
+                * State is valid if there are means to put the device into it.
+                * D3hot is only valid if _PR3 present.
+                */
+               if (ps->resources.count ||
+                   (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
                        ps->flags.valid = 1;
 
                ps->power = -1; /* Unknown - driver assigned */
@@ -908,6 +928,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
        device->power.states[ACPI_STATE_D3].flags.valid = 1;
        device->power.states[ACPI_STATE_D3].power = 0;
 
+       /* Set D3cold's explicit_set flag if _PS3 exists. */
+       if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
+               device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1;
+
        acpi_bus_init_power(device);
 
        return 0;
@@ -944,6 +968,10 @@ static int acpi_bus_get_flags(struct acpi_device *device)
        if (ACPI_SUCCESS(status))
                device->flags.lockable = 1;
 
+       /* Power resources cannot be power manageable. */
+       if (device->device_type == ACPI_BUS_TYPE_POWER)
+               return 0;
+
        /* Presence of _PS0|_PR0 indicates 'power manageable' */
        status = acpi_get_handle(device->handle, "_PS0", &temp);
        if (ACPI_FAILURE(status))
@@ -1059,13 +1087,12 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
        if (!id)
                return;
 
-       id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
+       id->id = kstrdup(dev_id, GFP_KERNEL);
        if (!id->id) {
                kfree(id);
                return;
        }
 
-       strcpy(id->id, dev_id);
        list_add_tail(&id->list, &device->pnp.ids);
 }
 
@@ -1131,6 +1158,11 @@ static void acpi_device_set_id(struct acpi_device *device)
                        for (i = 0; i < cid_list->count; i++)
                                acpi_add_id(device, cid_list->ids[i].string);
                }
+#ifdef CONFIG_PCI_GUESTDEV
+               if (info->valid & ACPI_VALID_UID)
+                       device->pnp.unique_id = kstrdup(info->unique_id.string,
+                                                       GFP_KERNEL);
+#endif
                if (info->valid & ACPI_VALID_ADR) {
                        device->pnp.bus_address = info->address;
                        device->flags.bus_address = 1;