linux/arch/x86/mach-generic/probe.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003 Andi Kleen, SuSE Labs.
   3 * Subject to the GNU Public License, v.2
   4 *
   5 * Generic x86 APIC driver probe layer.
   6 */
   7#include <linux/threads.h>
   8#include <linux/cpumask.h>
   9#include <linux/string.h>
  10#include <linux/kernel.h>
  11#include <linux/ctype.h>
  12#include <linux/init.h>
  13#include <linux/errno.h>
  14#include <asm/fixmap.h>
  15#include <asm/mpspec.h>
  16#include <asm/apicdef.h>
  17#include <asm/genapic.h>
  18
  19extern struct genapic apic_numaq;
  20extern struct genapic apic_summit;
  21extern struct genapic apic_bigsmp;
  22extern struct genapic apic_es7000;
  23extern struct genapic apic_default;
  24
  25struct genapic *genapic = &apic_default;
  26
  27static struct genapic *apic_probe[] __initdata = {
  28#ifdef CONFIG_X86_NUMAQ
  29        &apic_numaq,
  30#endif
  31#ifdef CONFIG_X86_SUMMIT
  32        &apic_summit,
  33#endif
  34#ifdef CONFIG_X86_BIGSMP
  35        &apic_bigsmp,
  36#endif
  37#ifdef CONFIG_X86_ES7000
  38        &apic_es7000,
  39#endif
  40        &apic_default,  /* must be last */
  41        NULL,
  42};
  43
  44static int cmdline_apic __initdata;
  45static int __init parse_apic(char *arg)
  46{
  47        int i;
  48
  49        if (!arg)
  50                return -EINVAL;
  51
  52        for (i = 0; apic_probe[i]; i++) {
  53                if (!strcmp(apic_probe[i]->name, arg)) {
  54                        genapic = apic_probe[i];
  55                        cmdline_apic = 1;
  56                        return 0;
  57                }
  58        }
  59
  60        /* Parsed again by __setup for debug/verbose */
  61        return 0;
  62}
  63early_param("apic", parse_apic);
  64
  65void __init generic_bigsmp_probe(void)
  66{
  67#ifdef CONFIG_X86_BIGSMP
  68        /*
  69         * This routine is used to switch to bigsmp mode when
  70         * - There is no apic= option specified by the user
  71         * - generic_apic_probe() has chosen apic_default as the sub_arch
  72         * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
  73         */
  74
  75        if (!cmdline_apic && genapic == &apic_default)
  76                if (apic_bigsmp.probe()) {
  77                        genapic = &apic_bigsmp;
  78                        printk(KERN_INFO "Overriding APIC driver with %s\n",
  79                               genapic->name);
  80                }
  81#endif
  82}
  83
  84void __init generic_apic_probe(void)
  85{
  86        if (!cmdline_apic) {
  87                int i;
  88                for (i = 0; apic_probe[i]; i++) {
  89                        if (apic_probe[i]->probe()) {
  90                                genapic = apic_probe[i];
  91                                break;
  92                        }
  93                }
  94                /* Not visible without early console */
  95                if (!apic_probe[i])
  96                        panic("Didn't find an APIC driver");
  97        }
  98        printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
  99}
 100
 101/* These functions can switch the APIC even after the initial ->probe() */
 102
 103int __init mps_oem_check(struct mp_config_table *mpc, char *oem,
 104                                 char *productid)
 105{
 106        int i;
 107        for (i = 0; apic_probe[i]; ++i) {
 108                if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
 109                        if (!cmdline_apic) {
 110                                genapic = apic_probe[i];
 111                                printk(KERN_INFO "Switched to APIC driver `%s'.\n",
 112                                       genapic->name);
 113                        }
 114                        return 1;
 115                }
 116        }
 117        return 0;
 118}
 119
 120int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 121{
 122        int i;
 123        for (i = 0; apic_probe[i]; ++i) {
 124                if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
 125                        if (!cmdline_apic) {
 126                                genapic = apic_probe[i];
 127                                printk(KERN_INFO "Switched to APIC driver `%s'.\n",
 128                                       genapic->name);
 129                        }
 130                        return 1;
 131                }
 132        }
 133        return 0;
 134}
 135
 136int hard_smp_processor_id(void)
 137{
 138        return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
 139}
 140