es7000_32.c 17.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 * Written by: Garry Forsgren, Unisys Corporation
 *             Natalie Protasevich, Unisys Corporation
I
Ingo Molnar 已提交
4
 *
L
Linus Torvalds 已提交
5 6 7
 * This file contains the code to configure and interface
 * with Unisys ES7000 series hardware system manager.
 *
I
Ingo Molnar 已提交
8 9 10 11
 * Copyright (c) 2003 Unisys Corporation.
 * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
 *
 *   All Rights Reserved.
L
Linus Torvalds 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 *
 * Contact information: Unisys Corporation, Township Line & Union Meeting
 * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
 *
 * http://www.unisys.com
 */
30 31 32

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

I
Ingo Molnar 已提交
33 34 35 36
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <linux/cpumask.h>
#include <linux/threads.h>
L
Linus Torvalds 已提交
37
#include <linux/kernel.h>
I
Ingo Molnar 已提交
38 39
#include <linux/module.h>
#include <linux/reboot.h>
L
Linus Torvalds 已提交
40
#include <linux/string.h>
I
Ingo Molnar 已提交
41
#include <linux/types.h>
L
Linus Torvalds 已提交
42 43
#include <linux/errno.h>
#include <linux/acpi.h>
I
Ingo Molnar 已提交
44
#include <linux/init.h>
45
#include <linux/gfp.h>
I
Ingo Molnar 已提交
46
#include <linux/nmi.h>
I
Ingo Molnar 已提交
47
#include <linux/smp.h>
I
Ingo Molnar 已提交
48
#include <linux/io.h>
I
Ingo Molnar 已提交
49

L
Linus Torvalds 已提交
50
#include <asm/apicdef.h>
I
Ingo Molnar 已提交
51 52 53
#include <asm/atomic.h>
#include <asm/fixmap.h>
#include <asm/mpspec.h>
54
#include <asm/setup.h>
I
Ingo Molnar 已提交
55 56
#include <asm/apic.h>
#include <asm/ipi.h>
L
Linus Torvalds 已提交
57

Y
Yinghai Lu 已提交
58 59 60 61
/*
 * ES7000 chipsets
 */

I
Ingo Molnar 已提交
62 63 64
#define NON_UNISYS			0
#define ES7000_CLASSIC			1
#define ES7000_ZORRO			2
Y
Yinghai Lu 已提交
65

I
Ingo Molnar 已提交
66 67
#define	MIP_REG				1
#define	MIP_PSAI_REG			4
Y
Yinghai Lu 已提交
68

I
Ingo Molnar 已提交
69 70 71
#define	MIP_BUSY			1
#define	MIP_SPIN			0xf0000
#define	MIP_VALID			0x0100000000000000ULL
72
#define	MIP_SW_APIC			0x1020b
Y
Yinghai Lu 已提交
73

I
Ingo Molnar 已提交
74
#define	MIP_PORT(val)			((val >> 32) & 0xffff)
Y
Yinghai Lu 已提交
75

I
Ingo Molnar 已提交
76
#define	MIP_RD_LO(val)			(val & 0xffffffff)
Y
Yinghai Lu 已提交
77

78 79 80 81 82 83 84 85 86 87 88
struct mip_reg {
	unsigned long long		off_0x00;
	unsigned long long		off_0x08;
	unsigned long long		off_0x10;
	unsigned long long		off_0x18;
	unsigned long long		off_0x20;
	unsigned long long		off_0x28;
	unsigned long long		off_0x30;
	unsigned long long		off_0x38;
};

Y
Yinghai Lu 已提交
89
struct mip_reg_info {
I
Ingo Molnar 已提交
90 91 92 93
	unsigned long long		mip_info;
	unsigned long long		delivery_info;
	unsigned long long		host_reg;
	unsigned long long		mip_reg;
Y
Yinghai Lu 已提交
94 95 96
};

