2008-02-19 23:57:17 +01:00
/*
* Copyright 2003 Andi Kleen , SuSE Labs .
* Subject to the GNU Public License , v .2
*
2005-04-16 15:20:36 -07:00
* Generic x86 APIC driver probe layer .
2008-02-19 23:57:17 +01:00
*/
2005-04-16 15:20:36 -07:00
# include <linux/threads.h>
# include <linux/cpumask.h>
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/ctype.h>
# include <linux/init.h>
2006-09-26 10:52:32 +02:00
# include <linux/errno.h>
2005-04-16 15:20:36 -07:00
# include <asm/fixmap.h>
# include <asm/mpspec.h>
# include <asm/apicdef.h>
# include <asm/genapic.h>
2008-06-08 18:31:54 -07:00
extern struct genapic apic_numaq ;
2005-04-16 15:20:36 -07:00
extern struct genapic apic_summit ;
extern struct genapic apic_bigsmp ;
extern struct genapic apic_es7000 ;
extern struct genapic apic_default ;
struct genapic * genapic = & apic_default ;
2007-10-17 18:04:36 +02:00
static struct genapic * apic_probe [ ] __initdata = {
2008-06-08 18:31:54 -07:00
# ifdef CONFIG_X86_NUMAQ
& apic_numaq ,
# endif
# ifdef CONFIG_X86_SUMMIT
2005-04-16 15:20:36 -07:00
& apic_summit ,
2008-06-08 18:31:54 -07:00
# endif
# ifdef CONFIG_X86_BIGSMP
2008-02-19 23:57:17 +01:00
& apic_bigsmp ,
2008-06-08 18:31:54 -07:00
# endif
# ifdef CONFIG_X86_ES7000
2005-04-16 15:20:36 -07:00
& apic_es7000 ,
2008-06-08 18:31:54 -07:00
# endif
2005-04-16 15:20:36 -07:00
& apic_default , /* must be last */
NULL ,
} ;
2006-09-26 10:52:32 +02:00
static int cmdline_apic __initdata ;
static int __init parse_apic ( char * arg )
{
int i ;
if ( ! arg )
return - EINVAL ;
for ( i = 0 ; apic_probe [ i ] ; i + + ) {
if ( ! strcmp ( apic_probe [ i ] - > name , arg ) ) {
genapic = apic_probe [ i ] ;
cmdline_apic = 1 ;
return 0 ;
}
}
2006-12-07 02:14:11 +01:00
/* Parsed again by __setup for debug/verbose */
return 0 ;
2006-09-26 10:52:32 +02:00
}
early_param ( " apic " , parse_apic ) ;
2005-09-03 15:56:31 -07:00
void __init generic_bigsmp_probe ( void )
{
2008-06-09 17:00:15 -07:00
# ifdef CONFIG_X86_BIGSMP
2005-09-03 15:56:31 -07:00
/*
* This routine is used to switch to bigsmp mode when
* - There is no apic = option specified by the user
2007-10-20 01:13:56 +02:00
* - generic_apic_probe ( ) has chosen apic_default as the sub_arch
2005-09-03 15:56:31 -07:00
* - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
*/
if ( ! cmdline_apic & & genapic = = & apic_default )
if ( apic_bigsmp . probe ( ) ) {
genapic = & apic_bigsmp ;
printk ( KERN_INFO " Overriding APIC driver with %s \n " ,
genapic - > name ) ;
}
2008-06-08 18:31:54 -07:00
# endif
2005-09-03 15:56:31 -07:00
}
2006-09-26 10:52:32 +02:00
void __init generic_apic_probe ( void )
2008-02-19 23:57:17 +01:00
{
2006-09-26 10:52:32 +02:00
if ( ! cmdline_apic ) {
int i ;
for ( i = 0 ; apic_probe [ i ] ; i + + ) {
if ( apic_probe [ i ] - > probe ( ) ) {
2005-04-16 15:20:36 -07:00
genapic = apic_probe [ i ] ;
2006-09-26 10:52:32 +02:00
break ;
2005-04-16 15:20:36 -07:00
}
}
2006-09-26 10:52:32 +02:00
/* Not visible without early console */
if ( ! apic_probe [ i ] )
panic ( " Didn't find an APIC driver " ) ;
2005-04-16 15:20:36 -07:00
}
printk ( KERN_INFO " Using APIC driver %s \n " , genapic - > name ) ;
2008-02-19 23:57:17 +01:00
}
2005-04-16 15:20:36 -07:00
/* These functions can switch the APIC even after the initial ->probe() */
2008-06-08 18:31:54 -07:00
int __init mps_oem_check ( struct mp_config_table * mpc , char * oem ,
char * productid )
2008-02-19 23:57:17 +01:00
{
2005-04-16 15:20:36 -07:00
int i ;
2008-02-19 23:57:17 +01:00
for ( i = 0 ; apic_probe [ i ] ; + + i ) {
if ( apic_probe [ i ] - > mps_oem_check ( mpc , oem , productid ) ) {
2006-05-30 22:47:51 +02:00
if ( ! cmdline_apic ) {
genapic = apic_probe [ i ] ;
printk ( KERN_INFO " Switched to APIC driver `%s'. \n " ,
genapic - > name ) ;
}
2005-04-16 15:20:36 -07:00
return 1 ;
2008-02-19 23:57:17 +01:00
}
}
2005-04-16 15:20:36 -07:00
return 0 ;
2008-02-19 23:57:17 +01:00
}
2005-04-16 15:20:36 -07:00
int __init acpi_madt_oem_check ( char * oem_id , char * oem_table_id )
{
int i ;
2008-02-19 23:57:17 +01:00
for ( i = 0 ; apic_probe [ i ] ; + + i ) {
if ( apic_probe [ i ] - > acpi_madt_oem_check ( oem_id , oem_table_id ) ) {
2006-05-30 22:47:51 +02:00
if ( ! cmdline_apic ) {
genapic = apic_probe [ i ] ;
printk ( KERN_INFO " Switched to APIC driver `%s'. \n " ,
genapic - > name ) ;
}
2005-04-16 15:20:36 -07:00
return 1 ;
2008-02-19 23:57:17 +01:00
}
}
return 0 ;
2005-04-16 15:20:36 -07:00
}
int hard_smp_processor_id ( void )
{
return genapic - > get_apic_id ( * ( unsigned long * ) ( APIC_BASE + APIC_ID ) ) ;
}