ACPICA: Utilities: Fix memory leak in acpi_ut_copy_iobject_to_iobject
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / scan.c
index 7efe546a8c42704137f3cbae8a3159485f3473b9..f775fa0d850feee4996b7e90bd6158c379841e1b 100644 (file)
@@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(acpi_initialize_hp_context);
 
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
-       if (!handler || !handler->attach)
+       if (!handler)
                return -EINVAL;
 
        list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
@@ -1551,9 +1551,13 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
         */
        if (acpi_has_method(device->handle, "_PSC"))
                device->power.flags.explicit_get = 1;
+
        if (acpi_has_method(device->handle, "_IRC"))
                device->power.flags.inrush_current = 1;
 
+       if (acpi_has_method(device->handle, "_DSW"))
+               device->power.flags.dsw_present = 1;
+
        /*
         * Enumerate supported power management states
         */
@@ -1793,8 +1797,10 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
                        return;
                }
 
-               if (info->valid & ACPI_VALID_HID)
+               if (info->valid & ACPI_VALID_HID) {
                        acpi_add_id(pnp, info->hardware_id.string);
+                       pnp->type.platform_id = 1;
+               }
                if (info->valid & ACPI_VALID_CID) {
                        cid_list = &info->compatible_id_list;
                        for (i = 0; i < cid_list->count; i++)
@@ -1973,6 +1979,9 @@ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
 {
        const struct acpi_device_id *devid;
 
+       if (handler->match)
+               return handler->match(idstr, matchid);
+
        for (devid = handler->ids; devid->id[0]; devid++)
                if (!strcmp((char *)devid->id, idstr)) {
                        if (matchid)
@@ -2061,6 +2070,44 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
        return AE_OK;
 }
 
+static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
+{
+       bool *is_spi_i2c_slave_p = data;
+
+       if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+               return 1;
+
+       /*
+        * devices that are connected to UART still need to be enumerated to
+        * platform bus
+        */
+       if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+               *is_spi_i2c_slave_p = true;
+
+        /* no need to do more checking */
+       return -1;
+}
+
+static void acpi_default_enumeration(struct acpi_device *device)
+{
+       struct list_head resource_list;
+       bool is_spi_i2c_slave = false;
+
+       if (!device->pnp.type.platform_id || device->handler)
+               return;
+
+       /*
+        * Do not enemerate SPI/I2C slaves as they will be enuerated by their
+        * respective parents.
+        */
+       INIT_LIST_HEAD(&resource_list);
+       acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
+                              &is_spi_i2c_slave);
+       acpi_dev_free_resource_list(&resource_list);
+       if (!is_spi_i2c_slave)
+               acpi_create_platform_device(device);
+}
+
 static int acpi_scan_attach_handler(struct acpi_device *device)
 {
        struct acpi_hardware_id *hwid;
@@ -2072,6 +2119,10 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
 
                handler = acpi_scan_match_handler(hwid->id, &devid);
                if (handler) {
+                       if (!handler->attach) {
+                               device->pnp.type.platform_id = 0;
+                               continue;
+                       }
                        device->handler = handler;
                        ret = handler->attach(device, devid);
                        if (ret > 0)
@@ -2082,6 +2133,9 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
                                break;
                }
        }
+       if (!ret)
+               acpi_default_enumeration(device);
+
        return ret;
 }
 
@@ -2241,11 +2295,11 @@ int __init acpi_scan_init(void)
        acpi_pci_root_init();
        acpi_pci_link_init();
        acpi_processor_init();
-       acpi_platform_init();
        acpi_lpss_init();
        acpi_cmos_rtc_init();
        acpi_container_init();
        acpi_memory_hotplug_init();
+       acpi_pnp_init();
 
        mutex_lock(&acpi_scan_lock);
        /*
@@ -2259,12 +2313,16 @@ int __init acpi_scan_init(void)
        if (result)
                goto out;
 
-       result = acpi_bus_scan_fixed();
-       if (result) {
-               acpi_detach_data(acpi_root->handle, acpi_scan_drop_device);
-               acpi_device_del(acpi_root);
-               put_device(&acpi_root->dev);
-               goto out;
+       /* Fixed feature devices do not exist on HW-reduced platform */
+       if (!acpi_gbl_reduced_hardware) {
+               result = acpi_bus_scan_fixed();
+               if (result) {
+                       acpi_detach_data(acpi_root->handle,
+                                        acpi_scan_drop_device);
+                       acpi_device_del(acpi_root);
+                       put_device(&acpi_root->dev);
+                       goto out;
+               }
        }
 
        acpi_update_all_gpes();