| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2007-10-12 21:10:53 -04:00
										 |  |  |  * IBM Summit-Specific Code | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Written By: Matthew Dobson, IBM Corporation | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2003 IBM Corp. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation; either version 2 of the License, or (at | 
					
						
							|  |  |  |  * your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 
					
						
							|  |  |  |  * NON INFRINGEMENT.  See the GNU General Public License for more | 
					
						
							|  |  |  |  * details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Send feedback to <colpatch@us.ibm.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | #define pr_fmt(fmt) "summit: %s: " fmt, __func__
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/mm.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <asm/io.h>
 | 
					
						
							| 
									
										
										
										
											2008-04-19 23:55:20 +09:00
										 |  |  | #include <asm/bios_ebda.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * APIC driver for the IBM "Summit" chipset. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/threads.h>
 | 
					
						
							|  |  |  | #include <linux/cpumask.h>
 | 
					
						
							|  |  |  | #include <asm/mpspec.h>
 | 
					
						
							|  |  |  | #include <asm/apic.h>
 | 
					
						
							|  |  |  | #include <asm/smp.h>
 | 
					
						
							|  |  |  | #include <asm/fixmap.h>
 | 
					
						
							|  |  |  | #include <asm/apicdef.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-29 19:31:49 -08:00
										 |  |  | #include <asm/ipi.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/gfp.h>
 | 
					
						
							|  |  |  | #include <linux/smp.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static unsigned summit_get_apic_id(unsigned long x) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return (x >> 24) & 0xFF; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-13 14:49:55 +10:30
										 |  |  | static inline void summit_send_IPI_mask(const struct cpumask *mask, int vector) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-29 19:31:49 -08:00
										 |  |  | 	default_send_IPI_mask_sequence_logical(mask, vector); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static void summit_send_IPI_allbutself(int vector) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-13 14:49:55 +10:30
										 |  |  | 	default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static void summit_send_IPI_all(int vector) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-13 14:49:55 +10:30
										 |  |  | 	summit_send_IPI_mask(cpu_online_mask, vector); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/tsc.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern int use_cyclone; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_X86_SUMMIT_NUMA
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static void setup_summit(void); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static inline void setup_summit(void) {} | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static int summit_mps_oem_check(struct mpc_table *mpc, char *oem, | 
					
						
							|  |  |  | 		char *productid) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!strncmp(oem, "IBM ENSW", 8) && | 
					
						
							|  |  |  | 			(!strncmp(productid, "VIGIL SMP", 9) | 
					
						
							|  |  |  | 			 || !strncmp(productid, "EXA", 3) | 
					
						
							|  |  |  | 			 || !strncmp(productid, "RUTHLESS SMP", 12))){ | 
					
						
							|  |  |  | 		mark_tsc_unstable("Summit based system"); | 
					
						
							|  |  |  | 		use_cyclone = 1; /*enable cyclone-timer*/ | 
					
						
							|  |  |  | 		setup_summit(); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Hook from generic ACPI tables.c */ | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (!strncmp(oem_id, "IBM", 3) && | 
					
						
							|  |  |  | 	    (!strncmp(oem_table_id, "SERVIGIL", 8) | 
					
						
							|  |  |  | 	     || !strncmp(oem_table_id, "EXA", 3))){ | 
					
						
							|  |  |  | 		mark_tsc_unstable("Summit based system"); | 
					
						
							|  |  |  | 		use_cyclone = 1; /*enable cyclone-timer*/ | 
					
						
							|  |  |  | 		setup_summit(); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct rio_table_hdr { | 
					
						
							|  |  |  | 	unsigned char version;      /* Version number of this data structure           */ | 
					
						
							|  |  |  | 	                            /* Version 3 adds chassis_num & WP_index           */ | 
					
						
							|  |  |  | 	unsigned char num_scal_dev; /* # of Scalability devices (Twisters for Vigil)   */ | 
					
						
							|  |  |  | 	unsigned char num_rio_dev;  /* # of RIO I/O devices (Cyclones and Winnipegs)   */ | 
					
						
							|  |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct scal_detail { | 
					
						
							|  |  |  | 	unsigned char node_id;      /* Scalability Node ID                             */ | 
					
						
							|  |  |  | 	unsigned long CBAR;         /* Address of 1MB register space                   */ | 
					
						
							|  |  |  | 	unsigned char port0node;    /* Node ID port connected to: 0xFF=None            */ | 
					
						
							|  |  |  | 	unsigned char port0port;    /* Port num port connected to: 0,1,2, or 0xFF=None */ | 
					
						
							|  |  |  | 	unsigned char port1node;    /* Node ID port connected to: 0xFF = None          */ | 
					
						
							|  |  |  | 	unsigned char port1port;    /* Port num port connected to: 0,1,2, or 0xFF=None */ | 
					
						
							|  |  |  | 	unsigned char port2node;    /* Node ID port connected to: 0xFF = None          */ | 
					
						
							|  |  |  | 	unsigned char port2port;    /* Port num port connected to: 0,1,2, or 0xFF=None */ | 
					
						
							|  |  |  | 	unsigned char chassis_num;  /* 1 based Chassis number (1 = boot node)          */ | 
					
						
							|  |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct rio_detail { | 
					
						
							|  |  |  | 	unsigned char node_id;      /* RIO Node ID                                     */ | 
					
						
							|  |  |  | 	unsigned long BBAR;         /* Address of 1MB register space                   */ | 
					
						
							|  |  |  | 	unsigned char type;         /* Type of device                                  */ | 
					
						
							|  |  |  | 	unsigned char owner_id;     /* For WPEG: Node ID of Cyclone that owns this WPEG*/ | 
					
						
							|  |  |  | 	                            /* For CYC:  Node ID of Twister that owns this CYC */ | 
					
						
							|  |  |  | 	unsigned char port0node;    /* Node ID port connected to: 0xFF=None            */ | 
					
						
							|  |  |  | 	unsigned char port0port;    /* Port num port connected to: 0,1,2, or 0xFF=None */ | 
					
						
							|  |  |  | 	unsigned char port1node;    /* Node ID port connected to: 0xFF=None            */ | 
					
						
							|  |  |  | 	unsigned char port1port;    /* Port num port connected to: 0,1,2, or 0xFF=None */ | 
					
						
							|  |  |  | 	unsigned char first_slot;   /* For WPEG: Lowest slot number below this WPEG    */ | 
					
						
							|  |  |  | 	                            /* For CYC:  0                                     */ | 
					
						
							|  |  |  | 	unsigned char status;       /* For WPEG: Bit 0 = 1 : the XAPIC is used         */ | 
					
						
							|  |  |  | 	                            /*                 = 0 : the XAPIC is not used, ie:*/ | 
					
						
							|  |  |  | 	                            /*                     ints fwded to another XAPIC */ | 
					
						
							|  |  |  | 	                            /*           Bits1:7 Reserved                      */ | 
					
						
							|  |  |  | 	                            /* For CYC:  Bits0:7 Reserved                      */ | 
					
						
							|  |  |  | 	unsigned char WP_index;     /* For WPEG: WPEG instance index - lower ones have */ | 
					
						
							|  |  |  | 	                            /*           lower slot numbers/PCI bus numbers    */ | 
					
						
							|  |  |  | 	                            /* For CYC:  No meaning                            */ | 
					
						
							|  |  |  | 	unsigned char chassis_num;  /* 1 based Chassis number                          */ | 
					
						
							|  |  |  | 	                            /* For LookOut WPEGs this field indicates the      */ | 
					
						
							|  |  |  | 	                            /* Expansion Chassis #, enumerated from Boot       */ | 
					
						
							|  |  |  | 	                            /* Node WPEG external port, then Boot Node CYC     */ | 
					
						
							|  |  |  | 	                            /* external port, then Next Vigil chassis WPEG     */ | 
					
						
							|  |  |  | 	                            /* external port, etc.                             */ | 
					
						
							|  |  |  | 	                            /* Shared Lookouts have only 1 chassis number (the */ | 
					
						
							|  |  |  | 	                            /* first one assigned)                             */ | 
					
						
							|  |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef enum { | 
					
						
							|  |  |  | 	CompatTwister = 0,  /* Compatibility Twister               */ | 
					
						
							|  |  |  | 	AltTwister    = 1,  /* Alternate Twister of internal 8-way */ | 
					
						
							|  |  |  | 	CompatCyclone = 2,  /* Compatibility Cyclone               */ | 
					
						
							|  |  |  | 	AltCyclone    = 3,  /* Alternate Cyclone of internal 8-way */ | 
					
						
							|  |  |  | 	CompatWPEG    = 4,  /* Compatibility WPEG                  */ | 
					
						
							|  |  |  | 	AltWPEG       = 5,  /* Second Planar WPEG                  */ | 
					
						
							|  |  |  | 	LookOutAWPEG  = 6,  /* LookOut WPEG                        */ | 
					
						
							|  |  |  | 	LookOutBWPEG  = 7,  /* LookOut WPEG                        */ | 
					
						
							|  |  |  | } node_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int is_WPEG(struct rio_detail *rio){ | 
					
						
							|  |  |  | 	return (rio->type == CompatWPEG || rio->type == AltWPEG || | 
					
						
							|  |  |  | 		rio->type == LookOutAWPEG || rio->type == LookOutBWPEG); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-13 14:49:57 +10:30
										 |  |  | static const struct cpumask *summit_target_cpus(void) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* CPU_MASK_ALL (0xff) has undefined behaviour with
 | 
					
						
							|  |  |  | 	 * dest_LowestPrio mode logical clustered apic interrupt routing | 
					
						
							|  |  |  | 	 * Just start on cpu 0.  IRQ balancing will spread load | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2009-03-13 14:49:54 +10:30
										 |  |  | 	return cpumask_of(0); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 01:06:59 +03:00
										 |  |  | static unsigned long summit_check_apicid_used(physid_mask_t *map, int apicid) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* we don't use the phys_cpu_present_map to indicate apicid presence */ | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static unsigned long summit_check_apicid_present(int bit) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:36 +01:00
										 |  |  | static int summit_early_logical_apicid(int cpu) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:36 +01:00
										 |  |  | 	u8 my_id = early_per_cpu(x86_cpu_to_apicid, cpu); | 
					
						
							| 
									
										
										
										
											2009-02-17 15:09:08 +01:00
										 |  |  | 	u8 my_cluster = APIC_CLUSTER(my_id); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | #ifdef CONFIG_SMP
 | 
					
						
							|  |  |  | 	u8 lid; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Create logical APIC IDs by counting CPUs already in cluster. */ | 
					
						
							|  |  |  | 	for (count = 0, i = nr_cpu_ids; --i >= 0; ) { | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:30 +01:00
										 |  |  | 		lid = early_per_cpu(x86_cpu_to_logical_apicid, i); | 
					
						
							| 
									
										
										
										
											2009-02-17 15:09:08 +01:00
										 |  |  | 		if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 			++count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	/* We only have a 4 wide bitmap in cluster mode.  If a deranged
 | 
					
						
							|  |  |  | 	 * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ | 
					
						
							|  |  |  | 	BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:36 +01:00
										 |  |  | 	return my_cluster | (1UL << count); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void summit_init_apic_ldr(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int cpu = smp_processor_id(); | 
					
						
							|  |  |  | 	unsigned long id = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | 
					
						
							|  |  |  | 	unsigned long val; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 	apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE); | 
					
						
							|  |  |  | 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; | 
					
						
							|  |  |  | 	val |= SET_APIC_LOGICAL_ID(id); | 
					
						
							|  |  |  | 	apic_write(APIC_LDR, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static int summit_apic_id_registered(void) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static void summit_setup_apic_routing(void) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 	pr_info("Enabling APIC mode:  Summit.  Using %d I/O APICs\n", | 
					
						
							|  |  |  | 		nr_ioapics); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static int summit_cpu_present_to_apicid(int mps_cpu) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (mps_cpu < nr_cpu_ids) | 
					
						
							|  |  |  | 		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return BAD_APICID; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 01:06:59 +03:00
										 |  |  | static void summit_ioapic_phys_id_map(physid_mask_t *phys_id_map, physid_mask_t *retmap) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* For clustered we don't have a good way to do this yet - hack */ | 
					
						
							| 
									
										
										
										
											2009-11-10 01:06:59 +03:00
										 |  |  | 	physids_promote(0x0FL, retmap); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 01:06:59 +03:00
										 |  |  | static void summit_apicid_to_cpu_present(int apicid, physid_mask_t *retmap) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-10 01:06:59 +03:00
										 |  |  | 	physid_set_mask_of_physid(0, retmap); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-31 15:18:40 +02:00
										 |  |  | static int summit_check_phys_apicid_present(int physical_apicid) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-14 09:49:35 +02:00
										 |  |  | static inline int | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-02 10:53:58 +01:00
										 |  |  | 	unsigned int round = 0; | 
					
						
							| 
									
										
										
										
											2012-06-14 09:49:55 +02:00
										 |  |  | 	unsigned int cpu, apicid = 0; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:32 +01:00
										 |  |  | 	 * The cpus in the mask must all be on the apic cluster. | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-06-07 15:16:25 +02:00
										 |  |  | 	for_each_cpu_and(cpu, cpumask, cpu_online_mask) { | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:32 +01:00
										 |  |  | 		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 10:53:58 +01:00
										 |  |  | 		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 			pr_err("Not a valid mask!\n"); | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | 			return -EINVAL; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-03-02 10:53:58 +01:00
										 |  |  | 		apicid |= new_apicid; | 
					
						
							|  |  |  | 		round++; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-06-14 09:50:27 +02:00
										 |  |  | 	if (!round) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | 	*dest_id = apicid; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | static int | 
					
						
							|  |  |  | summit_cpu_mask_to_apicid_and(const struct cpumask *inmask, | 
					
						
							|  |  |  | 			      const struct cpumask *andmask, | 
					
						
							|  |  |  | 			      unsigned int *apicid) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	cpumask_var_t cpumask; | 
					
						
							| 
									
										
										
										
											2012-06-14 09:50:11 +02:00
										 |  |  | 	*apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC)) | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cpumask_and(cpumask, inmask, andmask); | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | 	summit_cpu_mask_to_apicid(cpumask, apicid); | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	free_cpumask_var(cpumask); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-07 15:15:59 +02:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * cpuid returns the value latched in the HW at reset, not the APIC ID | 
					
						
							|  |  |  |  * register's value.  For any box whose BIOS changes APIC IDs, like | 
					
						
							|  |  |  |  * clustered APIC systems, we must use hard_smp_processor_id. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-02-24 21:41:33 +01:00
										 |  |  | static int summit_phys_pkg_id(int cpuid_apic, int index_msb) | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	return hard_smp_processor_id() >> index_msb; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int probe_summit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* probed later in mptable/ACPI hooks */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-29 11:29:22 +01:00
										 |  |  | #ifdef CONFIG_X86_SUMMIT_NUMA
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static struct rio_table_hdr *rio_table_hdr; | 
					
						
							|  |  |  | static struct scal_detail   *scal_devs[MAX_NUMNODES]; | 
					
						
							|  |  |  | static struct rio_detail    *rio_devs[MAX_NUMNODES*4]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-08 18:31:54 -07:00
										 |  |  | #ifndef CONFIG_X86_NUMAQ
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static int mp_bus_id_to_node[MAX_MP_BUSSES]; | 
					
						
							| 
									
										
										
										
											2008-06-08 18:31:54 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-03-11 22:55:48 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	int twister = 0, node = 0; | 
					
						
							|  |  |  | 	int i, bus, num_buses; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	for (i = 0; i < rio_table_hdr->num_rio_dev; i++) { | 
					
						
							|  |  |  | 		if (rio_devs[i]->node_id == rio_devs[wpeg_num]->owner_id) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			twister = rio_devs[i]->owner_id; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	if (i == rio_table_hdr->num_rio_dev) { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_err("Couldn't find owner Cyclone for Winnipeg!\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return last_bus; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	for (i = 0; i < rio_table_hdr->num_scal_dev; i++) { | 
					
						
							|  |  |  | 		if (scal_devs[i]->node_id == twister) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			node = scal_devs[i]->node_id; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	if (i == rio_table_hdr->num_scal_dev) { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_err("Couldn't find owner Twister for Cyclone!\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return last_bus; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	switch (rio_devs[wpeg_num]->type) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	case CompatWPEG: | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * The Compatibility Winnipeg controls the 2 legacy buses, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		 * the 66MHz PCI bus [2 slots] and the 2 "extra" buses in case | 
					
						
							|  |  |  | 		 * a PCI-PCI bridge card is used in either slot: total 5 buses. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		num_buses = 5; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case AltWPEG: | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * The Alternate Winnipeg controls the 2 133MHz buses [1 slot | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		 * each], their 2 "extra" buses, the 100MHz bus [2 slots] and | 
					
						
							|  |  |  | 		 * the "extra" buses for each of those slots: total 7 buses. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		num_buses = 7; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case LookOutAWPEG: | 
					
						
							|  |  |  | 	case LookOutBWPEG: | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * A Lookout Winnipeg controls 3 100MHz buses [2 slots each] | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		 * & the "extra" buses for each of those slots: total 9 buses. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		num_buses = 9; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_info("Unsupported Winnipeg type!\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return last_bus; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	for (bus = last_bus; bus < last_bus + num_buses; bus++) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		mp_bus_id_to_node[bus] = node; | 
					
						
							|  |  |  | 	return bus; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | static int build_detail_arrays(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned long ptr; | 
					
						
							|  |  |  | 	int i, scal_detail_size, rio_detail_size; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_warn("MAX_NUMNODES too low!  Defined as %d, but system has %d nodes\n", | 
					
						
							|  |  |  | 			MAX_NUMNODES, rio_table_hdr->num_scal_dev); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	switch (rio_table_hdr->version) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_warn("Invalid Rio Grande Table Version: %d\n", | 
					
						
							|  |  |  | 			rio_table_hdr->version); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		scal_detail_size = 11; | 
					
						
							|  |  |  | 		rio_detail_size = 13; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 		scal_detail_size = 12; | 
					
						
							|  |  |  | 		rio_detail_size = 15; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ptr = (unsigned long)rio_table_hdr + 3; | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	for (i = 0; i < rio_table_hdr->num_scal_dev; i++, ptr += scal_detail_size) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		scal_devs[i] = (struct scal_detail *)ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	for (i = 0; i < rio_table_hdr->num_rio_dev; i++, ptr += rio_detail_size) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		rio_devs[i] = (struct rio_detail *)ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-02 11:34:28 +01:00
										 |  |  | void setup_summit(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned long		ptr; | 
					
						
							|  |  |  | 	unsigned short		offset; | 
					
						
							|  |  |  | 	int			i, next_wpeg, next_bus = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* The pointer to the EBDA is stored in the word @ phys 0x40E(40:0E) */ | 
					
						
							| 
									
										
										
										
											2008-04-19 23:55:20 +09:00
										 |  |  | 	ptr = get_bios_ebda(); | 
					
						
							|  |  |  | 	ptr = (unsigned long)phys_to_virt(ptr); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rio_table_hdr = NULL; | 
					
						
							|  |  |  | 	offset = 0x180; | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	while (offset) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		/* The block id is stored in the 2nd word */ | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 		if (*((unsigned short *)(ptr + offset + 2)) == 0x4752) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			/* set the pointer past the offset & block id */ | 
					
						
							|  |  |  | 			rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* The next offset is stored in the 1st word.  0 means no more */ | 
					
						
							|  |  |  | 		offset = *((unsigned short *)(ptr + offset)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 	if (!rio_table_hdr) { | 
					
						
							| 
									
										
										
										
											2012-05-21 19:50:07 -07:00
										 |  |  | 		pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!build_detail_arrays()) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* The first Winnipeg we're looking for has an index of 0 */ | 
					
						
							|  |  |  | 	next_wpeg = 0; | 
					
						
							|  |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2008-02-22 23:09:34 +01:00
										 |  |  | 		for (i = 0; i < rio_table_hdr->num_rio_dev; i++) { | 
					
						
							|  |  |  | 			if (is_WPEG(rio_devs[i]) && rio_devs[i]->WP_index == next_wpeg) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 				/* It's the Winnipeg we're looking for! */ | 
					
						
							|  |  |  | 				next_bus = setup_pci_node_map_for_wpeg(i, next_bus); | 
					
						
							|  |  |  | 				next_wpeg++; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * If we go through all Rio devices and don't find one with | 
					
						
							|  |  |  | 		 * the next index, it means we've found all the Winnipegs, | 
					
						
							|  |  |  | 		 * and thus all the PCI buses. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if (i == rio_table_hdr->num_rio_dev) | 
					
						
							|  |  |  | 			next_wpeg = 0; | 
					
						
							|  |  |  | 	} while (next_wpeg != 0); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-29 11:29:22 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-20 17:51:20 -07:00
										 |  |  | static struct apic apic_summit = { | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.name				= "summit", | 
					
						
							|  |  |  | 	.probe				= probe_summit, | 
					
						
							|  |  |  | 	.acpi_madt_oem_check		= summit_acpi_madt_oem_check, | 
					
						
							| 
									
										
										
										
											2012-03-14 15:17:34 +08:00
										 |  |  | 	.apic_id_valid			= default_apic_id_valid, | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 	.apic_id_registered		= summit_apic_id_registered, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.irq_delivery_mode		= dest_LowestPrio, | 
					
						
							|  |  |  | 	/* logical delivery broadcast to all CPUs: */ | 
					
						
							|  |  |  | 	.irq_dest_mode			= 1, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.target_cpus			= summit_target_cpus, | 
					
						
							|  |  |  | 	.disable_esr			= 1, | 
					
						
							|  |  |  | 	.dest_logical			= APIC_DEST_LOGICAL, | 
					
						
							|  |  |  | 	.check_apicid_used		= summit_check_apicid_used, | 
					
						
							|  |  |  | 	.check_apicid_present		= summit_check_apicid_present, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-07 15:14:49 +02:00
										 |  |  | 	.vector_allocation_domain	= flat_vector_allocation_domain, | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 	.init_apic_ldr			= summit_init_apic_ldr, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.ioapic_phys_id_map		= summit_ioapic_phys_id_map, | 
					
						
							|  |  |  | 	.setup_apic_routing		= summit_setup_apic_routing, | 
					
						
							|  |  |  | 	.multi_timer_check		= NULL, | 
					
						
							|  |  |  | 	.cpu_present_to_apicid		= summit_cpu_present_to_apicid, | 
					
						
							|  |  |  | 	.apicid_to_cpu_present		= summit_apicid_to_cpu_present, | 
					
						
							|  |  |  | 	.setup_portio_remap		= NULL, | 
					
						
							|  |  |  | 	.check_phys_apicid_present	= summit_check_phys_apicid_present, | 
					
						
							|  |  |  | 	.enable_apic_mode		= NULL, | 
					
						
							|  |  |  | 	.phys_pkg_id			= summit_phys_pkg_id, | 
					
						
							|  |  |  | 	.mps_oem_check			= summit_mps_oem_check, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.get_apic_id			= summit_get_apic_id, | 
					
						
							|  |  |  | 	.set_apic_id			= NULL, | 
					
						
							|  |  |  | 	.apic_id_mask			= 0xFF << 24, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.cpu_mask_to_apicid_and		= summit_cpu_mask_to_apicid_and, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.send_IPI_mask			= summit_send_IPI_mask, | 
					
						
							|  |  |  | 	.send_IPI_mask_allbutself	= NULL, | 
					
						
							|  |  |  | 	.send_IPI_allbutself		= summit_send_IPI_allbutself, | 
					
						
							|  |  |  | 	.send_IPI_all			= summit_send_IPI_all, | 
					
						
							| 
									
										
										
										
											2009-01-30 23:42:18 +01:00
										 |  |  | 	.send_IPI_self			= default_send_IPI_self, | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW, | 
					
						
							|  |  |  | 	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.wait_for_init_deassert		= default_wait_for_init_deassert, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.smp_callin_clear_local_apic	= NULL, | 
					
						
							|  |  |  | 	.inquire_remote_apic		= default_inquire_remote_apic, | 
					
						
							| 
									
										
										
										
											2009-02-16 23:02:14 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.read				= native_apic_mem_read, | 
					
						
							|  |  |  | 	.write				= native_apic_mem_write, | 
					
						
							| 
									
										
										
										
											2012-05-16 19:03:52 +03:00
										 |  |  | 	.eoi_write			= native_apic_mem_write, | 
					
						
							| 
									
										
										
										
											2009-02-16 23:02:14 -08:00
										 |  |  | 	.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, | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-23 14:37:36 +01:00
										 |  |  | 	.x86_32_early_logical_apicid	= summit_early_logical_apicid, | 
					
						
							| 
									
										
										
										
											2009-01-28 18:49:31 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2011-05-20 17:51:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | apic_driver(apic_summit); |