From e7891c733f9b26c851edde50cf886a30bd133dbd Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 22 May 2008 14:35:21 -0700 Subject: PCI/x86: write_pci_config_byte fix offset also add write_pci_config_16 Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- include/asm-x86/pci-direct.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/asm-x86') diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h index 5b21485be57..7bd40b4de75 100644 --- a/include/asm-x86/pci-direct.h +++ b/include/asm-x86/pci-direct.h @@ -11,6 +11,7 @@ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset); extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset); extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val); extern void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val); +extern void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val); extern int early_pci_allowed(void); -- cgit v1.2.3 From e3f2baebf4209b5927e23fa65d5977d31db936b3 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 22 May 2008 14:35:11 -0700 Subject: PCI/x86: early dump pci conf space v2 Allows us to dump PCI space before any kernel changes have been made. Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- arch/x86/kernel/setup_64.c | 5 +++++ arch/x86/pci/common.c | 4 ++++ arch/x86/pci/early.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ include/asm-x86/pci-direct.h | 3 +++ 4 files changed, 63 insertions(+) (limited to 'include/asm-x86') diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 6dff1286ad8..524b6850b2c 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -361,6 +361,11 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); +#ifdef CONFIG_PCI + if (pci_early_dump_regs) + early_dump_pci_devices(); +#endif + #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT if (init_ohci1394_dma_early) init_ohci1394_dma_on_all_controllers(); diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 3a5261bdff5..d19fd07bafd 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -20,6 +20,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; +unsigned int pci_early_dump_regs; static int pci_bf_sort; int pci_routeirq; int pcibios_last_bus = -1; @@ -511,6 +512,9 @@ char * __devinit pcibios_setup(char *str) } else if (!strcmp(str, "use_crs")) { pci_probe |= PCI_USE__CRS; return NULL; + } else if (!strcmp(str, "earlydump")) { + pci_early_dump_regs = 1; + return NULL; } else if (!strcmp(str, "routeirq")) { pci_routeirq = 1; return NULL; diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c index 8e2821e8dac..858dbe3399f 100644 --- a/arch/x86/pci/early.c +++ b/arch/x86/pci/early.c @@ -64,3 +64,54 @@ int early_pci_allowed(void) return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) == PCI_PROBE_CONF1; } + +void early_dump_pci_device(u8 bus, u8 slot, u8 func) +{ + int i; + int j; + u32 val; + + printk("PCI: %02x:%02x:%02x", bus, slot, func); + + for (i = 0; i < 256; i += 4) { + if (!(i & 0x0f)) + printk("\n%04x:",i); + + val = read_pci_config(bus, slot, func, i); + for (j = 0; j < 4; j++) { + printk(" %02x", val & 0xff); + val >>= 8; + } + } + printk("\n"); +} + +void early_dump_pci_devices(void) +{ + unsigned bus, slot, func; + + if (!early_pci_allowed()) + return; + + for (bus = 0; bus < 256; bus++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u8 type; + class = read_pci_config(bus, slot, func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + early_dump_pci_device(bus, slot, func); + + /* No multi-function device? */ + type = read_pci_config_byte(bus, slot, func, + PCI_HEADER_TYPE); + if (!(type & 0x80)) + break; + } + } + } +} + diff --git a/include/asm-x86/pci-direct.h b/include/asm-x86/pci-direct.h index 7bd40b4de75..80c775d9fe2 100644 --- a/include/asm-x86/pci-direct.h +++ b/include/asm-x86/pci-direct.h @@ -15,4 +15,7 @@ extern void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val); extern int early_pci_allowed(void); +extern unsigned int pci_early_dump_regs; +extern void early_dump_pci_device(u8 bus, u8 slot, u8 func); +extern void early_dump_pci_devices(void); #endif -- cgit v1.2.3 From c1e3b377ad48febba6f91b8ae42c44ee4d4ab45e Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 24 Jun 2008 17:58:53 +0800 Subject: ACPI: Create "idle=halt" bootparam "idle=halt" limits the idle loop to using the halt instruction. No MWAIT, no IO accesses, no C-states deeper than C1. If something is broken in the idle code, "idle=halt" is a less severe workaround than "idle=poll" which disables all power savings. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown Signed-off-by: Andi Kleen --- Documentation/kernel-parameters.txt | 4 +++- arch/ia64/kernel/process.c | 2 ++ arch/x86/kernel/process.c | 17 ++++++++++++++++- drivers/acpi/processor_idle.c | 22 ++++++++++++++++++++++ include/asm-ia64/processor.h | 1 + include/asm-x86/processor.h | 1 + 6 files changed, 45 insertions(+), 2 deletions(-) (limited to 'include/asm-x86') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 312fe77764a..65db7f4711a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -818,7 +818,7 @@ and is between 256 and 4096 characters. It is defined in the file See Documentation/ide/ide.txt. idle= [X86] - Format: idle=poll or idle=mwait + Format: idle=poll or idle=mwait, idle=halt Poll forces a polling idle loop that can slightly improves the performance of waking up a idle CPU, but will use a lot of power and make the system run hot. Not recommended. @@ -826,6 +826,8 @@ and is between 256 and 4096 characters. It is defined in the file to not use it because it doesn't save as much power as a normal idle loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same as idle=poll. + idle=halt. Halt is forced to be used for CPU idle. + In such case C2/C3 won't be used again. ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem Claim all unknown PCI IDE storage controllers. diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index fabaf08d9a6..612b3c4a060 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -55,6 +55,8 @@ void (*ia64_mark_idle)(int); unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); +unsigned long idle_halt; +EXPORT_SYMBOL(idle_halt); void ia64_do_show_stack (struct unw_frame_info *info, void *arg) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7dceea94723..7fc72949876 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -7,6 +7,10 @@ #include #include #include +#include + +unsigned long idle_halt; +EXPORT_SYMBOL(idle_halt); struct kmem_cache *task_xstate_cachep; @@ -325,7 +329,18 @@ static int __init idle_setup(char *str) pm_idle = poll_idle; } else if (!strcmp(str, "mwait")) force_mwait = 1; - else + else if (!strcmp(str, "halt")) { + /* + * When the boot option of idle=halt is added, halt is + * forced to be used for CPU idle. In such case CPU C2/C3 + * won't be used again. + * To continue to load the CPU idle driver, don't touch + * the boot_option_idle_override. + */ + pm_idle = default_idle; + idle_halt = 1; + return 0; + } else return -1; boot_option_idle_override = 1; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0fc310e7dfd..c75c7ace8c1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * Include the apic definitions for x86 to have the APIC timer related defines @@ -57,6 +58,7 @@ #include #include +#include #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" @@ -955,6 +957,17 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) } else { continue; } + if (cx.type == ACPI_STATE_C1 && idle_halt) { + /* + * In most cases the C1 space_id obtained from + * _CST object is FIXED_HARDWARE access mode. + * But when the option of idle=halt is added, + * the entry_method type should be changed from + * CSTATE_FFH to CSTATE_HALT. + */ + cx.entry_method = ACPI_CSTATE_HALT; + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); + } } else { snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", cx.address); @@ -1780,6 +1793,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, return 0; if (!first_run) { + if (idle_halt) { + /* + * When the boot option of "idle=halt" is added, halt + * is used for CPU IDLE. + * In such case C2/C3 is meaningless. So the max_cstate + * is set to one. + */ + max_cstate = 1; + } dmi_check_system(processor_power_dmi_table); max_cstate = acpi_processor_cstate_check(max_cstate); if (max_cstate < ACPI_C_STATES_MAX) diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index 6aff126fc07..f36e28a5f61 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -763,6 +763,7 @@ prefetchw (const void *x) #define spin_lock_prefetch(x) prefetchw(x) extern unsigned long boot_option_idle_override; +extern unsigned long idle_halt; #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 7f738270459..bc221623248 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -727,6 +727,7 @@ extern int force_mwait; extern void select_idle_routine(const struct cpuinfo_x86 *c); extern unsigned long boot_option_idle_override; +extern unsigned long idle_halt; extern void enable_sep_cpu(void); extern int sysenter_setup(void); -- cgit v1.2.3 From da5e09a1b3e5a9fc0b15a3feb64e921ccc55ba74 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 24 Jun 2008 18:01:09 +0800 Subject: ACPI : Create "idle=nomwait" bootparam "idle=nomwait" disables the use of the MWAIT instruction from both C1 (C1_FFH) and deeper (C2C3_FFH) C-states. When MWAIT is unavailable, the BIOS and OS generally negotiate to use the HALT instruction for C1, and use IO accesses for deeper C-states. This option is useful for power and performance comparisons, and also to work around BIOS bugs where broken MWAIT support is advertised. http://bugzilla.kernel.org/show_bug.cgi?id=10807 http://bugzilla.kernel.org/show_bug.cgi?id=10914 Signed-off-by: Zhao Yakui Signed-off-by: Li Shaohua Signed-off-by: Len Brown Signed-off-by: Andi Kleen --- Documentation/kernel-parameters.txt | 3 ++- arch/ia64/kernel/process.c | 2 ++ arch/x86/kernel/process.c | 11 +++++++++++ drivers/acpi/processor_core.c | 13 +++++++++++++ drivers/acpi/processor_idle.c | 6 +++++- include/asm-ia64/processor.h | 1 + include/asm-x86/processor.h | 1 + 7 files changed, 35 insertions(+), 2 deletions(-) (limited to 'include/asm-x86') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 65db7f4711a..5e497d16fb5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -818,7 +818,7 @@ and is between 256 and 4096 characters. It is defined in the file See Documentation/ide/ide.txt. idle= [X86] - Format: idle=poll or idle=mwait, idle=halt + Format: idle=poll or idle=mwait, idle=halt, idle=nomwait Poll forces a polling idle loop that can slightly improves the performance of waking up a idle CPU, but will use a lot of power and make the system run hot. Not recommended. @@ -828,6 +828,7 @@ and is between 256 and 4096 characters. It is defined in the file as idle=poll. idle=halt. Halt is forced to be used for CPU idle. In such case C2/C3 won't be used again. + idle=nomwait. Disable mwait for CPU C-states ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem Claim all unknown PCI IDE storage controllers. diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 612b3c4a060..3ab8373103e 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -57,6 +57,8 @@ unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); unsigned long idle_halt; EXPORT_SYMBOL(idle_halt); +unsigned long idle_nomwait; +EXPORT_SYMBOL(idle_nomwait); void ia64_do_show_stack (struct unw_frame_info *info, void *arg) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7fc72949876..4d629c62f4f 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -11,6 +11,8 @@ unsigned long idle_halt; EXPORT_SYMBOL(idle_halt); +unsigned long idle_nomwait; +EXPORT_SYMBOL(idle_nomwait); struct kmem_cache *task_xstate_cachep; @@ -340,6 +342,15 @@ static int __init idle_setup(char *str) pm_idle = default_idle; idle_halt = 1; return 0; + } else if (!strcmp(str, "nomwait")) { + /* + * If the boot option of "idle=nomwait" is added, + * it means that mwait will be disabled for CPU C2/C3 + * states. In such case it won't touch the variable + * of boot_option_idle_override. + */ + idle_nomwait = 1; + return 0; } else return -1; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 9a803f85ccf..4e1bb89fd6c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -265,7 +265,20 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr) if (!pdc_in) return status; + if (idle_nomwait) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); + + } status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index c75c7ace8c1..d592dbb1d12 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -957,13 +957,17 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) } else { continue; } - if (cx.type == ACPI_STATE_C1 && idle_halt) { + if (cx.type == ACPI_STATE_C1 && + (idle_halt || idle_nomwait)) { /* * In most cases the C1 space_id obtained from * _CST object is FIXED_HARDWARE access mode. * But when the option of idle=halt is added, * the entry_method type should be changed from * CSTATE_FFH to CSTATE_HALT. + * When the option of idle=nomwait is added, + * the C1 entry_method type should be + * CSTATE_HALT. */ cx.entry_method = ACPI_CSTATE_HALT; snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h index f36e28a5f61..f88fa054d01 100644 --- a/include/asm-ia64/processor.h +++ b/include/asm-ia64/processor.h @@ -764,6 +764,7 @@ prefetchw (const void *x) extern unsigned long boot_option_idle_override; extern unsigned long idle_halt; +extern unsigned long idle_nomwait; #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index bc221623248..55402d2ab93 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -728,6 +728,7 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c); extern unsigned long boot_option_idle_override; extern unsigned long idle_halt; +extern unsigned long idle_nomwait; extern void enable_sep_cpu(void); extern int sysenter_setup(void); -- cgit v1.2.3 From 2567d71cc7acd99f0a0dd02e17fe17fd7df7b30c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 15 Jul 2008 15:02:27 +1000 Subject: x86: fix asm/e820.h for userspace inclusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit asm-x86/e820.h is included from userspace. 'x86: make e820.c to have common functions' (b79cd8f1268bab57ff85b19d131f7f23deab2dee) broke it: make -C Documentation/lguest cc -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include lguest.c -lz -o lguest In file included from ../../include/asm-x86/bootparam.h:8, from lguest.c:45: ../../include/asm/e820.h:66: error: expected ‘)’ before ‘start’ ../../include/asm/e820.h:67: error: expected ‘)’ before ‘start’ ../../include/asm/e820.h:68: error: expected ‘)’ before ‘start’ ../../include/asm/e820.h:72: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘e820_update_range’ ... Signed-off-by: Rusty Russell Cc: Yinghai Lu Signed-off-by: Ingo Molnar --- include/asm-x86/e820.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/asm-x86') diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h index 33e793e991d..06633b01dd5 100644 --- a/include/asm-x86/e820.h +++ b/include/asm-x86/e820.h @@ -59,6 +59,7 @@ struct e820map { struct e820entry map[E820_X_MAX]; }; +#ifdef __KERNEL__ /* see comment in arch/x86/kernel/e820.c */ extern struct e820map e820; extern struct e820map e820_saved; @@ -115,7 +116,7 @@ extern void setup_memory_map(void); extern char *default_machine_specific_memory_setup(void); extern char *machine_specific_memory_setup(void); extern char *memory_setup(void); - +#endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ #define ISA_START_ADDRESS 0xa0000 -- cgit v1.2.3