struct psai {
I
Ingo Molnar 已提交
97 98 99
	unsigned long long		entry_type;
	unsigned long long		addr;
	unsigned long long		bep_addr;
Y
Yinghai Lu 已提交
100 101 102
};

#ifdef CONFIG_ACPI
I
Ingo Molnar 已提交
103

104
struct es7000_oem_table {
I
Ingo Molnar 已提交
105 106 107
	struct acpi_table_header	Header;
	u32				OEMTableAddr;
	u32				OEMTableSize;
Y
Yinghai Lu 已提交
108
};
I
Ingo Molnar 已提交
109 110 111 112

static unsigned long			oem_addrX;
static unsigned long			oem_size;

Y
Yinghai Lu 已提交
113 114
#endif

L
Linus Torvalds 已提交
115 116 117 118
/*
 * ES7000 Globals
 */

I
Ingo Molnar 已提交
119
static volatile unsigned long		*psai;
I
Ingo Molnar 已提交
120 121 122
static struct mip_reg			*mip_reg;
static struct mip_reg			*host_reg;
static int 				mip_port;
I
Ingo Molnar 已提交
123 124
static unsigned long			mip_addr;
static unsigned long			host_addr;
L
Linus Torvalds 已提交
125

I
Ingo Molnar 已提交
126
int					es7000_plat;
127

L
Linus Torvalds 已提交
128 129 130 131 132
/*
 * GSI override for ES7000 platforms.
 */


133
static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
{
	unsigned long vect = 0, psaival = 0;

	if (psai == NULL)
		return -1;

	vect = ((unsigned long)__pa(eip)/0x1000) << 16;
	psaival = (0x1000000 | vect | cpu);

	while (*psai & 0x1000000)
		;

	*psai = psaival;

	return 0;
}
150

151
static int es7000_apic_is_cluster(void)
152
{
153 154
	/* MPENTIUMIII */
	if (boot_cpu_data.x86 == 6 &&
155
	    (boot_cpu_data.x86_model >= 7 && boot_cpu_data.x86_model <= 11))
156
		return 1;
157

158 159
	return 0;
}
160

161
static void setup_unisys(void)
162 163 164 165 166 167 168 169 170
{
	/*
	 * Determine the generation of the ES7000 currently running.
	 *
	 * es7000_plat = 1 if the machine is a 5xx ES7000 box
	 * es7000_plat = 2 if the machine is a x86_64 ES7000 box
	 *
	 */
	if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
171
		es7000_plat = ES7000_ZORRO;
172
	else
173
		es7000_plat = ES7000_CLASSIC;
174 175
}

L
Linus Torvalds 已提交
176
/*
I
Ingo Molnar 已提交
177
 * Parse the OEM Table:
L
Linus Torvalds 已提交
178
 */
179
static int parse_unisys_oem(char *oemptr)
L
Linus Torvalds 已提交
180
{
181
	int			i;
L
Linus Torvalds 已提交
182
	int 			success = 0;
183 184 185 186
	unsigned char		type, size;
	unsigned long		val;
	char			*tp = NULL;
	struct psai		*psaip = NULL;
L
Linus Torvalds 已提交
187 188 189 190 191 192 193
	struct mip_reg_info 	*mi;
	struct mip_reg		*host, *mip;

	tp = oemptr;

	tp += 8;

194
	for (i = 0; i <= 6; i++) {
L
Linus Torvalds 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
		type = *tp++;
		size = *tp++;
		tp -= 2;
		switch (type) {
		case MIP_REG:
			mi = (struct mip_reg_info *)tp;
			val = MIP_RD_LO(mi->host_reg);
			host_addr = val;
			host = (struct mip_reg *)val;
			host_reg = __va(host);
			val = MIP_RD_LO(mi->mip_reg);
			mip_port = MIP_PORT(mi->mip_info);
			mip_addr = val;
			mip = (struct mip_reg *)val;
			mip_reg = __va(mip);
210
			pr_debug("host_reg = 0x%lx\n",
211
				 (unsigned long)host_reg);
212
			pr_debug("mip_reg = 0x%lx\n",
213
				 (unsigned long)mip_reg);
L
Linus Torvalds 已提交
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
			success++;
			break;
		case MIP_PSAI_REG:
			psaip = (struct psai *)tp;
			if (tp != NULL) {
				if (psaip->addr)
					psai = __va(psaip->addr);
				else
					psai = NULL;
				success++;
			}
			break;
		default:
			break;
		}
		tp += size;
	}

I
Ingo Molnar 已提交
232
	if (success < 2)
233
		es7000_plat = NON_UNISYS;
I
Ingo Molnar 已提交
234
	else
235
		setup_unisys();
I
Ingo Molnar 已提交
236

L
Linus Torvalds 已提交
237 238 239
	return es7000_plat;
}

