Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / scan.c
index aa997c66d697897c3bf752d7acf8c5ed6338009d..2649a068671d3914d5f1eae97e4d91b1c2c56ed1 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kthread.h>
 #include <linux/dmi.h>
 #include <linux/nls.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/pgtable.h>
 
@@ -1768,15 +1769,9 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
        if (acpi_has_method(device->handle, pathname))
                ps->flags.explicit_set = 1;
 
-       /*
-        * State is valid if there are means to put the device into it.
-        * D3hot is only valid if _PR3 present.
-        */
-       if (!list_empty(&ps->resources)
-           || (ps->flags.explicit_set && state < ACPI_STATE_D3_HOT)) {
+       /* State is valid if there are means to put the device into it. */
+       if (!list_empty(&ps->resources) || ps->flags.explicit_set)
                ps->flags.valid = 1;
-               ps->flags.os_accessible = 1;
-       }
 
        ps->power = -1;         /* Unknown - driver assigned */
        ps->latency = -1;       /* Unknown - driver assigned */
@@ -1812,21 +1807,13 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
                acpi_bus_init_power_state(device, i);
 
        INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources);
+       if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
+               device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
 
-       /* Set defaults for D0 and D3 states (always valid) */
+       /* Set defaults for D0 and D3hot states (always valid) */
        device->power.states[ACPI_STATE_D0].flags.valid = 1;
        device->power.states[ACPI_STATE_D0].power = 100;
-       device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
-       device->power.states[ACPI_STATE_D3_COLD].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;
-
-       /* Presence of _PS3 or _PRx means we can put the device into D3 cold */
-       if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set ||
-                       device->power.flags.power_resources)
-               device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
+       device->power.states[ACPI_STATE_D3_HOT].flags.valid = 1;
 
        if (acpi_bus_init_power(device))
                device->flags.power_manageable = 0;
@@ -2167,6 +2154,39 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
        kfree(pnp->unique_id);
 }
 
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+       unsigned long long cca = 0;
+       acpi_status status;
+       struct acpi_device *parent = adev->parent;
+
+       if (parent && parent->flags.cca_seen) {
+               /*
+                * From ACPI spec, OSPM will ignore _CCA if an ancestor
+                * already saw one.
+                */
+               adev->flags.cca_seen = 1;
+               cca = parent->flags.coherent_dma;
+       } else {
+               status = acpi_evaluate_integer(adev->handle, "_CCA",
+                                              NULL, &cca);
+               if (ACPI_SUCCESS(status))
+                       adev->flags.cca_seen = 1;
+               else if (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED))
+                       /*
+                        * If architecture does not specify that _CCA is
+                        * required for DMA-able devices (e.g. x86),
+                        * we default to _CCA=1.
+                        */
+                       cca = 1;
+               else
+                       acpi_handle_debug(adev->handle,
+                                         "ACPI device is missing _CCA.\n");
+       }
+
+       adev->flags.coherent_dma = cca;
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
                             int type, unsigned long long sta)
 {
@@ -2185,6 +2205,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
        device->flags.visited = false;
        device_initialize(&device->dev);
        dev_set_uevent_suppress(&device->dev, true);
+       acpi_init_coherency(device);
 }
 
 void acpi_device_add_finalize(struct acpi_device *device)