]> Git Repo - linux.git/commitdiff
Merge branches 'acpi-scan', 'acpi-pnp' and 'acpi-sleep'
authorRafael J. Wysocki <[email protected]>
Tue, 22 Dec 2020 14:51:11 +0000 (15:51 +0100)
committerRafael J. Wysocki <[email protected]>
Tue, 22 Dec 2020 14:51:11 +0000 (15:51 +0100)
* acpi-scan:
  ACPI: scan: Add Intel Baytrail Mailbox Device to acpi_ignore_dep_ids
  ACPI: scan: Avoid unnecessary second pass in acpi_bus_scan()
  ACPI: scan: Defer enumeration of devices with _DEP lists
  ACPI: scan: Evaluate _DEP before adding the device

* acpi-pnp:
  ACPI: PNP: compare the string length in the matching_id()

* acpi-sleep:
  ACPI: PM: s2idle: Move x86-specific code to the x86 directory
  ACPI: PM: s2idle: Add AMD support to handle _DSM

1  2  3  4 
drivers/acpi/scan.c

diff --combined drivers/acpi/scan.c
index a1b226eb2ce259f81090757a26db3c4114f081f3,05814d188c7d21aeead6f3d6d080c78ec8adeb19,bc6a79e3322092a1eefd89ec577f8c8d4ea7ad71,bc6a79e3322092a1eefd89ec577f8c8d4ea7ad71..80b668c80073a58417e6bd6a2ad0d1ddc0f28d31
@@@@@ -51,8 -51,8 -51,8 -51,8 +51,8 @@@@@ static u64 spcr_uart_addr
    
    struct acpi_dep_data {
        struct list_head node;
  --    acpi_handle master;
  --    acpi_handle slave;
  ++    acpi_handle supplier;
  ++    acpi_handle consumer;
    };
    
    void acpi_scan_lock_acquire(void)