240
#ifdef CONFIG_ACPI
241
static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
L
Linus Torvalds 已提交
242
{
243
	struct acpi_table_header *header = NULL;
I
Ingo Molnar 已提交
244
	struct es7000_oem_table *table;
245
	acpi_size tbl_size;
I
Ingo Molnar 已提交
246 247
	acpi_status ret;
	int i = 0;
248

I
Ingo Molnar 已提交
249 250 251 252
	for (;;) {
		ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size);
		if (!ACPI_SUCCESS(ret))
			return -1;
253

I
Ingo Molnar 已提交
254 255
		if (!memcmp((char *) &header->oem_id, "UNISYS", 6))
			break;
256

257
		early_acpi_os_unmap_memory(header, tbl_size);
L
Linus Torvalds 已提交
258
	}
I
Ingo Molnar 已提交
259 260 261 262 263 264 265 266 267 268 269

	table = (void *)header;

	oem_addrX	= table->OEMTableAddr;
	oem_size	= table->OEMTableSize;

	early_acpi_os_unmap_memory(header, tbl_size);

	*oem_addr	= (unsigned long)__acpi_map_table(oem_addrX, oem_size);

	return 0;
L
Linus Torvalds 已提交
270
}
271

272
static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
273
{
274 275 276 277
	if (!oem_addr)
		return;

	__acpi_unmap_table((char *)oem_addr, oem_size);
278
}
I
Ingo Molnar 已提交
279 280 281 282 283 284 285 286 287 288 289

static int es7000_check_dsdt(void)
{
	struct acpi_table_header header;

	if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) &&
	    !strncmp(header.oem_id, "UNISYS", 6))
		return 1;
	return 0;
}

290
static int es7000_acpi_ret;
291

I
Ingo Molnar 已提交
292
/* Hook from generic ACPI tables.c */
293
static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
I
Ingo Molnar 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
{
	unsigned long oem_addr = 0;
	int check_dsdt;
	int ret = 0;

	/* check dsdt at first to avoid clear fix_map for oem_addr */
	check_dsdt = es7000_check_dsdt();

	if (!find_unisys_acpi_oem_table(&oem_addr)) {
		if (check_dsdt) {
			ret = parse_unisys_oem((char *)oem_addr);
		} else {
			setup_unisys();
			ret = 1;
		}
		/*
		 * we need to unmap it
		 */
		unmap_unisys_acpi_oem_table(oem_addr);
	}
314 315 316 317

	es7000_acpi_ret = ret;

	return ret && !es7000_apic_is_cluster();
I
Ingo Molnar 已提交
318
}
319

320
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
321 322 323 324 325 326
{
	int ret = es7000_acpi_ret;

	return ret && es7000_apic_is_cluster();
}

I
Ingo Molnar 已提交
327
#else /* !CONFIG_ACPI: */
328
static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
I
Ingo Molnar 已提交
329 330 331
{
	return 0;
}
332

333
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
334 335 336
{
	return 0;
}
I
Ingo Molnar 已提交
337
#endif /* !CONFIG_ACPI */
L
Linus Torvalds 已提交
338

