* Re: [PATCH] x86: introduce x86_ops
2008-07-19 9:07 [PATCH] x86: introduce x86_ops Yinghai Lu
@ 2008-07-19 9:16 ` Joerg Roedel
2008-07-19 9:19 ` Yinghai Lu
2008-07-20 1:01 ` [PATCH] x86: use x86_ops with numaq Yinghai Lu
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Joerg Roedel @ 2008-07-19 9:16 UTC (permalink / raw)
To: Yinghai Lu; +Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, linux-kernel
Hi Yinghai,
can you please write a short commit message explaining the benefit? Also
x86_ops sounds a bit too generic for some architecture specific
initialization function pointers imho.
Joerg
On Sat, Jul 19, 2008 at 02:07:25AM -0700, Yinghai Lu wrote:
>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>
> ---
> arch/x86/kernel/e820.c | 9 +-------
> arch/x86/kernel/mpparse.c | 17 ++++------------
> arch/x86/kernel/setup.c | 4 +++
> arch/x86/kernel/visws_quirks.c | 42 +++++++++++++++++++----------------------
> arch/x86/mach-default/setup.c | 24 +++++++----------------
> include/asm-x86/setup.h | 18 ++++++++++-------
> 6 files changed, 50 insertions(+), 64 deletions(-)
>
> Index: linux-2.6/arch/x86/kernel/e820.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/e820.c
> +++ linux-2.6/arch/x86/kernel/e820.c
> @@ -1299,11 +1299,6 @@ void __init e820_reserve_resources(void)
> }
> }
>
> -/*
> - * Non-standard memory setup can be specified via this quirk:
> - */
> -char * (*arch_memory_setup_quirk)(void);
> -
> char *__init default_machine_specific_memory_setup(void)
> {
> char *who = "BIOS-e820";
> @@ -1344,8 +1339,8 @@ char *__init default_machine_specific_me
>
> char *__init __attribute__((weak)) machine_specific_memory_setup(void)
> {
> - if (arch_memory_setup_quirk) {
> - char *who = arch_memory_setup_quirk();
> + if (x86_ops->arch_memory_setup) {
> + char *who = x86_ops->arch_memory_setup();
>
> if (who)
> return who;
> Index: linux-2.6/arch/x86/kernel/mpparse.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/mpparse.c
> +++ linux-2.6/arch/x86/kernel/mpparse.c
> @@ -27,6 +27,7 @@
> #include <asm/bios_ebda.h>
> #include <asm/e820.h>
> #include <asm/trampoline.h>
> +#include <asm/setup.h>
>
> #include <mach_apic.h>
> #ifdef CONFIG_X86_32
> @@ -728,20 +729,14 @@ static inline void __init construct_defa
> static struct intel_mp_floating *mpf_found;
>
> /*
> - * Machine specific quirk for finding the SMP config before other setup
> - * activities destroy the table:
> - */
> -int (*mach_get_smp_config_quirk)(unsigned int early);
> -
> -/*
> * Scan the memory blocks for an SMP configuration block.
> */
> static void __init __get_smp_config(unsigned int early)
> {
> struct intel_mp_floating *mpf = mpf_found;
>
> - if (mach_get_smp_config_quirk) {
> - if (mach_get_smp_config_quirk(early))
> + if (x86_ops->mach_get_smp_config) {
> + if (x86_ops->mach_get_smp_config(early))
> return;
> }
> if (acpi_lapic && early)
> @@ -901,14 +896,12 @@ static int __init smp_scan_config(unsign
> return 0;
> }
>
> -int (*mach_find_smp_config_quirk)(unsigned int reserve);
> -
> static void __init __find_smp_config(unsigned int reserve)
> {
> unsigned int address;
>
> - if (mach_find_smp_config_quirk) {
> - if (mach_find_smp_config_quirk(reserve))
> + if (x86_ops->mach_find_smp_config) {
> + if (x86_ops->mach_find_smp_config(reserve))
> return;
> }
> /*
> Index: linux-2.6/arch/x86/kernel/setup.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/setup.c
> +++ linux-2.6/arch/x86/kernel/setup.c
> @@ -574,6 +574,10 @@ static int __init setup_elfcorehdr(char
> early_param("elfcorehdr", setup_elfcorehdr);
> #endif
>
> +static struct x86_ops default_x86_ops __initdata;
> +
> +struct x86_ops *x86_ops __initdata = &default_x86_ops;
> +
> /*
> * Determine if we were loaded by an EFI loader. If so, then we have also been
> * passed the efi memmap, systab, etc., so we should use these data structures
> Index: linux-2.6/arch/x86/kernel/visws_quirks.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/visws_quirks.c
> +++ linux-2.6/arch/x86/kernel/visws_quirks.c
> @@ -73,7 +73,7 @@ int is_visws_box(void)
> return visws_board_type >= 0;
> }
>
> -static int __init visws_time_init_quirk(void)
> +static int __init visws_time_init(void)
> {
> printk(KERN_INFO "Starting Cobalt Timer system clock\n");
>
> @@ -93,7 +93,7 @@ static int __init visws_time_init_quirk(
> return 0;
> }
>
> -static int __init visws_pre_intr_init_quirk(void)
> +static int __init visws_pre_intr_init(void)
> {
> init_VISWS_APIC_irqs();
>
> @@ -114,7 +114,7 @@ EXPORT_SYMBOL(sgivwfb_mem_size);
>
> long long mem_size __initdata = 0;
>
> -static char * __init visws_memory_setup_quirk(void)
> +static char * __init visws_memory_setup(void)
> {
> long long gfx_mem_size = 8 * MB;
>
> @@ -176,7 +176,7 @@ static void visws_machine_power_off(void
> outl(PIIX_SPECIAL_STOP, 0xCFC);
> }
>
> -static int __init visws_get_smp_config_quirk(unsigned int early)
> +static int __init visws_get_smp_config(unsigned int early)
> {
> /*
> * Prevent MP-table parsing by the generic code:
> @@ -192,7 +192,7 @@ extern unsigned int __cpuinitdata maxcpu
> * No problem for Linux.
> */
>
> -static void __init MP_processor_info (struct mpc_config_processor *m)
> +static void __init MP_processor_info(struct mpc_config_processor *m)
> {
> int ver, logical_apicid;
> physid_mask_t apic_cpus;
> @@ -232,7 +232,7 @@ static void __init MP_processor_info (st
> apic_version[m->mpc_apicid] = ver;
> }
>
> -int __init visws_find_smp_config_quirk(unsigned int reserve)
> +static int __init visws_find_smp_config(unsigned int reserve)
> {
> struct mpc_config_processor *mp = phys_to_virt(CO_CPU_TAB_PHYS);
> unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
> @@ -258,7 +258,17 @@ int __init visws_find_smp_config_quirk(u
> return 1;
> }
>
> -extern int visws_trap_init_quirk(void);
> +static int visws_trap_init(void);
> +
> +static struct x86_ops visws_x86_ops __initdata = {
> + .arch_time_init = visws_time_init,
> + .arch_pre_intr_init = visws_pre_intr_init,
> + .arch_memory_setup = visws_memory_setup,
> + .arch_intr_init = NULL,
> + .arch_trap_init = visws_trap_init,
> + .mach_get_smp_config = visws_get_smp_config,
> + .mach_find_smp_config = visws_find_smp_config,
> +};
>
> void __init visws_early_detect(void)
> {
> @@ -272,16 +282,10 @@ void __init visws_early_detect(void)
>
> /*
> * Install special quirks for timer, interrupt and memory setup:
> - */
> - arch_time_init_quirk = visws_time_init_quirk;
> - arch_pre_intr_init_quirk = visws_pre_intr_init_quirk;
> - arch_memory_setup_quirk = visws_memory_setup_quirk;
> -
> - /*
> * Fall back to generic behavior for traps:
> + * Override generic MP-table parsing:
> */
> - arch_intr_init_quirk = NULL;
> - arch_trap_init_quirk = visws_trap_init_quirk;
> + x86_ops = &visws_x86_ops;
>
> /*
> * Install reboot quirks:
> @@ -294,12 +298,6 @@ void __init visws_early_detect(void)
> */
> no_broadcast = 0;
>
> - /*
> - * Override generic MP-table parsing:
> - */
> - mach_get_smp_config_quirk = visws_get_smp_config_quirk;
> - mach_find_smp_config_quirk = visws_find_smp_config_quirk;
> -
> #ifdef CONFIG_X86_IO_APIC
> /*
> * Turn off IO-APIC detection and initialization:
> @@ -426,7 +424,7 @@ static __init void cobalt_init(void)
> co_apic_read(CO_APIC_ID));
> }
>
> -int __init visws_trap_init_quirk(void)
> +static int __init visws_trap_init(void)
> {
> lithium_init();
> cobalt_init();
> Index: linux-2.6/arch/x86/mach-default/setup.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/mach-default/setup.c
> +++ linux-2.6/arch/x86/mach-default/setup.c
> @@ -10,14 +10,6 @@
> #include <asm/e820.h>
> #include <asm/setup.h>
>
> -/*
> - * Any quirks to be performed to initialize timers/irqs/etc?
> - */
> -int (*arch_time_init_quirk)(void);
> -int (*arch_pre_intr_init_quirk)(void);
> -int (*arch_intr_init_quirk)(void);
> -int (*arch_trap_init_quirk)(void);
> -
> #ifdef CONFIG_HOTPLUG_CPU
> #define DEFAULT_SEND_IPI (1)
> #else
> @@ -37,8 +29,8 @@ int no_broadcast=DEFAULT_SEND_IPI;
> **/
> void __init pre_intr_init_hook(void)
> {
> - if (arch_pre_intr_init_quirk) {
> - if (arch_pre_intr_init_quirk())
> + if (x86_ops->arch_pre_intr_init) {
> + if (x86_ops->arch_pre_intr_init())
> return;
> }
> init_ISA_irqs();
> @@ -64,8 +56,8 @@ static struct irqaction irq2 = {
> **/
> void __init intr_init_hook(void)
> {
> - if (arch_intr_init_quirk) {
> - if (arch_intr_init_quirk())
> + if (x86_ops->arch_intr_init) {
> + if (x86_ops->arch_intr_init())
> return;
> }
> #ifdef CONFIG_X86_LOCAL_APIC
> @@ -97,8 +89,8 @@ void __init pre_setup_arch_hook(void)
> **/
> void __init trap_init_hook(void)
> {
> - if (arch_trap_init_quirk) {
> - if (arch_trap_init_quirk())
> + if (x86_ops->arch_trap_init) {
> + if (x86_ops->arch_trap_init())
> return;
> }
> }
> @@ -119,13 +111,13 @@ static struct irqaction irq0 = {
> **/
> void __init time_init_hook(void)
> {
> - if (arch_time_init_quirk) {
> + if (x86_ops->arch_time_init) {
> /*
> * A nonzero return code does not mean failure, it means
> * that the architecture quirk does not want any
> * generic (timer) setup to be performed after this:
> */
> - if (arch_time_init_quirk())
> + if (x86_ops->arch_time_init())
> return;
> }
>
> Index: linux-2.6/include/asm-x86/setup.h
> ===================================================================
> --- linux-2.6.orig/include/asm-x86/setup.h
> +++ linux-2.6/include/asm-x86/setup.h
> @@ -19,13 +19,17 @@ static inline int is_visws_box(void) { r
> /*
> * Any setup quirks to be performed?
> */
> -extern int (*arch_time_init_quirk)(void);
> -extern int (*arch_pre_intr_init_quirk)(void);
> -extern int (*arch_intr_init_quirk)(void);
> -extern int (*arch_trap_init_quirk)(void);
> -extern char * (*arch_memory_setup_quirk)(void);
> -extern int (*mach_get_smp_config_quirk)(unsigned int early);
> -extern int (*mach_find_smp_config_quirk)(unsigned int reserve);
> +struct x86_ops {
> + int (*arch_time_init)(void);
> + int (*arch_pre_intr_init)(void);
> + int (*arch_intr_init)(void);
> + int (*arch_trap_init)(void);
> + char * (*arch_memory_setup)(void);
> + int (*mach_get_smp_config)(unsigned int early);
> + int (*mach_find_smp_config)(unsigned int reserve);
> +};
> +
> +extern struct x86_ops *x86_ops;
>
> #ifndef CONFIG_PARAVIRT
> #define paravirt_post_allocator_init() do {} while (0)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH] x86: use x86_ops with numaq
2008-07-19 9:07 [PATCH] x86: introduce x86_ops Yinghai Lu
2008-07-19 9:16 ` Joerg Roedel
@ 2008-07-20 1:01 ` Yinghai Lu
2008-07-20 7:28 ` Ingo Molnar
2008-07-20 1:02 ` [PATCH] x86: add pre_time_init in x86_ops Yinghai Lu
2008-07-20 7:21 ` [PATCH] x86: introduce x86_ops Ingo Molnar
3 siblings, 1 reply; 9+ messages in thread
From: Yinghai Lu @ 2008-07-20 1:01 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel
move numaq related mps table handling to numaq_32.c
also moving calling to smp_read_mpc_oem() to smp_read_mpc directly
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
arch/x86/kernel/mpparse.c | 191 +++--------------------------
arch/x86/kernel/numaq_32.c | 190 +++++++++++++++++++++++++++-
include/asm-x86/mach-generic/mach_mpspec.h | 2
include/asm-x86/setup.h | 10 +
4 files changed, 212 insertions(+), 181 deletions(-)
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -49,76 +49,6 @@ static int __init mpf_checksum(unsigned
return sum & 0xFF;
}
-#ifdef CONFIG_X86_NUMAQ
-int found_numaq;
-/*
- * Have to match translation table entries to main table entries by counter
- * hence the mpc_record variable .... can't see a less disgusting way of
- * doing this ....
- */
-struct mpc_config_translation {
- unsigned char mpc_type;
- unsigned char trans_len;
- unsigned char trans_type;
- unsigned char trans_quad;
- unsigned char trans_global;
- unsigned char trans_local;
- unsigned short trans_reserved;
-};
-
-
-static int mpc_record;
-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
- __cpuinitdata;
-
-static inline int generate_logical_apicid(int quad, int phys_apicid)
-{
- return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
-}
-
-
-static inline int mpc_apic_id(struct mpc_config_processor *m,
- struct mpc_config_translation *translation_record)
-{
- int quad = translation_record->trans_quad;
- int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
-
- printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
- m->mpc_apicid,
- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
- m->mpc_apicver, quad, logical_apicid);
- return logical_apicid;
-}
-
-int mp_bus_id_to_node[MAX_MP_BUSSES];
-
-int mp_bus_id_to_local[MAX_MP_BUSSES];
-
-static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
- struct mpc_config_translation *translation)
-{
- int quad = translation->trans_quad;
- int local = translation->trans_local;
-
- mp_bus_id_to_node[m->mpc_busid] = quad;
- mp_bus_id_to_local[m->mpc_busid] = local;
- printk(KERN_INFO "Bus #%d is %s (node %d)\n",
- m->mpc_busid, name, quad);
-}
-
-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
-static void mpc_oem_pci_bus(struct mpc_config_bus *m,
- struct mpc_config_translation *translation)
-{
- int quad = translation->trans_quad;
- int local = translation->trans_local;
-
- quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
-}
-
-#endif
-
static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
{
int apicid;
@@ -128,14 +58,12 @@ static void __cpuinit MP_processor_info(
disabled_cpus++;
return;
}
-#ifdef CONFIG_X86_NUMAQ
- if (found_numaq)
- apicid = mpc_apic_id(m, translation_table[mpc_record]);
+
+ if (x86_ops->mpc_apic_id)
+ apicid = x86_ops->mpc_apic_id(m);
else
apicid = m->mpc_apicid;
-#else
- apicid = m->mpc_apicid;
-#endif
+
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
bootup_cpu = " (Bootup-CPU)";
boot_cpu_physical_apicid = m->mpc_apicid;
@@ -152,12 +80,10 @@ static void __init MP_bus_info(struct mp
memcpy(str, m->mpc_bustype, 6);
str[6] = 0;
-#ifdef CONFIG_X86_NUMAQ
- if (found_numaq)
- mpc_oem_bus_info(m, str, translation_table[mpc_record]);
-#else
- printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
-#endif
+ if (x86_ops->mpc_oem_bus_info)
+ x86_ops->mpc_oem_bus_info(m, str);
+ else
+ printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
#if MAX_MP_BUSSES < 256
if (m->mpc_busid >= MAX_MP_BUSSES) {
@@ -174,10 +100,9 @@ static void __init MP_bus_info(struct mp
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
#endif
} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
-#ifdef CONFIG_X86_NUMAQ
- if (found_numaq)
- mpc_oem_pci_bus(m, translation_table[mpc_record]);
-#endif
+ if (x86_ops->mpc_oem_pci_bus)
+ x86_ops->mpc_oem_pci_bus(m);
+
clear_bit(m->mpc_busid, mp_bus_not_pci);
#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
@@ -317,83 +242,6 @@ static void __init MP_lintsrc_info(struc
m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
}
-#ifdef CONFIG_X86_NUMAQ
-static void __init MP_translation_info(struct mpc_config_translation *m)
-{
- printk(KERN_INFO
- "Translation: record %d, type %d, quad %d, global %d, local %d\n",
- mpc_record, m->trans_type, m->trans_quad, m->trans_global,
- m->trans_local);
-
- if (mpc_record >= MAX_MPC_ENTRY)
- printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
- else
- translation_table[mpc_record] = m; /* stash this for later */
- if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
- node_set_online(m->trans_quad);
-}
-
-/*
- * Read/parse the MPC oem tables
- */
-
-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
- unsigned short oemsize)
-{
- int count = sizeof(*oemtable); /* the header size */
- unsigned char *oemptr = ((unsigned char *)oemtable) + count;
-
- mpc_record = 0;
- printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
- oemtable);
- if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
- printk(KERN_WARNING
- "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
- oemtable->oem_signature[0], oemtable->oem_signature[1],
- oemtable->oem_signature[2], oemtable->oem_signature[3]);
- return;
- }
- if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
- printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
- return;
- }
- while (count < oemtable->oem_length) {
- switch (*oemptr) {
- case MP_TRANSLATION:
- {
- struct mpc_config_translation *m =
- (struct mpc_config_translation *)oemptr;
- MP_translation_info(m);
- oemptr += sizeof(*m);
- count += sizeof(*m);
- ++mpc_record;
- break;
- }
- default:
- {
- printk(KERN_WARNING
- "Unrecognised OEM table entry type! - %d\n",
- (int)*oemptr);
- return;
- }
- }
- }
-}
-
-void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
-{
- if (strncmp(oem, "IBM NUMA", 8))
- printk("Warning! Not a NUMA-Q system!\n");
- else
- found_numaq = 1;
-
- if (mpc->mpc_oemptr)
- smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
- mpc->mpc_oemsize);
-}
-#endif /* CONFIG_X86_NUMAQ */
-
/*
* Read/parse the MPC
*/
@@ -458,7 +306,6 @@ static int __init smp_read_mpc(struct mp
} else
mps_oem_check(mpc, oem, str);
#endif
-
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -466,12 +313,17 @@ static int __init smp_read_mpc(struct mp
if (early)
return 1;
+ if (mpc->mpc_oemptr && x86_ops->smp_read_mpc_oem) {
+ struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
+ x86_ops->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
+ }
+
/*
* Now process the configuration blocks.
*/
-#ifdef CONFIG_X86_NUMAQ
- mpc_record = 0;
-#endif
+ if (x86_ops->mpc_record)
+ *x86_ops->mpc_record = 0;
+
while (count < mpc->mpc_length) {
switch (*mpt) {
case MP_PROCESSOR:
@@ -537,9 +389,8 @@ static int __init smp_read_mpc(struct mp
count = mpc->mpc_length;
break;
}
-#ifdef CONFIG_X86_NUMAQ
- ++mpc_record;
-#endif
+ if (x86_ops->mpc_record)
+ (*x86_ops->mpc_record)++;
}
#ifdef CONFIG_X86_GENERICARCH
Index: linux-2.6/arch/x86/kernel/numaq_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/numaq_32.c
+++ linux-2.6/arch/x86/kernel/numaq_32.c
@@ -33,6 +33,7 @@
#include <asm/processor.h>
#include <asm/mpspec.h>
#include <asm/e820.h>
+#include <asm/setup.h>
#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
@@ -71,6 +72,181 @@ static void __init smp_dump_qct(void)
}
}
+
+void __init numaq_tsc_disable(void)
+{
+ if (!found_numaq)
+ return;
+
+ if (num_online_nodes() > 1) {
+ printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
+ setup_clear_cpu_cap(X86_FEATURE_TSC);
+ }
+}
+
+int found_numaq;
+/*
+ * Have to match translation table entries to main table entries by counter
+ * hence the mpc_record variable .... can't see a less disgusting way of
+ * doing this ....
+ */
+struct mpc_config_translation {
+ unsigned char mpc_type;
+ unsigned char trans_len;
+ unsigned char trans_type;
+ unsigned char trans_quad;
+ unsigned char trans_global;
+ unsigned char trans_local;
+ unsigned short trans_reserved;
+};
+
+/* x86_ops member */
+static int mpc_record;
+static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
+ __cpuinitdata;
+
+static inline int generate_logical_apicid(int quad, int phys_apicid)
+{
+ return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
+}
+
+/* x86_ops member */
+static int mpc_apic_id(struct mpc_config_processor *m)
+{
+ int quad = translation_table[mpc_record]->trans_quad;
+ int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
+
+ printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
+ m->mpc_apicid,
+ (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+ (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+ m->mpc_apicver, quad, logical_apicid);
+ return logical_apicid;
+}
+
+int mp_bus_id_to_node[MAX_MP_BUSSES];
+
+int mp_bus_id_to_local[MAX_MP_BUSSES];
+
+/* x86_ops member */
+static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name)
+{
+ int quad = translation_table[mpc_record]->trans_quad;
+ int local = translation_table[mpc_record]->trans_local;
+
+ mp_bus_id_to_node[m->mpc_busid] = quad;
+ mp_bus_id_to_local[m->mpc_busid] = local;
+ printk(KERN_INFO "Bus #%d is %s (node %d)\n",
+ m->mpc_busid, name, quad);
+}
+
+int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+
+/* x86_ops member */
+static void mpc_oem_pci_bus(struct mpc_config_bus *m)
+{
+ int quad = translation_table[mpc_record]->trans_quad;
+ int local = translation_table[mpc_record]->trans_local;
+
+ quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
+}
+
+static void __init MP_translation_info(struct mpc_config_translation *m)
+{
+ printk(KERN_INFO
+ "Translation: record %d, type %d, quad %d, global %d, local %d\n",
+ mpc_record, m->trans_type, m->trans_quad, m->trans_global,
+ m->trans_local);
+
+ if (mpc_record >= MAX_MPC_ENTRY)
+ printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+ else
+ translation_table[mpc_record] = m; /* stash this for later */
+ if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+ node_set_online(m->trans_quad);
+}
+
+static int __init mpf_checksum(unsigned char *mp, int len)
+{
+ int sum = 0;
+
+ while (len--)
+ sum += *mp++;
+
+ return sum & 0xFF;
+}
+
+/*
+ * Read/parse the MPC oem tables
+ */
+
+static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
+ unsigned short oemsize)
+{
+ int count = sizeof(*oemtable); /* the header size */
+ unsigned char *oemptr = ((unsigned char *)oemtable) + count;
+
+ mpc_record = 0;
+ printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
+ oemtable);
+ if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
+ printk(KERN_WARNING
+ "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+ oemtable->oem_signature[0], oemtable->oem_signature[1],
+ oemtable->oem_signature[2], oemtable->oem_signature[3]);
+ return;
+ }
+ if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
+ printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+ return;
+ }
+ while (count < oemtable->oem_length) {
+ switch (*oemptr) {
+ case MP_TRANSLATION:
+ {
+ struct mpc_config_translation *m =
+ (struct mpc_config_translation *)oemptr;
+ MP_translation_info(m);
+ oemptr += sizeof(*m);
+ count += sizeof(*m);
+ ++mpc_record;
+ break;
+ }
+ default:
+ {
+ printk(KERN_WARNING
+ "Unrecognised OEM table entry type! - %d\n",
+ (int)*oemptr);
+ return;
+ }
+ }
+ }
+}
+
+static struct x86_ops numaq_x86_ops __initdata = {
+ .arch_time_init = NULL,
+ .arch_pre_intr_init = NULL,
+ .arch_memory_setup = NULL,
+ .arch_intr_init = NULL,
+ .arch_trap_init = NULL,
+ .mach_get_smp_config = NULL,
+ .mach_find_smp_config = NULL,
+ .mpc_record = &mpc_record,
+ .mpc_apic_id = mpc_apic_id,
+ .mpc_oem_bus_info = mpc_oem_bus_info,
+ .mpc_oem_pci_bus = mpc_oem_pci_bus,
+ .smp_read_mpc_oem = smp_read_mpc_oem,
+};
+
+void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+{
+ if (strncmp(oem, "IBM NUMA", 8))
+ printk("Warning! Not a NUMA-Q system!\n");
+ else
+ found_numaq = 1;
+}
+
static __init void early_check_numaq(void)
{
/*
@@ -82,6 +258,9 @@ static __init void early_check_numaq(voi
*/
if (smp_found_config)
early_get_smp_config();
+
+ if (found_numaq)
+ x86_ops = &numaq_x86_ops;
}
int __init get_memcfg_numaq(void)
@@ -92,14 +271,3 @@ int __init get_memcfg_numaq(void)
smp_dump_qct();
return 1;
}
-
-void __init numaq_tsc_disable(void)
-{
- if (!found_numaq)
- return;
-
- if (num_online_nodes() > 1) {
- printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
- setup_clear_cpu_cap(X86_FEATURE_TSC);
- }
-}
Index: linux-2.6/include/asm-x86/mach-generic/mach_mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mach-generic/mach_mpspec.h
+++ linux-2.6/include/asm-x86/mach-generic/mach_mpspec.h
@@ -7,4 +7,6 @@
/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
#define MAX_MP_BUSSES 260
+extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid);
#endif /* __ASM_MACH_MPSPEC_H */
Index: linux-2.6/include/asm-x86/setup.h
===================================================================
--- linux-2.6.orig/include/asm-x86/setup.h
+++ linux-2.6/include/asm-x86/setup.h
@@ -19,6 +19,9 @@ static inline int is_visws_box(void) { r
/*
* Any setup quirks to be performed?
*/
+struct mpc_config_processor;
+struct mpc_config_bus;
+struct mp_config_oemtable;
struct x86_ops {
int (*arch_time_init)(void);
int (*arch_pre_intr_init)(void);
@@ -27,6 +30,13 @@ struct x86_ops {
char * (*arch_memory_setup)(void);
int (*mach_get_smp_config)(unsigned int early);
int (*mach_find_smp_config)(unsigned int reserve);
+
+ int *mpc_record;
+ int (*mpc_apic_id)(struct mpc_config_processor *m);
+ void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name);
+ void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
+ void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
+ unsigned short oemsize);
};
extern struct x86_ops *x86_ops;
^ permalink raw reply [flat|nested] 9+ messages in thread