@@@@@ -719,42 -719,43 -719,6 -719,6 +719,43 @@@@@ int acpi_device_add(struct acpi_device 
    /* --------------------------------------------------------------------------
                                     Device Enumeration
       -------------------------------------------------------------------------- */
  ++static bool acpi_info_matches_ids(struct acpi_device_info *info,
  ++                              const char * const ids[])
  ++{
  ++    struct acpi_pnp_device_id_list *cid_list = NULL;
  ++    int i;
  ++
  ++    if (!(info->valid & ACPI_VALID_HID))
  ++            return false;
  ++
  ++    if (info->valid & ACPI_VALID_CID)
  ++            cid_list = &info->compatible_id_list;
  ++
  ++    for (i = 0; ids[i]; i++) {
  ++            int j;
  ++
  ++            if (!strcmp(info->hardware_id.string, ids[i]))
  ++                    return true;
  ++
  ++            if (!cid_list)
  ++                    continue;
  ++
  ++            for (j = 0; j < cid_list->count; j++) {
  ++                    if (!strcmp(cid_list->ids[j].string, ids[i]))
  ++                            return true;
  ++            }
  ++    }
  ++
  ++    return false;
  ++}
  ++
  ++/* List of HIDs for which we ignore matching ACPI devices, when checking _DEP lists. */
  ++static const char * const acpi_ignore_dep_ids[] = {
  ++    "PNP0D80", /* Windows-compatible System Power Management Controller */
+ ++    "INT33BD", /* Intel Baytrail Mailbox Device */
  ++    NULL
  ++};
  ++
    static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
    {
        struct acpi_device *device = NULL;
@@@@@ -1272,8 -1273,8 -1236,10 -1236,10 +1273,8 @@@@@ static bool acpi_object_is_system_bus(a
    }
    
    static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
  --                            int device_type)
  ++                            int device_type, struct acpi_device_info *info)
    {
  --    acpi_status status;
  --    struct acpi_device_info *info;
        struct acpi_pnp_device_id_list *cid_list;
        int i;
    
                        break;
                }
    
  --            status = acpi_get_object_info(handle, &info);
  --            if (ACPI_FAILURE(status)) {
  ++            if (!info) {
                        pr_err(PREFIX "%s: Error reading device info\n",
                                        __func__);
                        return;
                if (info->valid & ACPI_VALID_CLS)
                        acpi_add_id(pnp, info->class_code.string);
    
  --            kfree(info);
  --
                /*
                 * Some devices don't reliably have _HIDs & _CIDs, so add
                 * synthetic HIDs to make sure drivers can find them.
@@@@@ -1614,17 -1615,17 -1583,16 -1583,16 +1615,17 @@@@@ static bool acpi_device_enumeration_by_
    }
    
    void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
  --                         int type, unsigned long long sta)
  ++                         int type, unsigned long long sta,
  ++                         struct acpi_device_info *info)
    {
        INIT_LIST_HEAD(&device->pnp.ids);
        device->device_type = type;
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
 ---    device->fwnode.ops = &acpi_device_fwnode_ops;
 +++    fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
        acpi_set_device_status(device, sta);
        acpi_device_get_busid(device);
  --    acpi_set_pnp_ids(handle, &device->pnp, type);
  ++    acpi_set_pnp_ids(handle, &device->pnp, type, info);
        acpi_init_properties(device);
        acpi_bus_get_flags(device);
        device->flags.match_driver = false;
        device_initialize(&device->dev);
        dev_set_uevent_suppress(&device->dev, true);
        acpi_init_coherency(device);
- --    /* Assume there are unmet deps until acpi_device_dep_initialize() runs */
- --    device->dep_unmet = 1;
    }
    
    void acpi_device_add_finalize(struct acpi_device *device)
@@@@@ -1652,20 -1651,20 -1620,14 -1620,14 +1651,20 @@@@@ static int acpi_add_single_object(struc
        int result;
        struct acpi_device *device;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  ++    struct acpi_device_info *info = NULL;
  ++
  ++    if (handle != ACPI_ROOT_OBJECT && type == ACPI_BUS_TYPE_DEVICE)
  ++            acpi_get_object_info(handle, &info);
    
        device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
        if (!device) {
                printk(KERN_ERR PREFIX "Memory allocation error\n");
  ++            kfree(info);
                return -ENOMEM;
        }
    
  --    acpi_init_device_object(device, handle, type, sta);
  ++    acpi_init_device_object(device, handle, type, sta, info);
  ++    kfree(info);
        /*
         * For ACPI_BUS_TYPE_DEVICE getting the status is delayed till here so
         * that we can call acpi_bus_get_status() and use its quirk handling.
@@@@@ -1842,61 -1841,84 -1804,67 -1804,67 +1841,84 @@@@@ static void acpi_scan_init_hotplug(stru
        }
    }
    
- --static void acpi_device_dep_initialize(struct acpi_device *adev)
+ ++static u32 acpi_scan_check_dep(acpi_handle handle)
    {
- --    struct acpi_dep_data *dep;
        struct acpi_handle_list dep_devices;
        acpi_status status;
+ ++    u32 count;
        int i;
    
- --    adev->dep_unmet = 0;
- --
- --    if (!acpi_has_method(adev->handle, "_DEP"))
- --            return;
+ ++    /*
+ ++     * Check for _HID here to avoid deferring the enumeration of:
+ ++     * 1. PCI devices.
+ ++     * 2. ACPI nodes describing USB ports.
+ ++     * Still, checking for _HID catches more then just these cases ...
+ ++     */
+ ++    if (!acpi_has_method(handle, "_DEP") || !acpi_has_method(handle, "_HID"))
+ ++            return 0;
    
- --    status = acpi_evaluate_reference(adev->handle, "_DEP", NULL,
- --                                    &dep_devices);
+ ++    status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_devices);
        if (ACPI_FAILURE(status)) {
- --            dev_dbg(&adev->dev, "Failed to evaluate _DEP.\n");
- --            return;
+ ++            acpi_handle_debug(handle, "Failed to evaluate _DEP.\n");
+ ++            return 0;
        }
    
- --    for (i = 0; i < dep_devices.count; i++) {
+ ++    for (count = 0, i = 0; i < dep_devices.count; i++) {
                struct acpi_device_info *info;
- --            int skip;
+ ++            struct acpi_dep_data *dep;
+ ++            bool skip;
    
                status = acpi_get_object_info(dep_devices.handles[i], &info);
                if (ACPI_FAILURE(status)) {
- --                    dev_dbg(&adev->dev, "Error reading _DEP device info\n");
+ ++                    acpi_handle_debug(handle, "Error reading _DEP device info\n");
                        continue;
                }
    
  --            /*
  --             * Skip the dependency of Windows System Power
  --             * Management Controller
  --             */
  --            skip = info->valid & ACPI_VALID_HID &&
  --                    !strcmp(info->hardware_id.string, "INT3396");
  --
  ++            skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
                kfree(info);
    
                if (skip)
                        continue;
    
- --            dep = kzalloc(sizeof(struct acpi_dep_data), GFP_KERNEL);
+ ++            dep = kzalloc(sizeof(*dep), GFP_KERNEL);
                if (!dep)
- --                    return;
+ ++                    continue;
+ ++
+ ++            count++;
    
  --            dep->master = dep_devices.handles[i];
  --            dep->slave  = adev->handle;
  --            adev->dep_unmet++;
  ++            dep->supplier = dep_devices.handles[i];
-               dep->consumer  = adev->handle;
-               adev->dep_unmet++;
+ ++            dep->consumer = handle;
    
                mutex_lock(&acpi_dep_list_lock);
                list_add_tail(&dep->node , &acpi_dep_list);
                mutex_unlock(&acpi_dep_list_lock);
        }
+ ++
+ ++    return count;
    }
    
- --static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
- --                                  void *not_used, void **return_value)
+ ++static void acpi_scan_dep_init(struct acpi_device *adev)
+ ++{
+ ++    struct acpi_dep_data *dep;
+ ++
+ ++    mutex_lock(&acpi_dep_list_lock);
+ ++
+ ++    list_for_each_entry(dep, &acpi_dep_list, node) {
+ ++            if (dep->consumer == adev->handle)
+ ++                    adev->dep_unmet++;
+ ++    }
+ ++
+ ++    mutex_unlock(&acpi_dep_list_lock);
+ ++}
+ ++
+ ++static bool acpi_bus_scan_second_pass;
+ ++
+ ++static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
+ ++                                  struct acpi_device **adev_p)
    {
        struct acpi_device *device = NULL;
- --    int type;
        unsigned long long sta;
+ ++    int type;
        int result;
    
        acpi_bus_get_device(handle, &device);
                return AE_OK;
        }
    