I
Ingo Molnar 已提交
339
static void es7000_spin(int n)
L
Linus Torvalds 已提交
340 341 342 343 344 345 346
{
	int i = 0;

	while (i++ < n)
		rep_nop();
}

347
static int es7000_mip_write(struct mip_reg *mip_reg)
L
Linus Torvalds 已提交
348
{
I
Ingo Molnar 已提交
349 350
	int status = 0;
	int spin;
L
Linus Torvalds 已提交
351 352

	spin = MIP_SPIN;
I
Ingo Molnar 已提交
353 354
	while ((host_reg->off_0x38 & MIP_VALID) != 0) {
		if (--spin <= 0) {
I
Ingo Molnar 已提交
355
			WARN(1,	"Timeout waiting for Host Valid Flag\n");
I
Ingo Molnar 已提交
356 357
			return -1;
		}
L
Linus Torvalds 已提交
358 359 360 361 362 363 364 365
		es7000_spin(MIP_SPIN);
	}

	memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
	outb(1, mip_port);

	spin = MIP_SPIN;

I
Ingo Molnar 已提交
366
	while ((mip_reg->off_0x38 & MIP_VALID) == 0) {
L
Linus Torvalds 已提交
367
		if (--spin <= 0) {
I
Ingo Molnar 已提交
368
			WARN(1,	"Timeout waiting for MIP Valid Flag\n");
L
Linus Torvalds 已提交
369 370 371 372 373
			return -1;
		}
		es7000_spin(MIP_SPIN);
	}

I
Ingo Molnar 已提交
374 375 376
	status = (mip_reg->off_0x00 & 0xffff0000000000ULL) >> 48;
	mip_reg->off_0x38 &= ~MIP_VALID;

L
Linus Torvalds 已提交
377 378 379
	return status;
}

380
static void es7000_enable_apic_mode(void)
L
Linus Torvalds 已提交
381
{
382 383 384 385
	struct mip_reg es7000_mip_reg;
	int mip_status;

	if (!es7000_plat)
L
Linus Torvalds 已提交
386
		return;
387

388
	pr_info("Enabling APIC mode.\n");
389 390 391
	memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
	es7000_mip_reg.off_0x00 = MIP_SW_APIC;
	es7000_mip_reg.off_0x38 = MIP_VALID;
392

I
Ingo Molnar 已提交
393 394
	while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
		WARN(1, "Command failed, status = %x\n", mip_status);
L
Linus Torvalds 已提交
395
}
I
Ingo Molnar 已提交
396

397
static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask)
I
Ingo Molnar 已提交
398 399 400 401 402 403 404 405 406
{
	/* Careful. Some cpus do not strictly honor the set of cpus
	 * specified in the interrupt destination when using lowest
	 * priority interrupt delivery mode.
	 *
	 * In particular there was a hyperthreading cpu observed to
	 * deliver interrupts to the wrong hyperthread when only one
	 * hyperthread was specified in the interrupt desitination.
	 */
407 408
	cpumask_clear(retmask);
	cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
I
Ingo Molnar 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
}


static void es7000_wait_for_init_deassert(atomic_t *deassert)
{
	while (!atomic_read(deassert))
		cpu_relax();
}

static unsigned int es7000_get_apic_id(unsigned long x)
{
	return (x >> 24) & 0xFF;
}

static void es7000_send_IPI_mask(const struct cpumask *mask, int vector)
{
425
	default_send_IPI_mask_sequence_phys(mask, vector);
I
Ingo Molnar 已提交
426 427 428 429
}

static void es7000_send_IPI_allbutself(int vector)
{
430
	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
I
Ingo Molnar 已提交
431 432 433 434 435 436 437 438 439
}

static void es7000_send_IPI_all(int vector)
{
	es7000_send_IPI_mask(cpu_online_mask, vector);
}

static int es7000_apic_id_registered(void)
{
440
	return 1;
I
Ingo Molnar 已提交
441 442
}

