Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 379b97e2 authored by Mike Travis's avatar Mike Travis Committed by Ingo Molnar
Browse files

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: default avatarMike Travis <travis@sgi.com>
Acked-by: default avatarHedi Berriche <hedi@sgi.com>
Acked-by: default avatarDimitri Sivanich <sivanich@sgi.com>
Link: http://lkml.kernel.org/r/20150409182629.112998930@asylum.americas.sgi.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 7a4e0170
Loading
Loading
Loading
Loading
+49 −25
Original line number Diff line number Diff line
@@ -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) {
	/*
	 * 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 =
			(is_uv1 ? UV1_HUB_REVISION_BASE :
			(is_uv2 ? UV2_HUB_REVISION_BASE :
				  UV3_HUB_REVISION_BASE));
		!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, "UVL"))
			uv_system_type = UV_LEGACY_APIC;
		else if (!strcmp(oem_table_id, "UVX"))

	if (!strcmp(oem_table_id, "UVX")) {		/* most common */
		uv_system_type = UV_X2APIC;
		else if (!strcmp(oem_table_id, "UVH")) {
		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_system_type = UV_NON_UNIQUE_APIC;
		uv_set_apicid_hibit();
			return 1;
		}
		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)