diff --git a/[refs] b/[refs] index e3d41694f2ce..4d953476fe16 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 98c1fc934c097d84dc30c639e9bdb0b992ef53e2 +refs/heads/master: bdb9441e9c325d50b5ae17f7d3205d65b8ed2e5f diff --git a/trunk/Documentation/debugging-via-ohci1394.txt b/trunk/Documentation/debugging-via-ohci1394.txt index c360d4e91b48..de4804e8b396 100644 --- a/trunk/Documentation/debugging-via-ohci1394.txt +++ b/trunk/Documentation/debugging-via-ohci1394.txt @@ -36,15 +36,14 @@ available (notebooks) or too slow for extensive debug information (like ACPI). Drivers ------- -The ohci1394 driver in drivers/ieee1394 initializes the OHCI-1394 controllers -to a working state and enables physical DMA by default for all remote nodes. -This can be turned off by ohci1394's module parameter phys_dma=0. - -The alternative firewire-ohci driver in drivers/firewire uses filtered physical -DMA, hence is not yet suitable for remote debugging. - -Because ohci1394 depends on the PCI enumeration to be completed, an -initialization routine which runs pretty early (long before console_init() +The OHCI-1394 drivers in drivers/firewire and drivers/ieee1394 initialize +the OHCI-1394 controllers to a working state and can be used to enable +physical DMA. By default you only have to load the driver, and physical +DMA access will be granted to all remote nodes, but it can be turned off +when using the ohci1394 driver. + +Because these drivers depend on the PCI enumeration to be completed, an +initialization routine which can runs pretty early (long before console_init(), which makes the printk buffer appear on the console can be called) was written. To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu: diff --git a/trunk/arch/um/kernel/process.c b/trunk/arch/um/kernel/process.c index e8cb9ff183e9..fc50d2f959d1 100644 --- a/trunk/arch/um/kernel/process.c +++ b/trunk/arch/um/kernel/process.c @@ -128,6 +128,8 @@ void *get_current(void) return current; } +extern void schedule_tail(struct task_struct *prev); + /* * This is called magically, by its address being stuffed in a jmp_buf * and being longjmp-d to. diff --git a/trunk/arch/x86/Kconfig.cpu b/trunk/arch/x86/Kconfig.cpu index 6d50064db182..e09a6b73a1aa 100644 --- a/trunk/arch/x86/Kconfig.cpu +++ b/trunk/arch/x86/Kconfig.cpu @@ -377,19 +377,6 @@ config X86_OOSTORE def_bool y depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR -# -# P6_NOPs are a relatively minor optimization that require a family >= -# 6 processor, except that it is broken on certain VIA chips. -# Furthermore, AMD chips prefer a totally different sequence of NOPs -# (which work on all CPUs). As a result, disallow these if we're -# compiling X86_GENERIC but not X86_64 (these NOPs do work on all -# x86-64 capable chips); the list of processors in the right-hand clause -# are the cores that benefit from this optimization. -# -config X86_P6_NOP - def_bool y - depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || PENTIUM4) - config X86_TSC def_bool y depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64 @@ -403,7 +390,6 @@ config X86_CMOV config X86_MINIMUM_CPU_FAMILY int default "64" if X86_64 - default "6" if X86_32 && X86_P6_NOP default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK) default "3" diff --git a/trunk/arch/x86/boot/memory.c b/trunk/arch/x86/boot/memory.c index e77d89f9e8aa..378353956b5d 100644 --- a/trunk/arch/x86/boot/memory.c +++ b/trunk/arch/x86/boot/memory.c @@ -37,12 +37,6 @@ static int detect_memory_e820(void) "=m" (*desc) : "D" (desc), "d" (SMAP), "a" (0xe820)); - /* BIOSes which terminate the chain with CF = 1 as opposed - to %ebx = 0 don't always report the SMAP signature on - the final, failing, probe. */ - if (err) - break; - /* Some BIOSes stop returning SMAP in the middle of the search loop. We don't know exactly how the BIOS screwed up the map at that point, we might have a @@ -53,6 +47,9 @@ static int detect_memory_e820(void) break; } + if (err) + break; + count++; desc++; } while (next && count < E820MAX); diff --git a/trunk/arch/x86/kernel/asm-offsets_32.c b/trunk/arch/x86/kernel/asm-offsets_32.c index 8ea040124f7d..a33d53017997 100644 --- a/trunk/arch/x86/kernel/asm-offsets_32.c +++ b/trunk/arch/x86/kernel/asm-offsets_32.c @@ -128,11 +128,13 @@ void foo(void) OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending); #endif -#if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE) +#ifdef CONFIG_LGUEST_GUEST BLANK(); OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir); +#endif +#ifdef CONFIG_LGUEST BLANK(); OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); diff --git a/trunk/arch/x86/kernel/cpu/common.c b/trunk/arch/x86/kernel/cpu/common.c index a38aafaefc23..f86a3c4a2669 100644 --- a/trunk/arch/x86/kernel/cpu/common.c +++ b/trunk/arch/x86/kernel/cpu/common.c @@ -504,7 +504,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Clear all flags overriden by options */ for (i = 0; i < NCAPINTS; i++) - c->x86_capability[i] &= ~cleared_cpu_caps[i]; + c->x86_capability[i] ^= cleared_cpu_caps[i]; /* Init Machine Check Exception if available. */ mcheck_init(c); diff --git a/trunk/arch/x86/kernel/cpu/mtrr/main.c b/trunk/arch/x86/kernel/cpu/mtrr/main.c index be83336fddba..b6e136f23d3d 100644 --- a/trunk/arch/x86/kernel/cpu/mtrr/main.c +++ b/trunk/arch/x86/kernel/cpu/mtrr/main.c @@ -43,7 +43,6 @@ #include #include #include -#include #include "mtrr.h" u32 num_var_ranges = 0; @@ -650,7 +649,6 @@ static __init int amd_special_default_mtrr(void) /** * mtrr_trim_uncached_memory - trim RAM not covered by MTRRs - * @end_pfn: ending page frame number * * Some buggy BIOSes don't setup the MTRRs properly for systems with certain * memory configurations. This routine checks that the highest MTRR matches @@ -690,11 +688,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) /* kvm/qemu doesn't have mtrr set right, don't trim them all */ if (!highest_pfn) { - if (!kvm_para_available()) { - printk(KERN_WARNING - "WARNING: strange, CPU MTRRs all blank?\n"); - WARN_ON(1); - } + printk(KERN_WARNING "WARNING: strange, CPU MTRRs all blank?\n"); + WARN_ON(1); return 0; } diff --git a/trunk/arch/x86/kernel/cpu/transmeta.c b/trunk/arch/x86/kernel/cpu/transmeta.c index e8b422c1c512..200fb3f9ebfb 100644 --- a/trunk/arch/x86/kernel/cpu/transmeta.c +++ b/trunk/arch/x86/kernel/cpu/transmeta.c @@ -76,6 +76,13 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) /* All Transmeta CPUs have a constant TSC */ set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); + /* If we can run i686 user-space code, call us an i686 */ +#define USER686 ((1 << X86_FEATURE_TSC)|\ + (1 << X86_FEATURE_CX8)|\ + (1 << X86_FEATURE_CMOV)) + if (c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686) + c->x86 = 6; + #ifdef CONFIG_SYSCTL /* randomize_va_space slows us down enormously; it probably triggers retranslation of x86->native bytecode */ diff --git a/trunk/arch/x86/kernel/entry_64.S b/trunk/arch/x86/kernel/entry_64.S index c20c9e7e08dd..2ad9a1bc6a73 100644 --- a/trunk/arch/x86/kernel/entry_64.S +++ b/trunk/arch/x86/kernel/entry_64.S @@ -453,7 +453,6 @@ ENTRY(stub_execve) CFI_REGISTER rip, r11 SAVE_REST FIXUP_TOP_OF_STACK %r11 - movq %rsp, %rcx call sys_execve RESTORE_TOP_OF_STACK %r11 movq %rax,RAX(%rsp) @@ -1037,16 +1036,15 @@ ENDPROC(child_rip) * rdi: name, rsi: argv, rdx: envp * * We want to fallback into: - * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs) + * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs) * * do_sys_execve asm fallback arguments: - * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack + * rdi: name, rsi: argv, rdx: envp, fake frame on the stack */ ENTRY(kernel_execve) CFI_STARTPROC FAKE_STACK_FRAME $0 SAVE_ALL - movq %rsp,%rcx call sys_execve movq %rax, RAX(%rsp) RESTORE_REST diff --git a/trunk/arch/x86/kernel/head_32.S b/trunk/arch/x86/kernel/head_32.S index fd8ca53943a8..25eb98540a41 100644 --- a/trunk/arch/x86/kernel/head_32.S +++ b/trunk/arch/x86/kernel/head_32.S @@ -606,7 +606,7 @@ ENTRY(_stext) .section ".bss.page_aligned","wa" .align PAGE_SIZE_asm #ifdef CONFIG_X86_PAE -swapper_pg_pmd: +ENTRY(swapper_pg_pmd) .fill 1024*KPMDS,4,0 #else ENTRY(swapper_pg_dir) diff --git a/trunk/arch/x86/kernel/head_64.S b/trunk/arch/x86/kernel/head_64.S index a007454133a3..eb415043a929 100644 --- a/trunk/arch/x86/kernel/head_64.S +++ b/trunk/arch/x86/kernel/head_64.S @@ -379,24 +379,18 @@ NEXT_PAGE(level2_ident_pgt) /* Since I easily can, map the first 1G. * Don't set NX because code runs from these pages. */ - PMDS(0, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD) + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC, PTRS_PER_PMD) NEXT_PAGE(level2_kernel_pgt) - /* - * 128 MB kernel mapping. We spend a full page on this pagetable - * anyway. - * - * The kernel code+data+bss must not be bigger than that. - * - * (NOTE: at +128MB starts the module area, see MODULES_VADDR. - * If you want to increase this then increase MODULES_VADDR - * too.) - */ - PMDS(0, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, - KERNEL_IMAGE_SIZE/PMD_SIZE) + /* 40MB kernel mapping. The kernel code cannot be bigger than that. + When you change this change KERNEL_TEXT_SIZE in page.h too. */ + /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ + PMDS(0x0000000000000000, __PAGE_KERNEL_LARGE_EXEC|_PAGE_GLOBAL, KERNEL_TEXT_SIZE/PMD_SIZE) + /* Module mapping starts here */ + .fill (PTRS_PER_PMD - (KERNEL_TEXT_SIZE/PMD_SIZE)),8,0 NEXT_PAGE(level2_spare_pgt) - .fill 512, 8, 0 + .fill 512,8,0 #undef PMDS #undef NEXT_PAGE diff --git a/trunk/arch/x86/kernel/hpet.c b/trunk/arch/x86/kernel/hpet.c index 235fd6c77504..429d084e014d 100644 --- a/trunk/arch/x86/kernel/hpet.c +++ b/trunk/arch/x86/kernel/hpet.c @@ -368,8 +368,8 @@ static int hpet_clocksource_register(void) return 0; } -/** - * hpet_enable - Try to setup the HPET timer. Returns 1 on success. +/* + * Try to setup the HPET timer */ int __init hpet_enable(void) { diff --git a/trunk/arch/x86/kernel/process_64.c b/trunk/arch/x86/kernel/process_64.c index 43f287744f9f..b0cc8f0136d8 100644 --- a/trunk/arch/x86/kernel/process_64.c +++ b/trunk/arch/x86/kernel/process_64.c @@ -730,16 +730,16 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ asmlinkage long sys_execve(char __user *name, char __user * __user *argv, - char __user * __user *envp, struct pt_regs *regs) + char __user * __user *envp, struct pt_regs regs) { long error; char * filename; filename = getname(name); error = PTR_ERR(filename); - if (IS_ERR(filename)) + if (IS_ERR(filename)) return error; - error = do_execve(filename, argv, envp, regs); + error = do_execve(filename, argv, envp, ®s); putname(filename); return error; } diff --git a/trunk/arch/x86/kernel/setup_64.c b/trunk/arch/x86/kernel/setup_64.c index 7637dc91c79b..6fd804f07821 100644 --- a/trunk/arch/x86/kernel/setup_64.c +++ b/trunk/arch/x86/kernel/setup_64.c @@ -1021,7 +1021,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) /* Clear all flags overriden by options */ for (i = 0; i < NCAPINTS; i++) - c->x86_capability[i] &= ~cleared_cpu_caps[i]; + c->x86_capability[i] ^= cleared_cpu_caps[i]; #ifdef CONFIG_X86_MCE mcheck_init(c); diff --git a/trunk/arch/x86/kernel/smpboot_64.c b/trunk/arch/x86/kernel/smpboot_64.c index 0880f2c388a9..d53bd6fcb428 100644 --- a/trunk/arch/x86/kernel/smpboot_64.c +++ b/trunk/arch/x86/kernel/smpboot_64.c @@ -554,10 +554,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) int timeout; unsigned long start_rip; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; - INIT_WORK(&c_idle.work, do_fork_idle); /* allocate memory for gdts of secondary cpus. Hotplug is considered */ if (!cpu_gdt_descr[cpu].address && diff --git a/trunk/arch/x86/kernel/stacktrace.c b/trunk/arch/x86/kernel/stacktrace.c index c28c342c162f..02f0f61f5b11 100644 --- a/trunk/arch/x86/kernel/stacktrace.c +++ b/trunk/arch/x86/kernel/stacktrace.c @@ -25,8 +25,6 @@ static int save_stack_stack(void *data, char *name) static void save_stack_address(void *data, unsigned long addr, int reliable) { struct stack_trace *trace = data; - if (!reliable) - return; if (trace->skip > 0) { trace->skip--; return; @@ -39,8 +37,6 @@ static void save_stack_address_nosched(void *data, unsigned long addr, int reliable) { struct stack_trace *trace = (struct stack_trace *)data; - if (!reliable) - return; if (in_sched_functions(addr)) return; if (trace->skip > 0) { diff --git a/trunk/arch/x86/kernel/tsc_32.c b/trunk/arch/x86/kernel/tsc_32.c index f14cfd9d1f94..43517e324be8 100644 --- a/trunk/arch/x86/kernel/tsc_32.c +++ b/trunk/arch/x86/kernel/tsc_32.c @@ -28,8 +28,7 @@ EXPORT_SYMBOL_GPL(tsc_khz); static int __init tsc_setup(char *str) { printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " - "cannot disable TSC completely.\n"); - mark_tsc_unstable("user disabled TSC"); + "cannot disable TSC.\n"); return 1; } #else diff --git a/trunk/arch/x86/kernel/vsyscall_64.c b/trunk/arch/x86/kernel/vsyscall_64.c index b6be812fac05..3f8242774580 100644 --- a/trunk/arch/x86/kernel/vsyscall_64.c +++ b/trunk/arch/x86/kernel/vsyscall_64.c @@ -44,6 +44,11 @@ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) #define __syscall_clobber "r11","cx","memory" +#define __pa_vsymbol(x) \ + ({unsigned long v; \ + extern char __vsyscall_0; \ + asm("" : "=r" (v) : "0" (x)); \ + ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); }) /* * vsyscall_gtod_data contains data that is : @@ -97,7 +102,7 @@ static __always_inline void do_get_tz(struct timezone * tz) static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz) { int ret; - asm volatile("syscall" + asm volatile("vsysc2: syscall" : "=a" (ret) : "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber ); @@ -107,7 +112,7 @@ static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz) static __always_inline long time_syscall(long *t) { long secs; - asm volatile("syscall" + asm volatile("vsysc1: syscall" : "=a" (secs) : "0" (__NR_time),"D" (t) : __syscall_clobber); return secs; @@ -222,10 +227,50 @@ long __vsyscall(3) venosys_1(void) } #ifdef CONFIG_SYSCTL + +#define SYSCALL 0x050f +#define NOP2 0x9090 + +/* + * NOP out syscall in vsyscall page when not needed. + */ +static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + extern u16 vsysc1, vsysc2; + u16 __iomem *map1; + u16 __iomem *map2; + int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); + if (!write) + return ret; + /* gcc has some trouble with __va(__pa()), so just do it this + way. */ + map1 = ioremap(__pa_vsymbol(&vsysc1), 2); + if (!map1) + return -ENOMEM; + map2 = ioremap(__pa_vsymbol(&vsysc2), 2); + if (!map2) { + ret = -ENOMEM; + goto out; + } + if (!vsyscall_gtod_data.sysctl_enabled) { + writew(SYSCALL, map1); + writew(SYSCALL, map2); + } else { + writew(NOP2, map1); + writew(NOP2, map2); + } + iounmap(map2); +out: + iounmap(map1); + return ret; +} + static ctl_table kernel_table2[] = { { .procname = "vsyscall64", .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int), - .mode = 0644 }, + .mode = 0644, + .proc_handler = vsyscall_sysctl_change }, {} }; @@ -234,6 +279,7 @@ static ctl_table kernel_root_table2[] = { .child = kernel_table2 }, {} }; + #endif /* Assume __initcall executes before all user space. Hopefully kmod diff --git a/trunk/arch/x86/lguest/boot.c b/trunk/arch/x86/lguest/boot.c index cccb38a59653..5afdde4895dc 100644 --- a/trunk/arch/x86/lguest/boot.c +++ b/trunk/arch/x86/lguest/boot.c @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -76,6 +75,15 @@ * behaving in simplified but equivalent ways. In particular, the Guest is the * same kernel as the Host (or at least, built from the same source code). :*/ +/* Declarations for definitions in lguest_guest.S */ +extern char lguest_noirq_start[], lguest_noirq_end[]; +extern const char lgstart_cli[], lgend_cli[]; +extern const char lgstart_sti[], lgend_sti[]; +extern const char lgstart_popf[], lgend_popf[]; +extern const char lgstart_pushf[], lgend_pushf[]; +extern const char lgstart_iret[], lgend_iret[]; +extern void lguest_iret(void); + struct lguest_data lguest_data = { .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF }, .noirq_start = (u32)lguest_noirq_start, @@ -481,7 +489,7 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) { *pmdp = pmdval; lazy_hcall(LHCALL_SET_PMD, __pa(pmdp)&PAGE_MASK, - (__pa(pmdp)&(PAGE_SIZE-1)), 0); + (__pa(pmdp)&(PAGE_SIZE-1))/4, 0); } /* There are a couple of legacy places where the kernel sets a PTE, but we diff --git a/trunk/arch/x86/mm/init_64.c b/trunk/arch/x86/mm/init_64.c index a02a14f0f324..bb652f5a93fb 100644 --- a/trunk/arch/x86/mm/init_64.c +++ b/trunk/arch/x86/mm/init_64.c @@ -172,9 +172,8 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) } /* - * The head.S code sets up the kernel high mapping: - * - * from __START_KERNEL_map to __START_KERNEL_map + size (== _end-_text) + * The head.S code sets up the kernel high mapping from: + * __START_KERNEL_map to __START_KERNEL_map + KERNEL_TEXT_SIZE * * phys_addr holds the negative offset to the kernel, which is added * to the compile time generated pmds. This results in invalid pmds up @@ -516,6 +515,14 @@ void __init mem_init(void) /* clear_bss() already clear the empty_zero_page */ + /* temporary debugging - double check it's true: */ + { + int i; + + for (i = 0; i < 1024; i++) + WARN_ON_ONCE(empty_zero_page[i]); + } + reservedpages = 0; /* this will put all low memory onto the freelists */ diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index 14e48b5a94ba..464d8fc21ce6 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -44,12 +44,6 @@ static inline unsigned long highmap_end_pfn(void) #endif -#ifdef CONFIG_DEBUG_PAGEALLOC -# define debug_pagealloc 1 -#else -# define debug_pagealloc 0 -#endif - static inline int within(unsigned long addr, unsigned long start, unsigned long end) { @@ -361,48 +355,45 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, static LIST_HEAD(page_pool); static unsigned long pool_size, pool_pages, pool_low; -static unsigned long pool_used, pool_failed; +static unsigned long pool_used, pool_failed, pool_refill; -static void cpa_fill_pool(struct page **ret) +static void cpa_fill_pool(void) { - gfp_t gfp = GFP_KERNEL; - unsigned long flags; struct page *p; + gfp_t gfp = GFP_KERNEL; + /* Do not allocate from interrupt context */ + if (in_irq() || irqs_disabled()) + return; /* - * Avoid recursion (on debug-pagealloc) and also signal - * our priority to get to these pagetables: + * Check unlocked. I does not matter when we have one more + * page in the pool. The bit lock avoids recursive pool + * allocations: */ - if (current->flags & PF_MEMALLOC) + if (pool_pages >= pool_size || test_and_set_bit_lock(0, &pool_refill)) return; - current->flags |= PF_MEMALLOC; +#ifdef CONFIG_DEBUG_PAGEALLOC /* - * Allocate atomically from atomic contexts: + * We could do: + * gfp = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + * but this fails on !PREEMPT kernels */ - if (in_atomic() || irqs_disabled() || debug_pagealloc) - gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN; + gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN; +#endif - while (pool_pages < pool_size || (ret && !*ret)) { + while (pool_pages < pool_size) { p = alloc_pages(gfp, 0); if (!p) { pool_failed++; break; } - /* - * If the call site needs a page right now, provide it: - */ - if (ret && !*ret) { - *ret = p; - continue; - } - spin_lock_irqsave(&pgd_lock, flags); + spin_lock_irq(&pgd_lock); list_add(&p->lru, &page_pool); pool_pages++; - spin_unlock_irqrestore(&pgd_lock, flags); + spin_unlock_irq(&pgd_lock); } - - current->flags &= ~PF_MEMALLOC; + clear_bit_unlock(0, &pool_refill); } #define SHIFT_MB (20 - PAGE_SHIFT) @@ -423,15 +414,11 @@ void __init cpa_init(void) * GiB. Shift MiB to Gib and multiply the result by * POOL_PAGES_PER_GB: */ - if (debug_pagealloc) { - gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB; - pool_size = POOL_PAGES_PER_GB * gb; - } else { - pool_size = 1; - } + gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB; + pool_size = POOL_PAGES_PER_GB * gb; pool_low = pool_size; - cpa_fill_pool(NULL); + cpa_fill_pool(); printk(KERN_DEBUG "CPA: page pool initialized %lu of %lu pages preallocated\n", pool_pages, pool_size); @@ -453,20 +440,16 @@ static int split_large_page(pte_t *kpte, unsigned long address) spin_lock_irqsave(&pgd_lock, flags); if (list_empty(&page_pool)) { spin_unlock_irqrestore(&pgd_lock, flags); - base = NULL; - cpa_fill_pool(&base); - if (!base) - return -ENOMEM; - spin_lock_irqsave(&pgd_lock, flags); - } else { - base = list_first_entry(&page_pool, struct page, lru); - list_del(&base->lru); - pool_pages--; - - if (pool_pages < pool_low) - pool_low = pool_pages; + return -ENOMEM; } + base = list_first_entry(&page_pool, struct page, lru); + list_del(&base->lru); + pool_pages--; + + if (pool_pages < pool_low) + pool_low = pool_pages; + /* * Check for races, another CPU might have split this page * up for us already: @@ -751,8 +734,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, cpa_flush_all(cache); out: - cpa_fill_pool(NULL); - + cpa_fill_pool(); return ret; } @@ -915,7 +897,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable) * Try to refill the page pool here. We can do this only after * the tlb flush. */ - cpa_fill_pool(NULL); + cpa_fill_pool(); } #ifdef CONFIG_HIBERNATION diff --git a/trunk/arch/x86/vdso/Makefile b/trunk/arch/x86/vdso/Makefile index b8bd0c4aa02e..f385a4b4a484 100644 --- a/trunk/arch/x86/vdso/Makefile +++ b/trunk/arch/x86/vdso/Makefile @@ -48,7 +48,7 @@ obj-$(VDSO64-y) += vdso-syms.lds # Match symbols in the DSO that look like VDSO*; produce a file of constants. # sed-vdsosym := -e 's/^00*/0/' \ - -e 's/^\([[:xdigit:]]*\) . \(VDSO[[:alnum:]_]*\)$$/\2 = 0x\1;/p' + -e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p' quiet_cmd_vdsosym = VDSOSYM $@ cmd_vdsosym = $(NM) $< | sed -n $(sed-vdsosym) | LC_ALL=C sort > $@ diff --git a/trunk/drivers/firewire/fw-cdev.c b/trunk/drivers/firewire/fw-cdev.c index 46bc197a047f..7e73cbaa4121 100644 --- a/trunk/drivers/firewire/fw-cdev.c +++ b/trunk/drivers/firewire/fw-cdev.c @@ -109,17 +109,15 @@ static int fw_device_op_open(struct inode *inode, struct file *file) struct client *client; unsigned long flags; - device = fw_device_get_by_devt(inode->i_rdev); + device = fw_device_from_devt(inode->i_rdev); if (device == NULL) return -ENODEV; client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) { - fw_device_put(device); + if (client == NULL) return -ENOMEM; - } - client->device = device; + client->device = fw_device_get(device); INIT_LIST_HEAD(&client->event_list); INIT_LIST_HEAD(&client->resource_list); spin_lock_init(&client->lock); @@ -646,10 +644,6 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) struct fw_cdev_create_iso_context *request = buffer; struct fw_iso_context *context; - /* We only support one context at this time. */ - if (client->iso_context != NULL) - return -EBUSY; - if (request->channel > 63) return -EINVAL; @@ -796,9 +790,8 @@ static int ioctl_start_iso(struct client *client, void *buffer) { struct fw_cdev_start_iso *request = buffer; - if (client->iso_context == NULL || request->handle != 0) + if (request->handle != 0) return -EINVAL; - if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { if (request->tags == 0 || request->tags > 15) return -EINVAL; @@ -815,7 +808,7 @@ static int ioctl_stop_iso(struct client *client, void *buffer) { struct fw_cdev_stop_iso *request = buffer; - if (client->iso_context == NULL || request->handle != 0) + if (request->handle != 0) return -EINVAL; return fw_iso_context_stop(client->iso_context); diff --git a/trunk/drivers/firewire/fw-device.c b/trunk/drivers/firewire/fw-device.c index 2ab13e0f3469..de9066e69adf 100644 --- a/trunk/drivers/firewire/fw-device.c +++ b/trunk/drivers/firewire/fw-device.c @@ -358,9 +358,12 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fw_device *device = fw_device(dev); + u64 guid; - return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n", - device->config_rom[3], device->config_rom[4]); + guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4]; + + return snprintf(buf, PAGE_SIZE, "0x%016llx\n", + (unsigned long long)guid); } static struct device_attribute fw_device_attributes[] = { @@ -607,14 +610,12 @@ static DECLARE_RWSEM(idr_rwsem); static DEFINE_IDR(fw_device_idr); int fw_cdev_major; -struct fw_device *fw_device_get_by_devt(dev_t devt) +struct fw_device *fw_device_from_devt(dev_t devt) { struct fw_device *device; down_read(&idr_rwsem); device = idr_find(&fw_device_idr, MINOR(devt)); - if (device) - fw_device_get(device); up_read(&idr_rwsem); return device; @@ -626,14 +627,13 @@ static void fw_device_shutdown(struct work_struct *work) container_of(work, struct fw_device, work.work); int minor = MINOR(device->device.devt); - fw_device_cdev_remove(device); - device_for_each_child(&device->device, NULL, shutdown_unit); - device_unregister(&device->device); - down_write(&idr_rwsem); idr_remove(&fw_device_idr, minor); up_write(&idr_rwsem); - fw_device_put(device); + + fw_device_cdev_remove(device); + device_for_each_child(&device->device, NULL, shutdown_unit); + device_unregister(&device->device); } static struct device_type fw_device_type = { @@ -682,13 +682,10 @@ static void fw_device_init(struct work_struct *work) } err = -ENOMEM; - - fw_device_get(device); down_write(&idr_rwsem); if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) err = idr_get_new(&fw_device_idr, device, &minor); up_write(&idr_rwsem); - if (err < 0) goto error; @@ -720,22 +717,13 @@ static void fw_device_init(struct work_struct *work) */ if (atomic_cmpxchg(&device->state, FW_DEVICE_INITIALIZING, - FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) { + FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) fw_device_shutdown(&device->work.work); - } else { - if (device->config_rom_retries) - fw_notify("created device %s: GUID %08x%08x, S%d00, " - "%d config ROM retries\n", - device->device.bus_id, - device->config_rom[3], device->config_rom[4], - 1 << device->max_speed, - device->config_rom_retries); - else - fw_notify("created device %s: GUID %08x%08x, S%d00\n", - device->device.bus_id, - device->config_rom[3], device->config_rom[4], - 1 << device->max_speed); - } + else + fw_notify("created new fw device %s " + "(%d config rom retries, S%d00)\n", + device->device.bus_id, device->config_rom_retries, + 1 << device->max_speed); /* * Reschedule the IRM work if we just finished reading the @@ -753,9 +741,7 @@ static void fw_device_init(struct work_struct *work) idr_remove(&fw_device_idr, minor); up_write(&idr_rwsem); error: - fw_device_put(device); /* fw_device_idr's reference */ - - put_device(&device->device); /* our reference */ + put_device(&device->device); } static int update_unit(struct device *dev, void *data) diff --git a/trunk/drivers/firewire/fw-device.h b/trunk/drivers/firewire/fw-device.h index 43808c02793e..0854fe2bc110 100644 --- a/trunk/drivers/firewire/fw-device.h +++ b/trunk/drivers/firewire/fw-device.h @@ -77,13 +77,13 @@ fw_device_is_shutdown(struct fw_device *device) } struct fw_device *fw_device_get(struct fw_device *device); -struct fw_device *fw_device_get_by_devt(dev_t devt); void fw_device_put(struct fw_device *device); int fw_device_enable_phys_dma(struct fw_device *device); void fw_device_cdev_update(struct fw_device *device); void fw_device_cdev_remove(struct fw_device *device); +struct fw_device *fw_device_from_devt(dev_t devt); extern int fw_cdev_major; struct fw_unit { diff --git a/trunk/drivers/firewire/fw-sbp2.c b/trunk/drivers/firewire/fw-sbp2.c index 5259491580fc..19ece9b6d742 100644 --- a/trunk/drivers/firewire/fw-sbp2.c +++ b/trunk/drivers/firewire/fw-sbp2.c @@ -28,15 +28,14 @@ * and many others. */ -#include -#include -#include -#include #include -#include #include #include +#include +#include #include +#include +#include #include #include #include @@ -48,9 +47,9 @@ #include #include -#include "fw-device.h" -#include "fw-topology.h" #include "fw-transaction.h" +#include "fw-topology.h" +#include "fw-device.h" /* * So far only bridges from Oxford Semiconductor are known to support @@ -83,9 +82,6 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " * Avoids access beyond actual disk limits on devices with an off-by-one bug. * Don't use this with devices which don't have this bug. * - * - delay inquiry - * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. - * * - override internal blacklist * Instead of adding to the built-in blacklist, use only the workarounds * specified in the module load parameter. @@ -95,8 +91,6 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " #define SBP2_WORKAROUND_INQUIRY_36 0x2 #define SBP2_WORKAROUND_MODE_SENSE_8 0x4 #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 -#define SBP2_INQUIRY_DELAY 12 #define SBP2_WORKAROUND_OVERRIDE 0x100 static int sbp2_param_workarounds; @@ -106,7 +100,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) - ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) ", or a combination)"); @@ -139,7 +132,6 @@ struct sbp2_logical_unit { int generation; int retries; struct delayed_work work; - bool blocked; }; /* @@ -149,18 +141,16 @@ struct sbp2_logical_unit { struct sbp2_target { struct kref kref; struct fw_unit *unit; - const char *bus_id; - struct list_head lu_list; u64 management_agent_address; int directory_id; int node_id; int address_high; - unsigned int workarounds; - unsigned int mgt_orb_timeout; - int dont_block; /* counter for each logical unit */ - int blocked; /* ditto */ + unsigned workarounds; + struct list_head lu_list; + + unsigned int mgt_orb_timeout; }; /* @@ -170,7 +160,7 @@ struct sbp2_target { */ #define SBP2_MIN_LOGIN_ORB_TIMEOUT 5000U /* Timeout in ms */ #define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */ -#define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */ +#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */ #define SBP2_ORB_NULL 0x80000000 #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 @@ -307,7 +297,7 @@ struct sbp2_command_orb { static const struct { u32 firmware_revision; u32 model; - unsigned int workarounds; + unsigned workarounds; } sbp2_workarounds_table[] = { /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { .firmware_revision = 0x002800, @@ -315,11 +305,6 @@ static const struct { .workarounds = SBP2_WORKAROUND_INQUIRY_36 | SBP2_WORKAROUND_MODE_SENSE_8, }, - /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { - .firmware_revision = 0x002800, - .model = 0x000000, - .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY, - }, /* Initio bridges, actually only needed for some older ones */ { .firmware_revision = 0x000200, .model = ~0, @@ -516,9 +501,6 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, unsigned int timeout; int retval = -ENOMEM; - if (function == SBP2_LOGOUT_REQUEST && fw_device_is_shutdown(device)) - return 0; - orb = kzalloc(sizeof(*orb), GFP_ATOMIC); if (orb == NULL) return -ENOMEM; @@ -571,20 +553,20 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, retval = -EIO; if (sbp2_cancel_orbs(lu) == 0) { - fw_error("%s: orb reply timed out, rcode=0x%02x\n", - lu->tgt->bus_id, orb->base.rcode); + fw_error("orb reply timed out, rcode=0x%02x\n", + orb->base.rcode); goto out; } if (orb->base.rcode != RCODE_COMPLETE) { - fw_error("%s: management write failed, rcode 0x%02x\n", - lu->tgt->bus_id, orb->base.rcode); + fw_error("management write failed, rcode 0x%02x\n", + orb->base.rcode); goto out; } if (STATUS_GET_RESPONSE(orb->status) != 0 || STATUS_GET_SBP_STATUS(orb->status) != 0) { - fw_error("%s: error status: %d:%d\n", lu->tgt->bus_id, + fw_error("error status: %d:%d\n", STATUS_GET_RESPONSE(orb->status), STATUS_GET_SBP_STATUS(orb->status)); goto out; @@ -608,147 +590,29 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, static void complete_agent_reset_write(struct fw_card *card, int rcode, - void *payload, size_t length, void *done) -{ - complete(done); -} - -static void sbp2_agent_reset(struct sbp2_logical_unit *lu) + void *payload, size_t length, void *data) { - struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - DECLARE_COMPLETION_ONSTACK(done); - struct fw_transaction t; - static u32 z; - - fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - lu->command_block_agent_address + SBP2_AGENT_RESET, - &z, sizeof(z), complete_agent_reset_write, &done); - wait_for_completion(&done); -} + struct fw_transaction *t = data; -static void -complete_agent_reset_write_no_wait(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - kfree(data); + kfree(t); } -static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) +static int sbp2_agent_reset(struct sbp2_logical_unit *lu) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_transaction *t; - static u32 z; + static u32 zero; - t = kmalloc(sizeof(*t), GFP_ATOMIC); + t = kzalloc(sizeof(*t), GFP_ATOMIC); if (t == NULL) - return; + return -ENOMEM; fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, lu->tgt->node_id, lu->generation, device->max_speed, lu->command_block_agent_address + SBP2_AGENT_RESET, - &z, sizeof(z), complete_agent_reset_write_no_wait, t); -} - -static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation) -{ - struct fw_card *card = fw_device(lu->tgt->unit->device.parent)->card; - unsigned long flags; - - /* serialize with comparisons of lu->generation and card->generation */ - spin_lock_irqsave(&card->lock, flags); - lu->generation = generation; - spin_unlock_irqrestore(&card->lock, flags); -} - -static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) -{ - /* - * We may access dont_block without taking card->lock here: - * All callers of sbp2_allow_block() and all callers of sbp2_unblock() - * are currently serialized against each other. - * And a wrong result in sbp2_conditionally_block()'s access of - * dont_block is rather harmless, it simply misses its first chance. - */ - --lu->tgt->dont_block; -} - -/* - * Blocks lu->tgt if all of the following conditions are met: - * - Login, INQUIRY, and high-level SCSI setup of all of the target's - * logical units have been finished (indicated by dont_block == 0). - * - lu->generation is stale. - * - * Note, scsi_block_requests() must be called while holding card->lock, - * otherwise it might foil sbp2_[conditionally_]unblock()'s attempt to - * unblock the target. - */ -static void sbp2_conditionally_block(struct sbp2_logical_unit *lu) -{ - struct sbp2_target *tgt = lu->tgt; - struct fw_card *card = fw_device(tgt->unit->device.parent)->card; - struct Scsi_Host *shost = - container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - if (!tgt->dont_block && !lu->blocked && - lu->generation != card->generation) { - lu->blocked = true; - if (++tgt->blocked == 1) { - scsi_block_requests(shost); - fw_notify("blocked %s\n", lu->tgt->bus_id); - } - } - spin_unlock_irqrestore(&card->lock, flags); -} - -/* - * Unblocks lu->tgt as soon as all its logical units can be unblocked. - * Note, it is harmless to run scsi_unblock_requests() outside the - * card->lock protected section. On the other hand, running it inside - * the section might clash with shost->host_lock. - */ -static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu) -{ - struct sbp2_target *tgt = lu->tgt; - struct fw_card *card = fw_device(tgt->unit->device.parent)->card; - struct Scsi_Host *shost = - container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - unsigned long flags; - bool unblock = false; - - spin_lock_irqsave(&card->lock, flags); - if (lu->blocked && lu->generation == card->generation) { - lu->blocked = false; - unblock = --tgt->blocked == 0; - } - spin_unlock_irqrestore(&card->lock, flags); - - if (unblock) { - scsi_unblock_requests(shost); - fw_notify("unblocked %s\n", lu->tgt->bus_id); - } -} - -/* - * Prevents future blocking of tgt and unblocks it. - * Note, it is harmless to run scsi_unblock_requests() outside the - * card->lock protected section. On the other hand, running it inside - * the section might clash with shost->host_lock. - */ -static void sbp2_unblock(struct sbp2_target *tgt) -{ - struct fw_card *card = fw_device(tgt->unit->device.parent)->card; - struct Scsi_Host *shost = - container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - ++tgt->dont_block; - spin_unlock_irqrestore(&card->lock, flags); + &zero, sizeof(zero), complete_agent_reset_write, t); - scsi_unblock_requests(shost); + return 0; } static void sbp2_release_target(struct kref *kref) @@ -757,24 +621,23 @@ static void sbp2_release_target(struct kref *kref) struct sbp2_logical_unit *lu, *next; struct Scsi_Host *shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - - /* prevent deadlocks */ - sbp2_unblock(tgt); + struct fw_device *device = fw_device(tgt->unit->device.parent); list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { - if (lu->sdev) { + if (lu->sdev) scsi_remove_device(lu->sdev); - scsi_device_put(lu->sdev); - } - sbp2_send_management_orb(lu, tgt->node_id, lu->generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); + + if (!fw_device_is_shutdown(device)) + sbp2_send_management_orb(lu, tgt->node_id, + lu->generation, SBP2_LOGOUT_REQUEST, + lu->login_id, NULL); fw_core_remove_address_handler(&lu->address_handler); list_del(&lu->link); kfree(lu); } scsi_remove_host(shost); - fw_notify("released %s\n", tgt->bus_id); + fw_notify("released %s\n", tgt->unit->device.bus_id); put_device(&tgt->unit->device); scsi_host_put(shost); @@ -803,43 +666,33 @@ static void sbp2_login(struct work_struct *work) { struct sbp2_logical_unit *lu = container_of(work, struct sbp2_logical_unit, work.work); - struct sbp2_target *tgt = lu->tgt; - struct fw_device *device = fw_device(tgt->unit->device.parent); - struct Scsi_Host *shost; + struct Scsi_Host *shost = + container_of((void *)lu->tgt, struct Scsi_Host, hostdata[0]); struct scsi_device *sdev; struct scsi_lun eight_bytes_lun; + struct fw_unit *unit = lu->tgt->unit; + struct fw_device *device = fw_device(unit->device.parent); struct sbp2_login_response response; int generation, node_id, local_node_id; - if (fw_device_is_shutdown(device)) - goto out; - generation = device->generation; smp_rmb(); /* node_id must not be older than generation */ node_id = device->node_id; local_node_id = device->card->node_id; - /* If this is a re-login attempt, log out, or we might be rejected. */ - if (lu->sdev) - sbp2_send_management_orb(lu, device->node_id, generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); - if (sbp2_send_management_orb(lu, node_id, generation, SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { - if (lu->retries++ < 5) { + if (lu->retries++ < 5) sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); - } else { - fw_error("%s: failed to login to LUN %04x\n", - tgt->bus_id, lu->lun); - /* Let any waiting I/O fail from now on. */ - sbp2_unblock(lu->tgt); - } + else + fw_error("failed to login to %s LUN %04x\n", + unit->device.bus_id, lu->lun); goto out; } - tgt->node_id = node_id; - tgt->address_high = local_node_id << 16; - sbp2_set_generation(lu, generation); + lu->generation = generation; + lu->tgt->node_id = node_id; + lu->tgt->address_high = local_node_id << 16; /* Get command block agent offset and login id. */ lu->command_block_agent_address = @@ -847,8 +700,8 @@ static void sbp2_login(struct work_struct *work) response.command_block_agent.low; lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); - fw_notify("%s: logged in to LUN %04x (%d retries)\n", - tgt->bus_id, lu->lun, lu->retries); + fw_notify("logged in to %s LUN %04x (%d retries)\n", + unit->device.bus_id, lu->lun, lu->retries); #if 0 /* FIXME: The linux1394 sbp2 does this last step. */ @@ -858,62 +711,26 @@ static void sbp2_login(struct work_struct *work) PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect); sbp2_agent_reset(lu); - /* This was a re-login. */ - if (lu->sdev) { - sbp2_cancel_orbs(lu); - sbp2_conditionally_unblock(lu); - goto out; - } - - if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) - ssleep(SBP2_INQUIRY_DELAY); - memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff; eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff; - shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); sdev = __scsi_add_device(shost, 0, 0, scsilun_to_int(&eight_bytes_lun), lu); - /* - * FIXME: We are unable to perform reconnects while in sbp2_login(). - * Therefore __scsi_add_device() will get into trouble if a bus reset - * happens in parallel. It will either fail or leave us with an - * unusable sdev. As a workaround we check for this and retry the - * whole login and SCSI probing. - */ - - /* Reported error during __scsi_add_device() */ - if (IS_ERR(sdev)) - goto out_logout_login; - - /* Unreported error during __scsi_add_device() */ - smp_rmb(); /* get current card generation */ - if (generation != device->card->generation) { - scsi_remove_device(sdev); + if (IS_ERR(sdev)) { + sbp2_send_management_orb(lu, node_id, generation, + SBP2_LOGOUT_REQUEST, lu->login_id, NULL); + /* + * Set this back to sbp2_login so we fall back and + * retry login on bus reset. + */ + PREPARE_DELAYED_WORK(&lu->work, sbp2_login); + } else { + lu->sdev = sdev; scsi_device_put(sdev); - goto out_logout_login; } - - /* No error during __scsi_add_device() */ - lu->sdev = sdev; - sbp2_allow_block(lu); - goto out; - - out_logout_login: - smp_rmb(); /* generation may have changed */ - generation = device->generation; - smp_rmb(); /* node_id must not be older than generation */ - - sbp2_send_management_orb(lu, device->node_id, generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); - /* - * If a bus reset happened, sbp2_update will have requeued - * lu->work already. Reset the work from reconnect to login. - */ - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); out: - sbp2_target_put(tgt); + sbp2_target_put(lu->tgt); } static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) @@ -938,8 +755,6 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) lu->sdev = NULL; lu->lun = lun_entry & 0xffff; lu->retries = 0; - lu->blocked = false; - ++tgt->dont_block; INIT_LIST_HEAD(&lu->orb_list); INIT_DELAYED_WORK(&lu->work, sbp2_login); @@ -998,7 +813,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory, if (timeout > tgt->mgt_orb_timeout) fw_notify("%s: config rom contains %ds " "management ORB timeout, limiting " - "to %ds\n", tgt->bus_id, + "to %ds\n", tgt->unit->device.bus_id, timeout / 1000, tgt->mgt_orb_timeout / 1000); break; @@ -1021,12 +836,12 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, u32 firmware_revision) { int i; - unsigned int w = sbp2_param_workarounds; + unsigned w = sbp2_param_workarounds; if (w) fw_notify("Please notify linux1394-devel@lists.sourceforge.net " "if you need the workarounds parameter for %s\n", - tgt->bus_id); + tgt->unit->device.bus_id); if (w & SBP2_WORKAROUND_OVERRIDE) goto out; @@ -1048,7 +863,8 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, if (w) fw_notify("Workarounds for %s: 0x%x " "(firmware_revision 0x%06x, model_id 0x%06x)\n", - tgt->bus_id, w, firmware_revision, model); + tgt->unit->device.bus_id, + w, firmware_revision, model); tgt->workarounds = w; } @@ -1072,7 +888,6 @@ static int sbp2_probe(struct device *dev) tgt->unit = unit; kref_init(&tgt->kref); INIT_LIST_HEAD(&tgt->lu_list); - tgt->bus_id = unit->device.bus_id; if (fw_device_enable_phys_dma(device) < 0) goto fail_shost_put; @@ -1123,13 +938,10 @@ static void sbp2_reconnect(struct work_struct *work) { struct sbp2_logical_unit *lu = container_of(work, struct sbp2_logical_unit, work.work); - struct sbp2_target *tgt = lu->tgt; - struct fw_device *device = fw_device(tgt->unit->device.parent); + struct fw_unit *unit = lu->tgt->unit; + struct fw_device *device = fw_device(unit->device.parent); int generation, node_id, local_node_id; - if (fw_device_is_shutdown(device)) - goto out; - generation = device->generation; smp_rmb(); /* node_id must not be older than generation */ node_id = device->node_id; @@ -1138,17 +950,10 @@ static void sbp2_reconnect(struct work_struct *work) if (sbp2_send_management_orb(lu, node_id, generation, SBP2_RECONNECT_REQUEST, lu->login_id, NULL) < 0) { - /* - * If reconnect was impossible even though we are in the - * current generation, fall back and try to log in again. - * - * We could check for "Function rejected" status, but - * looking at the bus generation as simpler and more general. - */ - smp_rmb(); /* get current card generation */ - if (generation == device->card->generation || - lu->retries++ >= 5) { - fw_error("%s: failed to reconnect\n", tgt->bus_id); + if (lu->retries++ >= 5) { + fw_error("failed to reconnect to %s\n", + unit->device.bus_id); + /* Fall back and try to log in again. */ lu->retries = 0; PREPARE_DELAYED_WORK(&lu->work, sbp2_login); } @@ -1156,18 +961,17 @@ static void sbp2_reconnect(struct work_struct *work) goto out; } - tgt->node_id = node_id; - tgt->address_high = local_node_id << 16; - sbp2_set_generation(lu, generation); + lu->generation = generation; + lu->tgt->node_id = node_id; + lu->tgt->address_high = local_node_id << 16; - fw_notify("%s: reconnected to LUN %04x (%d retries)\n", - tgt->bus_id, lu->lun, lu->retries); + fw_notify("reconnected to %s LUN %04x (%d retries)\n", + unit->device.bus_id, lu->lun, lu->retries); sbp2_agent_reset(lu); sbp2_cancel_orbs(lu); - sbp2_conditionally_unblock(lu); out: - sbp2_target_put(tgt); + sbp2_target_put(lu->tgt); } static void sbp2_update(struct fw_unit *unit) @@ -1182,7 +986,6 @@ static void sbp2_update(struct fw_unit *unit) * Iteration over tgt->lu_list is therefore safe here. */ list_for_each_entry(lu, &tgt->lu_list, link) { - sbp2_conditionally_block(lu); lu->retries = 0; sbp2_queue_work(lu, 0); } @@ -1260,7 +1063,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) if (status != NULL) { if (STATUS_GET_DEAD(*status)) - sbp2_agent_reset_no_wait(orb->lu); + sbp2_agent_reset(orb->lu); switch (STATUS_GET_RESPONSE(*status)) { case SBP2_STATUS_REQUEST_COMPLETE: @@ -1286,7 +1089,6 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) * or when sending the write (less likely). */ result = DID_BUS_BUSY << 16; - sbp2_conditionally_block(orb->lu); } dma_unmap_single(device->card->device, orb->base.request_bus, @@ -1395,7 +1197,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) struct sbp2_logical_unit *lu = cmd->device->hostdata; struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct sbp2_command_orb *orb; - unsigned int max_payload; + unsigned max_payload; int retval = SCSI_MLQUEUE_HOST_BUSY; /* @@ -1473,10 +1275,6 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) { struct sbp2_logical_unit *lu = sdev->hostdata; - /* (Re-)Adding logical units via the SCSI stack is not supported. */ - if (!lu) - return -ENOSYS; - sdev->allow_restart = 1; /* @@ -1521,7 +1319,7 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) { struct sbp2_logical_unit *lu = cmd->device->hostdata; - fw_notify("%s: sbp2_scsi_abort\n", lu->tgt->bus_id); + fw_notify("sbp2_scsi_abort\n"); sbp2_agent_reset(lu); sbp2_cancel_orbs(lu); diff --git a/trunk/drivers/ieee1394/sbp2.c b/trunk/drivers/ieee1394/sbp2.c index 9e2b1964d71a..28e155a9e2a5 100644 --- a/trunk/drivers/ieee1394/sbp2.c +++ b/trunk/drivers/ieee1394/sbp2.c @@ -183,9 +183,6 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " * Avoids access beyond actual disk limits on devices with an off-by-one bug. * Don't use this with devices which don't have this bug. * - * - delay inquiry - * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. - * * - override internal blacklist * Instead of adding to the built-in blacklist, use only the workarounds * specified in the module load parameter. @@ -198,7 +195,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) - ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) ", or a combination)"); @@ -361,11 +357,6 @@ static const struct { .workarounds = SBP2_WORKAROUND_INQUIRY_36 | SBP2_WORKAROUND_MODE_SENSE_8, }, - /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { - .firmware_revision = 0x002800, - .model_id = 0x000000, - .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY, - }, /* Initio bridges, actually only needed for some older ones */ { .firmware_revision = 0x000200, .model_id = SBP2_ROM_VALUE_WILDCARD, @@ -923,9 +914,6 @@ static int sbp2_start_device(struct sbp2_lu *lu) sbp2_agent_reset(lu, 1); sbp2_max_speed_and_size(lu); - if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) - ssleep(SBP2_INQUIRY_DELAY); - error = scsi_add_device(lu->shost, 0, lu->ud->id, 0); if (error) { SBP2_ERR("scsi_add_device failed"); @@ -1974,9 +1962,6 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev) { struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0]; - if (sdev->lun != 0 || sdev->id != lu->ud->id || sdev->channel != 0) - return -ENODEV; - lu->sdev = sdev; sdev->allow_restart = 1; diff --git a/trunk/drivers/ieee1394/sbp2.h b/trunk/drivers/ieee1394/sbp2.h index 80d8e097b065..d2ecb0d8a1bb 100644 --- a/trunk/drivers/ieee1394/sbp2.h +++ b/trunk/drivers/ieee1394/sbp2.h @@ -343,8 +343,6 @@ enum sbp2lu_state_types { #define SBP2_WORKAROUND_INQUIRY_36 0x2 #define SBP2_WORKAROUND_MODE_SENSE_8 0x4 #define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 -#define SBP2_INQUIRY_DELAY 12 #define SBP2_WORKAROUND_OVERRIDE 0x100 #endif /* SBP2_H */ diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index 91a1bd67ac1d..96ee899d6502 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -314,12 +314,9 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer) static int lstats_show_proc(struct seq_file *m, void *v) { int i; - struct inode *inode = m->private; - struct task_struct *task = get_proc_task(inode); - - if (!task) - return -ESRCH; + struct task_struct *task = m->private; seq_puts(m, "Latency Top version : v0.1\n"); + for (i = 0; i < 32; i++) { if (task->latency_record[i].backtrace[0]) { int q; @@ -344,24 +341,32 @@ static int lstats_show_proc(struct seq_file *m, void *v) } } - put_task_struct(task); return 0; } static int lstats_open(struct inode *inode, struct file *file) { - return single_open(file, lstats_show_proc, inode); + int ret; + struct seq_file *m; + struct task_struct *task = get_proc_task(inode); + + ret = single_open(file, lstats_show_proc, NULL); + if (!ret) { + m = file->private_data; + m->private = task; + } + return ret; } static ssize_t lstats_write(struct file *file, const char __user *buf, size_t count, loff_t *offs) { - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct seq_file *m; + struct task_struct *task; - if (!task) - return -ESRCH; + m = file->private_data; + task = m->private; clear_all_latency_tracing(task); - put_task_struct(task); return count; } diff --git a/trunk/include/asm-x86/futex.h b/trunk/include/asm-x86/futex.h index c9952ea9f698..cd9f894dd2d7 100644 --- a/trunk/include/asm-x86/futex.h +++ b/trunk/include/asm-x86/futex.h @@ -102,13 +102,6 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr) static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { - -#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP) - /* Real i386 machines have no cmpxchg instruction */ - if (boot_cpu_data.x86 == 3) - return -ENOSYS; -#endif - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; diff --git a/trunk/include/asm-x86/lguest.h b/trunk/include/asm-x86/lguest.h index 9b17571e9bc3..4d9367b72976 100644 --- a/trunk/include/asm-x86/lguest.h +++ b/trunk/include/asm-x86/lguest.h @@ -23,17 +23,6 @@ /* Found in switcher.S */ extern unsigned long default_idt_entries[]; -/* Declarations for definitions in lguest_guest.S */ -extern char lguest_noirq_start[], lguest_noirq_end[]; -extern const char lgstart_cli[], lgend_cli[]; -extern const char lgstart_sti[], lgend_sti[]; -extern const char lgstart_popf[], lgend_popf[]; -extern const char lgstart_pushf[], lgend_pushf[]; -extern const char lgstart_iret[], lgend_iret[]; - -extern void lguest_iret(void); -extern void lguest_init(void); - struct lguest_regs { /* Manually saved part. */ diff --git a/trunk/include/asm-x86/nops.h b/trunk/include/asm-x86/nops.h index e3b2bce0aff8..fec025c7f58c 100644 --- a/trunk/include/asm-x86/nops.h +++ b/trunk/include/asm-x86/nops.h @@ -3,29 +3,17 @@ /* Define nops for use with alternative() */ -/* generic versions from gas - 1: nop - 2: movl %esi,%esi - 3: leal 0x00(%esi),%esi - 4: leal 0x00(,%esi,1),%esi - 6: leal 0x00000000(%esi),%esi - 7: leal 0x00000000(,%esi,1),%esi -*/ -#define GENERIC_NOP1 ".byte 0x90\n" -#define GENERIC_NOP2 ".byte 0x89,0xf6\n" -#define GENERIC_NOP3 ".byte 0x8d,0x76,0x00\n" -#define GENERIC_NOP4 ".byte 0x8d,0x74,0x26,0x00\n" -#define GENERIC_NOP5 GENERIC_NOP1 GENERIC_NOP4 -#define GENERIC_NOP6 ".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n" -#define GENERIC_NOP7 ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n" -#define GENERIC_NOP8 GENERIC_NOP1 GENERIC_NOP7 +/* generic versions from gas */ +#define GENERIC_NOP1 ".byte 0x90\n" +#define GENERIC_NOP2 ".byte 0x89,0xf6\n" +#define GENERIC_NOP3 ".byte 0x8d,0x76,0x00\n" +#define GENERIC_NOP4 ".byte 0x8d,0x74,0x26,0x00\n" +#define GENERIC_NOP5 GENERIC_NOP1 GENERIC_NOP4 +#define GENERIC_NOP6 ".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n" +#define GENERIC_NOP7 ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n" +#define GENERIC_NOP8 GENERIC_NOP1 GENERIC_NOP7 -/* Opteron 64bit nops - 1: nop - 2: osp nop - 3: osp osp nop - 4: osp osp osp nop -*/ +/* Opteron 64bit nops */ #define K8_NOP1 GENERIC_NOP1 #define K8_NOP2 ".byte 0x66,0x90\n" #define K8_NOP3 ".byte 0x66,0x66,0x90\n" @@ -35,35 +23,19 @@ #define K8_NOP7 K8_NOP4 K8_NOP3 #define K8_NOP8 K8_NOP4 K8_NOP4 -/* K7 nops - uses eax dependencies (arbitary choice) - 1: nop - 2: movl %eax,%eax - 3: leal (,%eax,1),%eax - 4: leal 0x00(,%eax,1),%eax - 6: leal 0x00000000(%eax),%eax - 7: leal 0x00000000(,%eax,1),%eax -*/ -#define K7_NOP1 GENERIC_NOP1 +/* K7 nops */ +/* uses eax dependencies (arbitary choice) */ +#define K7_NOP1 GENERIC_NOP1 #define K7_NOP2 ".byte 0x8b,0xc0\n" #define K7_NOP3 ".byte 0x8d,0x04,0x20\n" #define K7_NOP4 ".byte 0x8d,0x44,0x20,0x00\n" #define K7_NOP5 K7_NOP4 ASM_NOP1 #define K7_NOP6 ".byte 0x8d,0x80,0,0,0,0\n" -#define K7_NOP7 ".byte 0x8D,0x04,0x05,0,0,0,0\n" -#define K7_NOP8 K7_NOP7 ASM_NOP1 +#define K7_NOP7 ".byte 0x8D,0x04,0x05,0,0,0,0\n" +#define K7_NOP8 K7_NOP7 ASM_NOP1 -/* P6 nops - uses eax dependencies (Intel-recommended choice) - 1: nop - 2: osp nop - 3: nopl (%eax) - 4: nopl 0x00(%eax) - 5: nopl 0x00(%eax,%eax,1) - 6: osp nopl 0x00(%eax,%eax,1) - 7: nopl 0x00000000(%eax) - 8: nopl 0x00000000(%eax,%eax,1) -*/ +/* P6 nops */ +/* uses eax dependencies (Intel-recommended choice) */ #define P6_NOP1 GENERIC_NOP1 #define P6_NOP2 ".byte 0x66,0x90\n" #define P6_NOP3 ".byte 0x0f,0x1f,0x00\n" @@ -91,7 +63,9 @@ #define ASM_NOP6 K7_NOP6 #define ASM_NOP7 K7_NOP7 #define ASM_NOP8 K7_NOP8 -#elif defined(CONFIG_X86_P6_NOP) +#elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \ + defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \ + defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4) #define ASM_NOP1 P6_NOP1 #define ASM_NOP2 P6_NOP2 #define ASM_NOP3 P6_NOP3 diff --git a/trunk/include/asm-x86/page_64.h b/trunk/include/asm-x86/page_64.h index 143546073b95..f7393bc516ef 100644 --- a/trunk/include/asm-x86/page_64.h +++ b/trunk/include/asm-x86/page_64.h @@ -47,12 +47,8 @@ #define __PHYSICAL_MASK_SHIFT 46 #define __VIRTUAL_MASK_SHIFT 48 -/* - * Kernel image size is limited to 128 MB (see level2_kernel_pgt in - * arch/x86/kernel/head_64.S), and it is mapped here: - */ -#define KERNEL_IMAGE_SIZE (128*1024*1024) -#define KERNEL_IMAGE_START _AC(0xffffffff80000000, UL) +#define KERNEL_TEXT_SIZE (40*1024*1024) +#define KERNEL_TEXT_START _AC(0xffffffff80000000, UL) #ifndef __ASSEMBLY__ void clear_page(void *page); diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 9c17e828d6d4..e3ea12437547 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -242,7 +242,6 @@ struct task_struct; extern void sched_init(void); extern void sched_init_smp(void); -extern asmlinkage void schedule_tail(struct task_struct *prev); extern void init_idle(struct task_struct *idle, int cpu); extern void init_idle_bootup_task(struct task_struct *idle); @@ -1190,7 +1189,7 @@ struct task_struct { int softirq_context; #endif #ifdef CONFIG_LOCKDEP -# define MAX_LOCK_DEPTH 30UL +# define MAX_LOCK_DEPTH 48UL u64 curr_chain_key; int lockdep_depth; struct held_lock held_locks[MAX_LOCK_DEPTH]; diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 9adc2a473e6e..bee36100f110 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -666,7 +666,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) } /* Emit the output into the temporary buffer */ printed_len += vscnprintf(printk_buf + printed_len, - sizeof(printk_buf) - printed_len, fmt, args); + sizeof(printk_buf), fmt, args); /* * Copy the output into log_buf. If the caller didn't provide diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index f06950c8a6ce..b387a8de26a5 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -668,8 +668,6 @@ const_debug unsigned int sysctl_sched_nr_migrate = 32; */ unsigned int sysctl_sched_rt_period = 1000000; -static __read_mostly int scheduler_running; - /* * part of the period that we allow rt tasks to run in us. * default: 0.95s @@ -691,16 +689,14 @@ unsigned long long cpu_clock(int cpu) unsigned long flags; struct rq *rq; + local_irq_save(flags); + rq = cpu_rq(cpu); /* * Only call sched_clock() if the scheduler has already been * initialized (some code might call cpu_clock() very early): */ - if (unlikely(!scheduler_running)) - return 0; - - local_irq_save(flags); - rq = cpu_rq(cpu); - update_rq_clock(rq); + if (rq->idle) + update_rq_clock(rq); now = rq->clock; local_irq_restore(flags); @@ -3889,7 +3885,7 @@ pick_next_task(struct rq *rq, struct task_struct *prev) asmlinkage void __sched schedule(void) { struct task_struct *prev, *next; - unsigned long *switch_count; + long *switch_count; struct rq *rq; int cpu; @@ -7288,8 +7284,6 @@ void __init sched_init(void) * During early bootup we pretend to be a normal task: */ current->sched_class = &fair_sched_class; - - scheduler_running = 1; } #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP diff --git a/trunk/kernel/sched_fair.c b/trunk/kernel/sched_fair.c index c8e6492c5925..6c091d6e159d 100644 --- a/trunk/kernel/sched_fair.c +++ b/trunk/kernel/sched_fair.c @@ -202,12 +202,17 @@ static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq) static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) { - struct rb_node *last = rb_last(&cfs_rq->tasks_timeline); + struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; + struct sched_entity *se = NULL; + struct rb_node *parent; - if (!last) - return NULL; + while (*link) { + parent = *link; + se = rb_entry(parent, struct sched_entity, run_node); + link = &parent->rb_right; + } - return rb_entry(last, struct sched_entity, run_node); + return se; } /**************************************************************