443
static const struct cpumask *target_cpus_cluster(void)
I
Ingo Molnar 已提交
444
{
445
	return cpu_all_mask;
I
Ingo Molnar 已提交
446 447
}

448
static const struct cpumask *es7000_target_cpus(void)
I
Ingo Molnar 已提交
449
{
450
	return cpumask_of(smp_processor_id());
I
Ingo Molnar 已提交
451 452
}

453
static unsigned long es7000_check_apicid_used(physid_mask_t *map, int apicid)
I
Ingo Molnar 已提交
454 455 456
{
	return 0;
}
457

I
Ingo Molnar 已提交
458 459 460 461 462 463 464
static unsigned long es7000_check_apicid_present(int bit)
{
	return physid_isset(bit, phys_cpu_present_map);
}

static unsigned long calculate_ldr(int cpu)
{
I
Ingo Molnar 已提交
465
	unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
I
Ingo Molnar 已提交
466

I
Ingo Molnar 已提交
467
	return SET_APIC_LOGICAL_ID(id);
I
Ingo Molnar 已提交
468 469 470 471 472 473 474 475 476 477 478 479 480 481
}

/*
 * Set up the logical destination ID.
 *
 * Intel recommends to set DFR, LdR and TPR before enabling
 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
 * document number 292116).  So here it goes...
 */
static void es7000_init_apic_ldr_cluster(void)
{
	unsigned long val;
	int cpu = smp_processor_id();

482
	apic_write(APIC_DFR, APIC_DFR_CLUSTER);
I
Ingo Molnar 已提交
483 484 485 486 487 488 489 490 491
	val = calculate_ldr(cpu);
	apic_write(APIC_LDR, val);
}

static void es7000_init_apic_ldr(void)
{
	unsigned long val;
	int cpu = smp_processor_id();

492
	apic_write(APIC_DFR, APIC_DFR_FLAT);
I
Ingo Molnar 已提交
493 494 495 496 497 498 499
	val = calculate_ldr(cpu);
	apic_write(APIC_LDR, val);
}

static void es7000_setup_apic_routing(void)
{
	int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
I
Ingo Molnar 已提交
500

501
	pr_info("Enabling APIC mode:  %s. Using %d I/O APICs, target cpus %lx\n",
I
Ingo Molnar 已提交
502 503
		(apic_version[apic] == 0x14) ?
			"Physical Cluster" : "Logical Cluster",
504
		nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
I
Ingo Molnar 已提交
505 506 507 508 509 510 511 512 513 514 515 516 517
}

static int es7000_apicid_to_node(int logical_apicid)
{
	return 0;
}


static int es7000_cpu_present_to_apicid(int mps_cpu)
{
	if (!mps_cpu)
		return boot_cpu_physical_apicid;
	else if (mps_cpu < nr_cpu_ids)
I
Ingo Molnar 已提交
518
		return per_cpu(x86_bios_cpu_apicid, mps_cpu);
I
Ingo Molnar 已提交
519 520 521 522
	else
		return BAD_APICID;
}

I
Ingo Molnar 已提交
523 524
static int cpu_id;

525
static void es7000_apicid_to_cpu_present(int phys_apicid, physid_mask_t *retmap)
I
Ingo Molnar 已提交
526
{
527
	physid_set_mask_of_physid(cpu_id, retmap);
I
Ingo Molnar 已提交
528
	++cpu_id;
I
Ingo Molnar 已提交
529 530 531 532 533 534 535 536
}

/* Mapping from cpu number to logical apicid */
static int es7000_cpu_to_logical_apicid(int cpu)
{
#ifdef CONFIG_SMP
	if (cpu >= nr_cpu_ids)
		return BAD_APICID;
537
	return cpu_2_logical_apicid[cpu];
I
Ingo Molnar 已提交
538 539 540 541 542
#else
	return logical_smp_processor_id();
#endif
}

543
static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
I
Ingo Molnar 已提交
544 545
{
	/* For clustered we don't have a good way to do this yet - hack */
546
	physids_promote(0xFFL, retmap);
I
Ingo Molnar 已提交
547 548 549 550 551
}

static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
{
	boot_cpu_physical_apicid = read_apic_id();
I
Ingo Molnar 已提交
552
	return 1;
I
Ingo Molnar 已提交
553 554
}

555
static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
I
Ingo Molnar 已提交
556
{
557 558
	unsigned int round = 0;
	int cpu, uninitialized_var(apicid);
I
Ingo Molnar 已提交
559 560

	/*
561
	 * The cpus in the mask must all be on the apic cluster.
I
Ingo Molnar 已提交
562
	 */
563 564
	for_each_cpu(cpu, cpumask) {
		int new_apicid = es7000_cpu_to_logical_apicid(cpu);
I
Ingo Molnar 已提交
565

566 567
		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
			WARN(1, "Not a valid mask!");
I
Ingo Molnar 已提交
568

569
			return BAD_APICID;
I
Ingo Molnar 已提交
570
		}
571 572
		apicid = new_apicid;
		round++;
I
Ingo Molnar 已提交
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
	}
	return apicid;
}

