x86/apic/uv: Update the UV APIC driver check
Fix a bug in the OEM check function that determines if the system is a UV system and the BIOS is compatible with the kernel's UV apic driver. This prevents some possibly obscure panics and guards the system against being started on SGI hardware that does not have the required kernel support. Signed-off-by: Mike Travis <travis@sgi.com> Acked-by: Hedi Berriche <hedi@sgi.com> Acked-by: Dimitri Sivanich <sivanich@sgi.com> Link: http://lkml.kernel.org/r/20150409182629.112998930@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
7a4e017041
commit
379b97e280
1 changed files with 49 additions and 25 deletions
|
@ -144,36 +144,60 @@ static void __init uv_set_apicid_hibit(void)
|
||||||
|
|
||||||
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||||
{
|
{
|
||||||
int pnodeid, is_uv1, is_uv2, is_uv3;
|
int pnodeid;
|
||||||
|
int uv_apic;
|
||||||
|
|
||||||
if (strncmp(oem_id, "SGI", 3) != 0)
|
if (strncmp(oem_id, "SGI", 3) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
is_uv1 = !strcmp(oem_id, "SGI");
|
/*
|
||||||
is_uv2 = !strcmp(oem_id, "SGI2");
|
* Determine UV arch type.
|
||||||
is_uv3 = !strncmp(oem_id, "SGI3", 4); /* there are varieties of UV3 */
|
* SGI: UV100/1000
|
||||||
if (is_uv1 || is_uv2 || is_uv3) {
|
* SGI2: UV2000/3000
|
||||||
uv_hub_info->hub_revision =
|
* SGI3: UV300 (truncated to 4 chars because of different varieties)
|
||||||
(is_uv1 ? UV1_HUB_REVISION_BASE :
|
*/
|
||||||
(is_uv2 ? UV2_HUB_REVISION_BASE :
|
uv_hub_info->hub_revision =
|
||||||
UV3_HUB_REVISION_BASE));
|
!strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
|
||||||
pnodeid = early_get_pnodeid();
|
!strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
|
||||||
early_get_apic_pnode_shift();
|
!strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
|
||||||
x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
|
|
||||||
x86_platform.nmi_init = uv_nmi_init;
|
if (uv_hub_info->hub_revision == 0)
|
||||||
if (!strcmp(oem_table_id, "UVL"))
|
goto badbios;
|
||||||
uv_system_type = UV_LEGACY_APIC;
|
|
||||||
else if (!strcmp(oem_table_id, "UVX"))
|
pnodeid = early_get_pnodeid();
|
||||||
uv_system_type = UV_X2APIC;
|
early_get_apic_pnode_shift();
|
||||||
else if (!strcmp(oem_table_id, "UVH")) {
|
x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
|
||||||
__this_cpu_write(x2apic_extra_bits,
|
x86_platform.nmi_init = uv_nmi_init;
|
||||||
pnodeid << uvh_apicid.s.pnode_shift);
|
|
||||||
uv_system_type = UV_NON_UNIQUE_APIC;
|
if (!strcmp(oem_table_id, "UVX")) { /* most common */
|
||||||
uv_set_apicid_hibit();
|
uv_system_type = UV_X2APIC;
|
||||||
return 1;
|
uv_apic = 0;
|
||||||
}
|
|
||||||
|
} else if (!strcmp(oem_table_id, "UVH")) { /* only UV1 systems */
|
||||||
|
uv_system_type = UV_NON_UNIQUE_APIC;
|
||||||
|
__this_cpu_write(x2apic_extra_bits,
|
||||||
|
pnodeid << uvh_apicid.s.pnode_shift);
|
||||||
|
uv_set_apicid_hibit();
|
||||||
|
uv_apic = 1;
|
||||||
|
|
||||||
|
} else if (!strcmp(oem_table_id, "UVL")) { /* only used for */
|
||||||
|
uv_system_type = UV_LEGACY_APIC; /* very small systems */
|
||||||
|
uv_apic = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
goto badbios;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n",
|
||||||
|
oem_id, oem_table_id, uv_system_type,
|
||||||
|
uv_min_hub_revision_id, uv_apic);
|
||||||
|
|
||||||
|
return uv_apic;
|
||||||
|
|
||||||
|
badbios:
|
||||||
|
pr_err("UV: OEM_ID:%s OEM_TABLE_ID:%s\n", oem_id, oem_table_id);
|
||||||
|
pr_err("Current BIOS not supported, update kernel and/or BIOS\n");
|
||||||
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum uv_system_type get_uv_system_type(void)
|
enum uv_system_type get_uv_system_type(void)
|
||||||
|
|
Loading…
Reference in a new issue