ACPI / property: Refine consistency check for PRP0001
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 5 May 2015 13:43:07 +0000 (15:43 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 5 May 2015 13:43:07 +0000 (15:43 +0200)
Refine the check for the presence of the "compatible" property
if the PRP0001 device ID is present in the device's list of
ACPI/PNP IDs to also print the message if _DSD is missing
entirely or the format of it is incorrect.

One special case to take into accout is that the "compatible"
property need not be provided for devices having the PRP0001
device ID in their lists of ACPI/PNP IDs if they are ancestors
of PRP0001 devices with the "compatible" property present.
This is to cover heriarchies of device objects where the kernel
is only supposed to use a struct device representation for the
topmost one and the others represent, for example, functional
blocks of a composite device.

While at it, reduce the log level of the message to "info"
and reduce the log level of the "broken _DSD" message to
"debug" (noise reduction).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/acpi/property.c
include/acpi/acpi_bus.h

index 0d083736e25babf920140d9b0c88a84b47d6d729..76075eea5f646d36423ff19a084179a627227a60 100644 (file)
@@ -79,50 +79,51 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
 static void acpi_init_of_compatible(struct acpi_device *adev)
 {
        const union acpi_object *of_compatible;
-       struct acpi_hardware_id *hwid;
-       bool acpi_of = false;
        int ret;
 
-       /*
-        * Check if the special PRP0001 ACPI ID is present and in that
-        * case we fill in Device Tree compatible properties for this
-        * device.
-        */
-       list_for_each_entry(hwid, &adev->pnp.ids, list) {
-               if (!strcmp(hwid->id, "PRP0001")) {
-                       acpi_of = true;
-                       break;
-               }
-       }
-
-       if (!acpi_of)
-               return;
-
        ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
                                          &of_compatible);
        if (ret) {
                ret = acpi_dev_get_property(adev, "compatible",
                                            ACPI_TYPE_STRING, &of_compatible);
                if (ret) {
-                       acpi_handle_warn(adev->handle,
-                                        "PRP0001 requires compatible property\n");
+                       if (adev->parent
+                           && adev->parent->flags.of_compatible_ok)
+                               goto out;
+
                        return;
                }
        }
        adev->data.of_compatible = of_compatible;
+
+ out:
+       adev->flags.of_compatible_ok = 1;
 }
 
 void acpi_init_properties(struct acpi_device *adev)
 {
        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+       bool acpi_of = false;
+       struct acpi_hardware_id *hwid;
        const union acpi_object *desc;
        acpi_status status;
        int i;
 
+       /*
+        * Check if the special PRP0001 ACPI ID is present and in that case we
+        * fill in Device Tree compatible properties for this device.
+        */
+       list_for_each_entry(hwid, &adev->pnp.ids, list) {
+               if (!strcmp(hwid->id, "PRP0001")) {
+                       acpi_of = true;
+                       break;
+               }
+       }
+
        status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
                                            ACPI_TYPE_PACKAGE);
        if (ACPI_FAILURE(status))
-               return;
+               goto out;
 
        desc = buf.pointer;
        if (desc->package.count % 2)
@@ -156,13 +157,20 @@ void acpi_init_properties(struct acpi_device *adev)
                adev->data.pointer = buf.pointer;
                adev->data.properties = properties;
 
-               acpi_init_of_compatible(adev);
-               return;
+               if (acpi_of)
+                       acpi_init_of_compatible(adev);
+
+               goto out;
        }
 
  fail:
-       dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
+       dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n");
        ACPI_FREE(buf.pointer);
+
+ out:
+       if (acpi_of && !adev->flags.of_compatible_ok)
+               acpi_handle_info(adev->handle,
+                                "PRP0001 requires 'compatible' property\n");
 }
 
 void acpi_free_properties(struct acpi_device *adev)
index 8de4fa90e8c4add33967c8dbec6b7cfe2d01b2c4..da079976971fe1afd234cec0cad2b4e231f40b05 100644 (file)
@@ -208,7 +208,8 @@ struct acpi_device_flags {
        u32 visited:1;
        u32 hotplug_notify:1;
        u32 is_dock_station:1;
-       u32 reserved:23;
+       u32 of_compatible_ok:1;
+       u32 reserved:22;
 };
 
 /* File System */