static unsigned int
es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
			      const struct cpumask *andmask)
{
	int apicid = es7000_cpu_to_logical_apicid(0);
	cpumask_var_t cpumask;

	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
		return apicid;

	cpumask_and(cpumask, inmask, andmask);
	cpumask_and(cpumask, cpumask, cpu_online_mask);
	apicid = es7000_cpu_mask_to_apicid(cpumask);

	free_cpumask_var(cpumask);

	return apicid;
}

static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
{
	return cpuid_apic >> index_msb;
}

static int probe_es7000(void)
{
	/* probed later in mptable/ACPI hooks */
	return 0;
}

607 608 609
static int es7000_mps_ret;
static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem,
		char *productid)
I
Ingo Molnar 已提交
610
{
611 612
	int ret = 0;

I
Ingo Molnar 已提交
613 614 615 616 617
	if (mpc->oemptr) {
		struct mpc_oemtable *oem_table =
			(struct mpc_oemtable *)mpc->oemptr;

		if (!strncmp(oem, "UNISYS", 6))
618
			ret = parse_unisys_oem((char *)oem_table);
I
Ingo Molnar 已提交
619
	}
620 621 622 623 624 625

	es7000_mps_ret = ret;

	return ret && !es7000_apic_is_cluster();
}

626 627
static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
		char *productid)
628 629 630 631
{
	int ret = es7000_mps_ret;

	return ret && es7000_apic_is_cluster();
I
Ingo Molnar 已提交
632 633
}

634 635
/* We've been warned by a false positive warning.Use __refdata to keep calm. */
struct apic __refdata apic_es7000_cluster = {
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671

	.name				= "es7000",
	.probe				= probe_es7000,
	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check_cluster,
	.apic_id_registered		= es7000_apic_id_registered,

	.irq_delivery_mode		= dest_LowestPrio,
	/* logical delivery broadcast to all procs: */
	.irq_dest_mode			= 1,

	.target_cpus			= target_cpus_cluster,
	.disable_esr			= 1,
	.dest_logical			= 0,
	.check_apicid_used		= es7000_check_apicid_used,
	.check_apicid_present		= es7000_check_apicid_present,

	.vector_allocation_domain	= es7000_vector_allocation_domain,
	.init_apic_ldr			= es7000_init_apic_ldr_cluster,

	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
	.setup_apic_routing		= es7000_setup_apic_routing,
	.multi_timer_check		= NULL,
	.apicid_to_node			= es7000_apicid_to_node,
	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
	.setup_portio_remap		= NULL,
	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
	.enable_apic_mode		= es7000_enable_apic_mode,
	.phys_pkg_id			= es7000_phys_pkg_id,
	.mps_oem_check			= es7000_mps_oem_check_cluster,

	.get_apic_id			= es7000_get_apic_id,
	.set_apic_id			= NULL,
	.apic_id_mask			= 0xFF << 24,

672
	.cpu_mask_to_apicid		= es7000_cpu_mask_to_apicid,
673 674 675 676 677 678 679 680
	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,

	.send_IPI_mask			= es7000_send_IPI_mask,
	.send_IPI_mask_allbutself	= NULL,
	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
	.send_IPI_all			= es7000_send_IPI_all,
	.send_IPI_self			= default_send_IPI_self,

681
	.wakeup_secondary_cpu		= wakeup_secondary_cpu_via_mip,
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698

	.trampoline_phys_low		= 0x467,
	.trampoline_phys_high		= 0x469,

	.wait_for_init_deassert		= NULL,

	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
	.smp_callin_clear_local_apic	= NULL,
	.inquire_remote_apic		= default_inquire_remote_apic,

	.read				= native_apic_mem_read,
	.write				= native_apic_mem_write,
	.icr_read			= native_apic_icr_read,
	.icr_write			= native_apic_icr_write,
	.wait_icr_idle			= native_apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
};
I
Ingo Molnar 已提交
699

700
struct apic __refdata apic_es7000 = {
I
Ingo Molnar 已提交
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743

	.name				= "es7000",
	.probe				= probe_es7000,
	.acpi_madt_oem_check		= es7000_acpi_madt_oem_check,
	.apic_id_registered		= es7000_apic_id_registered,

	.irq_delivery_mode		= dest_Fixed,
	/* phys delivery to target CPUs: */
	.irq_dest_mode			= 0,

	.target_cpus			= es7000_target_cpus,
	.disable_esr			= 1,
	.dest_logical			= 0,
	.check_apicid_used		= es7000_check_apicid_used,
	.check_apicid_present		= es7000_check_apicid_present,

	.vector_allocation_domain	= es7000_vector_allocation_domain,
	.init_apic_ldr			= es7000_init_apic_ldr,

	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
	.setup_apic_routing		= es7000_setup_apic_routing,
	.multi_timer_check		= NULL,
	.apicid_to_node			= es7000_apicid_to_node,
	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
	.setup_portio_remap		= NULL,
	.check_phys_apicid_present	= es7000_check_phys_apicid_present,
	.enable_apic_mode		= es7000_enable_apic_mode,
	.phys_pkg_id			= es7000_phys_pkg_id,
	.mps_oem_check			= es7000_mps_oem_check,

	.get_apic_id			= es7000_get_apic_id,
	.set_apic_id			= NULL,
	.apic_id_mask			= 0xFF << 24,

	.cpu_mask_to_apicid		= es7000_cpu_mask_to_apicid,
	.cpu_mask_to_apicid_and		= es7000_cpu_mask_to_apicid_and,

	.send_IPI_mask			= es7000_send_IPI_mask,
	.send_IPI_mask_allbutself	= NULL,
	.send_IPI_allbutself		= es7000_send_IPI_allbutself,
	.send_IPI_all			= es7000_send_IPI_all,
744
	.send_IPI_self			= default_send_IPI_self,
I
Ingo Molnar 已提交
745 746 747 748 749 750 751 752 753

	.trampoline_phys_low		= 0x467,
	.trampoline_phys_high		= 0x469,

	.wait_for_init_deassert		= es7000_wait_for_init_deassert,

	/* Nothing to do for most platforms, since cleared by the INIT cycle: */
	.smp_callin_clear_local_apic	= NULL,
	.inquire_remote_apic		= default_inquire_remote_apic,
Y
Yinghai Lu 已提交
754 755 756 757 758 759 760

	.read				= native_apic_mem_read,
	.write				= native_apic_mem_write,
	.icr_read			= native_apic_icr_read,
	.icr_write			= native_apic_icr_write,
	.wait_icr_idle			= native_apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
I
Ingo Molnar 已提交
761
};