mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
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)
|
||||
{
|
||||
int pnodeid, is_uv1, is_uv2, is_uv3;
|
||||
int pnodeid;
|
||||
int uv_apic;
|
||||
|
||||
if (strncmp(oem_id, "SGI", 3) != 0)
|
||||
return 0;
|
||||
|
||||
is_uv1 = !strcmp(oem_id, "SGI");
|
||||
is_uv2 = !strcmp(oem_id, "SGI2");
|
||||
is_uv3 = !strncmp(oem_id, "SGI3", 4); /* there are varieties of UV3 */
|
||||
if (is_uv1 || is_uv2 || is_uv3) {
|
||||
uv_hub_info->hub_revision =
|
||||
(is_uv1 ? UV1_HUB_REVISION_BASE :
|
||||
(is_uv2 ? UV2_HUB_REVISION_BASE :
|
||||
UV3_HUB_REVISION_BASE));
|
||||
pnodeid = early_get_pnodeid();
|
||||
early_get_apic_pnode_shift();
|
||||
x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
|
||||
x86_platform.nmi_init = uv_nmi_init;
|
||||
if (!strcmp(oem_table_id, "UVL"))
|
||||
uv_system_type = UV_LEGACY_APIC;
|
||||
else if (!strcmp(oem_table_id, "UVX"))
|
||||
uv_system_type = UV_X2APIC;
|
||||
else if (!strcmp(oem_table_id, "UVH")) {
|
||||
__this_cpu_write(x2apic_extra_bits,
|
||||
pnodeid << uvh_apicid.s.pnode_shift);
|
||||
uv_system_type = UV_NON_UNIQUE_APIC;
|
||||
uv_set_apicid_hibit();
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Determine UV arch type.
|
||||
* SGI: UV100/1000
|
||||
* SGI2: UV2000/3000
|
||||
* SGI3: UV300 (truncated to 4 chars because of different varieties)
|
||||
*/
|
||||
uv_hub_info->hub_revision =
|
||||
!strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
|
||||
!strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
|
||||
!strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
|
||||
|
||||
if (uv_hub_info->hub_revision == 0)
|
||||
goto badbios;
|
||||
|
||||
pnodeid = early_get_pnodeid();
|
||||
early_get_apic_pnode_shift();
|
||||
x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
|
||||
x86_platform.nmi_init = uv_nmi_init;
|
||||
|
||||
if (!strcmp(oem_table_id, "UVX")) { /* most common */
|
||||
uv_system_type = UV_X2APIC;
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue