Skip to content

Commit

Permalink
ACPI: power: Skip duplicate power resource references in _PRx
Browse files Browse the repository at this point in the history
commit 7d7b467cb95bf29597b417d4990160d4ea6d69b9 upstream.

Some ACPI tables contain duplicate power resource references like this:

        Name (_PR0, Package (0x04)  // _PR0: Power Resources for D0
        {
            P28P,
            P18P,
            P18P,
            CLK4
        })

This causes a WARN_ON in sysfs_add_link_to_group() because we end up
adding a link to the same acpi_device twice:

sysfs: cannot create duplicate filename '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/808622C1:00/OVTI2680:00/power_resources_D0/LNXPOWER:0a'
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.12-301.fc29.x86_64 #1
Hardware name: Insyde CherryTrail/Type2 - Board Product Name, BIOS jumperx.T87.KFBNEEA02 04/13/2016
Call Trace:
 dump_stack+0x5c/0x80
 sysfs_warn_dup.cold.3+0x17/0x2a
 sysfs_do_create_link_sd.isra.2+0xa9/0xb0
 sysfs_add_link_to_group+0x30/0x50
 acpi_power_expose_list+0x74/0xa0
 acpi_power_add_remove_device+0x50/0xa0
 acpi_add_single_object+0x26b/0x5f0
 acpi_bus_check_add+0xc4/0x250
 ...

To address this issue, make acpi_extract_power_resources() check for
duplicates and simply skip them when found.

Cc: All applicable <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
[ rjw: Subject & changelog, comments ]
Signed-off-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
jwrdegoede authored and gregkh committed Jan 16, 2019
1 parent be22579 commit dff14f7
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions drivers/acpi/power.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
}
}

static bool acpi_power_resource_is_dup(union acpi_object *package,
unsigned int start, unsigned int i)
{
acpi_handle rhandle, dup;
unsigned int j;

/* The caller is expected to check the package element types */
rhandle = package->package.elements[i].reference.handle;
for (j = start; j < i; j++) {
dup = package->package.elements[j].reference.handle;
if (dup == rhandle)
return true;
}

return false;
}

int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
struct list_head *list)
{
Expand All @@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
err = -ENODEV;
break;
}

/* Some ACPI tables contain duplicate power resource references */
if (acpi_power_resource_is_dup(package, start, i))
continue;

err = acpi_add_power_resource(rhandle);
if (err)
break;
Expand Down

0 comments on commit dff14f7

Please sign in to comment.