diff --git a/[refs] b/[refs] index 912eaed5692a..27fe55b2047b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1929cef46fb057377e43a3d594404f1432db4934 +refs/heads/master: 87a9d57da41e70dc85adf23e158308527c051b3a diff --git a/trunk/Makefile b/trunk/Makefile index 662e820cfc4a..d49d96c35ce5 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -944,7 +944,7 @@ ifdef CONFIG_LOCALVERSION_AUTO localver-extra = $(scm-identifier) else ifneq ($(scm-identifier),) - ifeq ("$(origin LOCALVERSION)", "undefined") + ifeq ($(LOCALVERSION),) localver-extra = + endif endif diff --git a/trunk/arch/alpha/include/asm/bitops.h b/trunk/arch/alpha/include/asm/bitops.h index 1dce24bc455a..adfab8a21dfe 100644 --- a/trunk/arch/alpha/include/asm/bitops.h +++ b/trunk/arch/alpha/include/asm/bitops.h @@ -410,7 +410,7 @@ static inline unsigned long __arch_hweight64(unsigned long w) return __kernel_ctpop(w); } -static inline unsigned int __arch_weight32(unsigned int w) +static inline unsigned int __arch_hweight32(unsigned int w) { return __arch_hweight64(w); } diff --git a/trunk/arch/powerpc/Kconfig.debug b/trunk/arch/powerpc/Kconfig.debug index 2d38a50e66ba..53696da4518f 100644 --- a/trunk/arch/powerpc/Kconfig.debug +++ b/trunk/arch/powerpc/Kconfig.debug @@ -135,6 +135,13 @@ config DEBUGGER depends on KGDB || XMON default y +config IRQSTACKS + bool "Use separate kernel stacks when processing interrupts" + help + If you say Y here the kernel will use separate kernel stacks + for handling hard and soft interrupts. This can help avoid + overflowing the process kernel stacks. + config VIRQ_DEBUG bool "Expose hardware/virtual IRQ mapping via debugfs" depends on DEBUG_FS diff --git a/trunk/arch/powerpc/boot/Makefile b/trunk/arch/powerpc/boot/Makefile index fae8192c8fcc..ad0df7d0a643 100644 --- a/trunk/arch/powerpc/boot/Makefile +++ b/trunk/arch/powerpc/boot/Makefile @@ -141,7 +141,7 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE $(obj)/wrapper.a: $(obj-wlib) FORCE $(call if_changed,bootar) -hostprogs-y := addnote hack-coff mktree +hostprogs-y := addnote addRamDisk hack-coff mktree targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ diff --git a/trunk/arch/powerpc/boot/addRamDisk.c b/trunk/arch/powerpc/boot/addRamDisk.c new file mode 100644 index 000000000000..893f446cbd22 --- /dev/null +++ b/trunk/arch/powerpc/boot/addRamDisk.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define ElfHeaderSize (64 * 1024) +#define ElfPages (ElfHeaderSize / 4096) +#define KERNELBASE (0xc000000000000000) +#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) + +struct addr_range { + unsigned long long addr; + unsigned long memsize; + unsigned long offset; +}; + +static int check_elf64(void *p, int size, struct addr_range *r) +{ + Elf64_Ehdr *elf64 = p; + Elf64_Phdr *elf64ph; + + if (elf64->e_ident[EI_MAG0] != ELFMAG0 || + elf64->e_ident[EI_MAG1] != ELFMAG1 || + elf64->e_ident[EI_MAG2] != ELFMAG2 || + elf64->e_ident[EI_MAG3] != ELFMAG3 || + elf64->e_ident[EI_CLASS] != ELFCLASS64 || + elf64->e_ident[EI_DATA] != ELFDATA2MSB || + elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64) + return 0; + + if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size) + return 0; + + elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 + + (unsigned long)elf64->e_phoff); + + r->memsize = (unsigned long)elf64ph->p_memsz; + r->offset = (unsigned long)elf64ph->p_offset; + r->addr = (unsigned long long)elf64ph->p_vaddr; + +#ifdef DEBUG + printf("PPC64 ELF file, ph:\n"); + printf("p_type 0x%08x\n", elf64ph->p_type); + printf("p_flags 0x%08x\n", elf64ph->p_flags); + printf("p_offset 0x%016llx\n", elf64ph->p_offset); + printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr); + printf("p_paddr 0x%016llx\n", elf64ph->p_paddr); + printf("p_filesz 0x%016llx\n", elf64ph->p_filesz); + printf("p_memsz 0x%016llx\n", elf64ph->p_memsz); + printf("p_align 0x%016llx\n", elf64ph->p_align); + printf("... skipping 0x%08lx bytes of ELF header\n", + (unsigned long)elf64ph->p_offset); +#endif + + return 64; +} +static void get4k(FILE *file, char *buf ) +{ + unsigned j; + unsigned num = fread(buf, 1, 4096, file); + for ( j=num; j<4096; ++j ) + buf[j] = 0; +} + +static void put4k(FILE *file, char *buf ) +{ + fwrite(buf, 1, 4096, file); +} + +static void death(const char *msg, FILE *fdesc, const char *fname) +{ + fprintf(stderr, msg); + fclose(fdesc); + unlink(fname); + exit(1); +} + +int main(int argc, char **argv) +{ + char inbuf[4096]; + struct addr_range vmlinux; + FILE *ramDisk; + FILE *inputVmlinux; + FILE *outputVmlinux; + + char *rd_name, *lx_name, *out_name; + + size_t i; + unsigned long ramFileLen; + unsigned long ramLen; + unsigned long roundR; + unsigned long offset_end; + + unsigned long kernelLen; + unsigned long actualKernelLen; + unsigned long round; + unsigned long roundedKernelLen; + unsigned long ramStartOffs; + unsigned long ramPages; + unsigned long roundedKernelPages; + unsigned long hvReleaseData; + u_int32_t eyeCatcher = 0xc8a5d9c4; + unsigned long naca; + unsigned long xRamDisk; + unsigned long xRamDiskSize; + long padPages; + + + if (argc < 2) { + fprintf(stderr, "Name of RAM disk file missing.\n"); + exit(1); + } + rd_name = argv[1]; + + if (argc < 3) { + fprintf(stderr, "Name of vmlinux file missing.\n"); + exit(1); + } + lx_name = argv[2]; + + if (argc < 4) { + fprintf(stderr, "Name of vmlinux output file missing.\n"); + exit(1); + } + out_name = argv[3]; + + + ramDisk = fopen(rd_name, "r"); + if ( ! ramDisk ) { + fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name); + exit(1); + } + + inputVmlinux = fopen(lx_name, "r"); + if ( ! inputVmlinux ) { + fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name); + exit(1); + } + + outputVmlinux = fopen(out_name, "w+"); + if ( ! outputVmlinux ) { + fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name); + exit(1); + } + + i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux); + if (i != sizeof(inbuf)) { + fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i); + exit(1); + } + + i = check_elf64(inbuf, sizeof(inbuf), &vmlinux); + if (i == 0) { + fprintf(stderr, "You must have a linux kernel specified as argv[2]\n"); + exit(1); + } + + /* Input Vmlinux file */ + fseek(inputVmlinux, 0, SEEK_END); + kernelLen = ftell(inputVmlinux); + fseek(inputVmlinux, 0, SEEK_SET); + printf("kernel file size = %lu\n", kernelLen); + + actualKernelLen = kernelLen - ElfHeaderSize; + + printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen); + + round = actualKernelLen % 4096; + roundedKernelLen = actualKernelLen; + if ( round ) + roundedKernelLen += (4096 - round); + printf("Vmlinux length rounded up to a 4k multiple = %ld/0x%lx \n", roundedKernelLen, roundedKernelLen); + roundedKernelPages = roundedKernelLen / 4096; + printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); + + offset_end = _ALIGN_UP(vmlinux.memsize, 4096); + /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ + padPages = offset_end/4096 - roundedKernelPages; + + /* Check and see if the vmlinux is already larger than _end in System.map */ + if (padPages < 0) { + /* vmlinux is larger than _end - adjust the offset to the start of the embedded ram disk */ + offset_end = roundedKernelLen; + printf("vmlinux is larger than _end indicates it needs to be - offset_end = %lx \n", offset_end); + padPages = 0; + printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages); + } + else { + /* _end is larger than vmlinux - use the offset to _end that we calculated from the system map */ + printf("vmlinux is smaller than _end indicates is needed - offset_end = %lx \n", offset_end); + printf("will insert %lx pages between the vmlinux and the start of the ram disk \n", padPages); + } + + + + /* Input Ram Disk file */ + // Set the offset that the ram disk will be started at. + ramStartOffs = offset_end; /* determined from the input vmlinux file and the system map */ + printf("Ram Disk will start at offset = 0x%lx \n", ramStartOffs); + + fseek(ramDisk, 0, SEEK_END); + ramFileLen = ftell(ramDisk); + fseek(ramDisk, 0, SEEK_SET); + printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen); + + ramLen = ramFileLen; + + roundR = 4096 - (ramLen % 4096); + if ( roundR ) { + printf("Rounding RAM disk file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR); + ramLen += roundR; + } + + printf("Rounded RAM disk size is %ld/0x%lx \n", ramLen, ramLen); + ramPages = ramLen / 4096; + printf("RAM disk pages to copy = %ld/0x%lx\n", ramPages, ramPages); + + + + // Copy 64K ELF header + for (i=0; i<(ElfPages); ++i) { + get4k( inputVmlinux, inbuf ); + put4k( outputVmlinux, inbuf ); + } + + /* Copy the vmlinux (as full pages). */ + fseek(inputVmlinux, ElfHeaderSize, SEEK_SET); + for ( i=0; i -/* - * If CONFIG_RELOCATABLE is enabled we can place the kdump kernel anywhere. - * To keep enough space in the RMO for the first stage kernel on 64bit, we - * place it at 64MB. If CONFIG_RELOCATABLE is not enabled we must place - * the second stage at 32MB. - */ -#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC64) -#define KDUMP_KERNELBASE 0x4000000 -#else +/* Kdump kernel runs at 32 MB, change at your peril. */ #define KDUMP_KERNELBASE 0x2000000 -#endif /* How many bytes to reserve at zero for kdump. The reserve limit should * be greater or equal to the trampoline's end address. diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 3333bbdd23ef..30817d9b20cb 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -317,6 +317,7 @@ void fixup_irqs(const struct cpumask *map) } #endif +#ifdef CONFIG_IRQSTACKS static inline void handle_one_irq(unsigned int irq) { struct thread_info *curtp, *irqtp; @@ -357,6 +358,12 @@ static inline void handle_one_irq(unsigned int irq) if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } +#else +static inline void handle_one_irq(unsigned int irq) +{ + generic_handle_irq(irq); +} +#endif static inline void check_stack_overflow(void) { @@ -448,6 +455,7 @@ void exc_lvl_ctx_init(void) } #endif +#ifdef CONFIG_IRQSTACKS struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; @@ -484,6 +492,10 @@ static inline void do_softirq_onstack(void) irqtp->task = NULL; } +#else +#define do_softirq_onstack() __do_softirq() +#endif /* CONFIG_IRQSTACKS */ + void do_softirq(void) { unsigned long flags; diff --git a/trunk/arch/powerpc/kernel/machine_kexec_64.c b/trunk/arch/powerpc/kernel/machine_kexec_64.c index ed31a29c4ff7..26f9900f773c 100644 --- a/trunk/arch/powerpc/kernel/machine_kexec_64.c +++ b/trunk/arch/powerpc/kernel/machine_kexec_64.c @@ -182,12 +182,28 @@ static void kexec_prepare_cpus_wait(int wait_state) my_cpu = get_cpu(); /* Make sure each CPU has atleast made it to the state we need */ - for_each_online_cpu(i) { + for (i=0; i < NR_CPUS; i++) { if (i == my_cpu) continue; while (paca[i].kexec_state < wait_state) { barrier(); + if (!cpu_possible(i)) { + printk("kexec: cpu %d hw_cpu_id %d is not" + " possible, ignoring\n", + i, paca[i].hw_cpu_id); + break; + } + if (!cpu_online(i)) { + /* Fixme: this can be spinning in + * pSeries_secondary_wait with a paca + * waiting for it to go online. + */ + printk("kexec: cpu %d hw_cpu_id %d is not" + " online, ignoring\n", + i, paca[i].hw_cpu_id); + break; + } if (i != notified) { printk( "kexec: waiting for cpu %d (physical" " %d) to enter %i state\n", diff --git a/trunk/arch/powerpc/kernel/misc_32.S b/trunk/arch/powerpc/kernel/misc_32.S index 6bbd7a604d24..dc66d52dcff5 100644 --- a/trunk/arch/powerpc/kernel/misc_32.S +++ b/trunk/arch/powerpc/kernel/misc_32.S @@ -33,6 +33,7 @@ .text +#ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) mflr r0 stw r0,4(r1) @@ -55,6 +56,7 @@ _GLOBAL(call_handle_irq) lwz r0,4(r1) mtlr r0 blr +#endif /* CONFIG_IRQSTACKS */ /* * This returns the high 64 bits of the product of two 64-bit numbers. diff --git a/trunk/arch/powerpc/kernel/misc_64.S b/trunk/arch/powerpc/kernel/misc_64.S index e5144906a56d..a2b18dffa03e 100644 --- a/trunk/arch/powerpc/kernel/misc_64.S +++ b/trunk/arch/powerpc/kernel/misc_64.S @@ -28,6 +28,7 @@ .text +#ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) mflr r0 std r0,16(r1) @@ -51,6 +52,7 @@ _GLOBAL(call_handle_irq) ld r0,16(r1) mtlr r0 blr +#endif /* CONFIG_IRQSTACKS */ .section ".toc","aw" PPC64_CACHES: diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index 773424df828a..9d255b4f0a0e 100644 --- a/trunk/arch/powerpc/kernel/process.c +++ b/trunk/arch/powerpc/kernel/process.c @@ -1005,6 +1005,7 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, return error; } +#ifdef CONFIG_IRQSTACKS static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, unsigned long nbytes) { @@ -1029,6 +1030,10 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, return 0; } +#else +#define valid_irq_stack(sp, p, nb) 0 +#endif /* CONFIG_IRQSTACKS */ + int validate_sp(unsigned long sp, struct task_struct *p, unsigned long nbytes) { diff --git a/trunk/arch/powerpc/kernel/rtas_flash.c b/trunk/arch/powerpc/kernel/rtas_flash.c index 67a84d8f118d..bfc2abafac44 100644 --- a/trunk/arch/powerpc/kernel/rtas_flash.c +++ b/trunk/arch/powerpc/kernel/rtas_flash.c @@ -94,8 +94,12 @@ struct flash_block_list { struct flash_block_list *next; struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; }; +struct flash_block_list_header { /* just the header of flash_block_list */ + unsigned long num_blocks; + struct flash_block_list *next; +}; -static struct flash_block_list *rtas_firmware_flash_list; +static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; /* Use slab cache to guarantee 4k alignment */ static struct kmem_cache *flash_block_cache = NULL; @@ -104,14 +108,13 @@ static struct kmem_cache *flash_block_cache = NULL; /* Local copy of the flash block list. * We only allow one open of the flash proc file and create this - * list as we go. The rtas_firmware_flash_list varable will be - * set once the data is fully read. + * list as we go. This list will be put in the + * rtas_firmware_flash_list var once it is fully read. * * For convenience as we build the list we use virtual addrs, * we do not fill in the version number, and the length field * is treated as the number of entries currently in the block - * (i.e. not a byte count). This is all fixed when calling - * the flash routine. + * (i.e. not a byte count). This is all fixed on release. */ /* Status int must be first member of struct */ @@ -198,16 +201,16 @@ static int rtas_flash_release(struct inode *inode, struct file *file) if (uf->flist) { /* File was opened in write mode for a new flash attempt */ /* Clear saved list */ - if (rtas_firmware_flash_list) { - free_flash_list(rtas_firmware_flash_list); - rtas_firmware_flash_list = NULL; + if (rtas_firmware_flash_list.next) { + free_flash_list(rtas_firmware_flash_list.next); + rtas_firmware_flash_list.next = NULL; } if (uf->status != FLASH_AUTH) uf->status = flash_list_valid(uf->flist); if (uf->status == FLASH_IMG_READY) - rtas_firmware_flash_list = uf->flist; + rtas_firmware_flash_list.next = uf->flist; else free_flash_list(uf->flist); @@ -590,7 +593,7 @@ static void rtas_flash_firmware(int reboot_type) unsigned long rtas_block_list; int i, status, update_token; - if (rtas_firmware_flash_list == NULL) + if (rtas_firmware_flash_list.next == NULL) return; /* nothing to do */ if (reboot_type != SYS_RESTART) { @@ -607,25 +610,20 @@ static void rtas_flash_firmware(int reboot_type) return; } - /* - * NOTE: the "first" block must be under 4GB, so we create - * an entry with no data blocks in the reserved buffer in - * the kernel data segment. + /* NOTE: the "first" block list is a global var with no data + * blocks in the kernel data segment. We do this because + * we want to ensure this block_list addr is under 4GB. */ - spin_lock(&rtas_data_buf_lock); - flist = (struct flash_block_list *)&rtas_data_buf[0]; - flist->num_blocks = 0; - flist->next = rtas_firmware_flash_list; + rtas_firmware_flash_list.num_blocks = 0; + flist = (struct flash_block_list *)&rtas_firmware_flash_list; rtas_block_list = virt_to_abs(flist); if (rtas_block_list >= 4UL*1024*1024*1024) { printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); - spin_unlock(&rtas_data_buf_lock); return; } printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); /* Update the block_list in place. */ - rtas_firmware_flash_list = NULL; /* too hard to backout on error */ image_size = 0; for (f = flist; f; f = next) { /* Translate data addrs to absolute */ @@ -666,7 +664,6 @@ static void rtas_flash_firmware(int reboot_type) printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); break; } - spin_unlock(&rtas_data_buf_lock); } static void remove_flash_pde(struct proc_dir_entry *dp) diff --git a/trunk/arch/powerpc/kernel/setup_32.c b/trunk/arch/powerpc/kernel/setup_32.c index 7d84b210f168..8f58986c2ad9 100644 --- a/trunk/arch/powerpc/kernel/setup_32.c +++ b/trunk/arch/powerpc/kernel/setup_32.c @@ -241,6 +241,7 @@ int __init ppc_init(void) arch_initcall(ppc_init); +#ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { unsigned int i; @@ -254,6 +255,9 @@ static void __init irqstack_early_init(void) __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); } } +#else +#define irqstack_early_init() +#endif #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) static void __init exc_lvl_early_init(void) diff --git a/trunk/arch/powerpc/kernel/setup_64.c b/trunk/arch/powerpc/kernel/setup_64.c index 643dcac40fcb..f3fb5a79de52 100644 --- a/trunk/arch/powerpc/kernel/setup_64.c +++ b/trunk/arch/powerpc/kernel/setup_64.c @@ -432,6 +432,7 @@ static u64 slb0_limit(void) return 1UL << SID_SHIFT; } +#ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { u64 limit = slb0_limit(); @@ -450,6 +451,9 @@ static void __init irqstack_early_init(void) THREAD_SIZE, limit)); } } +#else +#define irqstack_early_init() +#endif #ifdef CONFIG_PPC_BOOK3E static void __init exc_lvl_early_init(void) diff --git a/trunk/arch/powerpc/mm/pgtable_32.c b/trunk/arch/powerpc/mm/pgtable_32.c index 34347b2e7e31..9fc02dc72ce9 100644 --- a/trunk/arch/powerpc/mm/pgtable_32.c +++ b/trunk/arch/powerpc/mm/pgtable_32.c @@ -115,7 +115,11 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *ptepage; +#ifdef CONFIG_HIGHPTE + gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO; +#else gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO; +#endif ptepage = alloc_pages(flags, 0); if (!ptepage) diff --git a/trunk/arch/powerpc/sysdev/mpic.c b/trunk/arch/powerpc/sysdev/mpic.c index 20b73c025a45..2102487612a4 100644 --- a/trunk/arch/powerpc/sysdev/mpic.c +++ b/trunk/arch/powerpc/sysdev/mpic.c @@ -1666,7 +1666,7 @@ static int mpic_resume(struct sys_device *dev) mpic->save_data[i].dest); #ifdef CONFIG_MPIC_U3_HT_IRQS - if (mpic->fixups) { + { struct mpic_irq_fixup *fixup = &mpic->fixups[i]; if (fixup->base) { diff --git a/trunk/arch/x86/kernel/e820.c b/trunk/arch/x86/kernel/e820.c index 0d6fc71bedb1..7bca3c6a02fb 100644 --- a/trunk/arch/x86/kernel/e820.c +++ b/trunk/arch/x86/kernel/e820.c @@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void) struct e820entry *ei = &e820.map[i]; if (ei->type == E820_NVS) - suspend_nvs_register(ei->addr, ei->size); + hibernate_nvs_register(ei->addr, ei->size); } return 0; diff --git a/trunk/drivers/acpi/acpi_pad.c b/trunk/drivers/acpi/acpi_pad.c index 446aced33aff..d269a8f3329c 100644 --- a/trunk/drivers/acpi/acpi_pad.c +++ b/trunk/drivers/acpi/acpi_pad.c @@ -46,8 +46,6 @@ static unsigned long power_saving_mwait_eax; static unsigned char tsc_detected_unstable; static unsigned char tsc_marked_unstable; -static unsigned char lapic_detected_unstable; -static unsigned char lapic_marked_unstable; static void power_saving_mwait_init(void) { @@ -77,6 +75,9 @@ static void power_saving_mwait_init(void) power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | (highest_subcstate - 1); + for_each_online_cpu(i) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i); + #if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86) switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -85,15 +86,13 @@ static void power_saving_mwait_init(void) * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. */ - if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) - tsc_detected_unstable = 1; - if (!boot_cpu_has(X86_FEATURE_ARAT)) - lapic_detected_unstable = 1; - break; + if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) + return; + + /*FALL THROUGH*/ default: - /* TSC & LAPIC could halt in idle */ + /* TSC could halt in idle */ tsc_detected_unstable = 1; - lapic_detected_unstable = 1; } #endif } @@ -181,20 +180,10 @@ static int power_saving_thread(void *data) mark_tsc_unstable("TSC halts in idle"); tsc_marked_unstable = 1; } - if (lapic_detected_unstable && !lapic_marked_unstable) { - int i; - /* LAPIC could halt in idle, so notify users */ - for_each_online_cpu(i) - clockevents_notify( - CLOCK_EVT_NOTIFY_BROADCAST_ON, - &i); - lapic_marked_unstable = 1; - } local_irq_disable(); cpu = smp_processor_id(); - if (lapic_marked_unstable) - clockevents_notify( - CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, + &cpu); stop_critical_timings(); __monitor((void *)¤t_thread_info()->flags, 0, 0); @@ -203,9 +192,8 @@ static int power_saving_thread(void *data) __mwait(power_saving_mwait_eax, 1); start_critical_timings(); - if (lapic_marked_unstable) - clockevents_notify( - CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, + &cpu); local_irq_enable(); if (jiffies > expire_time) { diff --git a/trunk/drivers/acpi/acpica/acconfig.h b/trunk/drivers/acpi/acpica/acconfig.h index b17d8de9f6ff..33181ad350d5 100644 --- a/trunk/drivers/acpi/acpica/acconfig.h +++ b/trunk/drivers/acpi/acpica/acconfig.h @@ -119,10 +119,6 @@ #define ACPI_MAX_LOOP_ITERATIONS 0xFFFF -/* Maximum sleep allowed via Sleep() operator */ - -#define ACPI_MAX_SLEEP 20000 /* Two seconds */ - /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) diff --git a/trunk/drivers/acpi/acpica/acevents.h b/trunk/drivers/acpi/acpica/acevents.h index c3f43daa8be3..64d1e5c2d4ae 100644 --- a/trunk/drivers/acpi/acpica/acevents.h +++ b/trunk/drivers/acpi/acpica/acevents.h @@ -80,6 +80,10 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); acpi_status acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info); +acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); + +acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); + struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number); diff --git a/trunk/drivers/acpi/acpica/acglobal.h b/trunk/drivers/acpi/acpica/acglobal.h index 899d68afc3c5..9070f1fe8f17 100644 --- a/trunk/drivers/acpi/acpica/acglobal.h +++ b/trunk/drivers/acpi/acpica/acglobal.h @@ -125,14 +125,6 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); */ u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE); -/* - * Optionally truncate I/O addresses to 16 bits. Provides compatibility - * with other ACPI implementations. NOTE: During ACPICA initialization, - * this value is set to TRUE if any Windows OSI strings have been - * requested by the BIOS. - */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE); - /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ struct acpi_table_fadt acpi_gbl_FADT; diff --git a/trunk/drivers/acpi/acpica/achware.h b/trunk/drivers/acpi/acpica/achware.h index 32391588e163..5900f135dc6d 100644 --- a/trunk/drivers/acpi/acpica/achware.h +++ b/trunk/drivers/acpi/acpica/achware.h @@ -90,11 +90,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); /* * hwgpe - GPE support */ -u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, - struct acpi_gpe_register_info *gpe_register_info); - -acpi_status -acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action); +acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); acpi_status acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info); diff --git a/trunk/drivers/acpi/acpica/evgpe.c b/trunk/drivers/acpi/acpica/evgpe.c index 7c2c336006a1..a221ad404167 100644 --- a/trunk/drivers/acpi/acpica/evgpe.c +++ b/trunk/drivers/acpi/acpica/evgpe.c @@ -69,7 +69,7 @@ acpi_status acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) { struct acpi_gpe_register_info *gpe_register_info; - u32 register_bit; + u8 register_bit; ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); @@ -78,8 +78,9 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) return_ACPI_STATUS(AE_NOT_EXIST); } - register_bit = acpi_hw_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = (u8) + (1 << + (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); /* Clear the wake/run bits up front */ @@ -99,6 +100,106 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info) return_ACPI_STATUS(AE_OK); } +/******************************************************************************* + * + * FUNCTION: acpi_ev_enable_gpe + * + * PARAMETERS: gpe_event_info - GPE to enable + * + * RETURN: Status + * + * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless + * of type or number of references. + * + * Note: The GPE lock should be already acquired when this function is called. + * + ******************************************************************************/ + +acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE(ev_enable_gpe); + + + /* + * We will only allow a GPE to be enabled if it has either an + * associated method (_Lxx/_Exx) or a handler. Otherwise, the + * GPE will be immediately disabled by acpi_ev_gpe_dispatch the + * first time it fires. + */ + if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { + return_ACPI_STATUS(AE_NO_HANDLER); + } + + /* Ensure the HW enable masks are current */ + + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Clear the GPE (of stale events) */ + + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Enable the requested GPE */ + + status = acpi_hw_write_gpe_enable_reg(gpe_event_info); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ev_disable_gpe + * + * PARAMETERS: gpe_event_info - GPE to disable + * + * RETURN: Status + * + * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, + * regardless of the type or number of references. + * + * Note: The GPE lock should be already acquired when this function is called. + * + ******************************************************************************/ + +acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(ev_disable_gpe); + + + /* + * Note: Always disable the GPE, even if we think that that it is already + * disabled. It is possible that the AML or some other code has enabled + * the GPE behind our back. + */ + + /* Ensure the HW enable masks are current */ + + status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Always H/W disable this GPE, even if we don't know the GPE type. + * Simply clear the enable bit for this particular GPE, but do not + * write out the current GPE enable mask since this may inadvertently + * enable GPEs too early. An example is a rogue GPE that has arrived + * during ACPICA initialization - possibly because AML or other code + * has enabled the GPE. + */ + status = acpi_hw_low_disable_gpe(gpe_event_info); + return_ACPI_STATUS(status); +} + /******************************************************************************* * @@ -350,6 +451,10 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) return_VOID; } + /* Update the GPE register masks for return to enabled state */ + + (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); + /* * Take a snapshot of the GPE info for this level - we copy the info to * prevent a race condition with remove_handler/remove_block. @@ -502,7 +607,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Disable the GPE, so it doesn't keep firing before the method has a * chance to run (it runs asynchronously with interrupts enabled). */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); + status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE[0x%2X]", @@ -539,7 +644,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) * Disable the GPE. The GPE will remain disabled a handler * is installed or ACPICA is restarted. */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); + status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to disable GPE[0x%2X]", diff --git a/trunk/drivers/acpi/acpica/evgpeblk.c b/trunk/drivers/acpi/acpica/evgpeblk.c index 341a38ce8aa6..7c28f2d9fd35 100644 --- a/trunk/drivers/acpi/acpica/evgpeblk.c +++ b/trunk/drivers/acpi/acpica/evgpeblk.c @@ -500,19 +500,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; gpe_event_info = &gpe_block->event_info[gpe_index]; - gpe_number = gpe_index + gpe_block->block_base_number; - - /* - * If the GPE has already been enabled for runtime - * signaling, make sure it remains enabled, but do not - * increment its reference counter. - */ - if (gpe_event_info->runtime_count) { - acpi_set_gpe(gpe_device, gpe_number, - ACPI_GPE_ENABLE); - gpe_enabled_count++; - continue; - } if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { wake_gpe_count++; @@ -529,6 +516,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, /* Enable this GPE */ + gpe_number = gpe_index + gpe_block->block_base_number; status = acpi_enable_gpe(gpe_device, gpe_number, ACPI_GPE_TYPE_RUNTIME); if (ACPI_FAILURE(status)) { diff --git a/trunk/drivers/acpi/acpica/evxface.c b/trunk/drivers/acpi/acpica/evxface.c index 4a531cdf7942..cc825023012a 100644 --- a/trunk/drivers/acpi/acpica/evxface.c +++ b/trunk/drivers/acpi/acpica/evxface.c @@ -719,6 +719,13 @@ acpi_install_gpe_handler(acpi_handle gpe_device, handler->context = context; handler->method_node = gpe_event_info->dispatch.method_node; + /* Disable the GPE before installing the handler */ + + status = acpi_ev_disable_gpe(gpe_event_info); + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + /* Install the handler */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); diff --git a/trunk/drivers/acpi/acpica/evxfevnt.c b/trunk/drivers/acpi/acpica/evxfevnt.c index d97b8dce1668..d5a5efc043bf 100644 --- a/trunk/drivers/acpi/acpica/evxfevnt.c +++ b/trunk/drivers/acpi/acpica/evxfevnt.c @@ -208,44 +208,6 @@ acpi_status acpi_enable_event(u32 event, u32 flags) ACPI_EXPORT_SYMBOL(acpi_enable_event) -/******************************************************************************* - * - * FUNCTION: acpi_clear_and_enable_gpe - * - * PARAMETERS: gpe_event_info - GPE to enable - * - * RETURN: Status - * - * DESCRIPTION: Clear the given GPE from stale events and enable it. - * - ******************************************************************************/ -static acpi_status -acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) -{ - acpi_status status; - - /* - * We will only allow a GPE to be enabled if it has either an - * associated method (_Lxx/_Exx) or a handler. Otherwise, the - * GPE will be immediately disabled by acpi_ev_gpe_dispatch the - * first time it fires. - */ - if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { - return_ACPI_STATUS(AE_NO_HANDLER); - } - - /* Clear the GPE (of stale events) */ - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Enable the requested GPE */ - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); - - return_ACPI_STATUS(status); -} - /******************************************************************************* * * FUNCTION: acpi_set_gpe @@ -287,11 +249,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) switch (action) { case ACPI_GPE_ENABLE: - status = acpi_clear_and_enable_gpe(gpe_event_info); + status = acpi_ev_enable_gpe(gpe_event_info); break; case ACPI_GPE_DISABLE: - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); + status = acpi_ev_disable_gpe(gpe_event_info); break; default: @@ -354,11 +316,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) gpe_event_info->runtime_count++; if (gpe_event_info->runtime_count == 1) { - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); - if (ACPI_SUCCESS(status)) { - status = acpi_clear_and_enable_gpe(gpe_event_info); - } - + status = acpi_ev_enable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { gpe_event_info->runtime_count--; goto unlock_and_exit; @@ -385,7 +343,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) */ gpe_event_info->wakeup_count++; if (gpe_event_info->wakeup_count == 1) { - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); } } @@ -445,12 +403,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type gpe_event_info->runtime_count--; if (!gpe_event_info->runtime_count) { - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); - if (ACPI_SUCCESS(status)) { - status = acpi_hw_low_set_gpe(gpe_event_info, - ACPI_GPE_DISABLE); - } - + status = acpi_ev_disable_gpe(gpe_event_info); if (ACPI_FAILURE(status)) { gpe_event_info->runtime_count++; goto unlock_and_exit; @@ -471,7 +424,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type gpe_event_info->wakeup_count--; if (!gpe_event_info->wakeup_count) { - status = acpi_ev_update_gpe_enable_masks(gpe_event_info); + (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); } } diff --git a/trunk/drivers/acpi/acpica/exsystem.c b/trunk/drivers/acpi/acpica/exsystem.c index 675aaa91a770..6d32e09327f1 100644 --- a/trunk/drivers/acpi/acpica/exsystem.c +++ b/trunk/drivers/acpi/acpica/exsystem.c @@ -201,14 +201,6 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long) acpi_ex_relinquish_interpreter(); - /* - * For compatibility with other ACPI implementations and to prevent - * accidental deep sleeps, limit the sleep time to something reasonable. - */ - if (how_long > ACPI_MAX_SLEEP) { - how_long = ACPI_MAX_SLEEP; - } - acpi_os_sleep(how_long); /* And now we must get the interpreter again */ diff --git a/trunk/drivers/acpi/acpica/hwgpe.c b/trunk/drivers/acpi/acpica/hwgpe.c index 3450309c2786..bd72319a38f0 100644 --- a/trunk/drivers/acpi/acpica/hwgpe.c +++ b/trunk/drivers/acpi/acpica/hwgpe.c @@ -57,47 +57,21 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /****************************************************************************** * - * FUNCTION: acpi_hw_gpe_register_bit - * - * PARAMETERS: gpe_event_info - Info block for the GPE - * gpe_register_info - Info block for the GPE register - * - * RETURN: Status - * - * DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given - * GPE set. - * - ******************************************************************************/ - -u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info, - struct acpi_gpe_register_info *gpe_register_info) -{ - return (u32)1 << (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_low_set_gpe + * FUNCTION: acpi_hw_low_disable_gpe * * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled - * action - Enable or disable * * RETURN: Status * - * DESCRIPTION: Enable or disable a single GPE in its enable register. + * DESCRIPTION: Disable a single GPE in the enable register. * ******************************************************************************/ -acpi_status -acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) +acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) { struct acpi_gpe_register_info *gpe_register_info; acpi_status status; u32 enable_mask; - u32 register_bit; - - ACPI_FUNCTION_ENTRY(); /* Get the info block for the entire GPE register */ @@ -113,27 +87,11 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) return (status); } - /* Set ot clear just the bit that corresponds to this GPE */ + /* Clear just the bit that corresponds to this GPE */ - register_bit = acpi_hw_gpe_register_bit(gpe_event_info, - gpe_register_info); - switch (action) { - case ACPI_GPE_COND_ENABLE: - if (!(register_bit & gpe_register_info->enable_for_run)) - return (AE_BAD_PARAMETER); - - case ACPI_GPE_ENABLE: - ACPI_SET_BIT(enable_mask, register_bit); - break; - - case ACPI_GPE_DISABLE: - ACPI_CLEAR_BIT(enable_mask, register_bit); - break; - - default: - ACPI_ERROR((AE_INFO, "Invalid action\n")); - return (AE_BAD_PARAMETER); - } + ACPI_CLEAR_BIT(enable_mask, ((u32)1 << + (gpe_event_info->gpe_number - + gpe_register_info->base_gpe_number))); /* Write the updated enable mask */ @@ -158,11 +116,23 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action) acpi_status acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) { + struct acpi_gpe_register_info *gpe_register_info; acpi_status status; ACPI_FUNCTION_ENTRY(); - status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE); + /* Get the info block for the entire GPE register */ + + gpe_register_info = gpe_event_info->register_info; + if (!gpe_register_info) { + return (AE_NOT_EXIST); + } + + /* Write the entire GPE (runtime) enable register */ + + status = acpi_hw_write(gpe_register_info->enable_for_run, + &gpe_register_info->enable_address); + return (status); } @@ -180,28 +150,21 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) { - struct acpi_gpe_register_info *gpe_register_info; acpi_status status; - u32 register_bit; + u8 register_bit; ACPI_FUNCTION_ENTRY(); - /* Get the info block for the entire GPE register */ - - gpe_register_info = gpe_event_info->register_info; - if (!gpe_register_info) { - return (AE_NOT_EXIST); - } - - register_bit = acpi_hw_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* * Write a one to the appropriate bit in the status register to * clear this GPE. */ status = acpi_hw_write(register_bit, - &gpe_register_info->status_address); + &gpe_event_info->register_info->status_address); return (status); } @@ -224,7 +187,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, acpi_event_status * event_status) { u32 in_byte; - u32 register_bit; + u8 register_bit; struct acpi_gpe_register_info *gpe_register_info; acpi_status status; acpi_event_status local_event_status = 0; @@ -241,8 +204,9 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = acpi_hw_gpe_register_bit(gpe_event_info, - gpe_register_info); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* GPE currently enabled? (enabled for runtime?) */ diff --git a/trunk/drivers/acpi/acpica/hwvalid.c b/trunk/drivers/acpi/acpica/hwvalid.c index e1d9c777b213..c10d587c1641 100644 --- a/trunk/drivers/acpi/acpica/hwvalid.c +++ b/trunk/drivers/acpi/acpica/hwvalid.c @@ -222,12 +222,6 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) u32 one_byte; u32 i; - /* Truncate address to 16 bits if requested */ - - if (acpi_gbl_truncate_io_addresses) { - address &= ACPI_UINT16_MAX; - } - /* Validate the entire request and perform the I/O */ status = acpi_hw_validate_io_request(address, width); @@ -285,12 +279,6 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) acpi_status status; u32 i; - /* Truncate address to 16 bits if requested */ - - if (acpi_gbl_truncate_io_addresses) { - address &= ACPI_UINT16_MAX; - } - /* Validate the entire request and perform the I/O */ status = acpi_hw_validate_io_request(address, width); diff --git a/trunk/drivers/acpi/acpica/nsinit.c b/trunk/drivers/acpi/acpica/nsinit.c index 4e5272c313e0..9bd6f050f299 100644 --- a/trunk/drivers/acpi/acpica/nsinit.c +++ b/trunk/drivers/acpi/acpica/nsinit.c @@ -193,15 +193,6 @@ acpi_status acpi_ns_initialize_devices(void) acpi_ns_init_one_device, NULL, &info, NULL); - /* - * Any _OSI requests should be completed by now. If the BIOS has - * requested any Windows OSI strings, we will always truncate - * I/O addresses to 16 bits -- for Windows compatibility. - */ - if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) { - acpi_gbl_truncate_io_addresses = TRUE; - } - ACPI_FREE(info.evaluate_info); if (ACPI_FAILURE(status)) { goto error_exit; diff --git a/trunk/drivers/acpi/blacklist.c b/trunk/drivers/acpi/blacklist.c index 01381be05e96..2815df66f6f7 100644 --- a/trunk/drivers/acpi/blacklist.c +++ b/trunk/drivers/acpi/blacklist.c @@ -218,14 +218,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { - .callback = dmi_disable_osi_vista, - .ident = "VGN-NS50B_L", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"), - }, - }, - { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index 7d857dabdde4..fd51c4ab4829 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device) /* Button's GPE is run-wake GPE */ acpi_enable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number, - ACPI_GPE_TYPE_RUNTIME); + ACPI_GPE_TYPE_WAKE_RUN); device->wakeup.run_wake_count++; device->wakeup.state.enabled = 1; } @@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type) if (device->wakeup.flags.valid) { acpi_disable_gpe(device->wakeup.gpe_device, device->wakeup.gpe_number, - ACPI_GPE_TYPE_RUNTIME); + ACPI_GPE_TYPE_WAKE_RUN); device->wakeup.run_wake_count--; device->wakeup.state.enabled = 0; } diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index 8a3b840c0bb2..acf2ab249842 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -347,6 +347,7 @@ static int __init acpi_fan_init(void) { int result = 0; + #ifdef CONFIG_ACPI_PROCFS acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); if (!acpi_fan_dir) @@ -355,9 +356,7 @@ static int __init acpi_fan_init(void) result = acpi_bus_register_driver(&acpi_fan_driver); if (result < 0) { -#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); -#endif return -ENODEV; } diff --git a/trunk/drivers/acpi/processor_driver.c b/trunk/drivers/acpi/processor_driver.c index 38ea0cc6dc49..b1034a9ada4e 100644 --- a/trunk/drivers/acpi/processor_driver.c +++ b/trunk/drivers/acpi/processor_driver.c @@ -581,11 +581,6 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) return 0; } -#ifdef CONFIG_SMP - if (pr->id >= setup_max_cpus && pr->id != 0) - return 0; -#endif - BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index 5b7c52e4a00f..3fb4bdea7e06 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -114,8 +114,6 @@ static int __acpi_pm_prepare(void) { int error = acpi_sleep_prepare(acpi_target_sleep_state); - suspend_nvs_save(); - if (error) acpi_target_sleep_state = ACPI_STATE_S0; return error; @@ -145,9 +143,6 @@ static void acpi_pm_finish(void) { u32 acpi_state = acpi_target_sleep_state; - suspend_nvs_free(); - acpi_ec_unblock_transactions(); - if (acpi_state == ACPI_STATE_S0) return; @@ -197,11 +192,6 @@ static int acpi_suspend_begin(suspend_state_t pm_state) u32 acpi_state = acpi_suspend_states[pm_state]; int error = 0; - error = suspend_nvs_alloc(); - - if (error) - return error; - if (sleep_states[acpi_state]) { acpi_target_sleep_state = acpi_state; acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -279,13 +269,12 @@ static int acpi_suspend_enter(suspend_state_t pm_state) if (acpi_state == ACPI_STATE_S3) acpi_restore_state_mem(); - suspend_nvs_restore(); - return ACPI_SUCCESS(status) ? 0 : -EFAULT; } static void acpi_suspend_finish(void) { + acpi_ec_unblock_transactions(); acpi_pm_finish(); } @@ -415,7 +404,7 @@ static int acpi_hibernation_begin(void) { int error; - error = s4_no_nvs ? 0 : suspend_nvs_alloc(); + error = s4_no_nvs ? 0 : hibernate_nvs_alloc(); if (!error) { acpi_target_sleep_state = ACPI_STATE_S4; acpi_sleep_tts_switch(acpi_target_sleep_state); @@ -429,7 +418,7 @@ static int acpi_hibernation_pre_snapshot(void) int error = acpi_pm_prepare(); if (!error) - suspend_nvs_save(); + hibernate_nvs_save(); return error; } @@ -452,6 +441,13 @@ static int acpi_hibernation_enter(void) return ACPI_SUCCESS(status) ? 0 : -EFAULT; } +static void acpi_hibernation_finish(void) +{ + hibernate_nvs_free(); + acpi_ec_unblock_transactions(); + acpi_pm_finish(); +} + static void acpi_hibernation_leave(void) { /* @@ -468,7 +464,7 @@ static void acpi_hibernation_leave(void) panic("ACPI S4 hardware signature mismatch"); } /* Restore the NVS memory area */ - suspend_nvs_restore(); + hibernate_nvs_restore(); /* Allow EC transactions to happen. */ acpi_ec_unblock_transactions_early(); } @@ -483,7 +479,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = { .begin = acpi_hibernation_begin, .end = acpi_pm_end, .pre_snapshot = acpi_hibernation_pre_snapshot, - .finish = acpi_pm_finish, + .finish = acpi_hibernation_finish, .prepare = acpi_pm_prepare, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, @@ -511,7 +507,7 @@ static int acpi_hibernation_begin_old(void) if (!error) { if (!s4_no_nvs) - error = suspend_nvs_alloc(); + error = hibernate_nvs_alloc(); if (!error) acpi_target_sleep_state = ACPI_STATE_S4; } @@ -521,7 +517,7 @@ static int acpi_hibernation_begin_old(void) static int acpi_hibernation_pre_snapshot_old(void) { acpi_pm_freeze(); - suspend_nvs_save(); + hibernate_nvs_save(); return 0; } @@ -533,8 +529,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = { .begin = acpi_hibernation_begin_old, .end = acpi_pm_end, .pre_snapshot = acpi_hibernation_pre_snapshot_old, + .finish = acpi_hibernation_finish, .prepare = acpi_pm_freeze, - .finish = acpi_pm_finish, .enter = acpi_hibernation_enter, .leave = acpi_hibernation_leave, .pre_restore = acpi_pm_freeze, diff --git a/trunk/drivers/acpi/system.c b/trunk/drivers/acpi/system.c index f8db50a0941c..c79e789ed03a 100644 --- a/trunk/drivers/acpi/system.c +++ b/trunk/drivers/acpi/system.c @@ -388,12 +388,10 @@ static ssize_t counter_set(struct kobject *kobj, if (index < num_gpes) { if (!strcmp(buf, "disable\n") && (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_disable_gpe(handle, index, - ACPI_GPE_TYPE_RUNTIME); + result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE); else if (!strcmp(buf, "enable\n") && !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_enable_gpe(handle, index, - ACPI_GPE_TYPE_RUNTIME); + result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE); else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index); diff --git a/trunk/drivers/acpi/wakeup.c b/trunk/drivers/acpi/wakeup.c index 388747a7ef4f..4b9d339a6e28 100644 --- a/trunk/drivers/acpi/wakeup.c +++ b/trunk/drivers/acpi/wakeup.c @@ -64,13 +64,16 @@ void acpi_enable_wakeup_device(u8 sleep_state) struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled + if (!dev->wakeup.flags.valid) + continue; + + if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) || sleep_state > (u32) dev->wakeup.sleep_state) continue; /* The wake-up power should have been enabled already. */ - acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE); + acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_ENABLE); } } @@ -93,8 +96,6 @@ void acpi_disable_wakeup_device(u8 sleep_state) || (sleep_state > (u32) dev->wakeup.sleep_state)) continue; - acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE); acpi_disable_wakeup_device_power(dev); } } @@ -108,8 +109,13 @@ int __init acpi_wakeup_device_init(void) struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - if (dev->wakeup.flags.always_enabled) - dev->wakeup.state.enabled = 1; + /* In case user doesn't load button driver */ + if (!dev->wakeup.flags.always_enabled || + dev->wakeup.state.enabled) + continue; + acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE); + dev->wakeup.state.enabled = 1; } mutex_unlock(&acpi_device_lock); return 0; diff --git a/trunk/drivers/char/tpm/tpm.h b/trunk/drivers/char/tpm/tpm.h index 792868d24f2a..8e00b4ddd083 100644 --- a/trunk/drivers/char/tpm/tpm.h +++ b/trunk/drivers/char/tpm/tpm.h @@ -224,7 +224,6 @@ struct tpm_readpubek_params_out { u8 algorithm[4]; u8 encscheme[2]; u8 sigscheme[2]; - __be32 paramsize; u8 parameters[12]; /*assuming RSA*/ __be32 keysize; u8 modulus[256]; diff --git a/trunk/include/acpi/acexcep.h b/trunk/include/acpi/acexcep.h index 17714beb868e..5958d7845bd5 100644 --- a/trunk/include/acpi/acexcep.h +++ b/trunk/include/acpi/acexcep.h @@ -212,7 +212,7 @@ char const *acpi_gbl_exception_names_env[] = { "AE_NO_GLOBAL_LOCK", "AE_ABORT_METHOD", "AE_SAME_HANDLER", - "AE_NO_HANDLER", + "AE_WAKE_ONLY_GPE", "AE_OWNER_ID_LIMIT" }; diff --git a/trunk/include/acpi/acpixf.h b/trunk/include/acpi/acpixf.h index 1371cc997393..0e4ab1fe5966 100644 --- a/trunk/include/acpi/acpixf.h +++ b/trunk/include/acpi/acpixf.h @@ -69,7 +69,6 @@ extern acpi_name acpi_gbl_trace_method_name; extern u32 acpi_gbl_trace_flags; extern u8 acpi_gbl_enable_aml_debug_object; extern u8 acpi_gbl_copy_dsdt_locally; -extern u8 acpi_gbl_truncate_io_addresses; extern u32 acpi_current_gpe_count; extern struct acpi_table_fadt acpi_gbl_FADT; diff --git a/trunk/include/acpi/actypes.h b/trunk/include/acpi/actypes.h index d55f4a7b824d..bade172cad47 100644 --- a/trunk/include/acpi/actypes.h +++ b/trunk/include/acpi/actypes.h @@ -663,11 +663,10 @@ typedef u32 acpi_event_status; #define ACPI_GPE_MAX 0xFF #define ACPI_NUM_GPE 256 -/* Actions for acpi_set_gpe and acpi_hw_low_set_gpe */ +/* Actions for acpi_set_gpe */ #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 -#define ACPI_GPE_COND_ENABLE 2 /* gpe_types for acpi_enable_gpe and acpi_disable_gpe */ diff --git a/trunk/include/linux/suspend.h b/trunk/include/linux/suspend.h index bc7d6bb4cd8e..5e781d824e6d 100644 --- a/trunk/include/linux/suspend.h +++ b/trunk/include/linux/suspend.h @@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; } static inline bool system_entering_hibernation(void) { return false; } #endif /* CONFIG_HIBERNATION */ -#ifdef CONFIG_SUSPEND_NVS -extern int suspend_nvs_register(unsigned long start, unsigned long size); -extern int suspend_nvs_alloc(void); -extern void suspend_nvs_free(void); -extern void suspend_nvs_save(void); -extern void suspend_nvs_restore(void); -#else /* CONFIG_SUSPEND_NVS */ -static inline int suspend_nvs_register(unsigned long a, unsigned long b) +#ifdef CONFIG_HIBERNATION_NVS +extern int hibernate_nvs_register(unsigned long start, unsigned long size); +extern int hibernate_nvs_alloc(void); +extern void hibernate_nvs_free(void); +extern void hibernate_nvs_save(void); +extern void hibernate_nvs_restore(void); +#else /* CONFIG_HIBERNATION_NVS */ +static inline int hibernate_nvs_register(unsigned long a, unsigned long b) { return 0; } -static inline int suspend_nvs_alloc(void) { return 0; } -static inline void suspend_nvs_free(void) {} -static inline void suspend_nvs_save(void) {} -static inline void suspend_nvs_restore(void) {} -#endif /* CONFIG_SUSPEND_NVS */ +static inline int hibernate_nvs_alloc(void) { return 0; } +static inline void hibernate_nvs_free(void) {} +static inline void hibernate_nvs_save(void) {} +static inline void hibernate_nvs_restore(void) {} +#endif /* CONFIG_HIBERNATION_NVS */ #ifdef CONFIG_PM_SLEEP void save_processor_state(void); diff --git a/trunk/init/main.c b/trunk/init/main.c index ac2e4a5f59ee..3bdb152f412f 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -125,9 +125,7 @@ static char *ramdisk_execute_command; #ifdef CONFIG_SMP /* Setup configured maximum number of CPUs to activate */ -unsigned int setup_max_cpus = NR_CPUS; -EXPORT_SYMBOL(setup_max_cpus); - +unsigned int __initdata setup_max_cpus = NR_CPUS; /* * Setup routine for controlling SMP activation diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index ca6066a6952e..5c36ea9d55d2 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -99,13 +99,9 @@ config PM_SLEEP_ADVANCED_DEBUG depends on PM_ADVANCED_DEBUG default n -config SUSPEND_NVS - bool - config SUSPEND bool "Suspend to RAM and standby" depends on PM && ARCH_SUSPEND_POSSIBLE - select SUSPEND_NVS if HAS_IOMEM default y ---help--- Allow the system to enter sleep states in which main memory is @@ -134,10 +130,13 @@ config SUSPEND_FREEZER Turning OFF this setting is NOT recommended! If in doubt, say Y. +config HIBERNATION_NVS + bool + config HIBERNATION bool "Hibernation (aka 'suspend to disk')" depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE - select SUSPEND_NVS if HAS_IOMEM + select HIBERNATION_NVS if HAS_IOMEM ---help--- Enable the suspend to disk (STD) functionality, which is usually called "hibernation" in user interfaces. STD checkpoints the diff --git a/trunk/kernel/power/Makefile b/trunk/kernel/power/Makefile index f9063c6b185d..524e058dcf06 100644 --- a/trunk/kernel/power/Makefile +++ b/trunk/kernel/power/Makefile @@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \ block_io.o -obj-$(CONFIG_SUSPEND_NVS) += nvs.o +obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o diff --git a/trunk/kernel/power/nvs.c b/trunk/kernel/power/hibernate_nvs.c similarity index 80% rename from trunk/kernel/power/nvs.c rename to trunk/kernel/power/hibernate_nvs.c index 1836db60bbb6..fdcad9ed5a7b 100644 --- a/trunk/kernel/power/nvs.c +++ b/trunk/kernel/power/hibernate_nvs.c @@ -15,7 +15,7 @@ /* * Platforms, like ACPI, may want us to save some memory used by them during - * suspend and to restore the contents of this memory during the subsequent + * hibernation and to restore the contents of this memory during the subsequent * resume. The code below implements a mechanism allowing us to do that. */ @@ -30,7 +30,7 @@ struct nvs_page { static LIST_HEAD(nvs_list); /** - * suspend_nvs_register - register platform NVS memory region to save + * hibernate_nvs_register - register platform NVS memory region to save * @start - physical address of the region * @size - size of the region * @@ -38,7 +38,7 @@ static LIST_HEAD(nvs_list); * things so that the data from page-aligned addresses in this region will * be copied into separate RAM pages. */ -int suspend_nvs_register(unsigned long start, unsigned long size) +int hibernate_nvs_register(unsigned long start, unsigned long size) { struct nvs_page *entry, *next; @@ -68,9 +68,9 @@ int suspend_nvs_register(unsigned long start, unsigned long size) } /** - * suspend_nvs_free - free data pages allocated for saving NVS regions + * hibernate_nvs_free - free data pages allocated for saving NVS regions */ -void suspend_nvs_free(void) +void hibernate_nvs_free(void) { struct nvs_page *entry; @@ -86,16 +86,16 @@ void suspend_nvs_free(void) } /** - * suspend_nvs_alloc - allocate memory necessary for saving NVS regions + * hibernate_nvs_alloc - allocate memory necessary for saving NVS regions */ -int suspend_nvs_alloc(void) +int hibernate_nvs_alloc(void) { struct nvs_page *entry; list_for_each_entry(entry, &nvs_list, node) { entry->data = (void *)__get_free_page(GFP_KERNEL); if (!entry->data) { - suspend_nvs_free(); + hibernate_nvs_free(); return -ENOMEM; } } @@ -103,9 +103,9 @@ int suspend_nvs_alloc(void) } /** - * suspend_nvs_save - save NVS memory regions + * hibernate_nvs_save - save NVS memory regions */ -void suspend_nvs_save(void) +void hibernate_nvs_save(void) { struct nvs_page *entry; @@ -119,12 +119,12 @@ void suspend_nvs_save(void) } /** - * suspend_nvs_restore - restore NVS memory regions + * hibernate_nvs_restore - restore NVS memory regions * * This function is going to be called with interrupts disabled, so it * cannot iounmap the virtual addresses used to access the NVS region. */ -void suspend_nvs_restore(void) +void hibernate_nvs_restore(void) { struct nvs_page *entry; diff --git a/trunk/kernel/power/suspend.c b/trunk/kernel/power/suspend.c index f37cb7dd4402..56e7dbb8b996 100644 --- a/trunk/kernel/power/suspend.c +++ b/trunk/kernel/power/suspend.c @@ -16,12 +16,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include "power.h" diff --git a/trunk/scripts/mod/modpost.c b/trunk/scripts/mod/modpost.c index f8779006986d..3318692e4e76 100644 --- a/trunk/scripts/mod/modpost.c +++ b/trunk/scripts/mod/modpost.c @@ -1342,7 +1342,7 @@ static unsigned int *reloc_location(struct elf_info *elf, int section = sechdr->sh_info; return (void *)elf->hdr + sechdrs[section].sh_offset + - r->r_offset - sechdrs[section].sh_addr; + (r->r_offset - sechdrs[section].sh_addr); } static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) diff --git a/trunk/security/keys/keyctl.c b/trunk/security/keys/keyctl.c index 6261745e4459..13074b454743 100644 --- a/trunk/security/keys/keyctl.c +++ b/trunk/security/keys/keyctl.c @@ -33,7 +33,7 @@ static int key_get_type_from_user(char *type, ret = strncpy_from_user(type, _type, len); if (ret < 0) - return ret; + return -EFAULT; if (ret == 0 || ret >= len) return -EINVAL; @@ -1080,7 +1080,7 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) return old_setting; error: abort_creds(new); - return ret; + return -EINVAL; } /* end keyctl_set_reqkey_keyring() */