+ ++    if (type == ACPI_BUS_TYPE_DEVICE && check_dep) {
+ ++            u32 count = acpi_scan_check_dep(handle);
+ ++            /* Bail out if the number of recorded dependencies is not 0. */
+ ++            if (count > 0) {
+ ++                    acpi_bus_scan_second_pass = true;
+ ++                    return AE_CTRL_DEPTH;
+ ++            }
+ ++    }
+ ++
        acpi_add_single_object(&device, handle, type, sta);
        if (!device)
                return AE_CTRL_DEPTH;
    
        acpi_scan_init_hotplug(device);
- --    acpi_device_dep_initialize(device);
+ ++    if (!check_dep)
+ ++            acpi_scan_dep_init(device);
    
- -- out:
- --    if (!*return_value)
- --            *return_value = device;
+ ++out:
+ ++    if (!*adev_p)
+ ++            *adev_p = device;
    
        return AE_OK;
    }
    
+ ++static acpi_status acpi_bus_check_add_1(acpi_handle handle, u32 lvl_not_used,
+ ++                                    void *not_used, void **ret_p)
+ ++{
+ ++    return acpi_bus_check_add(handle, true, (struct acpi_device **)ret_p);
+ ++}
+ ++
+ ++static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used,
+ ++                                    void *not_used, void **ret_p)
+ ++{
+ ++    return acpi_bus_check_add(handle, false, (struct acpi_device **)ret_p);
+ ++}
+ ++
    static void acpi_default_enumeration(struct acpi_device *device)
    {
        /*
@@@@@ -1993,12 -2037,16 -1961,12 -1961,12 +2037,16 @@@@@ static int acpi_scan_attach_handler(str
        return ret;
    }
    
- --static void acpi_bus_attach(struct acpi_device *device)
+ ++static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
    {
        struct acpi_device *child;
+ ++    bool skip = !first_pass && device->flags.visited;
        acpi_handle ejd;
        int ret;
    
+ ++    if (skip)
+ ++            goto ok;
+ ++
        if (ACPI_SUCCESS(acpi_bus_get_ejd(device->handle, &ejd)))
                register_dock_dependent_device(device, ejd);
    
    
     ok:
        list_for_each_entry(child, &device->children, node)
- --            acpi_bus_attach(child);
+ ++            acpi_bus_attach(child, first_pass);
    
- --    if (device->handler && device->handler->hotplug.notify_online)
+ ++    if (!skip && device->handler && device->handler->hotplug.notify_online)
                device->handler->hotplug.notify_online(device);
    }
    
@@@@@ -2058,14 -2106,15 -2026,14 -2026,14 +2106,15 @@@@@ void acpi_walk_dep_device_list(acpi_han
    
        mutex_lock(&acpi_dep_list_lock);
        list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
  --            if (dep->master == handle) {
  --                    acpi_bus_get_device(dep->slave, &adev);
  ++            if (dep->supplier == handle) {
  ++                    acpi_bus_get_device(dep->consumer, &adev);
                        if (!adev)
                                continue;
    
                        adev->dep_unmet--;
                        if (!adev->dep_unmet)
- --                            acpi_bus_attach(adev);
+ ++                            acpi_bus_attach(adev, true);
+ ++
                        list_del(&dep->node);
                        kfree(dep);
                }
@@@@@ -2090,17 -2139,37 -2058,17 -2058,17 +2139,37 @@@@@ EXPORT_SYMBOL_GPL(acpi_walk_dep_device_
     */
    int acpi_bus_scan(acpi_handle handle)
    {
- --    void *device = NULL;
+ ++    struct acpi_device *device = NULL;
+ ++
+ ++    acpi_bus_scan_second_pass = false;
  ++
-       if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
+ ++    /* Pass 1: Avoid enumerating devices with missing dependencies. */
+   
  --    if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
+ ++    if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device)))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
- --                                acpi_bus_check_add, NULL, NULL, &device);
+ ++                                acpi_bus_check_add_1, NULL, NULL,
+ ++                                (void **)&device);
+ ++
+ ++    if (!device)
+ ++            return -ENODEV;
  ++
-       if (device) {
-               acpi_bus_attach(device);
+ ++    acpi_bus_attach(device, true);
+   
  --    if (device) {
  --            acpi_bus_attach(device);
+ ++    if (!acpi_bus_scan_second_pass)
                return 0;
- --    }
- --    return -ENODEV;
+ ++
+ ++    /* Pass 2: Enumerate all of the remaining devices. */
+ ++
+ ++    device = NULL;
+ ++
+ ++    if (ACPI_SUCCESS(acpi_bus_check_add(handle, false, &device)))
+ ++            acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+ ++                                acpi_bus_check_add_2, NULL, NULL,
+ ++                                (void **)&device);
+ ++
+ ++    acpi_bus_attach(device, false);
+ ++
+ ++    return 0;
    }
    EXPORT_SYMBOL(acpi_bus_scan);
    
This page took 0.097365 seconds and 4 git commands to generate.