Skip to content

Commit

Permalink
ACPI / blacklist: add acpi_match_platform_list()
Browse files Browse the repository at this point in the history
ACPI OEM ID / OEM Table ID / Revision can be used to identify
a platform based on ACPI firmware info.  acpi_blacklisted(),
intel_pstate_platform_pwr_mgmt_exists(), and some other funcs,
have been using similar check to detect a list of platforms
that require special handlings.

Move the platform check in acpi_blacklisted() to a new common
utility function, acpi_match_platform_list(), so that other
drivers do not have to implement their own version.

There is no change in functionality.

Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
Reviewed-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Toshi Kani authored and Rafael J. Wysocki committed Aug 28, 2017
1 parent cc4a41f commit 5aa5911
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 69 deletions.
83 changes: 14 additions & 69 deletions drivers/acpi/blacklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,13 @@

#include "internal.h"

enum acpi_blacklist_predicates {
all_versions,
less_than_or_equal,
equal,
greater_than_or_equal,
};

struct acpi_blacklist_item {
char oem_id[7];
char oem_table_id[9];
u32 oem_revision;
char *table;
enum acpi_blacklist_predicates oem_revision_predicate;
char *reason;
u32 is_critical_error;
};

static struct dmi_system_id acpi_rev_dmi_table[] __initdata;

/*
* POLICY: If *anything* doesn't work, put it on the blacklist.
* If they are critical errors, mark it critical, and abort driver load.
*/
static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
static struct acpi_platform_list acpi_blacklist[] __initdata = {
/* Compaq Presario 1700 */
{"PTLTD ", " DSDT ", 0x06040000, ACPI_SIG_DSDT, less_than_or_equal,
"Multiple problems", 1},
Expand All @@ -67,65 +50,27 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = {
{"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal,
"Incorrect _ADR", 1},

{""}
{ }
};

int __init acpi_blacklisted(void)
{
int i = 0;
int i;
int blacklisted = 0;
struct acpi_table_header table_header;

while (acpi_blacklist[i].oem_id[0] != '\0') {
if (acpi_get_table_header(acpi_blacklist[i].table, 0, &table_header)) {
i++;
continue;
}

if (strncmp(acpi_blacklist[i].oem_id, table_header.oem_id, 6)) {
i++;
continue;
}

if (strncmp
(acpi_blacklist[i].oem_table_id, table_header.oem_table_id,
8)) {
i++;
continue;
}

if ((acpi_blacklist[i].oem_revision_predicate == all_versions)
|| (acpi_blacklist[i].oem_revision_predicate ==
less_than_or_equal
&& table_header.oem_revision <=
acpi_blacklist[i].oem_revision)
|| (acpi_blacklist[i].oem_revision_predicate ==
greater_than_or_equal
&& table_header.oem_revision >=
acpi_blacklist[i].oem_revision)
|| (acpi_blacklist[i].oem_revision_predicate == equal
&& table_header.oem_revision ==
acpi_blacklist[i].oem_revision)) {

printk(KERN_ERR PREFIX
"Vendor \"%6.6s\" System \"%8.8s\" "
"Revision 0x%x has a known ACPI BIOS problem.\n",
acpi_blacklist[i].oem_id,
acpi_blacklist[i].oem_table_id,
acpi_blacklist[i].oem_revision);
i = acpi_match_platform_list(acpi_blacklist);
if (i >= 0) {
pr_err(PREFIX "Vendor \"%6.6s\" System \"%8.8s\" Revision 0x%x has a known ACPI BIOS problem.\n",
acpi_blacklist[i].oem_id,
acpi_blacklist[i].oem_table_id,
acpi_blacklist[i].oem_revision);

printk(KERN_ERR PREFIX
"Reason: %s. This is a %s error\n",
acpi_blacklist[i].reason,
(acpi_blacklist[i].
is_critical_error ? "non-recoverable" :
"recoverable"));
pr_err(PREFIX "Reason: %s. This is a %s error\n",
acpi_blacklist[i].reason,
(acpi_blacklist[i].data ?
"non-recoverable" : "recoverable"));

blacklisted = acpi_blacklist[i].is_critical_error;
break;
} else {
i++;
}
blacklisted = acpi_blacklist[i].data;
}

(void)early_acpi_osi_init();
Expand Down
36 changes: 36 additions & 0 deletions drivers/acpi/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,3 +816,39 @@ static int __init acpi_backlight(char *str)
return 1;
}
__setup("acpi_backlight=", acpi_backlight);

/**
* acpi_match_platform_list - Check if the system matches with a given list
* @plat: pointer to acpi_platform_list table terminated by a NULL entry
*
* Return the matched index if the system is found in the platform list.
* Otherwise, return a negative error code.
*/
int acpi_match_platform_list(const struct acpi_platform_list *plat)
{
struct acpi_table_header hdr;
int idx = 0;

if (acpi_disabled)
return -ENODEV;

for (; plat->oem_id[0]; plat++, idx++) {
if (ACPI_FAILURE(acpi_get_table_header(plat->table, 0, &hdr)))
continue;

if (strncmp(plat->oem_id, hdr.oem_id, ACPI_OEM_ID_SIZE))
continue;

if (strncmp(plat->oem_table_id, hdr.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))
continue;

if ((plat->pred == all_versions) ||
(plat->pred == less_than_or_equal && hdr.oem_revision <= plat->oem_revision) ||
(plat->pred == greater_than_or_equal && hdr.oem_revision >= plat->oem_revision) ||
(plat->pred == equal && hdr.oem_revision == plat->oem_revision))
return idx;
}

return -ENODEV;
}
EXPORT_SYMBOL(acpi_match_platform_list);
19 changes: 19 additions & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,25 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
#define ACPI_OST_SC_DRIVER_LOAD_FAILURE 0x81
#define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82

enum acpi_predicate {
all_versions,
less_than_or_equal,
equal,
greater_than_or_equal,
};

/* Table must be terminted by a NULL entry */
struct acpi_platform_list {
char oem_id[ACPI_OEM_ID_SIZE+1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE+1];
u32 oem_revision;
char *table;
enum acpi_predicate pred;
char *reason;
u32 data;
};
int acpi_match_platform_list(const struct acpi_platform_list *plat);

extern void acpi_early_init(void);
extern void acpi_subsystem_init(void);

Expand Down

0 comments on commit 5aa5911

Please sign in to comment.