From 18317ab0ca5ac0c654be3eac31ebb781b4a5e9b2 Mon Sep 17 00:00:00 2001 From: Richard Knutsson Date: Mon, 21 Nov 2005 21:32:03 -0800 Subject: [PATCH 001/101] [PATCH] net: Fix compiler-error on dgrs.c when !CONFIG_PCI drivers/net/dgrs.c: In function `dgrs_init_module': drivers/net/dgrs.c:1598: `dgrs_pci_driver' undeclared (first use in this function) Signed-off-by: Richard Knutsson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/dgrs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 2a290cc397ad..70b47e4c4e9c 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -1458,6 +1458,8 @@ static struct pci_driver dgrs_pci_driver = { .probe = dgrs_pci_probe, .remove = __devexit_p(dgrs_pci_remove), }; +#else +static struct pci_driver dgrs_pci_driver = {}; #endif From 39d730ab87f07592e3a3794353f097d5184cae7a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 21 Nov 2005 21:32:04 -0800 Subject: [PATCH 002/101] [PATCH] uml: eliminate use of local in clone stub We have a bug in the i386 stub_syscall6 which pushes ebp before the system call and pops it afterwards. Because we use syscall6 to remap the stack, the old contents of the stack (and the former value of ebp) are no longer available. Some versions of gcc make from a real local, accessed through ebp, despite my efforts to make it obvious that references to from are really constants. This patch attempts to make it even more obvious by eliminating from and using a macro to access the stub's data explicitly with constants. My original thinking on this was to replace syscall6 with a remap_stack interface which saved ebp someplace and restored it afterwards. The problem is that there are no registers to put it in, except for esp. That could work, since we can store a constant in esp after the mmap because we just replaced the stack. However, this approach seems a tad cleaner. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/clone.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 4dc55f10cd18..39c0d7145d31 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -13,11 +13,13 @@ /* This is in a separate file because it needs to be compiled with any * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled */ + +#define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field) + void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { long err; - struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - @@ -30,15 +32,15 @@ stub_clone_handler(void) goto out; err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, - (long) &from->timer, 0); + (long) &STUB_DATA(timer), 0); if(err) goto out; err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, - from->fd, from->offset); + STUB_DATA(fd), STUB_DATA(offset)); out: /* save current result. Parent: pid; child: retcode of mmap */ - from->err = err; + STUB_DATA(err) = err; trap_myself(); } From e23181deec0d2a8be576faf9d71211abb84d5ccc Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 21 Nov 2005 21:32:08 -0800 Subject: [PATCH 003/101] [PATCH] uml: eliminate anonymous union and clean up symlink lossage This gives a name to the anonymous union introduced in skas-hold-own-ldt, allowing to build on a wider range of gccs. It also removes ldt.h, which somehow became real, and replaces it with a symlink, and creates ldt-x86_64.h as a copy of ldt-i386.h for now. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Makefile | 2 +- arch/um/sys-i386/ldt.c | 35 ++++++++++++++------------ include/asm-um/ldt-i386.h | 2 +- include/asm-um/{ldt.h => ldt-x86_64.h} | 7 +----- 4 files changed, 22 insertions(+), 24 deletions(-) rename include/asm-um/{ldt.h => ldt-x86_64.h} (95%) diff --git a/arch/um/Makefile b/arch/um/Makefile index e55d32e903bc..1b12feeba368 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -17,7 +17,7 @@ core-y += $(ARCH_DIR)/kernel/ \ # Have to precede the include because the included Makefiles reference them. SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \ - module.h vm-flags.h elf.h + module.h vm-flags.h elf.h ldt.h SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) # XXX: The "os" symlink is only used by arch/um/include/os.h, which includes diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 6360f1c958d0..17746b4c08ff 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -228,7 +228,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; if(size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->entries, size)) + if(copy_to_user(ptr, ldt->u.entries, size)) err = -EFAULT; bytecount -= size; ptr += size; @@ -239,7 +239,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) size = PAGE_SIZE; if(size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->pages[i], size)){ + if(copy_to_user(ptr, ldt->u.pages[i], size)){ err = -EFAULT; break; } @@ -321,10 +321,11 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; i++){ if(i == 0) - memcpy(&entry0, ldt->entries, sizeof(entry0)); - ldt->pages[i] = (struct ldt_entry *) - __get_free_page(GFP_KERNEL|__GFP_ZERO); - if(!ldt->pages[i]){ + memcpy(&entry0, ldt->u.entries, + sizeof(entry0)); + ldt->u.pages[i] = (struct ldt_entry *) + __get_free_page(GFP_KERNEL|__GFP_ZERO); + if(!ldt->u.pages[i]){ err = -ENOMEM; /* Undo the change in host */ memset(&ldt_info, 0, sizeof(ldt_info)); @@ -332,8 +333,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) goto out_unlock; } if(i == 0) { - memcpy(ldt->pages[0], &entry0, sizeof(entry0)); - memcpy(ldt->pages[0]+1, ldt->entries+1, + memcpy(ldt->u.pages[0], &entry0, + sizeof(entry0)); + memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); } ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; @@ -343,9 +345,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) ldt->entry_count = ldt_info.entry_number + 1; if(ldt->entry_count <= LDT_DIRECT_ENTRIES) - ldt_p = ldt->entries + ldt_info.entry_number; + ldt_p = ldt->u.entries + ldt_info.entry_number; else - ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + + ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && @@ -501,8 +503,8 @@ long init_new_ldt(struct mmu_context_skas * new_mm, */ down(&from_mm->ldt.semaphore); if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ - memcpy(new_mm->ldt.entries, from_mm->ldt.entries, - sizeof(new_mm->ldt.entries)); + memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, + sizeof(new_mm->ldt.u.entries)); } else{ i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; @@ -512,9 +514,10 @@ long init_new_ldt(struct mmu_context_skas * new_mm, err = -ENOMEM; break; } - new_mm->ldt.pages[i] = (struct ldt_entry*)page; - memcpy(new_mm->ldt.pages[i], - from_mm->ldt.pages[i], PAGE_SIZE); + new_mm->ldt.u.pages[i] = + (struct ldt_entry *) page; + memcpy(new_mm->ldt.u.pages[i], + from_mm->ldt.u.pages[i], PAGE_SIZE); } } new_mm->ldt.entry_count = from_mm->ldt.entry_count; @@ -532,7 +535,7 @@ void free_ldt(struct mmu_context_skas * mm) if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; while(i-- > 0){ - free_page((long )mm->ldt.pages[i]); + free_page((long )mm->ldt.u.pages[i]); } } mm->ldt.entry_count = 0; diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h index b42662929b6c..175722a91164 100644 --- a/include/asm-um/ldt-i386.h +++ b/include/asm-um/ldt-i386.h @@ -35,7 +35,7 @@ typedef struct uml_ldt { union { struct ldt_entry * pages[LDT_PAGES_MAX]; struct ldt_entry entries[LDT_DIRECT_ENTRIES]; - }; + } u; } uml_ldt_t; /* diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt-x86_64.h similarity index 95% rename from include/asm-um/ldt.h rename to include/asm-um/ldt-x86_64.h index 4466ff6de0fd..175722a91164 100644 --- a/include/asm-um/ldt.h +++ b/include/asm-um/ldt-x86_64.h @@ -35,7 +35,7 @@ typedef struct uml_ldt { union { struct ldt_entry * pages[LDT_PAGES_MAX]; struct ldt_entry entries[LDT_DIRECT_ENTRIES]; - }; + } u; } uml_ldt_t; /* @@ -67,8 +67,3 @@ typedef struct uml_ldt { (info)->useable == 0 ) #endif -#ifndef __UM_LDT_H -#define __UM_LDT_H - -#include "asm/arch/ldt.h" -#endif From 17d469715c6453e4994e6617e8f644bf10f38584 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 21 Nov 2005 21:32:09 -0800 Subject: [PATCH 004/101] [PATCH] uml: properly invoke x86_64 system calls This patch makes stub_segv use the stub_syscall macros. This was needed anyway, but the bug that prompted this was the discovery that gcc was storing stuff in RCX, which is trashed across a system call. This is exactly the sort of problem that the new macros fix. There is a stub_syscall0 for getpid. stub_segv was changed to be a libc file, and that caused some include changes. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysdep-i386/stub.h | 9 +++++++++ arch/um/include/sysdep-x86_64/stub.h | 12 +++++++++++- arch/um/sys-i386/Makefile | 2 +- arch/um/sys-i386/stub_segv.c | 11 +++++++---- arch/um/sys-x86_64/Makefile | 2 +- arch/um/sys-x86_64/stub_segv.c | 20 ++++++++++---------- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index a49ceb199ee5..6ba8cbbe0d36 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h @@ -16,6 +16,15 @@ extern void stub_clone_handler(void); #define STUB_MMAP_NR __NR_mmap2 #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) +static inline long stub_syscall0(long syscall) +{ + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall)); + + return ret; +} + static inline long stub_syscall1(long syscall, long arg1) { long ret; diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index 2bd6e7a97286..c41689c13dc9 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h @@ -6,7 +6,6 @@ #ifndef __SYSDEP_STUB_H #define __SYSDEP_STUB_H -#include #include #include @@ -20,6 +19,17 @@ extern void stub_clone_handler(void); #define __syscall_clobber "r11","rcx","memory" #define __syscall "syscall" +static inline long stub_syscall0(long syscall) +{ + long ret; + + __asm__ volatile (__syscall + : "=a" (ret) + : "0" (syscall) : __syscall_clobber ); + + return ret; +} + static inline long stub_syscall2(long syscall, long arg1, long arg2) { long ret; diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 6dfeb70f6957..150059dbee12 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -5,7 +5,7 @@ obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_MODULES) += module.o -USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o +USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o SYMLINKS = bitops.c semaphore.c highmem.c module.c diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index 1e88b275edac..a37f672ec964 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -3,9 +3,11 @@ * Licensed under the GPL */ -#include +#include +#include /* The only way I can see to get sigset_t */ #include #include "uml-config.h" +#include "sysdep/stub.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" @@ -13,13 +15,14 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct sigcontext *sc = (struct sigcontext *) (&sig + 1); + int pid; GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), sc); - __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); - __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" - "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); + pid = stub_syscall0(__NR_getpid); + stub_syscall2(__NR_kill, pid, SIGUSR1); + /* Load pointer to sigcontext into esp, since we need to leave * the stack in its original form when we do the sigreturn here, by * hand. diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index ea977df395a1..00b2025427df 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -12,7 +12,7 @@ lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \ obj-y := ksyms.o obj-$(CONFIG_MODULES) += module.o um_module.o -USER_OBJS := ptrace_user.o sigcontext.o +USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ thunk.S module.c diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index d1e53bdf2e85..a27099533198 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -3,14 +3,14 @@ * Licensed under the GPL */ -#include +#include +#include #include #include -#include #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" -#include +#include "sysdep/stub.h" /* Copied from sys-x86_64/signal.c - Can't find an equivalent definition * in the libc headers anywhere. @@ -31,21 +31,21 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct ucontext *uc; + int pid; __asm__("movq %%rdx, %0" : "=g" (uc) :); GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), &uc->uc_mcontext); - __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); - __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" - "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : - "%rdi", "%rax", "%rsi"); + pid = stub_syscall0(__NR_getpid); + stub_syscall2(__NR_kill, pid, SIGUSR1); + /* sys_sigreturn expects that the stack pointer will be 8 bytes into * the signal frame. So, we use the ucontext pointer, which we know * already, to get the signal frame pointer, and add 8 to that. */ - __asm__("movq %0, %%rsp": : + __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": : "g" ((unsigned long) container_of(uc, struct rt_sigframe, - uc) + 8)); - __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); + uc) + 8), + "g" (__NR_rt_sigreturn)); } From aa1a64ee12ae130706f3fc0007841ce9b0ddf9c2 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 21 Nov 2005 21:32:10 -0800 Subject: [PATCH 005/101] [PATCH] uml: eliminate use of libc PAGE_SIZE On some systems, libc PAGE_SIZE calls getpagesize, which can't happen from a stub. So, I use UM_KERN_PAGE_SIZE, which is less variable in its definition, instead. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/skas/clone.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 39c0d7145d31..cb37ce9124a6 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -9,9 +9,13 @@ #include "stub-data.h" #include "uml-config.h" #include "sysdep/stub.h" +#include "kern_constants.h" /* This is in a separate file because it needs to be compiled with any * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled + * + * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize + * on some systems. */ #define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field) @@ -22,7 +26,7 @@ stub_clone_handler(void) long err; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - + UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); if(err != 0) goto out; @@ -36,9 +40,10 @@ stub_clone_handler(void) if(err) goto out; - err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, - STUB_DATA(fd), STUB_DATA(offset)); + err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, + UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, STUB_DATA(fd), + STUB_DATA(offset)); out: /* save current result. Parent: pid; child: retcode of mmap */ STUB_DATA(err) = err; From ed5297a94090d9a9f27b0ce1f9601ebe73561cff Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:11 -0800 Subject: [PATCH 006/101] [PATCH] unpaged: get_user_pages VM_RESERVED The PageReserved removal in 2.6.15-rc1 prohibited get_user_pages on the areas flagged VM_RESERVED in place of PageReserved. That is correct in theory - we ought not to interfere with struct pages in such a reserved area; but in practice it broke BTTV for one. So revert to prohibiting only on VM_IO: if someone gets into trouble with get_user_pages on VM_RESERVED, it'll just be a "don't do that". You can argue that videobuf_mmap_mapper shouldn't set VM_RESERVED in the first place, but now's not the time for breaking drivers without notice. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 2998cfc12f5b..cfce5f1f30f2 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -968,7 +968,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, continue; } - if (!vma || (vma->vm_flags & (VM_IO | VM_RESERVED)) + if (!vma || (vma->vm_flags & VM_IO) || !(vm_flags & vma->vm_flags)) return i ? : -EFAULT; From 83e9b7e929d1323b9a155d186f77aa8c06155cc3 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:12 -0800 Subject: [PATCH 007/101] [PATCH] unpaged: private write VM_RESERVED The PageReserved removal in 2.6.15-rc1 issued a "deprecated" message when you tried to mmap or mprotect MAP_PRIVATE PROT_WRITE a VM_RESERVED, and failed with -EACCES: because do_wp_page lacks the refinement to COW pages in those areas, nor do we expect to find anonymous pages in them; and it seemed just bloat to add code for handling such a peculiar case. But immediately it caused vbetool and ddcprobe (using lrmi) to fail. So revert the "deprecated" messages, letting mmap and mprotect succeed. But leave do_wp_page's BUG_ON(vma->vm_flags & VM_RESERVED) in place until we've added the code to do it right: so this particular patch is only good if the app doesn't really need to write to that private area. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmap.c | 11 ----------- mm/mprotect.c | 8 -------- 2 files changed, 19 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 4f8def03428c..11ca5927d5ff 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1076,17 +1076,6 @@ munmap_back: error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; - if ((vma->vm_flags & (VM_SHARED | VM_WRITE | VM_RESERVED)) - == (VM_WRITE | VM_RESERVED)) { - printk(KERN_WARNING "program %s is using MAP_PRIVATE, " - "PROT_WRITE mmap of VM_RESERVED memory, which " - "is deprecated. Please report this to " - "linux-kernel@vger.kernel.org\n",current->comm); - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - error = -EACCES; - goto unmap_and_free_vma; - } } else if (vm_flags & VM_SHARED) { error = shmem_zero_setup(vma); if (error) diff --git a/mm/mprotect.c b/mm/mprotect.c index 17a2b52b753b..653b8571c1ed 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -124,14 +124,6 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, * a MAP_NORESERVE private mapping to writable will now reserve. */ if (newflags & VM_WRITE) { - if (oldflags & VM_RESERVED) { - BUG_ON(oldflags & VM_WRITE); - printk(KERN_WARNING "program %s is using MAP_PRIVATE, " - "PROT_WRITE mprotect of VM_RESERVED memory, " - "which is deprecated. Please report this to " - "linux-kernel@vger.kernel.org\n",current->comm); - return -EACCES; - } if (!(oldflags & (VM_ACCOUNT|VM_WRITE|VM_SHARED|VM_HUGETLB))) { charged = nrpages; if (security_vm_enough_memory(charged)) From 1cdca61bf8537043edde8ef784ce1a1351361dac Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:13 -0800 Subject: [PATCH 008/101] [PATCH] unpaged: sound nopage get_page Something noticed when studying use of VM_RESERVED in different drivers: snd_usX2Y_hwdep_pcm_vm_nopage omitted to get_page: fixed. And how did this work before? Aargh! That nopage is returning a page from within a buffer allocated by snd_malloc_pages, which allocates a high-order page, then does SetPageReserved on each 0-order page within. That would have worked in 2.6.14, because when the area was unmapped, PageReserved inhibited put_page. 2.6.15-rc1 removed that inhibition (while leaving ineffective PageReserveds around for now), but it hasn't caused trouble because.. we've not been freeing from VM_RESERVED at all. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/usb/usx2y/usx2yhwdeppcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 0dc828ff9e94..c9136a98755f 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -691,6 +691,7 @@ static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area, snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM); vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->hwdep_pcm_shm + offset; page = virt_to_page(vaddr); + get_page(page); if (type) *type = VM_FAULT_MINOR; From 664beed0190fae687ac51295694004902ddeb18e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:14 -0800 Subject: [PATCH 009/101] [PATCH] unpaged: unifdefed PageCompound It looks like snd_xxx is not the only nopage to be using PageReserved as a way of holding a high-order page together: which no longer works, but is masked by our failure to free from VM_RESERVED areas. We cannot fix that bug without first substituting another way to hold the high-order page together, while farming out the 0-order pages from within it. That's just what PageCompound is designed for, but it's been kept under CONFIG_HUGETLB_PAGE. Remove the #ifdefs: which saves some space (out- of-line put_page), doesn't slow down what most needs to be fast (already using hugetlb), and unifies the way we handle high-order pages. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 19 ------------------- include/linux/page-flags.h | 4 ---- mm/page_alloc.c | 5 ----- mm/swap.c | 3 --- 4 files changed, 31 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0986d19be0b7..9701210c6680 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -311,8 +311,6 @@ struct page { extern void FASTCALL(__page_cache_release(struct page *)); -#ifdef CONFIG_HUGETLB_PAGE - static inline int page_count(struct page *page) { if (PageCompound(page)) @@ -329,23 +327,6 @@ static inline void get_page(struct page *page) void put_page(struct page *page); -#else /* CONFIG_HUGETLB_PAGE */ - -#define page_count(p) (atomic_read(&(p)->_count) + 1) - -static inline void get_page(struct page *page) -{ - atomic_inc(&page->_count); -} - -static inline void put_page(struct page *page) -{ - if (put_page_testzero(page)) - __page_cache_release(page); -} - -#endif /* CONFIG_HUGETLB_PAGE */ - /* * Multiple processes may "see" the same page. E.g. for untouched * mappings of /dev/null, all processes see the same page full of diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index f34767c5fc79..343083fec258 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -287,11 +287,7 @@ extern void __mod_page_state(unsigned long offset, unsigned long delta); #define ClearPageReclaim(page) clear_bit(PG_reclaim, &(page)->flags) #define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags) -#ifdef CONFIG_HUGETLB_PAGE #define PageCompound(page) test_bit(PG_compound, &(page)->flags) -#else -#define PageCompound(page) 0 -#endif #define SetPageCompound(page) set_bit(PG_compound, &(page)->flags) #define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bd4de592dc23..23b84c4e1a57 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -148,10 +148,6 @@ static void bad_page(const char *function, struct page *page) add_taint(TAINT_BAD_PAGE); } -#ifndef CONFIG_HUGETLB_PAGE -#define prep_compound_page(page, order) do { } while (0) -#define destroy_compound_page(page, order) do { } while (0) -#else /* * Higher-order pages are called "compound pages". They are structured thusly: * @@ -205,7 +201,6 @@ static void destroy_compound_page(struct page *page, unsigned long order) ClearPageCompound(p); } } -#endif /* CONFIG_HUGETLB_PAGE */ /* * function for dealing with page's order in buddy system. diff --git a/mm/swap.c b/mm/swap.c index d09cf7f03e76..73d351439ef6 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -34,8 +34,6 @@ /* How many pages do we try to swap or page in/out together? */ int page_cluster; -#ifdef CONFIG_HUGETLB_PAGE - void put_page(struct page *page) { if (unlikely(PageCompound(page))) { @@ -52,7 +50,6 @@ void put_page(struct page *page) __page_cache_release(page); } EXPORT_SYMBOL(put_page); -#endif /* * Writeback is about to end against a page which has been marked for immediate From 0b14c179a483e71ea41df2aa4a661760063115bd Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:15 -0800 Subject: [PATCH 010/101] [PATCH] unpaged: VM_UNPAGED Although we tend to associate VM_RESERVED with remap_pfn_range, quite a few drivers set VM_RESERVED on areas which are then populated by nopage. The PageReserved removal in 2.6.15-rc1 changed VM_RESERVED not to free pages in zap_pte_range, without changing those drivers not to set it: so their pages just leak away. Let's not change miscellaneous drivers now: introduce VM_UNPAGED at the core, to flag the special areas where the ptes may have no struct page, or if they have then it's not to be touched. Replace most instances of VM_RESERVED in core mm by VM_UNPAGED. Force it on in remap_pfn_range, and the sparc and sparc64 io_remap_pfn_range. Revert addition of VM_RESERVED to powerpc vdso, it's not needed there. Is it needed anywhere? It still governs the mm->reserved_vm statistic, and special vmas not to be merged, and areas not to be core dumped; but could probably be eliminated later (the drivers are probably specifying it because in 2.4 it kept swapout off the vma, but in 2.6 we work from the LRU, which these pages don't get on). Use the VM_SHM slot for VM_UNPAGED, and define VM_SHM to 0: it serves no purpose whatsoever, and should be removed from drivers when we clean up. Signed-off-by: Hugh Dickins Acked-by: William Irwin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/vdso.c | 3 +-- arch/sparc/mm/generic.c | 2 +- arch/sparc64/mm/generic.c | 2 +- include/linux/mm.h | 5 +++-- mm/fremap.c | 4 ++-- mm/madvise.c | 2 +- mm/memory.c | 30 ++++++++++++++++++------------ mm/mempolicy.c | 2 +- mm/msync.c | 4 ++-- 9 files changed, 30 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 0d4d8bec0df4..b44b36e0c293 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -285,8 +285,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, * It's fine to use that for setting breakpoints in the vDSO code * pages though */ - vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | - VM_MAYEXEC | VM_RESERVED; + vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; vma->vm_ops = &vdso_vmops; diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c index 9604893ffdbd..0410bae681f8 100644 --- a/arch/sparc/mm/generic.c +++ b/arch/sparc/mm/generic.c @@ -74,7 +74,7 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; /* See comment in mm/memory.c remap_pfn_range */ - vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_flags |= VM_IO | VM_RESERVED | VM_UNPAGED; prot = __pgprot(pg_iobits); offset -= from; diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index 112c316e7cd2..8fd4cb1f050a 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -128,7 +128,7 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; /* See comment in mm/memory.c remap_pfn_range */ - vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_flags |= VM_IO | VM_RESERVED | VM_UNPAGED; prot = __pgprot(pg_iobits); offset -= from; diff --git a/include/linux/mm.h b/include/linux/mm.h index 9701210c6680..f0cdfd18db55 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -144,7 +144,8 @@ extern unsigned int kobjsize(const void *objp); #define VM_GROWSDOWN 0x00000100 /* general info on the segment */ #define VM_GROWSUP 0x00000200 -#define VM_SHM 0x00000400 /* shared memory area, don't swap out */ +#define VM_SHM 0x00000000 /* Means nothing: delete it later */ +#define VM_UNPAGED 0x00000400 /* Pages managed without map count */ #define VM_DENYWRITE 0x00000800 /* ETXTBSY on write attempts.. */ #define VM_EXECUTABLE 0x00001000 @@ -157,7 +158,7 @@ extern unsigned int kobjsize(const void *objp); #define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */ #define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */ -#define VM_RESERVED 0x00080000 /* Pages managed in a special way */ +#define VM_RESERVED 0x00080000 /* Count as reserved_vm like IO */ #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ diff --git a/mm/fremap.c b/mm/fremap.c index d862be3bc3e3..94254c5d7a18 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -65,7 +65,7 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, pte_t pte_val; spinlock_t *ptl; - BUG_ON(vma->vm_flags & VM_RESERVED); + BUG_ON(vma->vm_flags & VM_UNPAGED); pgd = pgd_offset(mm, addr); pud = pud_alloc(mm, pgd, addr); @@ -122,7 +122,7 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, pte_t pte_val; spinlock_t *ptl; - BUG_ON(vma->vm_flags & VM_RESERVED); + BUG_ON(vma->vm_flags & VM_UNPAGED); pgd = pgd_offset(mm, addr); pud = pud_alloc(mm, pgd, addr); diff --git a/mm/madvise.c b/mm/madvise.c index 17aaf3e16449..328a3bcce527 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -126,7 +126,7 @@ static long madvise_dontneed(struct vm_area_struct * vma, unsigned long start, unsigned long end) { *prev = vma; - if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_RESERVED)) + if (vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_UNPAGED)) return -EINVAL; if (unlikely(vma->vm_flags & VM_NONLINEAR)) { diff --git a/mm/memory.c b/mm/memory.c index cfce5f1f30f2..ece04963158e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -334,7 +334,7 @@ static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss) /* * This function is called to print an error when a pte in a - * !VM_RESERVED region is found pointing to an invalid pfn (which + * !VM_UNPAGED region is found pointing to an invalid pfn (which * is an error. * * The calling function must still handle the error. @@ -381,15 +381,15 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, goto out_set_pte; } - /* If the region is VM_RESERVED, the mapping is not + /* If the region is VM_UNPAGED, the mapping is not * mapped via rmap - duplicate the pte as is. */ - if (vm_flags & VM_RESERVED) + if (vm_flags & VM_UNPAGED) goto out_set_pte; pfn = pte_pfn(pte); /* If the pte points outside of valid memory but - * the region is not VM_RESERVED, we have a problem. + * the region is not VM_UNPAGED, we have a problem. */ if (unlikely(!pfn_valid(pfn))) { print_bad_pte(vma, pte, addr); @@ -528,7 +528,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, * readonly mappings. The tradeoff is that copy_page_range is more * efficient than faulting. */ - if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_RESERVED))) { + if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_UNPAGED))) { if (!vma->anon_vma) return 0; } @@ -572,7 +572,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, (*zap_work) -= PAGE_SIZE; - if (!(vma->vm_flags & VM_RESERVED)) { + if (!(vma->vm_flags & VM_UNPAGED)) { unsigned long pfn = pte_pfn(ptent); if (unlikely(!pfn_valid(pfn))) print_bad_pte(vma, ptent, addr); @@ -1191,10 +1191,16 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, * rest of the world about it: * VM_IO tells people not to look at these pages * (accesses can have side effects). - * VM_RESERVED tells the core MM not to "manage" these pages - * (e.g. refcount, mapcount, try to swap them out). + * VM_RESERVED is specified all over the place, because + * in 2.4 it kept swapout's vma scan off this vma; but + * in 2.6 the LRU scan won't even find its pages, so this + * flag means no more than count its pages in reserved_vm, + * and omit it from core dump, even when VM_IO turned off. + * VM_UNPAGED tells the core MM not to "manage" these pages + * (e.g. refcount, mapcount, try to swap them out): in + * particular, zap_pte_range does not try to free them. */ - vma->vm_flags |= VM_IO | VM_RESERVED; + vma->vm_flags |= VM_IO | VM_RESERVED | VM_UNPAGED; BUG_ON(addr >= end); pfn -= addr >> PAGE_SHIFT; @@ -1276,7 +1282,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, pte_t entry; int ret = VM_FAULT_MINOR; - BUG_ON(vma->vm_flags & VM_RESERVED); + BUG_ON(vma->vm_flags & VM_UNPAGED); if (unlikely(!pfn_valid(pfn))) { /* @@ -1924,7 +1930,7 @@ retry: inc_mm_counter(mm, anon_rss); lru_cache_add_active(new_page); page_add_anon_rmap(new_page, vma, address); - } else if (!(vma->vm_flags & VM_RESERVED)) { + } else if (!(vma->vm_flags & VM_UNPAGED)) { inc_mm_counter(mm, file_rss); page_add_file_rmap(new_page); } @@ -2203,7 +2209,7 @@ static int __init gate_vma_init(void) gate_vma.vm_start = FIXADDR_USER_START; gate_vma.vm_end = FIXADDR_USER_END; gate_vma.vm_page_prot = PAGE_READONLY; - gate_vma.vm_flags = VM_RESERVED; + gate_vma.vm_flags = 0; return 0; } __initcall(gate_vma_init); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 5abc57c2b8bd..5609a31bdf22 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -269,7 +269,7 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, first = find_vma(mm, start); if (!first) return ERR_PTR(-EFAULT); - if (first->vm_flags & VM_RESERVED) + if (first->vm_flags & VM_UNPAGED) return ERR_PTR(-EACCES); prev = NULL; for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) { diff --git a/mm/msync.c b/mm/msync.c index 0e040e9c39d8..b3f4caf3010b 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -97,9 +97,9 @@ static void msync_page_range(struct vm_area_struct *vma, /* For hugepages we can't go walking the page table normally, * but that's ok, hugetlbfs is memory based, so we don't need * to do anything more on an msync(). - * Can't do anything with VM_RESERVED regions either. + * Can't do anything with VM_UNPAGED regions either. */ - if (vma->vm_flags & (VM_HUGETLB|VM_RESERVED)) + if (vma->vm_flags & (VM_HUGETLB|VM_UNPAGED)) return; BUG_ON(addr >= end); From 101d2be7646b7dd1c367d50208a59b29fce61398 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:16 -0800 Subject: [PATCH 011/101] [PATCH] unpaged: VM_NONLINEAR VM_RESERVED There's one peculiar use of VM_RESERVED which the previous patch left behind: because VM_NONLINEAR's try_to_unmap_cluster uses vm_private_data as a swapout cursor, but should never meet VM_RESERVED vmas, it was a way of extending VM_NONLINEAR to VM_RESERVED vmas using vm_private_data for some other purpose. But that's an empty set - they don't have the populate function required. So just throw away those VM_RESERVED tests. But one more interesting in rmap.c has to go too: try_to_unmap_one will want to swap out an anonymous page from VM_RESERVED or VM_UNPAGED area. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/fremap.c | 6 ++---- mm/rmap.c | 15 +++++---------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/mm/fremap.c b/mm/fremap.c index 94254c5d7a18..007cbad9331e 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -204,12 +204,10 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, * Make sure the vma is shared, that it supports prefaulting, * and that the remapped range is valid and fully within * the single existing vma. vm_private_data is used as a - * swapout cursor in a VM_NONLINEAR vma (unless VM_RESERVED - * or VM_LOCKED, but VM_LOCKED could be revoked later on). + * swapout cursor in a VM_NONLINEAR vma. */ if (vma && (vma->vm_flags & VM_SHARED) && - (!vma->vm_private_data || - (vma->vm_flags & (VM_NONLINEAR|VM_RESERVED))) && + (!vma->vm_private_data || (vma->vm_flags & VM_NONLINEAR)) && vma->vm_ops && vma->vm_ops->populate && end > start && start >= vma->vm_start && end <= vma->vm_end) { diff --git a/mm/rmap.c b/mm/rmap.c index 914d04b98bee..377d417ec15f 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -529,10 +529,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma) * If the page is mlock()d, we cannot swap it out. * If it's recently referenced (perhaps page_referenced * skipped over this mm) then we should reactivate it. - * - * Pages belonging to VM_RESERVED regions should not happen here. */ - if ((vma->vm_flags & (VM_LOCKED|VM_RESERVED)) || + if ((vma->vm_flags & VM_LOCKED) || ptep_clear_flush_young(vma, address, pte)) { ret = SWAP_FAIL; goto out_unmap; @@ -727,7 +725,7 @@ static int try_to_unmap_file(struct page *page) list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) { - if (vma->vm_flags & (VM_LOCKED|VM_RESERVED)) + if (vma->vm_flags & VM_LOCKED) continue; cursor = (unsigned long) vma->vm_private_data; if (cursor > max_nl_cursor) @@ -761,7 +759,7 @@ static int try_to_unmap_file(struct page *page) do { list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) { - if (vma->vm_flags & (VM_LOCKED|VM_RESERVED)) + if (vma->vm_flags & VM_LOCKED) continue; cursor = (unsigned long) vma->vm_private_data; while ( cursor < max_nl_cursor && @@ -783,11 +781,8 @@ static int try_to_unmap_file(struct page *page) * in locked vmas). Reset cursor on all unreserved nonlinear * vmas, now forgetting on which ones it had fallen behind. */ - list_for_each_entry(vma, &mapping->i_mmap_nonlinear, - shared.vm_set.list) { - if (!(vma->vm_flags & VM_RESERVED)) - vma->vm_private_data = NULL; - } + list_for_each_entry(vma, &mapping->i_mmap_nonlinear, shared.vm_set.list) + vma->vm_private_data = NULL; out: spin_unlock(&mapping->i_mmap_lock); return ret; From 920fc356f58d0e455bdfa53451f1c58eb211a846 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:17 -0800 Subject: [PATCH 012/101] [PATCH] unpaged: COW on VM_UNPAGED Remove the BUG_ON(vma->vm_flags & VM_UNPAGED) from do_wp_page, and let it do Copy-On-Write without touching the VM_UNPAGED's page counts - but this is incomplete, because the anonymous page it inserts will itself need to be handled, here and in other functions - next patch. We still don't copy the page if the pfn is invalid, because the copy_user_highpage interface does not allow it. But that's not been a problem in the past: can be added in later if the need arises. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index ece04963158e..107b619cfb16 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1277,22 +1277,28 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, pte_t *page_table, pmd_t *pmd, spinlock_t *ptl, pte_t orig_pte) { - struct page *old_page, *new_page; + struct page *old_page, *src_page, *new_page; unsigned long pfn = pte_pfn(orig_pte); pte_t entry; int ret = VM_FAULT_MINOR; - BUG_ON(vma->vm_flags & VM_UNPAGED); - if (unlikely(!pfn_valid(pfn))) { /* * Page table corrupted: show pte and kill process. + * Or it's an attempt to COW an out-of-map VM_UNPAGED + * entry, which copy_user_highpage does not support. */ print_bad_pte(vma, orig_pte, address); ret = VM_FAULT_OOM; goto unlock; } old_page = pfn_to_page(pfn); + src_page = old_page; + + if (unlikely(vma->vm_flags & VM_UNPAGED)) { + old_page = NULL; + goto gotten; + } if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { int reuse = can_share_swap_page(old_page); @@ -1313,11 +1319,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, * Ok, we need to copy. Oh, well.. */ page_cache_get(old_page); +gotten: pte_unmap_unlock(page_table, ptl); if (unlikely(anon_vma_prepare(vma))) goto oom; - if (old_page == ZERO_PAGE(address)) { + if (src_page == ZERO_PAGE(address)) { new_page = alloc_zeroed_user_highpage(vma, address); if (!new_page) goto oom; @@ -1325,7 +1332,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, new_page = alloc_page_vma(GFP_HIGHUSER, vma, address); if (!new_page) goto oom; - copy_user_highpage(new_page, old_page, address); + copy_user_highpage(new_page, src_page, address); } /* @@ -1333,11 +1340,14 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, */ page_table = pte_offset_map_lock(mm, pmd, address, &ptl); if (likely(pte_same(*page_table, orig_pte))) { - page_remove_rmap(old_page); - if (!PageAnon(old_page)) { + if (old_page) { + page_remove_rmap(old_page); + if (!PageAnon(old_page)) { + dec_mm_counter(mm, file_rss); + inc_mm_counter(mm, anon_rss); + } + } else inc_mm_counter(mm, anon_rss); - dec_mm_counter(mm, file_rss); - } flush_cache_page(vma, address, pfn); entry = mk_pte(new_page, vma->vm_page_prot); entry = maybe_mkwrite(pte_mkdirty(entry), vma); @@ -1351,13 +1361,16 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, new_page = old_page; ret |= VM_FAULT_WRITE; } - page_cache_release(new_page); - page_cache_release(old_page); + if (new_page) + page_cache_release(new_page); + if (old_page) + page_cache_release(old_page); unlock: pte_unmap_unlock(page_table, ptl); return ret; oom: - page_cache_release(old_page); + if (old_page) + page_cache_release(old_page); return VM_FAULT_OOM; } From ee498ed730283e9cdfc8913f12b90a2246f1a8cc Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:18 -0800 Subject: [PATCH 013/101] [PATCH] unpaged: anon in VM_UNPAGED copy_one_pte needs to copy the anonymous COWed pages in a VM_UNPAGED area, zap_pte_range needs to free them, do_wp_page needs to COW them: just like ordinary pages, not like the unpaged. But recognizing them is a little subtle: because PageReserved is no longer a condition for remap_pfn_range, we can now mmap all of /dev/mem (whether the distro permits, and whether it's advisable on this or that architecture, is another matter). So if we can see a PageAnon, it may not be ours to mess with (or may be ours from elsewhere in the address space). I suspect there's an entertaining insoluble self-referential problem here, but the page_is_anon function does a good practical job, and MAP_PRIVATE PROT_WRITE VM_UNPAGED will always be an odd choice. In updating the comment on page_address_in_vma, noticed a potential NULL dereference, in a path we don't actually take, but fixed it. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory.c | 63 ++++++++++++++++++++++++++++++++++------------------- mm/rmap.c | 7 ++++-- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 107b619cfb16..3666a4c6dd22 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -349,6 +349,22 @@ void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr) dump_stack(); } +/* + * page_is_anon applies strict checks for an anonymous page belonging to + * this vma at this address. It is used on VM_UNPAGED vmas, which are + * usually populated with shared originals (which must not be counted), + * but occasionally contain private COWed copies (when !VM_SHARED, or + * perhaps via ptrace when VM_SHARED). An mmap of /dev/mem might window + * free pages, pages from other processes, or from other parts of this: + * it's tricky, but try not to be deceived by foreign anonymous pages. + */ +static inline int page_is_anon(struct page *page, + struct vm_area_struct *vma, unsigned long addr) +{ + return page && PageAnon(page) && page_mapped(page) && + page_address_in_vma(page, vma) == addr; +} + /* * copy one vm_area from one task to the other. Assumes the page tables * already present in the new task to be cleared in the whole range @@ -381,23 +397,22 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, goto out_set_pte; } - /* If the region is VM_UNPAGED, the mapping is not - * mapped via rmap - duplicate the pte as is. - */ - if (vm_flags & VM_UNPAGED) - goto out_set_pte; - pfn = pte_pfn(pte); - /* If the pte points outside of valid memory but + page = pfn_valid(pfn)? pfn_to_page(pfn): NULL; + + if (unlikely(vm_flags & VM_UNPAGED)) + if (!page_is_anon(page, vma, addr)) + goto out_set_pte; + + /* + * If the pte points outside of valid memory but * the region is not VM_UNPAGED, we have a problem. */ - if (unlikely(!pfn_valid(pfn))) { + if (unlikely(!page)) { print_bad_pte(vma, pte, addr); goto out_set_pte; /* try to do something sane */ } - page = pfn_to_page(pfn); - /* * If it's a COW mapping, write protect it both * in the parent and the child @@ -568,17 +583,20 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, continue; } if (pte_present(ptent)) { - struct page *page = NULL; + struct page *page; + unsigned long pfn; (*zap_work) -= PAGE_SIZE; - if (!(vma->vm_flags & VM_UNPAGED)) { - unsigned long pfn = pte_pfn(ptent); - if (unlikely(!pfn_valid(pfn))) - print_bad_pte(vma, ptent, addr); - else - page = pfn_to_page(pfn); - } + pfn = pte_pfn(ptent); + page = pfn_valid(pfn)? pfn_to_page(pfn): NULL; + + if (unlikely(vma->vm_flags & VM_UNPAGED)) { + if (!page_is_anon(page, vma, addr)) + page = NULL; + } else if (unlikely(!page)) + print_bad_pte(vma, ptent, addr); + if (unlikely(details) && page) { /* * unmap_shared_mapping_pages() wants to @@ -1295,10 +1313,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, old_page = pfn_to_page(pfn); src_page = old_page; - if (unlikely(vma->vm_flags & VM_UNPAGED)) { - old_page = NULL; - goto gotten; - } + if (unlikely(vma->vm_flags & VM_UNPAGED)) + if (!page_is_anon(old_page, vma, address)) { + old_page = NULL; + goto gotten; + } if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { int reuse = can_share_swap_page(old_page); diff --git a/mm/rmap.c b/mm/rmap.c index 377d417ec15f..2e034a0b89ab 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -225,7 +225,9 @@ vma_address(struct page *page, struct vm_area_struct *vma) /* * At what user virtual address is page expected in vma? checking that the - * page matches the vma: currently only used by unuse_process, on anon pages. + * page matches the vma: currently only used on anon pages, by unuse_vma; + * and by extraordinary checks on anon pages in VM_UNPAGED vmas, taking + * care that an mmap of /dev/mem might window free and foreign pages. */ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) { @@ -234,7 +236,8 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) (void *)page->mapping - PAGE_MAPPING_ANON) return -EFAULT; } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { - if (vma->vm_file->f_mapping != page->mapping) + if (!vma->vm_file || + vma->vm_file->f_mapping != page->mapping) return -EFAULT; } else return -EFAULT; From f57e88a8d83de8d844b57e16b84d2f762fe9f092 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:19 -0800 Subject: [PATCH 014/101] [PATCH] unpaged: ZERO_PAGE in VM_UNPAGED It's strange enough to be looking out for anonymous pages in VM_UNPAGED areas, let's not insert the ZERO_PAGE there - though whether it would matter will depend on what we decide about ZERO_PAGE refcounting. But whereas do_anonymous_page may (exceptionally) be called on a VM_UNPAGED area, do_no_page should never be: just BUG_ON. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/mem.c | 2 +- mm/memory.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 91dd669273e0..29c3b631445a 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -591,7 +591,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size) if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) goto out_up; - if (vma->vm_flags & (VM_SHARED | VM_HUGETLB)) + if (vma->vm_flags & (VM_SHARED | VM_HUGETLB | VM_UNPAGED)) break; count = vma->vm_end - addr; if (count > size) diff --git a/mm/memory.c b/mm/memory.c index 3666a4c6dd22..d1f46f4e4c8a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1812,7 +1812,16 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, spinlock_t *ptl; pte_t entry; - if (write_access) { + /* + * A VM_UNPAGED vma will normally be filled with present ptes + * by remap_pfn_range, and never arrive here; but it might have + * holes, or if !VM_DONTEXPAND, mremap might have expanded it. + * It's weird enough handling anon pages in unpaged vmas, we do + * not want to worry about ZERO_PAGEs too (it may or may not + * matter if their counts wrap): just give them anon pages. + */ + + if (write_access || (vma->vm_flags & VM_UNPAGED)) { /* Allocate our own private page. */ pte_unmap(page_table); @@ -1887,6 +1896,7 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma, int anon = 0; pte_unmap(page_table); + BUG_ON(vma->vm_flags & VM_UNPAGED); if (vma->vm_file) { mapping = vma->vm_file->f_mapping; @@ -1962,7 +1972,7 @@ retry: inc_mm_counter(mm, anon_rss); lru_cache_add_active(new_page); page_add_anon_rmap(new_page, vma, address); - } else if (!(vma->vm_flags & VM_UNPAGED)) { + } else { inc_mm_counter(mm, file_rss); page_add_file_rmap(new_page); } From 689bcebfda16d7bace742740bfb3137fff30b529 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:20 -0800 Subject: [PATCH 015/101] [PATCH] unpaged: PG_reserved bad_page It used to be the case that PG_reserved pages were silently never freed, but in 2.6.15-rc1 they may be freed with a "Bad page state" message. We should work through such cases as they appear, fixing the code; but for now it's safer to issue the message without freeing the page, leaving PG_reserved set. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 23b84c4e1a57..1731236dec35 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -140,8 +140,7 @@ static void bad_page(const char *function, struct page *page) 1 << PG_reclaim | 1 << PG_slab | 1 << PG_swapcache | - 1 << PG_writeback | - 1 << PG_reserved ); + 1 << PG_writeback ); set_page_count(page, 0); reset_page_mapcount(page); page->mapping = NULL; @@ -335,7 +334,7 @@ static inline void __free_pages_bulk (struct page *page, zone->free_area[order].nr_free++; } -static inline void free_pages_check(const char *function, struct page *page) +static inline int free_pages_check(const char *function, struct page *page) { if ( page_mapcount(page) || page->mapping != NULL || @@ -353,6 +352,12 @@ static inline void free_pages_check(const char *function, struct page *page) bad_page(function, page); if (PageDirty(page)) __ClearPageDirty(page); + /* + * For now, we report if PG_reserved was found set, but do not + * clear it, and do not free the page. But we shall soon need + * to do more, for when the ZERO_PAGE count wraps negative. + */ + return PageReserved(page); } /* @@ -392,11 +397,10 @@ void __free_pages_ok(struct page *page, unsigned int order) { LIST_HEAD(list); int i; + int reserved = 0; arch_free_page(page, order); - mod_page_state(pgfree, 1 << order); - #ifndef CONFIG_MMU if (order > 0) for (i = 1 ; i < (1 << order) ; ++i) @@ -404,8 +408,12 @@ void __free_pages_ok(struct page *page, unsigned int order) #endif for (i = 0 ; i < (1 << order) ; ++i) - free_pages_check(__FUNCTION__, page + i); + reserved += free_pages_check(__FUNCTION__, page + i); + if (reserved) + return; + list_add(&page->lru, &list); + mod_page_state(pgfree, 1 << order); kernel_map_pages(page, 1<mapping != NULL || @@ -481,12 +489,20 @@ static void prep_new_page(struct page *page, int order) 1 << PG_reserved ))) bad_page(__FUNCTION__, page); + /* + * For now, we report if PG_reserved was found set, but do not + * clear it, and do not allocate the page: as a safety net. + */ + if (PageReserved(page)) + return 1; + page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_checked | 1 << PG_mappedtodisk); set_page_private(page, 0); set_page_refs(page, order); kernel_map_pages(page, 1 << order, 1); + return 0; } /* @@ -669,11 +685,14 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) arch_free_page(page, 0); - kernel_map_pages(page, 1, 0); - inc_page_state(pgfree); if (PageAnon(page)) page->mapping = NULL; - free_pages_check(__FUNCTION__, page); + if (free_pages_check(__FUNCTION__, page)) + return; + + inc_page_state(pgfree); + kernel_map_pages(page, 1, 0); + pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; local_irq_save(flags); list_add(&page->lru, &pcp->list); @@ -712,12 +731,14 @@ static struct page * buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) { unsigned long flags; - struct page *page = NULL; + struct page *page; int cold = !!(gfp_flags & __GFP_COLD); +again: if (order == 0) { struct per_cpu_pages *pcp; + page = NULL; pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; local_irq_save(flags); if (pcp->count <= pcp->low) @@ -739,7 +760,8 @@ buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) if (page != NULL) { BUG_ON(bad_range(zone, page)); mod_page_state_zone(zone, pgalloc, 1 << order); - prep_new_page(page, order); + if (prep_new_page(page, order)) + goto again; if (gfp_flags & __GFP_ZERO) prep_zero_page(page, order, gfp_flags); From 0b0db14c536debd92328819fe6c51a49717e8440 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:20 -0800 Subject: [PATCH 016/101] [PATCH] unpaged: copy_page_range vma For copy_one_pte's print_bad_pte to show the task correctly (instead of "???"), dup_mmap must pass down parent vma rather than child vma. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/fork.c b/kernel/fork.c index e0d0b77343f8..1c1cf8dc396b 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -263,7 +263,7 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) rb_parent = &tmp->vm_rb; mm->map_count++; - retval = copy_page_range(mm, oldmm, tmp); + retval = copy_page_range(mm, oldmm, mpnt); if (tmp->vm_ops && tmp->vm_ops->open) tmp->vm_ops->open(tmp); From f3d48f0373c14a6203202f7b1dfc7b0d8aaf6ed2 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Mon, 21 Nov 2005 21:32:22 -0800 Subject: [PATCH 017/101] [PATCH] unpaged: fix sound Bad page states Earlier I unifdefed PageCompound, so that snd_pcm_mmap_control_nopage and others can give out a 0-order component of a higher-order page, which won't be mistakenly freed when zap_pte_range unmaps it. But many Bad page states reported a PG_reserved was freed after all: I had missed that we need to say __GFP_COMP to get compound page behaviour. Some of these higher-order pages are allocated by snd_malloc_pages, some by snd_malloc_dev_pages; or if SBUS, by sbus_alloc_consistent - but that has no gfp arg, so add __GFP_COMP into its sparc32/64 implementations. I'm still rather puzzled that DRM seems not to need a similar change. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/ioport.c | 2 +- arch/sparc64/kernel/sbus.c | 2 +- sound/core/memalloc.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index d0f2bd227c4c..d39c9f206271 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -252,7 +252,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) } order = get_order(len_total); - if ((va = __get_free_pages(GFP_KERNEL, order)) == 0) + if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0) goto err_nopages; if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 96b825055668..d95a1bcf163d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -327,7 +327,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma order = get_order(size); if (order >= 10) return NULL; - first_page = __get_free_pages(GFP_KERNEL, order); + first_page = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); if (first_page == 0UL) return NULL; memset((char *)first_page, 0, PAGE_SIZE << order); diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 129abab5ce98..e4b8959dd4bb 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -197,6 +197,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags) snd_assert(size > 0, return NULL); snd_assert(gfp_flags != 0, return NULL); + gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ pg = get_order(size); if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) { mark_pages(virt_to_page(res), pg); @@ -241,6 +242,7 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d snd_assert(dma != NULL, return NULL); pg = get_order(size); gfp_flags = GFP_KERNEL + | __GFP_COMP /* compound page lets parts be mapped */ | __GFP_NORETRY /* don't trigger OOM-killer */ | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags); From 86e07ce71a8aad5074f7316f9b297d2137630283 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 21 Nov 2005 21:32:23 -0800 Subject: [PATCH 018/101] [PATCH] Fix error handling with put_compat_statfs() In fs/compat.c, whenever put_compat_statfs() returns an error, the containing syscall returns -EFAULT. This is presumably by analogy with the non-compat case, where any non-zero code from copy_to_user() should be translated into an EFAULT. However, put_compat_statfs() is also return -EOVERFLOW. The same applies for put_compat_statfs64(). This bug can be observed with a statfs() on a hugetlbfs directory. hugetlbfs, when mounted without limits reports available, free and total blocks as -1 (itself a bug, another patch coming). statfs() will mysteriously return EFAULT although it's parameters are perfectly valid addresses. This patch causes the compat versions of statfs() and statfs64() to correctly propogate the return values from put_compat_statfs() and put_compat_statfs64(). Signed-off-by: David Gibson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/compat.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index 0f7abf246d32..818634120b69 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -168,8 +168,8 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs if (!error) { struct kstatfs tmp; error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); - if (!error && put_compat_statfs(buf, &tmp)) - error = -EFAULT; + if (!error) + error = put_compat_statfs(buf, &tmp); path_release(&nd); } return error; @@ -186,8 +186,8 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user if (!file) goto out; error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); - if (!error && put_compat_statfs(buf, &tmp)) - error = -EFAULT; + if (!error) + error = put_compat_statfs(buf, &tmp); fput(file); out: return error; @@ -236,8 +236,8 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s if (!error) { struct kstatfs tmp; error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); - if (!error && put_compat_statfs64(buf, &tmp)) - error = -EFAULT; + if (!error) + error = put_compat_statfs64(buf, &tmp); path_release(&nd); } return error; @@ -257,8 +257,8 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c if (!file) goto out; error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); - if (!error && put_compat_statfs64(buf, &tmp)) - error = -EFAULT; + if (!error) + error = put_compat_statfs64(buf, &tmp); fput(file); out: return error; From 74a8a65c526187fe636a6a2abcb7d9ebc5c753ab Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 21 Nov 2005 21:32:24 -0800 Subject: [PATCH 019/101] [PATCH] Fix hugetlbfs_statfs() reporting of block limits Currently, if a hugetlbfs is mounted without limits (the default), statfs() will return -1 for max/free/used blocks. This does not appear to be in line with normal convention: simple_statfs() and shmem_statfs() both return 0 in similar cases. Worse, it confuses the translation logic in put_compat_statfs(), causing it to return -EOVERFLOW on such a mount. This patch alters hugetlbfs_statfs() to return 0 for max/free/used blocks on a mount without limits. Note that we need the test in the patch below, rather than just using 0 in the sbinfo structure, because the -1 marked in the free blocks field is used internally to tell the Signed-off-by: David Gibson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hugetlbfs/inode.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 64983ab55586..8c1cef3bb677 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -512,10 +512,14 @@ static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_bsize = HPAGE_SIZE; if (sbinfo) { spin_lock(&sbinfo->stat_lock); - buf->f_blocks = sbinfo->max_blocks; - buf->f_bavail = buf->f_bfree = sbinfo->free_blocks; - buf->f_files = sbinfo->max_inodes; - buf->f_ffree = sbinfo->free_inodes; + /* If no limits set, just report 0 for max/free/used + * blocks, like simple_statfs() */ + if (sbinfo->max_blocks >= 0) { + buf->f_blocks = sbinfo->max_blocks; + buf->f_bavail = buf->f_bfree = sbinfo->free_blocks; + buf->f_files = sbinfo->max_inodes; + buf->f_ffree = sbinfo->free_inodes; + } spin_unlock(&sbinfo->stat_lock); } buf->f_namelen = NAME_MAX; From b4627dea032ab1f6e472fcf030e28f22ea971f9b Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 21 Nov 2005 21:32:25 -0800 Subject: [PATCH 020/101] [PATCH] fbcon: Console Rotation - Fix wrong shift calculation The shift value (amount to shift the bitmap so first pixel starts at origin(0,0)) is incorrect. This causes corrupted characters or a kernel crash if fontwidth is not divisible by 8 at 270 degrees, or fontheight not divisible by 8 at 180 degrees. Report and part of the fix contributed by Knut Petersen. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon_rotate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h index 90c672096c2e..e504fbf5c604 100644 --- a/drivers/video/console/fbcon_rotate.h +++ b/drivers/video/console/fbcon_rotate.h @@ -49,7 +49,7 @@ static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat) static inline void rotate_ud(const char *in, char *out, u32 width, u32 height) { int i, j; - int shift = width % 8; + int shift = (8 - (width % 8)) & 7; width = (width + 7) & ~7; @@ -85,7 +85,7 @@ static inline void rotate_cw(const char *in, char *out, u32 width, u32 height) static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) { int i, j, h = height, w = width; - int shift = width % 8; + int shift = (8 - (width % 8)) & 7; width = (width + 7) & ~7; height = (height + 7) & ~7; From 5ef897c71a8985b62b7ec320a37376daaad364d0 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 21 Nov 2005 21:32:26 -0800 Subject: [PATCH 021/101] [PATCH] vgacon: Fix usage of stale height value on vc initialization Reported by: Wayne E. Harlan "[1.] One line summary of the problem: When the kernel option "vga=1" is used, additional tty's (alt+control+Fx with x=2,3,4,5, etc) do not provide the full 50 lines of output. The first one does have 50 lines, however. [2.] Full description of the problem/report: These addtitional tty's show only 39 lines plus the top pixel of the 40-th line. The remaining lines are black and not shown. Kernel version 2.6.13.4 does not show this problem." This bug is caused by using a stale font height value on vgacon_init. Booting with vga=1 gives an 80x50 screen with an 8x8 font. Somewhere during the initialization, the font was changed to 8x9 and the first vc was correctly resized to 80x44. However, the rest of the vc's were not allocated yet, and when they were subsequently initialized, they still used a font height of 8 (instead of 9) causing the mentioned bug. Fix by saving the new font height to vga_video_font_height. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/vgacon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 274f90543e32..167de397e4b4 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -966,6 +966,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) outb_p(0x12, vga_video_port_reg); /* Vertical display limit */ outb_p(vde, vga_video_port_val); spin_unlock_irq(&vga_lock); + vga_video_font_height = fontheight; for (i = 0; i < MAX_NR_CONSOLES; i++) { struct vc_data *c = vc_cons[i].d; From 0bd0f9fb190a0fc0fb25b764c8b04869711f7657 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 21 Nov 2005 21:32:28 -0800 Subject: [PATCH 022/101] [PATCH] hugetlb: fix race in set_max_huge_pages for multiple updaters of nr_huge_pages If there are multiple updaters to /proc/sys/vm/nr_hugepages simultaneously it is possible for the nr_huge_pages variable to become incorrect. There is no locking in the set_max_huge_pages function around alloc_fresh_huge_page which is able to update nr_huge_pages. Two callers to alloc_fresh_huge_page could race against each other as could a call to alloc_fresh_huge_page and a call to update_and_free_page. This patch just expands the area covered by the hugetlb_lock to cover the call into alloc_fresh_huge_page. I'm not sure how we could say that a sysctl section is performance critical where more specific locking would be needed. My reproducer was to run a couple copies of the following script simultaneously while [ true ]; do echo 1000 > /proc/sys/vm/nr_hugepages echo 500 > /proc/sys/vm/nr_hugepages echo 750 > /proc/sys/vm/nr_hugepages echo 100 > /proc/sys/vm/nr_hugepages echo 0 > /proc/sys/vm/nr_hugepages done and then watch /proc/meminfo and eventually you will see things like HugePages_Total: 100 HugePages_Free: 109 After applying the patch all seemed well. Signed-off-by: Eric Paris Acked-by: William Irwin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 728e9bda12ea..3e52df7c471b 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -22,6 +22,10 @@ unsigned long max_huge_pages; static struct list_head hugepage_freelists[MAX_NUMNODES]; static unsigned int nr_huge_pages_node[MAX_NUMNODES]; static unsigned int free_huge_pages_node[MAX_NUMNODES]; + +/* + * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages + */ static DEFINE_SPINLOCK(hugetlb_lock); static void enqueue_huge_page(struct page *page) @@ -61,8 +65,10 @@ static struct page *alloc_fresh_huge_page(void) HUGETLB_PAGE_ORDER); nid = (nid + 1) % num_online_nodes(); if (page) { + spin_lock(&hugetlb_lock); nr_huge_pages++; nr_huge_pages_node[page_to_nid(page)]++; + spin_unlock(&hugetlb_lock); } return page; } From e738cf6d03786486b7e1adbaed1c5c4e14d23626 Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Mon, 21 Nov 2005 21:32:28 -0800 Subject: [PATCH 023/101] [PATCH] cpufreq: silence cpufreq for UP drivers/cpufreq/cpufreq.c: In function `cpufreq_remove_dev': drivers/cpufreq/cpufreq.c:696: warning: unused variable `cpu_sys_dev' Signed-off-by: Grant Coady Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 23a63207d747..1c0f62d0f938 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -693,8 +693,8 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) unsigned int cpu = sys_dev->id; unsigned long flags; struct cpufreq_policy *data; - struct sys_device *cpu_sys_dev; #ifdef CONFIG_SMP + struct sys_device *cpu_sys_dev; unsigned int j; #endif From 79e448bf2d71d52d28c99be4faff9cc51928f90b Mon Sep 17 00:00:00 2001 From: Matthew Dobson Date: Mon, 21 Nov 2005 21:32:29 -0800 Subject: [PATCH 024/101] [PATCH] Fix a bug in scsi_get_command scsi_get_command() attempts to write into a structure that may not have been successfully allocated. Move this write inside the if statement that ensures we won't panic the kernel with a NULL pointer dereference. Signed-off-by: Matthew Dobson Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 0be60bba58d3..180676d7115a 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -265,10 +265,10 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) spin_lock_irqsave(&dev->list_lock, flags); list_add_tail(&cmd->list, &dev->cmd_list); spin_unlock_irqrestore(&dev->list_lock, flags); + cmd->jiffies_at_alloc = jiffies; } else put_device(&dev->sdev_gendev); - cmd->jiffies_at_alloc = jiffies; return cmd; } EXPORT_SYMBOL(scsi_get_command); From 6c52f1377d9cc4bedec5d4e1e3b22756b8978399 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 21 Nov 2005 21:32:30 -0800 Subject: [PATCH 025/101] [PATCH] dell_rbu driver depends on x86[64] This driver only appears on IA32 & EM64T boxes. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index b6815c6c29a2..1e371a510dd2 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -60,6 +60,7 @@ config EFI_PCDP config DELL_RBU tristate "BIOS update support for DELL systems via sysfs" + depends on X86 select FW_LOADER help Say m if you want to have the option of updating the BIOS for your From 98766fbe604bc198ced93c57220c2d4a78ad6c11 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 21 Nov 2005 21:32:31 -0800 Subject: [PATCH 026/101] [PATCH] kernel Doc/ URL corrections Correct lots of URLs in Documentation/ Also a few minor whitespace cleanups and typo/spello fixes. Sadly there are still a lot of bad URLs remaining. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/arm/VFP/release-notes.txt | 2 +- Documentation/dvb/faq.txt | 1 - Documentation/filesystems/affs.txt | 2 +- Documentation/filesystems/ext2.txt | 3 +- Documentation/floppy.txt | 10 ++--- Documentation/ioctl-number.txt | 2 +- Documentation/kernel-docs.txt | 60 ++++++++++++++----------- Documentation/mca.txt | 2 +- Documentation/networking/driver.txt | 5 +-- Documentation/networking/iphase.txt | 2 +- Documentation/networking/irda.txt | 8 +--- Documentation/networking/ray_cs.txt | 3 +- Documentation/networking/vortex.txt | 28 ++++++------ Documentation/power/pci.txt | 2 +- Documentation/scsi/ibmmca.txt | 4 +- Documentation/usb/ibmcam.txt | 4 +- Documentation/usb/ov511.txt | 4 +- Documentation/usb/rio.txt | 6 +-- Documentation/video4linux/zr36120.txt | 7 ++- 19 files changed, 79 insertions(+), 76 deletions(-) diff --git a/Documentation/arm/VFP/release-notes.txt b/Documentation/arm/VFP/release-notes.txt index f28e0222f5e5..28a2795705ca 100644 --- a/Documentation/arm/VFP/release-notes.txt +++ b/Documentation/arm/VFP/release-notes.txt @@ -12,7 +12,7 @@ This release has been validated against the SoftFloat-2b library by John R. Hauser using the TestFloat-2a test suite. Details of this library and test suite can be found at: - http://www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html + http://www.jhauser.us/arithmetic/SoftFloat.html The operations which have been tested with this package are: diff --git a/Documentation/dvb/faq.txt b/Documentation/dvb/faq.txt index 3bf51e45c972..a42132d60dc8 100644 --- a/Documentation/dvb/faq.txt +++ b/Documentation/dvb/faq.txt @@ -60,7 +60,6 @@ Some very frequently asked questions about linuxtv-dvb Metzler Bros. DVB development; alternate drivers and DVB utilities, include dvb-mpegtools and tuxzap. - http://www.linuxstb.org/ http://sourceforge.net/projects/dvbtools/ Dave Chapman's dvbtools package, including dvbstream and dvbtune diff --git a/Documentation/filesystems/affs.txt b/Documentation/filesystems/affs.txt index 30c9738590f4..2d1524469c25 100644 --- a/Documentation/filesystems/affs.txt +++ b/Documentation/filesystems/affs.txt @@ -216,4 +216,4 @@ due to an incompatibility with the Amiga floppy controller. If you are interested in an Amiga Emulator for Linux, look at -http://www-users.informatik.rwth-aachen.de/~crux/uae.html +http://www.freiburg.linux.de/~uae/ diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt index a8edb376b041..3dd2872416a1 100644 --- a/Documentation/filesystems/ext2.txt +++ b/Documentation/filesystems/ext2.txt @@ -369,9 +369,8 @@ The kernel source file:/usr/src/linux/fs/ext2/ e2fsprogs (e2fsck) http://e2fsprogs.sourceforge.net/ Design & Implementation http://e2fsprogs.sourceforge.net/ext2intro.html Journaling (ext3) ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/ -Hashed Directories http://kernelnewbies.org/~phillips/htree/ Filesystem Resizing http://ext2resize.sourceforge.net/ -Compression (*) http://www.netspace.net.au/~reiter/e2compr/ +Compression (*) http://e2compr.sourceforge.net/ Implementations for: Windows 95/98/NT/2000 http://uranus.it.swin.edu.au/~jn/linux/Explore2fs.htm diff --git a/Documentation/floppy.txt b/Documentation/floppy.txt index 6fb10fcd82fb..6ccab88705cb 100644 --- a/Documentation/floppy.txt +++ b/Documentation/floppy.txt @@ -4,7 +4,7 @@ FAQ list: ========= A FAQ list may be found in the fdutils package (see below), and also -at http://fdutils.linux.lu/FAQ.html +at . LILO configuration options (Thinkpad users, read this) @@ -217,10 +217,10 @@ It also contains additional documentation about the floppy driver. The latest version can be found at fdutils homepage: http://fdutils.linux.lu -The fdutils-5.4 release can be found at: - http://fdutils.linux.lu/fdutils-5.4.src.tar.gz - http://www.tux.org/pub/knaff/fdutils/fdutils-5.4.src.tar.gz - ftp://metalab.unc.edu/pub/Linux/utils/disk-management/fdutils-5.4.src.tar.gz +The fdutils releases can be found at: + http://fdutils.linux.lu/download.html + http://www.tux.org/pub/knaff/fdutils/ + ftp://metalab.unc.edu/pub/Linux/utils/disk-management/ Reporting problems about the floppy driver ========================================== diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 87f4d052e39c..aa7ba00ec082 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -133,7 +133,7 @@ Code Seq# Include File Comments 'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system 'l' 40-7F linux/udf_fs_i.h in development: - + 'm' all linux/mtio.h conflict! 'm' all linux/soundcard.h conflict! 'm' all linux/synclink.h conflict! diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt index cb89fb3b61ef..99d24f2943ee 100644 --- a/Documentation/kernel-docs.txt +++ b/Documentation/kernel-docs.txt @@ -196,7 +196,7 @@ * Title: "Writing Linux Device Drivers" Author: Michael K. Johnson. - URL: http://people.redhat.com/johnsonm/devices.html + URL: http://users.evitech.fi/~tk/rtos/writing_linux_device_d.html Keywords: files, VFS, file operations, kernel interface, character vs block devices, I/O access, hardware interrupts, DMA, access to user memory, memory allocation, timers. @@ -284,7 +284,7 @@ * Title: "Linux Kernel Module Programming Guide" Author: Ori Pomerantz. - URL: http://www.tldp.org/LDP/lkmpg/mpg.html + URL: http://tldp.org/LDP/lkmpg/2.6/html/index.html Keywords: modules, GPL book, /proc, ioctls, system calls, interrupt handlers . Description: Very nice 92 pages GPL book on the topic of modules @@ -292,7 +292,7 @@ * Title: "Device File System (devfs) Overview" Author: Richard Gooch. - URL: http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.txt + URL: http://www.atnf.csiro.au/people/rgooch/linux/docs/devfs.html Keywords: filesystem, /dev, devfs, dynamic devices, major/minor allocation, device management. Description: Document describing Richard Gooch's controversial @@ -316,9 +316,8 @@ * Title: "The Kernel Hacking HOWTO" Author: Various Talented People, and Rusty. - URL: - http://www.lisoleg.net/doc/Kernel-Hacking-HOWTO/kernel-hacking-HOW - TO.html + Location: in kernel tree, Documentation/DocBook/kernel-hacking/ + (must be built as "make {htmldocs | psdocs | pdfdocs}) Keywords: HOWTO, kernel contexts, deadlock, locking, modules, symbols, return conventions. Description: From the Introduction: "Please understand that I @@ -332,13 +331,13 @@ originally written for the 2.3 kernels, but nearly all of it applies to 2.2 too; 2.0 is slightly different". - * Title: "ALSA 0.5.0 Developer documentation" - Author: Stephan 'Jumpy' Bartels . - URL: http://www.math.TU-Berlin.de/~sbartels/alsa/ + * Title: "Writing an ALSA Driver" + Author: Takashi Iwai + URL: http://www.alsa-project.org/~iwai/writing-an-alsa-driver/index.html Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware. Description: Advanced Linux Sound Architecture for developers, - both at kernel and user-level sides. Work in progress. ALSA is - supposed to be Linux's next generation sound architecture. + both at kernel and user-level sides. ALSA is the Linux kernel + sound architecture in the 2.6 kernel version. * Title: "Programming Guide for Linux USB Device Drivers" Author: Detlef Fliegl. @@ -369,8 +368,8 @@ filesystems, IPC and Networking Code. * Title: "Linux Kernel Mailing List Glossary" - Author: John Levon. - URL: http://www.movement.uklinux.net/glossary.html + Author: various + URL: http://kernelnewbies.org/glossary/ Keywords: glossary, terms, linux-kernel. Description: From the introduction: "This glossary is intended as a brief description of some of the acronyms and terms you may hear @@ -378,9 +377,8 @@ * Title: "Linux Kernel Locking HOWTO" Author: Various Talented People, and Rusty. - URL: - http://netfilter.kernelnotes.org/unreliable-guides/kernel-locking- - HOWTO.html + Location: in kernel tree, Documentation/DocBook/kernel-locking/ + (must be built as "make {htmldocs | psdocs | pdfdocs}) Keywords: locks, locking, spinlock, semaphore, atomic, race condition, bottom halves, tasklets, softirqs. Description: The title says it all: document describing the @@ -490,7 +488,7 @@ * Title: "Get those boards talking under Linux." Author: Alex Ivchenko. - URL: http://www.ednmag.com/ednmag/reg/2000/06222000/13df2.htm + URL: http://www.edn.com/article/CA46968.html Keywords: data-acquisition boards, drivers, modules, interrupts, memory allocation. Description: Article written for people wishing to make their data @@ -498,7 +496,7 @@ overview on writing drivers, from the naming of functions to interrupt handling. Notes: Two-parts article. Part II is at - http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm + URL: http://www.edn.com/article/CA46998.html * Title: "Linux PCMCIA Programmer's Guide" Author: David Hinds. @@ -529,7 +527,7 @@ definitive guide for hackers, virus coders and system administrators." Author: pragmatic/THC. - URL: http://packetstorm.securify.com/groups/thc/LKM_HACKING.html + URL: http://packetstormsecurity.org/docs/hack/LKM_HACKING.html Keywords: syscalls, intercept, hide, abuse, symbol table. Description: Interesting paper on how to abuse the Linux kernel in order to intercept and modify syscalls, make @@ -537,8 +535,7 @@ write kernel modules based virus... and solutions for admins to avoid all those abuses. Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x - kernels. Also available in txt format at - http://www.blacknemesis.org/hacking/txt/cllkm.txt + kernels. BOOKS: (Not on-line) @@ -557,7 +554,17 @@ ISBN: 0-59600-008-1 Notes: Further information in http://www.oreilly.com/catalog/linuxdrive2/ - + + * Title: "Linux Device Drivers, 3nd Edition" + Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman + Publisher: O'Reilly & Associates. + Date: 2005. + Pages: 636. + ISBN: 0-596-00590-3 + Notes: Further information in + http://www.oreilly.com/catalog/linuxdrive3/ + PDF format, URL: http://lwn.net/Kernel/LDD3/ + * Title: "Linux Kernel Internals" Author: Michael Beck. Publisher: Addison-Wesley. @@ -766,12 +773,15 @@ documents, FAQs... * Name: "linux-kernel mailing list archives and search engines" + URL: http://vger.kernel.org/vger-lists.html URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html - URL: http://www.kernelnotes.org/lnxlists/linux-kernel/ - URL: http://www.geocrawler.com + URL: http://marc.theaimsgroup.com/?l=linux-kernel + URL: http://groups.google.com/group/mlist.linux.kernel + URL: http://www.cs.helsinki.fi/linux/linux-kernel/ + URL: http://www.lib.uaa.alaska.edu/linux-kernel/ Keywords: linux-kernel, archives, search. Description: Some of the linux-kernel mailing list archivers. If you have a better/another one, please let me know. _________________________________________________________________ - Document last updated on Thu Jun 28 15:09:39 CEST 2001 + Document last updated on Sat 2005-NOV-19 diff --git a/Documentation/mca.txt b/Documentation/mca.txt index 6e32c305c65a..60913354cb7d 100644 --- a/Documentation/mca.txt +++ b/Documentation/mca.txt @@ -252,7 +252,7 @@ their names here, but I don't have a list handy. Check the MCA Linux home page (URL below) for a perpetually out-of-date list. ===================================================================== -MCA Linux Home Page: http://glycerine.itsmm.uni.edu/mca/ +MCA Linux Home Page: http://www.dgmicro.com/mca/ Christophe Beauregard chrisb@truespectra.com diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt index 11fd0ef5ff57..a9ad58b49cc5 100644 --- a/Documentation/networking/driver.txt +++ b/Documentation/networking/driver.txt @@ -1,7 +1,4 @@ -Documents about softnet driver issues in general can be found -at: - - http://www.firstfloor.org/~andi/softnet/ +Document about softnet driver issues Transmit path guidelines: diff --git a/Documentation/networking/iphase.txt b/Documentation/networking/iphase.txt index 39ccb8595bf1..493203a080a8 100644 --- a/Documentation/networking/iphase.txt +++ b/Documentation/networking/iphase.txt @@ -22,7 +22,7 @@ The features and limitations of this driver are as follows: - All variants of Interphase ATM PCI (i)Chip adapter cards are supported, including x575 (OC3, control memory 128K , 512K and packet memory 128K, 512K and 1M), x525 (UTP25) and x531 (DS3 and E3). See - http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM + http://www.iphase.com/site/iphase-web/?epi_menuItemID=e196f04b4b3b40502f150882e21046a0 for details. - Only x86 platforms are supported. - SMP is supported. diff --git a/Documentation/networking/irda.txt b/Documentation/networking/irda.txt index 9e5b8e66d6a5..bff26c138be6 100644 --- a/Documentation/networking/irda.txt +++ b/Documentation/networking/irda.txt @@ -3,12 +3,8 @@ of the IrDA Utilities. More detailed information about these and associated programs can be found on http://irda.sourceforge.net/ For more information about how to use the IrDA protocol stack, see the -Linux Infared HOWTO (http://www.tuxmobil.org/Infrared-HOWTO/Infrared-HOWTO.html) -by Werner Heuser +Linux Infrared HOWTO by Werner Heuser : + There is an active mailing list for discussing Linux-IrDA matters called irda-users@lists.sourceforge.net - - - - diff --git a/Documentation/networking/ray_cs.txt b/Documentation/networking/ray_cs.txt index b1def00bc4a3..5427f8c7df95 100644 --- a/Documentation/networking/ray_cs.txt +++ b/Documentation/networking/ray_cs.txt @@ -29,8 +29,7 @@ with nondefault parameters, they can be edited in will find them all. Information on card services is available at: - ftp://hyper.stanford.edu/pub/pcmcia/doc - http://hyper.stanford.edu/HyperNews/get/pcmcia/home.html + http://pcmcia-cs.sourceforge.net/ Card services user programs are still required for PCMCIA devices. diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt index 80e1cb19609f..3759acf95b29 100644 --- a/Documentation/networking/vortex.txt +++ b/Documentation/networking/vortex.txt @@ -11,7 +11,7 @@ The driver was written by Donald Becker Don is no longer the prime maintainer of this version of the driver. Please report problems to one or more of: - Andrew Morton + Andrew Morton Netdev mailing list Linux kernel mailing list @@ -274,24 +274,24 @@ Details of the device driver implementation are at the top of the source file. Additional documentation is available at Don Becker's Linux Drivers site: - http://www.scyld.com/network/vortex.html + http://www.scyld.com/vortex.html Donald Becker's driver development site: - http://www.scyld.com/network + http://www.scyld.com/network.html Donald's vortex-diag program is useful for inspecting the NIC's state: - http://www.scyld.com/diag/#pci-diags + http://www.scyld.com/ethercard_diag.html Donald's mii-diag program may be used for inspecting and manipulating the NIC's Media Independent Interface subsystem: - http://www.scyld.com/diag/#mii-diag + http://www.scyld.com/ethercard_diag.html#mii-diag Donald's wake-on-LAN page: - http://www.scyld.com/expert/wake-on-lan.html + http://www.scyld.com/wakeonlan.html 3Com's documentation for many NICs, including the ones supported by this driver is available at @@ -305,7 +305,7 @@ this driver is available at Driver updates and a detailed changelog for the modifications which were made for the 2.3/2,4 series kernel is available at - http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 + http://www.zip.com.au/~akpm/linux/#3c59x-bc Autonegotiation notes @@ -434,8 +434,8 @@ steps you should take: send all logs to the maintainer. 3) Download you card's diagnostic tool from Donald - Backer's website http://www.scyld.com/diag. Download - mii-diag.c as well. Build these. + Becker's website . + Download mii-diag.c as well. Build these. a) Run 'vortex-diag -aaee' and 'mii-diag -v' when the card is working correctly. Save the output. @@ -443,8 +443,8 @@ steps you should take: b) Run the above commands when the card is malfunctioning. Send both sets of output. -Finally, please be patient and be prepared to do some work. You may end up working on -this problem for a week or more as the maintainer asks more questions, asks for more -tests, asks for patches to be applied, etc. At the end of it all, the problem may even -remain unresolved. - +Finally, please be patient and be prepared to do some work. You may +end up working on this problem for a week or more as the maintainer +asks more questions, asks for more tests, asks for patches to be +applied, etc. At the end of it all, the problem may even remain +unresolved. diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index 6fc9d511fc39..73fc87e5dc38 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -335,5 +335,5 @@ this on the whole. PCI Local Bus Specification PCI Bus Power Management Interface Specification - http://pcisig.org + http://www.pcisig.com diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt index 2ffb3ae0ef4d..d16ce5b540f4 100644 --- a/Documentation/scsi/ibmmca.txt +++ b/Documentation/scsi/ibmmca.txt @@ -1108,7 +1108,7 @@ A: You have to activate MCA bus support, first. Q: Where can I find the latest info about this driver? A: See the file MAINTAINERS for the current WWW-address, which offers - updates, info and Q/A lists. At this files' origin, the webaddress + updates, info and Q/A lists. At this file's origin, the webaddress was: http://www.uni-mainz.de/~langm000/linux.html Q: My SCSI-adapter is not recognized by the driver, what can I do? A: Just force it to be recognized by kernel parameters. See section 5.1. @@ -1248,7 +1248,7 @@ -------------------- The address of the IBM SCSI-subsystem supporting WWW-page is: - http://www.uni-mainz.de/~langm000/linux.html + http://www.staff.uni-mainz.de/mlang/linux.html Here you can find info about the background of this driver, patches, troubleshooting support, news and a bugreport form. Please check that diff --git a/Documentation/usb/ibmcam.txt b/Documentation/usb/ibmcam.txt index ce2f21a3eac4..c25003644131 100644 --- a/Documentation/usb/ibmcam.txt +++ b/Documentation/usb/ibmcam.txt @@ -28,8 +28,8 @@ SUPPORTED CAMERAS: Xirlink "C-It" camera, also known as "IBM PC Camera". The device uses proprietary ASIC (and compression method); it is manufactured by Xirlink. See http://www.xirlink.com/ -http://www.ibmpccamera.com or http://www.c-itnow.com/ for -details and pictures. +(renamed to http://www.veo.com), http://www.ibmpccamera.com, +or http://www.c-itnow.com/ for details and pictures. This very chipset ("X Chip", as marked at the factory) is used in several other cameras, and they are supported diff --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt index e1974ec8217e..a7fc0432bff1 100644 --- a/Documentation/usb/ov511.txt +++ b/Documentation/usb/ov511.txt @@ -22,8 +22,8 @@ WHAT YOU NEED: http://www.ovt.com/omniusbp.html - A Video4Linux compatible frame grabber program (I recommend vidcat and xawtv) - vidcat is part of the w3cam package: http://www.hdk-berlin.de/~rasca/w3cam/ - xawtv is available at: http://www.in-berlin.de/User/kraxel/xawtv.html + vidcat is part of the w3cam package: http://mpx.freeshell.net/ + xawtv is available at: http://linux.bytesex.org/xawtv/ HOW TO USE IT: diff --git a/Documentation/usb/rio.txt b/Documentation/usb/rio.txt index 0aa79ab0088c..ab21db454694 100644 --- a/Documentation/usb/rio.txt +++ b/Documentation/usb/rio.txt @@ -46,9 +46,9 @@ Contact information: -------------------- The main page for the project is hosted at sourceforge.net in the following - address: http://rio500.sourceforge.net You can also go to the sourceforge - project page at: http://sourceforge.net/project/?group_id=1944 There is - also a mailing list: rio500-users@lists.sourceforge.net + URL: . You can also go to the project's + sourceforge home page at: . + There is also a mailing list: rio500-users@lists.sourceforge.net Authors: ------- diff --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt index 4af6c52595eb..5d6357eefde4 100644 --- a/Documentation/video4linux/zr36120.txt +++ b/Documentation/video4linux/zr36120.txt @@ -76,8 +76,11 @@ activates the GRAB bit. A few ms later the VSYNC (re-)rises and the zoran starts to work on a new and freshly broadcasted frame.... For pointers I used the specs of both chips. Below are the URLs: - http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf - http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf + http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf + http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf +Some alternatives for the Philips SAA 7110 datasheet are: + http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml + http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part The documentation has very little on absolute numbers or timings needed for the various modes/resolutions, but there are other From b6fcc80d03b41162ed88c3fb542aca9b654bc414 Mon Sep 17 00:00:00 2001 From: Kiyoshi Ueda Date: Mon, 21 Nov 2005 21:32:32 -0800 Subject: [PATCH 027/101] [PATCH] device-mapper dm-ioctl: missing put in table load error case An error path in table_load() forgets to release a table that won't now be referenced. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 54ec737195e0..a90b053368ee 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -974,6 +974,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) if (!hc) { DMWARN("device doesn't appear to be in the dev hash table."); up_write(&_hash_lock); + dm_table_put(t); return -ENXIO; } From c4cc66351a24da5feec298be2da59a85f68dd3ea Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 21 Nov 2005 21:32:33 -0800 Subject: [PATCH 028/101] [PATCH] device-mapper: list_versions fix In some circumstances the LIST_VERSIONS output is truncated because the size calculation forgets about a 'uint32_t' in each structure - but the inclusion of the whole of ALIGN_MASK frequently compensates for the omission. This is a quick workaround to use an upper bound. (The code ought to be fixed to supply the actual size.) Running 'dmsetup targets' may demonstrate the problem: when I run it, the last line comes out as 'erro' instead of 'error'. Consequently, 'lvcreate --type error' doesn't work. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index a90b053368ee..07d44e19536e 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -425,8 +425,8 @@ static void list_version_get_needed(struct target_type *tt, void *needed_param) { size_t *needed = needed_param; + *needed += sizeof(struct dm_target_versions); *needed += strlen(tt->name); - *needed += sizeof(tt->version); *needed += ALIGN_MASK; } From 0e56822d30184d0da35a6ecc51f38c4ceb457a80 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Mon, 21 Nov 2005 21:32:34 -0800 Subject: [PATCH 029/101] [PATCH] device-mapper: mirror log bitset fix The linux bitset operators (test_bit, set_bit etc) work on arrays of "unsigned long". dm-log uses such bitsets but treats them as arrays of uint32_t, only allocating and zeroing a multiple of 4 bytes (as 'clean_bits' is a uint32_t). The patch below fixes this problem. The problem is specific to 64-bit big endian machines such as s390x or ppc-64 and can prevent pvmove terminating. In the simplest case, if "region_count" were (say) 30, then bitset_size (below) would be 4 and bitset_uint32_count would be 1. Thus the memory for this butset, after allocation and zeroing would be 0 0 0 0 X X X X On a bigendian 64bit machine, bit 0 for this bitset is in the 8th byte! (and every bit that dm-log would use would be in the X area). 0 0 0 0 X X X X ^ here which hasn't been cleared properly. As the dm-raid1 code only syncs and counts regions which have a 0 in the 'sync_bits' bitset, and only finishes when it has counted high enough, a large number of 1's among those 'X's will cause the sync to not complete. It is worth noting that the code uses the same bitsets for in-memory and on-disk logs. As these bitsets are host-endian and host-sized, this means that they cannot safely be moved between computers with Signed-off-by: Neil Brown Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index e110655eabdb..a76349cb10a5 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -333,10 +333,10 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti, lc->sync = sync; /* - * Work out how many words we need to hold the bitset. + * Work out how many "unsigned long"s we need to hold the bitset. */ bitset_size = dm_round_up(region_count, - sizeof(*lc->clean_bits) << BYTE_SHIFT); + sizeof(unsigned long) << BYTE_SHIFT); bitset_size >>= BYTE_SHIFT; lc->bitset_uint32_count = bitset_size / 4; From 640eb3b0456f8273726d31160aa24568ae703eec Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Mon, 21 Nov 2005 21:32:35 -0800 Subject: [PATCH 030/101] [PATCH] device-mapper dm-mpath: endio spinlock fix do_end_io() can be called without interrupts blocked. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-mpath.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index f9b7b32d5d5c..f72a82fb9434 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1000,6 +1000,7 @@ static int do_end_io(struct multipath *m, struct bio *bio, { struct hw_handler *hwh = &m->hw_handler; unsigned err_flags = MP_FAIL_PATH; /* Default behavior */ + unsigned long flags; if (!error) return 0; /* I/O complete */ @@ -1010,17 +1011,17 @@ static int do_end_io(struct multipath *m, struct bio *bio, if (error == -EOPNOTSUPP) return error; - spin_lock(&m->lock); + spin_lock_irqsave(&m->lock, flags); if (!m->nr_valid_paths) { if (!m->queue_if_no_path) { - spin_unlock(&m->lock); + spin_unlock_irqrestore(&m->lock, flags); return -EIO; } else { - spin_unlock(&m->lock); + spin_unlock_irqrestore(&m->lock, flags); goto requeue; } } - spin_unlock(&m->lock); + spin_unlock_irqrestore(&m->lock, flags); if (hwh->type && hwh->type->error) err_flags = hwh->type->error(hwh, bio); @@ -1040,12 +1041,12 @@ static int do_end_io(struct multipath *m, struct bio *bio, dm_bio_restore(&mpio->details, bio); /* queue for the daemon to resubmit or fail */ - spin_lock(&m->lock); + spin_lock_irqsave(&m->lock, flags); bio_list_add(&m->queued_ios, bio); m->queue_size++; if (!m->queue_io) queue_work(kmultipathd, &m->process_queued_ios); - spin_unlock(&m->lock); + spin_unlock_irqrestore(&m->lock, flags); return 1; /* io not complete */ } From 233886dd32ad71daf9c21bf3728c0933a94870f0 Mon Sep 17 00:00:00 2001 From: "jblunck@suse.de" Date: Mon, 21 Nov 2005 21:32:36 -0800 Subject: [PATCH 031/101] [PATCH] device-mapper snapshot: bio_list fix bio_list_merge() should do nothing if the second list is empty - not oops. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-bio-list.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h index bc021e1fd4d1..bbf4615f0e30 100644 --- a/drivers/md/dm-bio-list.h +++ b/drivers/md/dm-bio-list.h @@ -33,6 +33,9 @@ static inline void bio_list_add(struct bio_list *bl, struct bio *bio) static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2) { + if (!bl2->head) + return; + if (bl->tail) bl->tail->bi_next = bl2->head; else From 7692c5dd48026d952199c2b97c3418f927cc0407 Mon Sep 17 00:00:00 2001 From: Jonathan E Brassow Date: Mon, 21 Nov 2005 21:32:37 -0800 Subject: [PATCH 032/101] [PATCH] device-mapper raid1: drop mark_region spinlock fix The spinlock region_lock is held while calling mark_region which can sleep. Drop the spinlock before calling that function. A region's state and inclusion in the clean list are altered by rh_inc and rh_dec. The state variable is set to RH_CLEAN in rh_dec, but only if 'pending' is zero. It is set to RH_DIRTY in rh_inc, but not if it is already so. The changes to 'pending', the state, and the region's inclusion in the clean list need to be atomicly. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-raid1.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 2375709a392c..6b0fc1670929 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -376,16 +376,18 @@ static void rh_inc(struct region_hash *rh, region_t region) read_lock(&rh->hash_lock); reg = __rh_find(rh, region); + spin_lock_irq(&rh->region_lock); atomic_inc(®->pending); - spin_lock_irq(&rh->region_lock); if (reg->state == RH_CLEAN) { - rh->log->type->mark_region(rh->log, reg->key); - reg->state = RH_DIRTY; list_del_init(®->list); /* take off the clean list */ - } - spin_unlock_irq(&rh->region_lock); + spin_unlock_irq(&rh->region_lock); + + rh->log->type->mark_region(rh->log, reg->key); + } else + spin_unlock_irq(&rh->region_lock); + read_unlock(&rh->hash_lock); } @@ -408,21 +410,17 @@ static void rh_dec(struct region_hash *rh, region_t region) reg = __rh_lookup(rh, region); read_unlock(&rh->hash_lock); + spin_lock_irqsave(&rh->region_lock, flags); if (atomic_dec_and_test(®->pending)) { - spin_lock_irqsave(&rh->region_lock, flags); - if (atomic_read(®->pending)) { /* check race */ - spin_unlock_irqrestore(&rh->region_lock, flags); - return; - } if (reg->state == RH_RECOVERING) { list_add_tail(®->list, &rh->quiesced_regions); } else { reg->state = RH_CLEAN; list_add(®->list, &rh->clean_regions); } - spin_unlock_irqrestore(&rh->region_lock, flags); should_wake = 1; } + spin_unlock_irqrestore(&rh->region_lock, flags); if (should_wake) wake(); From b3a5225f31180322fd7d692fd4cf786702826b94 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Mon, 21 Nov 2005 21:32:38 -0800 Subject: [PATCH 033/101] [PATCH] prefer pkg-config for the QT check This makes pkg-config now the prefered way to configure QT and properly fixes the recent Fedora breakage and leaves the old QT detection as fallback mechanism. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/kconfig/Makefile | 68 +++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 9d67782b812f..a96153fc793f 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -129,8 +129,8 @@ endif HOSTCFLAGS_lex.zconf.o := -I$(src) HOSTCFLAGS_zconf.tab.o := -I$(src) -HOSTLOADLIBES_qconf = -L$(QTLIBPATH) -Wl,-rpath,$(QTLIBPATH) -l$(LIBS_QT) -ldl -HOSTCXXFLAGS_qconf.o = -I$(QTDIR)/include -D LKC_DIRECT_LINK +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK HOSTLOADLIBES_gconf = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs` HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \ @@ -139,40 +139,50 @@ HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \ $(obj)/qconf.o: $(obj)/.tmp_qtcheck ifeq ($(qconf-target),1) -MOC = $(QTDIR)/bin/moc -QTLIBPATH = $(QTDIR)/lib +$(obj)/.tmp_qtcheck: $(src)/Makefile -include $(obj)/.tmp_qtcheck # QT needs some extra effort... $(obj)/.tmp_qtcheck: - @set -e; for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ - if [ -f $$d/include/qconfig.h ]; then DIR=$$d; break; fi; \ - done; \ - if [ -z "$$DIR" ]; then \ - echo "*"; \ - echo "* Unable to find the QT installation. Please make sure that the"; \ - echo "* QT development package is correctly installed and the QTDIR"; \ - echo "* environment variable is set to the correct location."; \ - echo "*"; \ - false; \ - fi; \ - LIBPATH=$$DIR/lib; LIB=qt; \ - if [ -f $$QTLIB/libqt-mt.so ] ; then \ - LIB=qt-mt; \ - LIBPATH=$$QTLIB; \ + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ else \ - $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ - LIBPATH=$$DIR/lib/$$($(HOSTCXX) -print-multi-os-directory); \ - if [ -f $$LIBPATH/libqt-mt.so ]; then LIB=qt-mt; fi; \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo "*"; \ + echo "* Unable to find the QT installation. Please make sure that"; \ + echo "* the QT development package is correctly installed and"; \ + echo "* either install pkg-config or set the QTDIR environment"; \ + echo "* variable to the correct location."; \ + echo "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ fi; \ - echo "QTDIR=$$DIR" > $@; echo "QTLIBPATH=$$LIBPATH" >> $@; \ - echo "LIBS_QT=$$LIB" >> $@; \ - if [ ! -x $$DIR/bin/moc -a -x /usr/bin/moc ]; then \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ echo "*"; \ - echo "* Unable to find $$DIR/bin/moc, using /usr/bin/moc instead."; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ echo "*"; \ - echo "MOC=/usr/bin/moc" >> $@; \ - fi + moc="/usr/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ endif $(obj)/gconf.o: $(obj)/.tmp_gtkcheck @@ -210,7 +220,7 @@ $(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h $(obj)/gconf.o: $(obj)/lkc_defs.h $(obj)/%.moc: $(src)/%.h - $(MOC) -i $< -o $@ + $(KC_QT_MOC) -i $< -o $@ $(obj)/lkc_defs.h: $(src)/lkc_proto.h sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' From af2b4079ab154bd12e8c12b02db5f31b31babe63 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 22 Nov 2005 14:38:04 -0800 Subject: [PATCH 034/101] [NET]: Shut up warnings in net/core/flow.c Not really a network problem, more a !SMP issue. net/core/flow.c:295: warning: statement with no effect flow.c:295: smp_call_function(flow_cache_flush_per_cpu, &info, 1, 0); Fix this by converting the macro to an inline function, which also increases the typechecking for !SMP builds. Signed-off-by: Russell King Signed-off-by: David S. Miller --- include/linux/smp.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index 9dfa3ee769ae..b6069c8e1f04 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -94,7 +94,13 @@ void smp_prepare_boot_cpu(void); */ #define raw_smp_processor_id() 0 #define hard_smp_processor_id() 0 -#define smp_call_function(func,info,retry,wait) ({ 0; }) + +static inline int smp_call_function(void (*func) (void *info), void *info, + int retry, int wait) +{ + return 0; +} + #define on_each_cpu(func,info,retry,wait) ({ func(info); 0; }) static inline void smp_send_reschedule(int cpu) { } #define num_booting_cpus() 1 From c27bd492fd84c590767a3c0f9f74e637b17af138 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 22 Nov 2005 14:41:50 -0800 Subject: [PATCH 035/101] [NETLINK]: Use tgid instead of pid for nlmsg_pid Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 8c38ee6d255e..96020d7087e8 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -476,7 +476,7 @@ static int netlink_autobind(struct socket *sock) struct hlist_head *head; struct sock *osk; struct hlist_node *node; - s32 pid = current->pid; + s32 pid = current->tgid; int err; static s32 rover = -4097; From 0ff60a45678e67b2547256a636fd00c1667ce4fa Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Tue, 22 Nov 2005 14:47:37 -0800 Subject: [PATCH 036/101] [IPV4]: Fix secondary IP addresses after promotion This patch fixes the problem with promoting aliases when: a) a single primary and > 1 secondary addresses b) multiple primary addresses each with at least one secondary address Based on earlier efforts from Brian Pomerantz , Patrick McHardy and Thomas Graf Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/route.h | 3 +++ net/ipv4/devinet.c | 40 ++++++++++++++++++++++++++++++---------- net/ipv4/fib_frontend.c | 2 +- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/net/route.h b/include/net/route.h index dbe79ca67d31..e3e5436f8017 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -126,6 +126,9 @@ extern int ip_rt_ioctl(unsigned int cmd, void __user *arg); extern void ip_rt_get_source(u8 *src, struct rtable *rt); extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); +struct in_ifaddr; +extern void fib_add_ifaddr(struct in_ifaddr *); + static inline void ip_rt_put(struct rtable * rt) { if (rt) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 4ec4b2ca6ab1..04a6fe3e95a2 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -234,7 +234,10 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy) { struct in_ifaddr *promote = NULL; - struct in_ifaddr *ifa1 = *ifap; + struct in_ifaddr *ifa, *ifa1 = *ifap; + struct in_ifaddr *last_prim = in_dev->ifa_list; + struct in_ifaddr *prev_prom = NULL; + int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); ASSERT_RTNL(); @@ -243,18 +246,22 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, **/ if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { - struct in_ifaddr *ifa; struct in_ifaddr **ifap1 = &ifa1->ifa_next; while ((ifa = *ifap1) != NULL) { + if (!(ifa->ifa_flags & IFA_F_SECONDARY) && + ifa1->ifa_scope <= ifa->ifa_scope) + last_prim = ifa; + if (!(ifa->ifa_flags & IFA_F_SECONDARY) || ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) { ifap1 = &ifa->ifa_next; + prev_prom = ifa; continue; } - if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) { + if (!do_promote) { *ifap1 = ifa->ifa_next; rtmsg_ifa(RTM_DELADDR, ifa); @@ -283,19 +290,32 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, */ rtmsg_ifa(RTM_DELADDR, ifa1); notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); + + if (promote) { + + if (prev_prom) { + prev_prom->ifa_next = promote->ifa_next; + promote->ifa_next = last_prim->ifa_next; + last_prim->ifa_next = promote; + } + + promote->ifa_flags &= ~IFA_F_SECONDARY; + rtmsg_ifa(RTM_NEWADDR, promote); + notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); + for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { + if (ifa1->ifa_mask != ifa->ifa_mask || + !inet_ifa_match(ifa1->ifa_address, ifa)) + continue; + fib_add_ifaddr(ifa); + } + + } if (destroy) { inet_free_ifa(ifa1); if (!in_dev->ifa_list) inetdev_destroy(in_dev); } - - if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) { - /* not sure if we should send a delete notify first? */ - promote->ifa_flags &= ~IFA_F_SECONDARY; - rtmsg_ifa(RTM_NEWADDR, promote); - notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); - } } static int inet_insert_ifa(struct in_ifaddr *ifa) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 2267c1fad879..882f88f6d13b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -407,7 +407,7 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); } -static void fib_add_ifaddr(struct in_ifaddr *ifa) +void fib_add_ifaddr(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; From 00cb277a4a1fb76aafb2fb28aa99f30546e619c5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 22 Nov 2005 14:54:34 -0800 Subject: [PATCH 037/101] [NETFILTER] ctnetlink: Fix refcount leak ip_conntrack/nat_proto Remove proto == NULL checking since ip_conntrack_[nat_]proto_find_get always returns a valid pointer. Fix missing ip_conntrack_proto_put in some paths. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netlink.c | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index de9f4464438d..6c18a2b6d5ce 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -59,11 +59,13 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); + /* If no protocol helper is found, this function will return the + * generic protocol helper, so proto won't *ever* be NULL */ proto = ip_conntrack_proto_find_get(tuple->dst.protonum); - if (likely(proto && proto->tuple_to_nfattr)) { + if (likely(proto->tuple_to_nfattr)) ret = proto->tuple_to_nfattr(skb, tuple); - ip_conntrack_proto_put(proto); - } + + ip_conntrack_proto_put(proto); return ret; @@ -128,9 +130,11 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct) struct nfattr *nest_proto; int ret; - - if (!proto || !proto->to_nfattr) + + if (!proto->to_nfattr) { + ip_conntrack_proto_put(proto); return 0; + } nest_proto = NFA_NEST(skb, CTA_PROTOINFO); @@ -527,10 +531,10 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, proto = ip_conntrack_proto_find_get(tuple->dst.protonum); - if (likely(proto && proto->nfattr_to_tuple)) { + if (likely(proto->nfattr_to_tuple)) ret = proto->nfattr_to_tuple(tb, tuple); - ip_conntrack_proto_put(proto); - } + + ip_conntrack_proto_put(proto); return ret; } @@ -596,8 +600,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, return -EINVAL; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); - if (!npt) - return 0; if (!npt->nfattr_to_range) { ip_nat_proto_put(npt); @@ -957,8 +959,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); proto = ip_conntrack_proto_find_get(npt); - if (!proto) - return -EINVAL; if (proto->from_nfattr) err = proto->from_nfattr(tb, ct); From e6d184e33109010412ad1d59719af74755a935f4 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 22 Nov 2005 14:56:32 -0800 Subject: [PATCH 038/101] [NET]: Fix ifenslave to not fail on lack of IP information Patch to ifenslave so that under older ABI versions, a failure to propogate ip information from master to slave does not result in a filure to enslave the slave device. Signed-off-by: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- Documentation/networking/ifenslave.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index f315d20d3867..545447ac503a 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c @@ -693,13 +693,7 @@ static int enslave(char *master_ifname, char *slave_ifname) /* Older bonding versions would panic if the slave has no IP * address, so get the IP setting from the master. */ - res = set_if_addr(master_ifname, slave_ifname); - if (res) { - fprintf(stderr, - "Slave '%s': Error: set address failed\n", - slave_ifname); - return res; - } + set_if_addr(master_ifname, slave_ifname); } else { res = clear_if_addr(slave_ifname); if (res) { @@ -1085,7 +1079,6 @@ static int set_if_addr(char *master_ifname, char *slave_ifname) slave_ifname, ifra[i].req_name, strerror(saved_errno)); - return res; } ipaddr = ifr.ifr_addr.sa_data; From a9b1ef8ec7df544b236b19fb6cc42ed2591b65cd Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 22 Nov 2005 15:30:29 -0800 Subject: [PATCH 039/101] [SPARC]: drivers/sbus/char/aurora.c: "extern inline" -> "static inline" "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- drivers/sbus/char/aurora.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 672f9f2b2163..92e6c5639dd3 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c @@ -124,25 +124,25 @@ static inline int aurora_paranoia_check(struct Aurora_port const * port, */ /* Get board number from pointer */ -extern inline int board_No (struct Aurora_board const * bp) +static inline int board_No (struct Aurora_board const * bp) { return bp - aurora_board; } /* Get port number from pointer */ -extern inline int port_No (struct Aurora_port const * port) +static inline int port_No (struct Aurora_port const * port) { return AURORA_PORT(port - aurora_port); } /* Get pointer to board from pointer to port */ -extern inline struct Aurora_board * port_Board(struct Aurora_port const * port) +static inline struct Aurora_board * port_Board(struct Aurora_port const * port) { return &aurora_board[AURORA_BOARD(port - aurora_port)]; } /* Wait for Channel Command Register ready */ -extern inline void aurora_wait_CCR(struct aurora_reg128 * r) +static inline void aurora_wait_CCR(struct aurora_reg128 * r) { unsigned long delay; @@ -161,7 +161,7 @@ printk("aurora_wait_CCR\n"); */ /* Must be called with enabled interrupts */ -extern inline void aurora_long_delay(unsigned long delay) +static inline void aurora_long_delay(unsigned long delay) { unsigned long i; @@ -420,7 +420,7 @@ static void aurora_release_io_range(struct Aurora_board *bp) sbus_iounmap((unsigned long)bp->r3, 4); } -extern inline void aurora_mark_event(struct Aurora_port * port, int event) +static inline void aurora_mark_event(struct Aurora_port * port, int event) { #ifdef AURORA_DEBUG printk("aurora_mark_event: start\n"); From ac3461ad632e86e7debd871776683c05ef3ba4c6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 22 Nov 2005 19:39:30 -0800 Subject: [PATCH 040/101] Fix up GFP_ZONEMASK for GFP_DMA32 usage There was some confusion about the different zone usage, this should fix up the resulting mess in the GFP zonemask handling. The different zone usage is still confusing (it's very easy to mix up the individual zone numbers with the GFP zone _list_ numbers), so we might want to clean up some of this in the future, but in the meantime this should fix the actual problems. Acked-by: Andi Kleen Signed-off-by: Linus Torvalds --- include/linux/gfp.h | 9 +++++++-- include/linux/mmzone.h | 18 ++++-------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 313dfe9b443a..8b2eab90abb6 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -11,7 +11,7 @@ struct vm_area_struct; /* * GFP bitmasks.. */ -/* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ +/* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low three bits) */ #define __GFP_DMA ((__force gfp_t)0x01u) #define __GFP_HIGHMEM ((__force gfp_t)0x02u) #ifdef CONFIG_DMA_IS_DMA32 @@ -74,7 +74,12 @@ struct vm_area_struct; #define GFP_DMA32 __GFP_DMA32 -#define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK)) +static inline int gfp_zone(gfp_t gfp) +{ + int zone = GFP_ZONEMASK & (__force int) gfp; + BUG_ON(zone >= GFP_ZONETYPES); + return zone; +} /* * There is only one page-allocator function, and two main namespaces to diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 2c8edad5dccf..9f22090df7dd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -91,21 +91,11 @@ struct per_cpu_pageset { * will be a maximum of 4 (2 ** 2) zonelists, for 3 modifiers there will * be 8 (2 ** 3) zonelists. GFP_ZONETYPES defines the number of possible * combinations of zone modifiers in "zone modifier space". + * + * NOTE! Make sure this matches the zones in */ -#define GFP_ZONEMASK 0x03 -/* - * As an optimisation any zone modifier bits which are only valid when - * no other zone modifier bits are set (loners) should be placed in - * the highest order bits of this field. This allows us to reduce the - * extent of the zonelists thus saving space. For example in the case - * of three zone modifier bits, we could require up to eight zonelists. - * If the left most zone modifier is a "loner" then the highest valid - * zonelist would be four allowing us to allocate only five zonelists. - * Use the first form when the left most bit is not a "loner", otherwise - * use the second. - */ -/* #define GFP_ZONETYPES (GFP_ZONEMASK + 1) */ /* Non-loner */ -#define GFP_ZONETYPES ((GFP_ZONEMASK + 1) / 2 + 1) /* Loner */ +#define GFP_ZONEMASK 0x07 +#define GFP_ZONETYPES 5 /* * On machines where it is needed (eg PCs) we divide physical memory From 1778d55edb62753a92b979fa57072c2e1ff3d062 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 22 Nov 2005 21:58:37 -0800 Subject: [PATCH 041/101] compat-ioctl.c: fix compile with no CONFIG_JBD The ext3 compat-ioctl translation wants to translate data structures that only declared when CONFIG_JBD was enabled. So make play nicely even when we don't actually end up using it. Acked-by: Andrew Morton Acked-by: Jeffrey Hundstad Acked-by: Zan Lynx Signed-off-by: Linus Torvalds --- include/linux/jbd.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/include/linux/jbd.h b/include/linux/jbd.h index aa56172c6fed..dcde7adfdce5 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -16,8 +16,6 @@ #ifndef _LINUX_JBD_H #define _LINUX_JBD_H -#if defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE) || !defined(__KERNEL__) - /* Allow this file to be included directly into e2fsprogs */ #ifndef __KERNEL__ #include "jfs_compat.h" @@ -1083,19 +1081,4 @@ extern int jbd_blocks_per_page(struct inode *inode); #endif /* __KERNEL__ */ -#endif /* CONFIG_JBD || CONFIG_JBD_MODULE || !__KERNEL__ */ - -/* - * Compatibility no-ops which allow the kernel to compile without CONFIG_JBD - * go here. - */ - -#if defined(__KERNEL__) && !(defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE)) - -#define J_ASSERT(expr) do {} while (0) -#define J_ASSERT_BH(bh, expr) do {} while (0) -#define buffer_jbd(bh) 0 -#define journal_buffer_journal_lru(bh) 0 - -#endif /* defined(__KERNEL__) && !defined(CONFIG_JBD) */ #endif /* _LINUX_JBD_H */ From 91f14480a55a7487d61c3fb40500380099e0da50 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 21 Nov 2005 02:12:32 -0600 Subject: [PATCH 042/101] [PATCH] powerpc: update my email address Email address update, changing old work address to personal (permanent) one. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 2 +- arch/powerpc/platforms/pseries/iommu.c | 2 +- arch/powerpc/sysdev/dart.h | 2 +- arch/powerpc/sysdev/u3_iommu.c | 4 ++-- include/asm-powerpc/iommu.h | 2 +- include/asm-powerpc/tce.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bf081b345820..2b54eeb2c899 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -3,7 +3,7 @@ * * Rewrite, cleanup: * - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * Dynamic DMA mapping support, iSeries-specific parts. * diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 97ba5214417f..c78f2b290a73 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -5,7 +5,7 @@ * * Rewrite, cleanup: * - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. * diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h index ea8f0d9eed8a..33ed9ed7fc1e 100644 --- a/arch/powerpc/sysdev/dart.h +++ b/arch/powerpc/sysdev/dart.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/u3_iommu.c index f32baf7f4693..5c1a26a6d00c 100644 --- a/arch/powerpc/sysdev/u3_iommu.c +++ b/arch/powerpc/sysdev/u3_iommu.c @@ -1,11 +1,11 @@ /* * arch/powerpc/sysdev/u3_iommu.c * - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * Based on pSeries_iommu.c: * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu. * diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 6a35e6570ccd..f89f06050893 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * Rewrite, cleanup: - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/asm-powerpc/tce.h b/include/asm-powerpc/tce.h index d099d5200f9b..980a094fd5a7 100644 --- a/include/asm-powerpc/tce.h +++ b/include/asm-powerpc/tce.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * Rewrite, cleanup: - * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From bd07ed2b4d7071716c09895e19849e8b04991656 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 23 Nov 2005 21:45:43 +1100 Subject: [PATCH 043/101] I think that if a PCI bus is a root bus, attached to a host bridge not a PCI->PCI bridge, then bus->self is allowed to be NULL. Certainly that's the case on my Pegasos, and it makes the MGA DRM driver oops... Signed-off-by: David Woodhouse Signed-off-by: Dave Airlie --- drivers/char/drm/mga_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 0cc7c305a7f6..1713451a5cc6 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -161,7 +161,7 @@ static int mga_driver_device_is_agp(drm_device_t * dev) * device. */ - if ((pdev->device == 0x0525) + if ((pdev->device == 0x0525) && pdev->bus->self && (pdev->bus->self->vendor == 0x3388) && (pdev->bus->self->device == 0x0021)) { return 0; From c41f47121d8bf44b886ef2039779dab8c1e3a25f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 23 Nov 2005 22:09:13 +1100 Subject: [PATCH 044/101] drm: add __GFP_COMP to the drm_alloc_pages The DRM only uses drm_alloc_pages for non-SG PCI cards using DRM. Signed-off-by: Hugh Dickins Signed-off-by: Dave Airlie --- drivers/char/drm/drm_memory.c | 2 +- drivers/char/drm/drm_memory_debug.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 2c74155aa84f..abef2acf99f5 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -95,7 +95,7 @@ unsigned long drm_alloc_pages(int order, int area) unsigned long addr; unsigned int sz; - address = __get_free_pages(GFP_KERNEL, order); + address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); if (!address) return 0; diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index 4542353195bd..b370aca718d2 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -221,7 +221,7 @@ unsigned long DRM(alloc_pages) (int order, int area) { } spin_unlock(&DRM(mem_lock)); - address = __get_free_pages(GFP_KERNEL, order); + address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); if (!address) { spin_lock(&DRM(mem_lock)); ++DRM(mem_stats)[area].fail_count; From 7655f493b74f3048c02458bc32cd0b144f7b394f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 23 Nov 2005 22:12:59 +1100 Subject: [PATCH 045/101] drm: move is_pci to the end of the structure We memset the structure across opens except for the flags. The correct fix is more intrusive but this should fix a problem with bad iounmaps seen on AGP radeons acting like PCI ones. Signed-off-by: Dave Airlie --- drivers/char/drm/radeon_drv.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 120ee5a8ebcc..7bda7e33d2bd 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -214,8 +214,6 @@ typedef struct drm_radeon_private { int microcode_version; - int is_pci; - struct { u32 boxes; int freelist_timeouts; @@ -275,6 +273,7 @@ typedef struct drm_radeon_private { /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ + int is_pci; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { From 2d0ebb36038c0626cde662a3b06da9787cfb68c3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 23 Nov 2005 08:44:05 -0800 Subject: [PATCH 046/101] Revert "[NET]: Shut up warnings in net/core/flow.c" This reverts commit af2b4079ab154bd12e8c12b02db5f31b31babe63 Changing the #define to an inline function breaks on non-SMP builds, since wuite a few places in the kernel do not implement the ipi handler when compiling for UP. Signed-off-by: Linus Torvalds --- include/linux/smp.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index b6069c8e1f04..9dfa3ee769ae 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -94,13 +94,7 @@ void smp_prepare_boot_cpu(void); */ #define raw_smp_processor_id() 0 #define hard_smp_processor_id() 0 - -static inline int smp_call_function(void (*func) (void *info), void *info, - int retry, int wait) -{ - return 0; -} - +#define smp_call_function(func,info,retry,wait) ({ 0; }) #define on_each_cpu(func,info,retry,wait) ({ func(info); 0; }) static inline void smp_send_reschedule(int cpu) { } #define num_booting_cpus() 1 From c2b5a251b9feca727661f1a3278cafb1de4c80f3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 3 Nov 2005 07:51:18 -0700 Subject: [PATCH 047/101] [PATCH] Check the irq number is within bounds Most of the functions already check. Do the ones that didn't. Signed-off-by: Matthew Wilcox Signed-off-by: Linus Torvalds --- kernel/irq/manage.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3bd7226d15fa..81c49a4d679e 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -36,6 +36,9 @@ void synchronize_irq(unsigned int irq) { struct irq_desc *desc = irq_desc + irq; + if (irq >= NR_IRQS) + return; + while (desc->status & IRQ_INPROGRESS) cpu_relax(); } @@ -60,6 +63,9 @@ void disable_irq_nosync(unsigned int irq) irq_desc_t *desc = irq_desc + irq; unsigned long flags; + if (irq >= NR_IRQS) + return; + spin_lock_irqsave(&desc->lock, flags); if (!desc->depth++) { desc->status |= IRQ_DISABLED; @@ -86,6 +92,9 @@ void disable_irq(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; + if (irq >= NR_IRQS) + return; + disable_irq_nosync(irq); if (desc->action) synchronize_irq(irq); @@ -108,6 +117,9 @@ void enable_irq(unsigned int irq) irq_desc_t *desc = irq_desc + irq; unsigned long flags; + if (irq >= NR_IRQS) + return; + spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 0: @@ -163,6 +175,9 @@ int setup_irq(unsigned int irq, struct irqaction * new) unsigned long flags; int shared = 0; + if (irq >= NR_IRQS) + return -EINVAL; + if (desc->handler == &no_irq_type) return -ENOSYS; /* From 3238c448c6e26d7c26d2e9b070ef149d066cb6c2 Mon Sep 17 00:00:00 2001 From: Adam Brooks Date: Wed, 23 Nov 2005 22:45:27 +0000 Subject: [PATCH 048/101] [ARM] 3173/1: Fix to allow 2.6.15-rc2 to compile for IOP3xx boards Patch from Adam Brooks Fixes an issue in 2.6.15-rc2 that prevented compilation of kernels for IOP3xx boards. Signed-off-by: Adam Brooks Signed-off-by: Russell King --- include/asm-arm/arch-iop3xx/timex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h index d4187fe9a85a..472badb451c4 100644 --- a/include/asm-arm/arch-iop3xx/timex.h +++ b/include/asm-arm/arch-iop3xx/timex.h @@ -4,7 +4,7 @@ * IOP3xx architecture timex specifications */ #include - +#include #if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244) From c101e77301877086e6f977fcfb140d1cbbe23fd5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 23 Nov 2005 13:37:36 -0800 Subject: [PATCH 049/101] [PATCH] revert floppy-fix-read-only-handling This fix causes problems on the very first floppy access - we haven't yet talked to the FDC so we don't know which state the write-protect tab is in. Revert for now. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 13b8a9bed66e..f7e765a1d313 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3714,12 +3714,6 @@ static int floppy_open(struct inode *inode, struct file *filp) USETF(FD_VERIFY); } - /* set underlying gendisk policy to reflect real ro/rw status */ - if (UTESTF(FD_DISK_WRITABLE)) - inode->i_bdev->bd_disk->policy = 0; - else - inode->i_bdev->bd_disk->policy = 1; - if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL))) goto out2; From 7b6ac9dffe6f4dd8776908b234ac1410ed15f112 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Nov 2005 13:37:37 -0800 Subject: [PATCH 050/101] [PATCH] mm: update split ptlock Kconfig Closer attention to the arithmetic shows that neither ppc64 nor sparc really uses one page for multiple page tables: how on earth could they, while pte_alloc_one returns just a struct page pointer, with no offset? Well, arm26 manages it by returning a pte_t pointer cast to a struct page pointer, harumph, then compensating in its pmd_populate. But arm26 is never SMP, so it's not a problem for split ptlock either. And the PA-RISC situation has been recently improved: CONFIG_PA20 works without the 16-byte alignment which inflated its spinlock_t. But the current union of spinlock_t with private does make the 7xxx struct page significantly larger, even without debug, so disable its split ptlock. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/Kconfig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mm/Kconfig b/mm/Kconfig index ae9ce6b73e8a..21eb51d4da8f 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -125,12 +125,10 @@ comment "Memory hotplug is currently incompatible with Software Suspend" # space can be handled with less contention: split it at this NR_CPUS. # Default to 4 for wider testing, though 8 might be more appropriate. # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. -# PA-RISC's debug spinlock_t is too large for the 32-bit struct page. -# ARM26 and SPARC32 and PPC64 may use one page for multiple page tables. +# PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. # config SPLIT_PTLOCK_CPUS int default "4096" if ARM && !CPU_CACHE_VIPT - default "4096" if PARISC && DEBUG_SPINLOCK && !64BIT - default "4096" if ARM26 || SPARC32 || PPC64 + default "4096" if PARISC && !PA20 default "4" From cc3327e7dfc16a9a3e164075234c869867a59e45 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Nov 2005 13:37:38 -0800 Subject: [PATCH 051/101] [PATCH] mm: unbloat get_futex_key The follow_page changes in get_futex_key have left it with two almost identical blocks, when handling the rare case of a futex in a nonlinear vma. get_user_pages will itself do that follow_page, and its additional find_extend_vma is hardly any overhead since the vma is already cached. Let's just delete the follow_page block and let get_user_pages do it. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/futex.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index aca8d10704f6..5872e3507f35 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -201,21 +201,6 @@ static int get_futex_key(unsigned long uaddr, union futex_key *key) * from swap. But that's a lot of code to duplicate here * for a rare case, so we simply fetch the page. */ - - /* - * Do a quick atomic lookup first - this is the fastpath. - */ - page = follow_page(mm, uaddr, FOLL_TOUCH|FOLL_GET); - if (likely(page != NULL)) { - key->shared.pgoff = - page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - put_page(page); - return 0; - } - - /* - * Do it the general way. - */ err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); if (err >= 0) { key->shared.pgoff = From 01edcd891c3e9f4bb992ff2ceb69836bf76f8ddf Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Nov 2005 13:37:39 -0800 Subject: [PATCH 052/101] [PATCH] mm: powerpc ptlock comments Update comments (only) on page_table_lock and mmap_sem in arch/powerpc. Removed the comment on page_table_lock from hash_huge_page: since it's no longer taking page_table_lock itself, it's irrelevant whether others are; but how it is safe (even against huge file truncation?) I can't say. Signed-off-by: Hugh Dickins Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/hugetlbpage.c | 4 +--- arch/powerpc/mm/mem.c | 2 +- arch/powerpc/mm/tlb_32.c | 6 ++++++ arch/powerpc/mm/tlb_64.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 426c269e552e..9250f14be8ef 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -754,9 +754,7 @@ repeat: } /* - * No need to use ldarx/stdcx here because all who - * might be updating the pte will hold the - * page_table_lock + * No need to use ldarx/stdcx here */ *ptep = __pte(new_pte & ~_PAGE_BUSY); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 4bd7b0a70996..ed6ed2e30dac 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -495,7 +495,7 @@ EXPORT_SYMBOL(flush_icache_user_range); * We use it to preload an HPTE into the hash table corresponding to * the updated linux PTE. * - * This must always be called with the mm->page_table_lock held + * This must always be called with the pte lock held. */ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index 6c3dc3c44c86..ad580f3742e5 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c @@ -149,6 +149,12 @@ void flush_tlb_mm(struct mm_struct *mm) return; } + /* + * It is safe to go down the mm's list of vmas when called + * from dup_mmap, holding mmap_sem. It would also be safe from + * unmap_region or exit_mmap, but not from vmtruncate on SMP - + * but it seems dup_mmap is the only SMP case which gets here. + */ for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) flush_range(mp->vm_mm, mp->vm_start, mp->vm_end); FINISH_FLUSH; diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index 53e31b834ace..859d29a0cac5 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -95,7 +95,7 @@ static void pte_free_submit(struct pte_freelist_batch *batch) void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) { - /* This is safe as we are holding page_table_lock */ + /* This is safe since tlb_gather_mmu has disabled preemption */ cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); @@ -206,7 +206,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) void pte_free_finish(void) { - /* This is safe as we are holding page_table_lock */ + /* This is safe since tlb_gather_mmu has disabled preemption */ struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); if (*batchp == NULL) From 7ce774b4808c019c2f143ff5dea1a1b094ff01e1 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Nov 2005 13:37:39 -0800 Subject: [PATCH 053/101] [PATCH] mm: powerpc init_mm without ptlock Restore an earlier mod which went missing in the powerpc reshuffle: the 4xx mmu_mapin_ram does not need to take init_mm.page_table_lock. Signed-off-by: Hugh Dickins Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/4xx_mmu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c index b7bcbc232f39..4d006aa1a0d1 100644 --- a/arch/powerpc/mm/4xx_mmu.c +++ b/arch/powerpc/mm/4xx_mmu.c @@ -110,13 +110,11 @@ unsigned long __init mmu_mapin_ram(void) pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; - spin_lock(&init_mm.page_table_lock); pmdp = pmd_offset(pgd_offset_k(v), v); pmd_val(*pmdp++) = val; pmd_val(*pmdp++) = val; pmd_val(*pmdp++) = val; pmd_val(*pmdp++) = val; - spin_unlock(&init_mm.page_table_lock); v += LARGE_PAGE_SIZE_16M; p += LARGE_PAGE_SIZE_16M; @@ -127,10 +125,8 @@ unsigned long __init mmu_mapin_ram(void) pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE; - spin_lock(&init_mm.page_table_lock); pmdp = pmd_offset(pgd_offset_k(v), v); pmd_val(*pmdp) = val; - spin_unlock(&init_mm.page_table_lock); v += LARGE_PAGE_SIZE_4M; p += LARGE_PAGE_SIZE_4M; From 7c72aaf29621d29ed19fd68c44edb45321645049 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 23 Nov 2005 13:37:40 -0800 Subject: [PATCH 054/101] [PATCH] mm: fill arch atomic64 gaps alpha, sparc64, x86_64 are each missing some primitives from their atomic64 support: fill in the gaps I've noticed by extrapolating asm, follow the groupings in each file. But powerpc and parisc still lack atomic64. Signed-off-by: Hugh Dickins Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: "David S. Miller" Cc: Andi Kleen Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-alpha/atomic.h | 7 +++-- include/asm-sparc64/atomic.h | 1 + include/asm-x86_64/atomic.h | 51 +++++++++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h index 36505bb4e8cb..6183eab006d4 100644 --- a/include/asm-alpha/atomic.h +++ b/include/asm-alpha/atomic.h @@ -118,8 +118,6 @@ static __inline__ long atomic_add_return(int i, atomic_t * v) return result; } -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - static __inline__ long atomic64_add_return(long i, atomic64_t * v) { long temp, result; @@ -189,6 +187,9 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) +#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) + #define atomic_dec_return(v) atomic_sub_return(1,(v)) #define atomic64_dec_return(v) atomic64_sub_return(1,(v)) @@ -199,6 +200,8 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) #define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0) #define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) +#define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0) + #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0) diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index 8198c3d0d007..3789fe315992 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h @@ -54,6 +54,7 @@ extern int atomic64_sub_ret(int, atomic64_t *); * other cases. */ #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) +#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) #define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0) #define atomic64_sub_and_test(i, v) (atomic64_sub_ret(i, v) == 0) diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h index 0866ef67f198..50db9f39274f 100644 --- a/include/asm-x86_64/atomic.h +++ b/include/asm-x86_64/atomic.h @@ -160,8 +160,8 @@ static __inline__ int atomic_inc_and_test(atomic_t *v) /** * atomic_add_negative - add and test if negative - * @v: pointer of type atomic_t * @i: integer value to add + * @v: pointer of type atomic_t * * Atomically adds @i to @v and returns true * if the result is negative, or false when @@ -178,6 +178,31 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v) return c; } +/** + * atomic_add_return - add and return + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v and returns @i + @v + */ +static __inline__ int atomic_add_return(int i, atomic_t *v) +{ + int __i = i; + __asm__ __volatile__( + LOCK "xaddl %0, %1;" + :"=r"(i) + :"m"(v->counter), "0"(i)); + return i + __i; +} + +static __inline__ int atomic_sub_return(int i, atomic_t *v) +{ + return atomic_add_return(-i,v); +} + +#define atomic_inc_return(v) (atomic_add_return(1,v)) +#define atomic_dec_return(v) (atomic_sub_return(1,v)) + /* An 64bit atomic type */ typedef struct { volatile long counter; } atomic64_t; @@ -320,14 +345,14 @@ static __inline__ int atomic64_inc_and_test(atomic64_t *v) /** * atomic64_add_negative - add and test if negative - * @v: pointer to atomic64_t * @i: integer value to add + * @v: pointer to type atomic64_t * * Atomically adds @i to @v and returns true * if the result is negative, or false when * result is greater than or equal to zero. */ -static __inline__ long atomic64_add_negative(long i, atomic64_t *v) +static __inline__ int atomic64_add_negative(long i, atomic64_t *v) { unsigned char c; @@ -339,27 +364,30 @@ static __inline__ long atomic64_add_negative(long i, atomic64_t *v) } /** - * atomic_add_return - add and return - * @v: pointer of type atomic_t + * atomic64_add_return - add and return * @i: integer value to add + * @v: pointer to type atomic64_t * * Atomically adds @i to @v and returns @i + @v */ -static __inline__ int atomic_add_return(int i, atomic_t *v) +static __inline__ long atomic64_add_return(long i, atomic64_t *v) { - int __i = i; + long __i = i; __asm__ __volatile__( - LOCK "xaddl %0, %1;" + LOCK "xaddq %0, %1;" :"=r"(i) :"m"(v->counter), "0"(i)); return i + __i; } -static __inline__ int atomic_sub_return(int i, atomic_t *v) +static __inline__ long atomic64_sub_return(long i, atomic64_t *v) { - return atomic_add_return(-i,v); + return atomic64_add_return(-i,v); } +#define atomic64_inc_return(v) (atomic64_add_return(1,v)) +#define atomic64_dec_return(v) (atomic64_sub_return(1,v)) + #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) /** @@ -381,9 +409,6 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v) }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -#define atomic_inc_return(v) (atomic_add_return(1,v)) -#define atomic_dec_return(v) (atomic_sub_return(1,v)) - /* These are x86-specific, used by some header files */ #define atomic_clear_mask(mask, addr) \ __asm__ __volatile__(LOCK "andl %0,%1" \ From 8bf1101bd52573e0573e374d56d2feecdbb5e444 Mon Sep 17 00:00:00 2001 From: Jim Keniston Date: Wed, 23 Nov 2005 13:37:42 -0800 Subject: [PATCH 055/101] [PATCH] kprobes: Fix return probes on sys_execve Fix a bug in kprobes that can cause an Oops or even a crash when a return probe is installed on one of the following functions: sys_execve, do_execve, load_*_binary, flush_old_exec, or flush_thread. The fix is to remove the call to kprobe_flush_task() in flush_thread(). This fix has been tested on all architectures for which the return-probes feature has been implemented (i386, x86_64, ppc64, ia64). Please apply. BACKGROUND Up to now, we have called kprobe_flush_task() under two situations: when a task exits, and when it execs. Flushing kretprobe_instances on exit is correct because (a) do_exit() doesn't return, and (b) one or more return-probed functions may be active when a task calls do_exit(). Neither is the case for sys_execve() and its callees. Initially, the mistaken call to kprobe_flush_task() on exec was harmless because we put the "real" return address of each active probed function back in the stack, just to be safe, when we recycled its kretprobe_instance. When support for ppc64 and ia64 was added, this safety measure couldn't be employed, and was eventually dropped even for i386 and x86_64. sys_execve() and its callees were informally blacklisted for return probes until this fix was developed. Acked-by: Prasanna S Panchamukhi Signed-off-by: Jim Keniston Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 7 ------- arch/ia64/kernel/process.c | 7 ------- arch/powerpc/kernel/process.c | 1 - arch/x86_64/kernel/process.c | 7 ------- 4 files changed, 22 deletions(-) diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 1cb261f225d5..df6c2bcde067 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -393,13 +393,6 @@ void flush_thread(void) { struct task_struct *tsk = current; - /* - * Remove function-return probe instances associated with this task - * and put them back on the free list. Do not insert an exit probe for - * this function, it will be disabled by kprobe_flush_task if you do. - */ - kprobe_flush_task(tsk); - memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); /* diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 4305d2ba76f6..2e33665d9c18 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -718,13 +718,6 @@ kernel_thread_helper (int (*fn)(void *), void *arg) void flush_thread (void) { - /* - * Remove function-return probe instances associated with this task - * and put them back on the free list. Do not insert an exit probe for - * this function, it will be disabled by kprobe_flush_task if you do. - */ - kprobe_flush_task(current); - /* drop floating-point and debug-register state if it exists: */ current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index de69fb37c731..a5a7542a8ff3 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -457,7 +457,6 @@ void flush_thread(void) if (t->flags & _TIF_ABI_PENDING) t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); #endif - kprobe_flush_task(current); #ifndef CONFIG_SMP if (last_task_used_math == current) diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 5afd63e8cef7..7519fc520eb3 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -351,13 +351,6 @@ void flush_thread(void) struct task_struct *tsk = current; struct thread_info *t = current_thread_info(); - /* - * Remove function-return probe instances associated with this task - * and put them back on the free list. Do not insert an exit probe for - * this function, it will be disabled by kprobe_flush_task if you do. - */ - kprobe_flush_task(tsk); - if (t->flags & _TIF_ABI_PENDING) t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); From 962b564cf1ec8041e8890a3c3847e3a630a08f42 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 23 Nov 2005 13:37:43 -0800 Subject: [PATCH 056/101] [PATCH] fix do_wait() vs exec() race When non-leader thread does exec, de_thread adds old leader to the init's ->children list in EXIT_ZOMBIE state and drops tasklist_lock. This means that release_task(leader) in de_thread() is racy vs do_wait() from init task. I think de_thread() should set old leader's state to EXIT_DEAD instead. Signed-off-by: Oleg Nesterov Cc: george anzinger Cc: Roland Dreier Cc: Ingo Molnar Cc: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index c466fec5de20..1f8a9fd2c9ed 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -668,7 +668,7 @@ static inline int de_thread(struct task_struct *tsk) if (!thread_group_leader(current)) { struct task_struct *parent; struct dentry *proc_dentry1, *proc_dentry2; - unsigned long exit_state, ptrace; + unsigned long ptrace; /* * Wait for the thread group leader to be a zombie. @@ -726,15 +726,15 @@ static inline int de_thread(struct task_struct *tsk) list_del(¤t->tasks); list_add_tail(¤t->tasks, &init_task.tasks); current->exit_signal = SIGCHLD; - exit_state = leader->exit_state; + + BUG_ON(leader->exit_state != EXIT_ZOMBIE); + leader->exit_state = EXIT_DEAD; write_unlock_irq(&tasklist_lock); spin_unlock(&leader->proc_lock); spin_unlock(¤t->proc_lock); proc_pid_flush(proc_dentry1); proc_pid_flush(proc_dentry2); - - BUG_ON(exit_state != EXIT_ZOMBIE); } /* From e9b15b54d3646108bbd3e054158b402025d3e704 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 23 Nov 2005 13:37:44 -0800 Subject: [PATCH 057/101] [PATCH] Fix crash in unregister_console() If unregister_console() is inadvertently called while no consoles are registered, it will crash trying to dereference NULL pointer. It is necessary to fix that because register_console() provides no indication that it actually registered the console passed in. In fact, it may well decide not to register it based on various things... (akpm: It'd be better to make register_console() return something and fix the callers. All 106 of them...) Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index ac8a08f36207..5287be83e3e7 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -956,7 +956,7 @@ int unregister_console(struct console *console) if (console_drivers == console) { console_drivers=console->next; res = 0; - } else { + } else if (console_drivers) { for (a=console_drivers->next, b=console_drivers ; a; b=a, a=b->next) { if (a == console) { From 5e391dc9e3fec68922137ae317bf680a74656c1b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 23 Nov 2005 13:37:45 -0800 Subject: [PATCH 058/101] [PATCH] powerpc: fix for hugepage areas straddling 4GB boundary Commit 7d24f0b8a53261709938ffabe3e00f88f6498df9 fixed bugs in the ppc64 SLB miss handler with respect to hugepage handling, and in the process tweaked the semantics of the hugepage address masks in mm_context_t. Unfortunately, it left out a couple of necessary changes to go with that change. First, the in_hugepage_area() macro was not updated to match, second prepare_hugepage_range() was not updated to correctly handle hugepages regions which straddled the 4GB point. The latter appears only to cause process-hangs when attempting to map such a region, but the former can cause oopses if a get_user_pages() is triggered at the wrong point. This patch addresses both bugs. Signed-off-by: David Gibson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/hugetlbpage.c | 6 +++--- include/asm-powerpc/page_64.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 9250f14be8ef..f867bba893ca 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -287,15 +287,15 @@ static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas) int prepare_hugepage_range(unsigned long addr, unsigned long len) { - int err; + int err = 0; if ( (addr+len) < addr ) return -EINVAL; - if ((addr + len) < 0x100000000UL) + if (addr < 0x100000000UL) err = open_low_hpage_areas(current->mm, LOW_ESID_MASK(addr, len)); - else + if ((addr + len) >= 0x100000000UL) err = open_high_hpage_areas(current->mm, HTLB_AREA_MASK(addr, len)); if (err) { diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h index 1e6e7846824f..58a3dd9a79ec 100644 --- a/include/asm-powerpc/page_64.h +++ b/include/asm-powerpc/page_64.h @@ -135,9 +135,9 @@ extern unsigned int HPAGE_SHIFT; #define in_hugepage_area(context, addr) \ (cpu_has_feature(CPU_FTR_16M_PAGE) && \ - ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \ - ( ((addr) < 0x100000000L) && \ - ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) ) + ( ( (addr) >= 0x100000000UL) \ + ? ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) \ + : ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) #else /* !CONFIG_HUGETLB_PAGE */ From 02b7068221eed702a37527fa2da4d63a27b3126a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 23 Nov 2005 13:37:47 -0800 Subject: [PATCH 059/101] [PATCH] jffs2 debug gcc-2.9x fix Work around gcc-2.95.x macro expansion bug. Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jffs2/debug.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index f193d43a8a59..162af6dfe292 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -82,28 +82,28 @@ do { \ printk(JFFS2_ERR_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ - __FUNCTION__, ##__VA_ARGS__); \ + __FUNCTION__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ printk(JFFS2_WARN_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ - __FUNCTION__, ##__VA_ARGS__); \ + __FUNCTION__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ - __FUNCTION__, ##__VA_ARGS__); \ + __FUNCTION__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ printk(JFFS2_DBG_MSG_PREFIX \ " (%d) %s: " fmt, current->pid, \ - __FUNCTION__, ##__VA_ARGS__); \ + __FUNCTION__ , ##__VA_ARGS__); \ } while(0) /* From 479ef592f3664dd629417098c8599261c0f689ab Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 23 Nov 2005 13:37:47 -0800 Subject: [PATCH 060/101] [PATCH] 32bit integer overflow in invalidate_inode_pages2() Fix a 32 bit integer overflow in invalidate_inode_pages2_range. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/truncate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/truncate.c b/mm/truncate.c index 29c18f68dc35..9173ab500604 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -282,8 +282,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping, * Zap the rest of the file in one hit. */ unmap_mapping_range(mapping, - page_index << PAGE_CACHE_SHIFT, - (end - page_index + 1) + (loff_t)page_index< Date: Wed, 23 Nov 2005 19:03:46 -0800 Subject: [PATCH 061/101] [NETFILTER]: ip_conntrack_netlink.c needs linux/interrupt.h net/ipv4/netfilter/ip_conntrack_netlink.c: In function 'ctnetlink_dump_table': net/ipv4/netfilter/ip_conntrack_netlink.c:409: warning: implicit declaration of function 'local_bh_disable' net/ipv4/netfilter/ip_conntrack_netlink.c:427: warning: implicit declaration of function 'local_bh_enable' Signed-off-by: Benoit Boissinot Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 6c18a2b6d5ce..3fce91bcc0ba 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include From 133747e8d1e912863edfb3869e36b97b9939d4fc Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Wed, 23 Nov 2005 19:04:08 -0800 Subject: [PATCH 062/101] [BRIDGE]: recompute features when adding a new device We must recompute bridge features everytime the list of underlying devices changes, or we might end up with features that are not supported by all devices (eg. NETIF_F_TSO) This patch adds the missing recompute when adding a device to the bridge. Signed-off-by: Olaf Rempel Signed-off-by: David S. Miller --- net/bridge/br_if.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index defcf6a8607c..975abe254b7a 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -366,6 +366,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); + br_features_recompute(br); if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP) && netif_carrier_ok(dev)) br_stp_enable_port(p); From 2b08c8d0468866f86da97f836c6ac14338cb81a9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 23 Nov 2005 15:43:50 -0800 Subject: [PATCH 063/101] [PATCH] Small fixes to driver core This patch (as603) makes a few small fixes to the driver core: Change spin_lock_irq for a klist lock to spin_lock; Fix reference count leaks; Minor spelling and formatting changes. Signed-off-by: Alan Stern Acked-by Patrick Mochel Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/base/bus.c | 21 +++++++++------------ drivers/base/dd.c | 8 +++----- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 03204bfd17af..fa601b085eba 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -133,7 +133,7 @@ static struct kobj_type ktype_bus = { decl_subsys(bus, &ktype_bus, NULL); -/* Manually detach a device from it's associated driver. */ +/* Manually detach a device from its associated driver. */ static int driver_helper(struct device *dev, void *data) { const char *name = data; @@ -151,14 +151,13 @@ static ssize_t driver_unbind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); - if ((dev) && - (dev->driver == drv)) { + if (dev && dev->driver == drv) { device_release_driver(dev); err = count; } - if (err) - return err; - return count; + put_device(dev); + put_bus(bus); + return err; } static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); @@ -175,16 +174,14 @@ static ssize_t driver_bind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device(bus, NULL, (void *)buf, driver_helper); - if ((dev) && - (dev->driver == NULL)) { + if (dev && dev->driver == NULL) { down(&dev->sem); err = driver_probe_device(drv, dev); up(&dev->sem); - put_device(dev); } - if (err) - return err; - return count; + put_device(dev); + put_bus(bus); + return err; } static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3565e9795301..3b419c9a1e7e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -62,7 +62,6 @@ void device_bind_driver(struct device * dev) * because we don't know the format of the ID structures, nor what * is to be considered a match and what is not. * - * * This function returns 1 if a match is found, an error if one * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. * @@ -158,7 +157,6 @@ static int __driver_attach(struct device * dev, void * data) driver_probe_device(drv, dev); up(&dev->sem); - return 0; } @@ -225,15 +223,15 @@ void driver_detach(struct device_driver * drv) struct device * dev; for (;;) { - spin_lock_irq(&drv->klist_devices.k_lock); + spin_lock(&drv->klist_devices.k_lock); if (list_empty(&drv->klist_devices.k_list)) { - spin_unlock_irq(&drv->klist_devices.k_lock); + spin_unlock(&drv->klist_devices.k_lock); break; } dev = list_entry(drv->klist_devices.k_list.prev, struct device, knode_driver.n_node); get_device(dev); - spin_unlock_irq(&drv->klist_devices.k_lock); + spin_unlock(&drv->klist_devices.k_lock); down(&dev->sem); if (dev->driver == drv) From 2c560ace1531870715fdfdae36fa9d75f4e63ae1 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 23 Nov 2005 15:43:57 -0800 Subject: [PATCH 064/101] [PATCH] MTD git tree location added to MAINTAINERS Here's the MTD one. More later as I find them. Signed-off-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index c5cf7d7e58b2..1e84be387420 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1695,6 +1695,7 @@ P: David Woodhouse M: dwmw2@infradead.org W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org +T: git kernel.org:/pub/scm/linux/kernel/git/tglx/mtd-2.6.git S: Maintained MICROTEK X6 SCANNER From 50306fb5398f0aac65047c966a4341adee37f512 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Wed, 23 Nov 2005 15:44:03 -0800 Subject: [PATCH 065/101] [PATCH] Clarify T: field in MAINTAINERS Pavel Machek points out that for git repos, what we include is not actually a URL. It is undesirable to use a URL since git repos can be accessed in many different ways. Signed-off-by: Jody McIntyre Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1e84be387420..6238c63c2be8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -58,7 +58,7 @@ P: Person M: Mail patches to L: Mailing list that is relevant to this area W: Web-page with status/info -T: SCM tree type and URL. Type is one of: git, hg, quilt. +T: SCM tree type and location. Type is one of: git, hg, quilt. S: Status, one of the following: Supported: Someone is actually paid to look after this. From 1adc123079207bf9ba5bcf3dbf52bcdb22f82c7c Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 23 Nov 2005 15:44:15 -0800 Subject: [PATCH 066/101] [PATCH] Add more SCM trees to MAINTAINERS Greg requested a patch to update MAINTAINERS with more SCM entries. The patch below is what I've found so far. Signed-off-by: Josh Boyer Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- MAINTAINERS | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6238c63c2be8..a74a0c726134 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -227,6 +227,7 @@ AGPGART DRIVER P: Dave Jones M: davej@codemonkey.org.uk W: http://www.codemonkey.org.uk/projects/agp/ +T: git kernel.org:/pub/scm/linux/kernel/git/davej/agpgart.git S: Maintained AHA152X SCSI DRIVER @@ -384,6 +385,7 @@ P: David Woodhouse M: dwmw2@infradead.org L: linux-audit@redhat.com W: http://people.redhat.com/sgrubb/audit/ +T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git S: Maintained AX.25 NETWORK LAYER @@ -432,6 +434,7 @@ L: bluez-devel@lists.sf.net W: http://bluez.sf.net W: http://www.bluez.org W: http://www.holtmann.org/linux/bluetooth/ +T: git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git S: Maintained BLUETOOTH RFCOMM LAYER @@ -547,6 +550,7 @@ P: Steve French M: sfrench@samba.org L: samba-technical@lists.samba.org W: http://us1.samba.org/samba/Linux_CIFS_client.html +T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git S: Supported CIRRUS LOGIC GENERIC FBDEV DRIVER @@ -608,6 +612,7 @@ P: Dave Jones M: davej@codemonkey.org.uk L: cpufreq@lists.linux.org.uk W: http://www.codemonkey.org.uk/projects/cpufreq/ +T: git kernel.org/pub/scm/linux/kernel/davej/cpufreq.git S: Maintained CPUID/MSR DRIVER @@ -641,6 +646,7 @@ M: herbert@gondor.apana.org.au P: David S. Miller M: davem@davemloft.net L: linux-crypto@vger.kernel.org +T: git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git S: Maintained CYBERPRO FB DRIVER @@ -1185,6 +1191,7 @@ P: Bartlomiej Zolnierkiewicz M: B.Zolnierkiewicz@elka.pw.edu.pl L: linux-kernel@vger.kernel.org L: linux-ide@vger.kernel.org +T: git kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git S: Maintained IDE/ATAPI CDROM DRIVER @@ -1279,6 +1286,7 @@ P: Vojtech Pavlik M: vojtech@suse.cz L: linux-input@atrey.karlin.mff.cuni.cz L: linux-joystick@atrey.karlin.mff.cuni.cz +T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git S: Maintained INOTIFY @@ -1392,6 +1400,7 @@ P: Kai Germaschewski M: kai.germaschewski@gmx.de L: isdn4linux@listserv.isdn4linux.de W: http://www.isdn4linux.de +T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git S: Maintained ISDN SUBSYSTEM (Eicon active card driver) @@ -1420,6 +1429,7 @@ P: Dave Kleikamp M: shaggy@austin.ibm.com L: jfs-discussion@lists.sourceforge.net W: http://jfs.sourceforge.net/ +T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git S: Supported KCONFIG @@ -1534,6 +1544,7 @@ P: Paul Mackerras M: paulus@samba.org W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org +T: git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git S: Supported LINUX FOR POWER MACINTOSH @@ -1601,6 +1612,7 @@ P: Chris Wright M: chrisw@osdl.org L: linux-security-module@wirex.com W: http://lsm.immunix.org +T: git kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git S: Supported LM83 HARDWARE MONITOR DRIVER @@ -1816,6 +1828,7 @@ M: yoshfuji@linux-ipv6.org P: Patrick McHardy M: kaber@coreworks.de L: netdev@vger.kernel.org +T: git kernel.org:/pub/scm/linux/kernel/davem/net-2.6.git S: Maintained IPVS @@ -1867,6 +1880,7 @@ M: aia21@cantab.net L: linux-ntfs-dev@lists.sourceforge.net L: linux-kernel@vger.kernel.org W: http://linux-ntfs.sf.net/ +T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git S: Maintained NVIDIA (RIVA) FRAMEBUFFER DRIVER @@ -2390,6 +2404,7 @@ P: Anton Blanchard M: anton@samba.org L: sparclinux@vger.kernel.org L: ultralinux@vger.kernel.org +T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git S: Maintained SHARP LH SUPPORT (LH7952X & LH7A40X) @@ -2528,6 +2543,7 @@ P: Adrian Bunk M: trivial@kernel.org L: linux-kernel@vger.kernel.org W: http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/ +T: git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git S: Maintained TMS380 TOKEN-RING NETWORK DRIVER @@ -2861,6 +2877,7 @@ P: Latchesar Ionkov M: lucho@ionkov.net L: v9fs-developer@lists.sourceforge.net W: http://v9fs.sf.net +T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs-devel.git S: Maintained VIDEO FOR LINUX From 2723ab91cb4019def10bdb01b0fecb85e6ac7884 Mon Sep 17 00:00:00 2001 From: Yuan Mu Date: Wed, 23 Nov 2005 15:44:21 -0800 Subject: [PATCH 067/101] [PATCH] hwmon: Fix missing boundary check when setting W83627THF in0 limits Add SENSORS_LIMIT in store VCore limit functions. This fixes a potential u8 overflow on out-of-range user input. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/hwmon/w83627hf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 4e9a04e1f08e..bbb3dcde146b 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -456,7 +456,9 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a (w83627thf == data->type || w83637hf == data->type)) /* use VRM9 calculation */ - data->in_min[0] = (u8)(((val * 100) - 70000 + 244) / 488); + data->in_min[0] = + SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, + 255); else /* use VRM8 (standard) calculation */ data->in_min[0] = IN_TO_REG(val); @@ -481,7 +483,9 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a (w83627thf == data->type || w83637hf == data->type)) /* use VRM9 calculation */ - data->in_max[0] = (u8)(((val * 100) - 70000 + 244) / 488); + data->in_max[0] = + SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, + 255); else /* use VRM8 (standard) calculation */ data->in_max[0] = IN_TO_REG(val); From d0d3cd6965d8e957764663cbb5aaa5ff486a2616 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 23 Nov 2005 15:44:26 -0800 Subject: [PATCH 068/101] [PATCH] hwmon: Fix lm78 VID conversion Fix the lm78 VID reading, which I accidentally broke while making this driver use the common vid_from_reg function rather than reimplementing its own in 2.6.14-rc1. I'm not proud of it, trust me. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/hwmon/lm78.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index bde0cda9477e..78cdd506439f 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -451,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL); static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) { struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(82, data->vid)); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); From 07eab46db7f78b2ed49bc9e41eda80695f93886f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 23 Nov 2005 15:44:31 -0800 Subject: [PATCH 069/101] [PATCH] hwmon: Fix missing it87 fan div init Fix a bug where setting the low fan speed limits will not work if no data was ever read through the sysfs interface and the fan clock dividers have not been explicitely set yet either. The reason is that data->fan_div[nr] may currently be used before it is initialized from the chip register values. The fix is to explicitely initialize data->fan_div[nr] before using it. Bug reported, and fix tested, by Nicolas Mailhot. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/hwmon/it87.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 6c41e25e670b..a61f5d00f10a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -522,8 +522,15 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); + u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); down(&data->update_lock); + switch (nr) { + case 0: data->fan_div[nr] = reg & 0x07; break; + case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; + case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break; + } + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); up(&data->update_lock); From 657a19ebb74128ec52f20b7e34705bdeadc59400 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Wed, 23 Nov 2005 15:44:35 -0800 Subject: [PATCH 070/101] [PATCH] hwmon: hdaps missing an axis Trivial patch to report both hdaps axises to the joystick device, not just the X axis. Signed-off-by: Robert Love Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/hwmon/hdaps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index c81bd4bce1b8..23a9e1ea8e32 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -570,7 +570,7 @@ static int __init hdaps_init(void) hdaps_idev->evbit[0] = BIT(EV_ABS); input_set_abs_params(hdaps_idev, ABS_X, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); - input_set_abs_params(hdaps_idev, ABS_X, + input_set_abs_params(hdaps_idev, ABS_Y, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); input_register_device(hdaps_idev); From dcb890749bbe63af96163c499e9c86b441fb6c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=E4kia?= Date: Wed, 23 Nov 2005 15:44:49 -0800 Subject: [PATCH 071/101] [PATCH] PCI: trivial printk updates in common.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified common.c so it's using the appropriate KERN_* in printk() calls. Signed-off-by: Daniel Marjamäkia Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/i386/pci/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index c96bea14b98f..f6bc48da4d2a 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -132,7 +132,7 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) } } - printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); + printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL); } @@ -144,7 +144,7 @@ static int __init pcibios_init(void) struct cpuinfo_x86 *c = &boot_cpu_data; if (!raw_pci_ops) { - printk("PCI: System does not support PCI\n"); + printk(KERN_WARNING "PCI: System does not support PCI\n"); return 0; } From 5a49f2036ad14092c11d09f186da86fd5ae49a05 Mon Sep 17 00:00:00 2001 From: Rajesh Shah Date: Wed, 23 Nov 2005 15:44:54 -0800 Subject: [PATCH 072/101] [PATCH] PCI Express Hotplug: clear sticky power-fault bit Per the PCI Express spec, the power-fault-detected bit in the slot status register can be set anytime hardware detects a power fault, regardless of whether the slot has a device populated in it or not. This bit is sticky and must be explicitly cleared. This patch is needed to allow hot-add after such a power fault has been detected. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/pci/hotplug/pciehp.h | 1 - drivers/pci/hotplug/pciehp_ctrl.c | 15 ++------------- drivers/pci/hotplug/pciehp_hpc.c | 10 +++++++++- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index c42b68d3aa24..6a61b9f286e1 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -59,7 +59,6 @@ struct slot { struct slot *next; u8 bus; u8 device; - u16 status; u32 number; u8 state; struct timer_list task_event; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 5e582eca21d8..83c4b865718a 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -207,7 +207,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) * power fault Cleared */ info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); - p_slot->status = 0x00; taskInfo->event_type = INT_POWER_FAULT_CLEAR; } else { /* @@ -215,8 +214,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) */ info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_POWER_FAULT; - /* set power fault status for this board */ - p_slot->status = 0xFF; info("power fault bit %x set\n", hp_slot); } if (rc) @@ -317,13 +314,10 @@ static int board_added(struct slot *p_slot) return rc; } - dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status); - /* Check for a power fault */ - if (p_slot->status == 0xFF) { - /* power fault occurred, but it was benign */ + if (p_slot->hpc_ops->query_power_fault(p_slot)) { + dbg("%s: power fault detected\n", __FUNCTION__); rc = POWER_FAILURE; - p_slot->status = 0; goto err_exit; } @@ -334,8 +328,6 @@ static int board_added(struct slot *p_slot) goto err_exit; } - p_slot->status = 0; - /* * Some PCI Express root ports require fixup after hot-plug operation. */ @@ -382,9 +374,6 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); - /* Change status to shutdown */ - p_slot->status = 0x01; - /* Wait for exclusive access to hardware */ down(&ctrl->crit_sect); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 2387e75da0fe..0b8b26beb163 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -750,7 +750,7 @@ static int hpc_power_on_slot(struct slot * slot) { struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; - u16 slot_ctrl; + u16 slot_ctrl, slot_status; int retval = 0; @@ -767,6 +767,14 @@ static int hpc_power_on_slot(struct slot * slot) return -1; } + /* Clear sticky power-fault bit from previous power failures */ + hp_register_read_word(php_ctlr->pci_dev, + SLOT_STATUS(slot->ctrl->cap_base), slot_status); + slot_status &= PWR_FAULT_DETECTED; + if (slot_status) + hp_register_write_word(php_ctlr->pci_dev, + SLOT_STATUS(slot->ctrl->cap_base), slot_status); + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); if (retval) { From ed6d14f9760857c745206c978b80352fc09cfd19 Mon Sep 17 00:00:00 2001 From: Rajesh Shah Date: Wed, 23 Nov 2005 15:44:59 -0800 Subject: [PATCH 073/101] [PATCH] PCI: remove bogus resource collision error When attempting to hotadd a PCI card with a bridge on it, I saw the kernel reporting resource collision errors even when there were really no collisions. The problem is that the code doesn't skip over "invalid" resources with their resource type flag not set. Others have reported similar problems at boot time and for non-bridge PCI card hotplug too, where the code flags a resource collision for disabled ROMs. This patch fixes both problems. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/i386/pci/i386.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index 6d6338500c3c..ed2c8c899bd3 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -221,6 +221,11 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) continue; r = &dev->resource[idx]; + if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) + continue; + if ((idx == PCI_ROM_RESOURCE) && + (!(r->flags & IORESOURCE_ROM_ENABLE))) + continue; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); return -EINVAL; @@ -230,8 +235,6 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; if (cmd != old_cmd) { printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); From f366633fc31db1668b4c261e94816d7304ae9810 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 23 Nov 2005 15:45:04 -0800 Subject: [PATCH 074/101] [PATCH] PCI: kernel-doc fix for pci-acpi.c Fix kernel-doc warning in pci/pci-acpi.c. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/pci/pci-acpi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index a9b00cc2d885..6917c6cb0912 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -178,6 +178,7 @@ EXPORT_SYMBOL(pci_osc_support_set); /** * pci_osc_control_set - commit requested control to Firmware + * @handle: acpi_handle for the target ACPI object * @flags: driver's requested control bits * * Attempt to take control from Firmware on requested control bits. From cac1a293469a868fab1ecc2dc1b6441728f7e0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=E4ki?= Date: Wed, 23 Nov 2005 15:45:09 -0800 Subject: [PATCH 075/101] [PATCH] PCI: direct.c: DBG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DBG() call where updated with the appropriate KERN_* symbol. Signed-off-by: Daniel Marjamäki Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/i386/pci/direct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c index 30b7e9b4f6a2..94331d6be7a3 100644 --- a/arch/i386/pci/direct.c +++ b/arch/i386/pci/direct.c @@ -201,7 +201,7 @@ static int __init pci_sanity_check(struct pci_raw_ops *o) return 1; } - DBG("PCI: Sanity check failed\n"); + DBG(KERN_WARNING "PCI: Sanity check failed\n"); return 0; } From 0b67ba63605a0107f4f3f6d928cdea1e8953fb63 Mon Sep 17 00:00:00 2001 From: Damian Wrobel Date: Wed, 23 Nov 2005 15:45:17 -0800 Subject: [PATCH 076/101] [PATCH] USB: SN9C10x driver - bad page state fix This patch solves the following problem I've already discovered on the latest 2.6.15-rc1-git1 kernel: Nov 13 07:37:28 wrobel kernel: Bad page state at free_hot_cold_page (in process 'motion', page c164e020) Nov 13 07:37:28 wrobel kernel: flags:0x40000400 mapping:00000000 mapcount:0 count:0 Nov 13 07:37:28 wrobel kernel: Backtrace: Nov 13 07:37:28 wrobel kernel: [] bad_page+0x85/0xbe Nov 13 07:37:28 wrobel kernel: [] free_hot_cold_page+0x54/0x129 Nov 13 07:37:28 wrobel kernel: [] __vunmap+0xa9/0xfe Nov 13 07:37:28 wrobel kernel: [] vmalloc_to_page+0x34/0x55 Nov 13 07:37:28 wrobel kernel: [] vfree+0x27/0x35 Nov 13 07:37:28 wrobel kernel: [] sn9c102_release_buffers+0x30/0x3f [sn9c102] Nov 13 07:37:28 wrobel kernel: [] sn9c102_release+0x37/0xeb [sn9c102] Nov 13 07:37:28 wrobel kernel: [] __fput+0xa9/0x1aa Nov 13 07:37:28 wrobel kernel: [] filp_close+0x49/0x6d Nov 13 07:37:30 wrobel kernel: [] sys_close+0x74/0x95 Nov 13 07:37:30 wrobel kernel: [] syscall_call+0x7/0xb Nov 13 07:37:31 wrobel kernel: Trying to fix it up, but a reboot is needed Signed-off-by: Damian Wrobel Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/media/sn9c102_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c index cf8cfbabefde..b2e66e3b90aa 100644 --- a/drivers/usb/media/sn9c102_core.c +++ b/drivers/usb/media/sn9c102_core.c @@ -199,7 +199,7 @@ static void sn9c102_release_buffers(struct sn9c102_device* cam) { if (cam->nbuffers) { rvfree(cam->frame[0].bufmem, - cam->nbuffers * cam->frame[0].buf.length); + cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length)); cam->nbuffers = 0; } } From b4723ae3cc66fd067a8e661b5c05d5bd41be29b5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 23 Nov 2005 15:45:23 -0800 Subject: [PATCH 077/101] [PATCH] USB: ftdi_sio: new IDs for KOBIL devices This patch adds two new devices to the ftdi_sio driver's device ID table. The device IDs were supplied by Stefan Nies of KOBIL Systems for two of their devices using the FTDI chip. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 61204bf7cd78..06e04b442ff1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -475,6 +475,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, + { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, + { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index ddb63df31ce6..773ea3eca086 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -127,6 +127,13 @@ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +/* + * The following are the values for two KOBIL chipcard terminals. + */ +#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ +#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ +#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ + /* * DSS-20 Sync Station for Sony Ericsson P800 */ From f03c17fc9abe8582d6ad830290b3093fdf1eea61 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 23 Nov 2005 15:45:28 -0800 Subject: [PATCH 078/101] [PATCH] USB: EHCI updates This fixes some bugs in EHCI suspend/resume that joined us over the past few releases (as usbcore, PCI, pmcore, and other components evolved): - Removes suspend and resume recursion from the EHCI driver, getting rid of the USB_SUSPEND special casing. - Updates the wakeup mechanism to work again; there's a newish usbcore call it needs to use. - Provide simpler tests for "do we need to restart from scratch", to address another case where PCI Vaux was lost. (In this case it was restoring a swsusp snapshot, but there could be others.) Un-exports a symbol that was temporarily exported. A notable change from previous version is that this doesn't move the spinlock init, so there's still a resume/reinit path bug. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/core/hub.c | 1 - drivers/usb/host/ehci-hcd.c | 3 +- drivers/usb/host/ehci-hub.c | 7 ++++ drivers/usb/host/ehci-pci.c | 71 ++++++++++++++++++------------------- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 840727948d84..f78bd124d290 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1669,7 +1669,6 @@ int usb_suspend_device(struct usb_device *udev) return 0; #endif } -EXPORT_SYMBOL_GPL(usb_suspend_device); /* * If the USB "suspend" state is in use (rather than "global suspend"), diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index af3c05eb86fc..f15144e96e14 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -636,9 +636,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) * stop that signaling. */ ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); - mod_timer (&hcd->rh_timer, - ehci->reset_done [i] + 1); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + usb_hcd_resume_root_hub(hcd); } } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 88cb4ada686e..82caf336e9b6 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -94,6 +94,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd) msleep(5); spin_lock_irq (&ehci->lock); + /* Ideally and we've got a real resume here, and no port's power + * was lost. (For PCI, that means Vaux was maintained.) But we + * could instead be restoring a swsusp snapshot -- so that BIOS was + * the last user of the controller, not reset/pm hardware keeping + * state we gave to it. + */ + /* re-init operational registers in case we lost power */ if (readl (&ehci->regs->intr_enable) == 0) { /* at least some APM implementations will try to deliver diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dfd9bd0b1828..0f2be91e5e0e 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -235,10 +235,11 @@ static void ehci_pci_stop (struct usb_hcd *hcd) /* suspend/resume, section 4.3 */ -/* These routines rely on the bus (pci, platform, etc) +/* These routines rely on the PCI bus glue * to handle powerdown and wakeup, and currently also on * transceivers that don't need any software attention to set up * the right sort of wakeup. + * Also they depend on separate root hub suspend/resume. */ static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) @@ -246,17 +247,9 @@ static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) struct ehci_hcd *ehci = hcd_to_ehci (hcd); if (time_before (jiffies, ehci->next_statechange)) - msleep (100); + msleep (10); -#ifdef CONFIG_USB_SUSPEND - (void) usb_suspend_device (hcd->self.root_hub); -#else - usb_lock_device (hcd->self.root_hub); - (void) ehci_bus_suspend (hcd); - usb_unlock_device (hcd->self.root_hub); -#endif - - // save (PCI) FLADJ in case of Vaux power loss + // could save FLADJ in case of Vaux power loss // ... we'd only use it to handle clock skew return 0; @@ -269,13 +262,18 @@ static int ehci_pci_resume (struct usb_hcd *hcd) struct usb_device *root = hcd->self.root_hub; int retval = -EINVAL; - // maybe restore (PCI) FLADJ + // maybe restore FLADJ if (time_before (jiffies, ehci->next_statechange)) msleep (100); + /* If CF is clear, we lost PCI Vaux power and need to restart. */ + if (readl (&ehci->regs->configured_flag) != cpu_to_le32(FLAG_CF)) + goto restart; + /* If any port is suspended (or owned by the companion), * we know we can/must resume the HC (and mustn't reset it). + * We just defer that to the root hub code. */ for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { u32 status; @@ -283,42 +281,43 @@ static int ehci_pci_resume (struct usb_hcd *hcd) status = readl (&ehci->regs->port_status [port]); if (!(status & PORT_POWER)) continue; - if (status & (PORT_SUSPEND | PORT_OWNER)) { - down (&hcd->self.root_hub->serialize); - retval = ehci_bus_resume (hcd); - up (&hcd->self.root_hub->serialize); - break; + if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { + usb_hcd_resume_root_hub(hcd); + return 0; } + } + +restart: + ehci_dbg(ehci, "lost power, restarting\n"); + for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { + port--; if (!root->children [port]) continue; - dbg_port (ehci, __FUNCTION__, port + 1, status); usb_set_device_state (root->children[port], USB_STATE_NOTATTACHED); } /* Else reset, to cope with power loss or flush-to-storage - * style "resume" having activated BIOS during reboot. + * style "resume" having let BIOS kick in during reboot. */ - if (port == 0) { - (void) ehci_halt (ehci); - (void) ehci_reset (ehci); - (void) ehci_pci_reset (hcd); + (void) ehci_halt (ehci); + (void) ehci_reset (ehci); + (void) ehci_pci_reset (hcd); - /* emptying the schedule aborts any urbs */ - spin_lock_irq (&ehci->lock); - if (ehci->reclaim) - ehci->reclaim_ready = 1; - ehci_work (ehci, NULL); - spin_unlock_irq (&ehci->lock); + /* emptying the schedule aborts any urbs */ + spin_lock_irq (&ehci->lock); + if (ehci->reclaim) + ehci->reclaim_ready = 1; + ehci_work (ehci, NULL); + spin_unlock_irq (&ehci->lock); - /* restart; khubd will disconnect devices */ - retval = ehci_run (hcd); + /* restart; khubd will disconnect devices */ + retval = ehci_run (hcd); - /* here we "know" root ports should always stay powered; - * but some controllers may lose all power. - */ - ehci_port_power (ehci, 1); - } + /* here we "know" root ports should always stay powered; + * but some controllers may lose all power. + */ + ehci_port_power (ehci, 1); return retval; } From abcc94480634f6fe9fc29b821261e8162c87ddd2 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 23 Nov 2005 15:45:32 -0800 Subject: [PATCH 079/101] [PATCH] USB: EHCI updates mostly whitespace cleanups This cleans up the recent updates to EHCI PCI support: - Gets rid of checks for "is this a PCI device", they're no longer needed since this is now all PCI-only code. - Reduce log spamming: MWI is only interesting in the atypical case that it can actually be used. - Whitespace cleanup, as appropriate for a new file with no other pending patches. So other than that minor logging change, no functional updates. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/host/ehci-pci.c | 260 +++++++++++++++++------------------- 1 file changed, 125 insertions(+), 135 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 0f2be91e5e0e..b654e3f800b4 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -27,7 +27,7 @@ /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... * off the controller (maybe it can boot from highspeed USB disks). */ -static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) +static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap) { struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); @@ -48,7 +48,7 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) where, cap); // some BIOS versions seem buggy... // return 1; - ehci_warn (ehci, "continuing after BIOS bug...\n"); + ehci_warn(ehci, "continuing after BIOS bug...\n"); /* disable all SMIs, and clear "BIOS owns" flag */ pci_write_config_dword(pdev, where + 4, 0); pci_write_config_byte(pdev, where + 2, 0); @@ -59,95 +59,93 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) } /* called by khubd or root hub init threads */ -static int ehci_pci_reset (struct usb_hcd *hcd) +static int ehci_pci_reset(struct usb_hcd *hcd) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 temp; unsigned count = 256/4; spin_lock_init (&ehci->lock); ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); - dbg_hcs_params (ehci, "reset"); - dbg_hcc_params (ehci, "reset"); + ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); + dbg_hcs_params(ehci, "reset"); + dbg_hcc_params(ehci, "reset"); /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl (&ehci->caps->hcs_params); + ehci->hcs_params = readl(&ehci->caps->hcs_params); - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + /* NOTE: only the parts below this line are PCI-specific */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { - ehci->is_tdi_rh_tt = 1; - tdi_reset (ehci); - } - break; - case PCI_VENDOR_ID_AMD: - /* AMD8111 EHCI doesn't work, according to AMD errata */ - if (pdev->device == 0x7463) { - ehci_info (ehci, "ignoring AMD8111 (errata)\n"); - return -EIO; - } - break; - case PCI_VENDOR_ID_NVIDIA: - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - switch (pdev->device) { - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_31BIT_MASK) < 0) - ehci_warn (ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; - } + switch (pdev->vendor) { + case PCI_VENDOR_ID_TDI: + if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { + ehci->is_tdi_rh_tt = 1; + tdi_reset(ehci); + } + break; + case PCI_VENDOR_ID_AMD: + /* AMD8111 EHCI doesn't work, according to AMD errata */ + if (pdev->device == 0x7463) { + ehci_info(ehci, "ignoring AMD8111 (errata)\n"); + return -EIO; + } + break; + case PCI_VENDOR_ID_NVIDIA: + /* NVidia reports that certain chips don't handle + * QH, ITD, or SITD addresses above 2GB. (But TD, + * data buffer, and periodic schedule are normal.) + */ + switch (pdev->device) { + case 0x003c: /* MCP04 */ + case 0x005b: /* CK804 */ + case 0x00d8: /* CK8 */ + case 0x00e8: /* CK8S */ + if (pci_set_consistent_dma_mask(pdev, + DMA_31BIT_MASK) < 0) + ehci_warn(ehci, "can't enable NVidia " + "workaround for >2GB RAM\n"); break; } + break; + } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability (pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = readl (&ehci->debug->control); - ehci_info (ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, 0x0a); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if ((temp & (3 << 13)) == (1 << 13)) { + temp &= 0x1fff; + ehci->debug = hcd->regs + temp; + temp = readl(&ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(ehci->hcs_params), + (temp & DBGP_ENABLED) + ? " IN USE" + : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; } + } - temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); - } else - temp = 0; + temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params)); /* EHCI 0.96 and later may have "extended capabilities" */ while (temp && count--) { u32 cap; - pci_read_config_dword (to_pci_dev(hcd->self.controller), + pci_read_config_dword(to_pci_dev(hcd->self.controller), temp, &cap); - ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); + ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp); switch (cap & 0xff) { case 1: /* BIOS/SMM/... handoff */ - if (bios_handoff (ehci, temp, cap) != 0) + if (bios_handoff(ehci, temp, cap) != 0) return -EOPNOTSUPP; break; case 0: /* illegal reserved capability */ - ehci_warn (ehci, "illegal capability!\n"); + ehci_warn(ehci, "illegal capability!\n"); cap = 0; /* FALLTHROUGH */ default: /* unknown */ @@ -156,77 +154,69 @@ static int ehci_pci_reset (struct usb_hcd *hcd) temp = (cap >> 8) & 0xff; } if (!count) { - ehci_err (ehci, "bogus capabilities ... PCI problems!\n"); + ehci_err(ehci, "bogus capabilities ... PCI problems!\n"); return -EIO; } if (ehci_is_TDI(ehci)) - ehci_reset (ehci); + ehci_reset(ehci); - ehci_port_power (ehci, 0); + ehci_port_power(ehci, 0); /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { - ehci_dbg (ehci, "bogus port configuration: " + ehci_dbg(ehci, "bogus port configuration: " "cc=%d x pcc=%d < ports=%d\n", HCS_N_CC(ehci->hcs_params), HCS_N_PCC(ehci->hcs_params), HCS_N_PORTS(ehci->hcs_params)); - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev; - - pdev = to_pci_dev(hcd->self.controller); - switch (pdev->vendor) { - case 0x17a0: /* GENESYS */ - /* GL880S: should be PORTS=2 */ - temp |= (ehci->hcs_params & ~0xf); - ehci->hcs_params = temp; - break; - case PCI_VENDOR_ID_NVIDIA: - /* NF4: should be PCC=10 */ - break; - } + switch (pdev->vendor) { + case 0x17a0: /* GENESYS */ + /* GL880S: should be PORTS=2 */ + temp |= (ehci->hcs_params & ~0xf); + ehci->hcs_params = temp; + break; + case PCI_VENDOR_ID_NVIDIA: + /* NF4: should be PCC=10 */ + break; } } /* force HC to halt state */ - return ehci_halt (ehci); + return ehci_halt(ehci); } -static int ehci_pci_start (struct usb_hcd *hcd) +static int ehci_pci_start(struct usb_hcd *hcd) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int result = 0; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int result = 0; + struct pci_dev *pdev; + u16 port_wake; - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev; - u16 port_wake; + pdev = to_pci_dev(hcd->self.controller); - pdev = to_pci_dev(hcd->self.controller); + /* Serial Bus Release Number is at PCI 0x60 offset */ + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - /* Serial Bus Release Number is at PCI 0x60 offset */ - pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + /* port wake capability, reported by boot firmware */ + pci_read_config_word(pdev, 0x62, &port_wake); + hcd->can_wakeup = (port_wake & 1) != 0; - /* port wake capability, reported by boot firmware */ - pci_read_config_word(pdev, 0x62, &port_wake); - hcd->can_wakeup = (port_wake & 1) != 0; + /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ + result = pci_set_mwi(pdev); + if (!result) + ehci_dbg(ehci, "MWI active\n"); - /* help hc dma work well with cachelines */ - result = pci_set_mwi(pdev); - if (result) - ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); - } - - return ehci_run (hcd); + return ehci_run(hcd); } /* always called by thread; normally rmmod */ -static void ehci_pci_stop (struct usb_hcd *hcd) +static void ehci_pci_stop(struct usb_hcd *hcd) { - ehci_stop (hcd); + ehci_stop(hcd); } /*-------------------------------------------------------------------------*/ @@ -242,12 +232,12 @@ static void ehci_pci_stop (struct usb_hcd *hcd) * Also they depend on separate root hub suspend/resume. */ -static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) +static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); - if (time_before (jiffies, ehci->next_statechange)) - msleep (10); + if (time_before(jiffies, ehci->next_statechange)) + msleep(10); // could save FLADJ in case of Vaux power loss // ... we'd only use it to handle clock skew @@ -255,30 +245,30 @@ static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) return 0; } -static int ehci_pci_resume (struct usb_hcd *hcd) +static int ehci_pci_resume(struct usb_hcd *hcd) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned port; struct usb_device *root = hcd->self.root_hub; int retval = -EINVAL; // maybe restore FLADJ - if (time_before (jiffies, ehci->next_statechange)) - msleep (100); + if (time_before(jiffies, ehci->next_statechange)) + msleep(100); /* If CF is clear, we lost PCI Vaux power and need to restart. */ - if (readl (&ehci->regs->configured_flag) != cpu_to_le32(FLAG_CF)) + if (readl(&ehci->regs->configured_flag) != cpu_to_le32(FLAG_CF)) goto restart; /* If any port is suspended (or owned by the companion), * we know we can/must resume the HC (and mustn't reset it). * We just defer that to the root hub code. */ - for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { + for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { u32 status; port--; - status = readl (&ehci->regs->port_status [port]); + status = readl(&ehci->regs->port_status [port]); if (!(status & PORT_POWER)) continue; if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { @@ -289,35 +279,35 @@ static int ehci_pci_resume (struct usb_hcd *hcd) restart: ehci_dbg(ehci, "lost power, restarting\n"); - for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { + for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { port--; if (!root->children [port]) continue; - usb_set_device_state (root->children[port], + usb_set_device_state(root->children[port], USB_STATE_NOTATTACHED); } /* Else reset, to cope with power loss or flush-to-storage * style "resume" having let BIOS kick in during reboot. */ - (void) ehci_halt (ehci); - (void) ehci_reset (ehci); - (void) ehci_pci_reset (hcd); + (void) ehci_halt(ehci); + (void) ehci_reset(ehci); + (void) ehci_pci_reset(hcd); /* emptying the schedule aborts any urbs */ - spin_lock_irq (&ehci->lock); + spin_lock_irq(&ehci->lock); if (ehci->reclaim) ehci->reclaim_ready = 1; - ehci_work (ehci, NULL); - spin_unlock_irq (&ehci->lock); + ehci_work(ehci, NULL); + spin_unlock_irq(&ehci->lock); /* restart; khubd will disconnect devices */ - retval = ehci_run (hcd); + retval = ehci_run(hcd); /* here we "know" root ports should always stay powered; * but some controllers may lose all power. */ - ehci_port_power (ehci, 1); + ehci_port_power(ehci, 1); return retval; } @@ -376,7 +366,7 @@ static const struct pci_device_id pci_ids [] = { { }, { /* end: all zeroes */ } }; -MODULE_DEVICE_TABLE (pci, pci_ids); +MODULE_DEVICE_TABLE(pci, pci_ids); /* pci driver glue; this is a "new style" PCI driver module */ static struct pci_driver ehci_pci_driver = { @@ -392,22 +382,22 @@ static struct pci_driver ehci_pci_driver = { #endif }; -static int __init ehci_hcd_pci_init (void) +static int __init ehci_hcd_pci_init(void) { if (usb_disabled()) return -ENODEV; - pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", hcd_name, - sizeof (struct ehci_qh), sizeof (struct ehci_qtd), - sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); + sizeof(struct ehci_qh), sizeof(struct ehci_qtd), + sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - return pci_register_driver (&ehci_pci_driver); + return pci_register_driver(&ehci_pci_driver); } -module_init (ehci_hcd_pci_init); +module_init(ehci_hcd_pci_init); -static void __exit ehci_hcd_pci_cleanup (void) +static void __exit ehci_hcd_pci_cleanup(void) { - pci_unregister_driver (&ehci_pci_driver); + pci_unregister_driver(&ehci_pci_driver); } -module_exit (ehci_hcd_pci_cleanup); +module_exit(ehci_hcd_pci_cleanup); From 188075211cc75a31190de4a19a084e3d83ee1c89 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 23 Nov 2005 15:45:37 -0800 Subject: [PATCH 080/101] [PATCH] USB: EHCI updates split init/reinit logic for resume Moving the PCI-specific parts of the EHCI driver into their own file created a few issues ... notably on resume paths which (like swsusp) require re-initializing the controller. This patch: - Splits the EHCI startup code into run-once HCD setup code and separate "init the hardware" reinit code. (That reinit code is a superset of the "early usb handoff" code.) - Then it makes the PCI init code run both, and the resume code only run the reinit code. - It also removes needless pci wrappers around EHCI start/stop methods. - Removes a byteswap issue that would be seen on big-endian hardware. The HCD glue still doesn't actually provide a good way to do all this run-one init stuff in one place though. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/host/ehci-hcd.c | 155 +++++++++++++++++---------------- drivers/usb/host/ehci-pci.c | 166 +++++++++++++++++------------------- 2 files changed, 161 insertions(+), 160 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f15144e96e14..29f52a44b928 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -411,50 +411,39 @@ static void ehci_stop (struct usb_hcd *hcd) dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); } -static int ehci_run (struct usb_hcd *hcd) +/* one-time init, only for memory state */ +static int ehci_init(struct usb_hcd *hcd) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 temp; int retval; u32 hcc_params; - int first; - /* skip some things on restart paths */ - first = (ehci->watchdog.data == 0); - if (first) { - init_timer (&ehci->watchdog); - ehci->watchdog.function = ehci_watchdog; - ehci->watchdog.data = (unsigned long) ehci; - } + spin_lock_init(&ehci->lock); + + init_timer(&ehci->watchdog); + ehci->watchdog.function = ehci_watchdog; + ehci->watchdog.data = (unsigned long) ehci; /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; - if (first && (retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0) + if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ - hcc_params = readl (&ehci->caps->hcc_params); - if (HCC_ISOC_CACHE (hcc_params)) // full frame cache + hcc_params = readl(&ehci->caps->hcc_params); + if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 8; else // N microframes cached - ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params); + ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; ehci->reclaim_ready = 0; ehci->next_uframe = -1; - /* controller state: unknown --> reset */ - - /* EHCI spec section 4.1 */ - if ((retval = ehci_reset (ehci)) != 0) { - ehci_mem_cleanup (ehci); - return retval; - } - writel (ehci->periodic_dma, &ehci->regs->frame_list); - /* * dedicate a qh for the async ring head, since we couldn't unlink * a 'real' qh without stopping the async schedule [4.8]. use it @@ -462,37 +451,13 @@ static int ehci_run (struct usb_hcd *hcd) * its dummy is used in hw_alt_next of many tds, to prevent the qh * from automatically advancing to the next td after short reads. */ - if (first) { - ehci->async->qh_next.qh = NULL; - ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); - ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); - ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); - ehci->async->hw_qtd_next = EHCI_LIST_END; - ehci->async->qh_state = QH_STATE_LINKED; - ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma); - } - writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); - - /* - * hcc_params controls whether ehci->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - * streaming mappings for I/O buffers, like pci_map_single(), - * can return segments above 4GB, if the device allows. - * - * NOTE: the dma mask is visible through dma_supported(), so - * drivers can pass this info along ... like NETIF_F_HIGHDMA, - * Scsi_Host.highmem_io, and so forth. It's readonly to all - * host side drivers though. - */ - if (HCC_64BIT_ADDR (hcc_params)) { - writel (0, &ehci->regs->segment); -#if 0 -// this is deeply broken on almost all architectures - if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK)) - ehci_info (ehci, "enabled 64bit DMA\n"); -#endif - } + ehci->async->qh_next.qh = NULL; + ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma); + ehci->async->hw_info1 = cpu_to_le32(QH_HEAD); + ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT); + ehci->async->hw_qtd_next = EHCI_LIST_END; + ehci->async->qh_state = QH_STATE_LINKED; + ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma); /* clear interrupt enables, set irq latency */ if (log2_irq_thresh < 0 || log2_irq_thresh > 6) @@ -507,13 +472,13 @@ static int ehci_run (struct usb_hcd *hcd) * make problems: throughput reduction (!), data errors... */ if (park) { - park = min (park, (unsigned) 3); + park = min(park, (unsigned) 3); temp |= CMD_PARK; temp |= park << 8; } - ehci_info (ehci, "park %d\n", park); + ehci_dbg(ehci, "park %d\n", park); } - if (HCC_PGM_FRAMELISTLEN (hcc_params)) { + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { /* periodic schedule size can be smaller than default */ temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); @@ -521,16 +486,63 @@ static int ehci_run (struct usb_hcd *hcd) case 0: ehci->periodic_size = 1024; break; case 1: ehci->periodic_size = 512; break; case 2: ehci->periodic_size = 256; break; - default: BUG (); + default: BUG(); } } + ehci->command = temp; + + ehci->reboot_notifier.notifier_call = ehci_reboot; + register_reboot_notifier(&ehci->reboot_notifier); + + return 0; +} + +/* start HC running; it's halted, ehci_init() has been run (once) */ +static int ehci_run (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + int retval; + u32 temp; + u32 hcc_params; + + /* EHCI spec section 4.1 */ + if ((retval = ehci_reset(ehci)) != 0) { + unregister_reboot_notifier(&ehci->reboot_notifier); + ehci_mem_cleanup(ehci); + return retval; + } + writel(ehci->periodic_dma, &ehci->regs->frame_list); + writel((u32)ehci->async->qh_dma, &ehci->regs->async_next); + + /* + * hcc_params controls whether ehci->regs->segment must (!!!) + * be used; it constrains QH/ITD/SITD and QTD locations. + * pci_pool consistent memory always uses segment zero. + * streaming mappings for I/O buffers, like pci_map_single(), + * can return segments above 4GB, if the device allows. + * + * NOTE: the dma mask is visible through dma_supported(), so + * drivers can pass this info along ... like NETIF_F_HIGHDMA, + * Scsi_Host.highmem_io, and so forth. It's readonly to all + * host side drivers though. + */ + hcc_params = readl(&ehci->caps->hcc_params); + if (HCC_64BIT_ADDR(hcc_params)) { + writel(0, &ehci->regs->segment); +#if 0 +// this is deeply broken on almost all architectures + if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK)) + ehci_info(ehci, "enabled 64bit DMA\n"); +#endif + } + + // Philips, Intel, and maybe others need CMD_RUN before the // root hub will detect new devices (why?); NEC doesn't - temp |= CMD_RUN; - writel (temp, &ehci->regs->command); - dbg_cmd (ehci, "init", temp); - - /* set async sleep time = 10 us ... ? */ + ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); + ehci->command |= CMD_RUN; + writel (ehci->command, &ehci->regs->command); + dbg_cmd (ehci, "init", ehci->command); /* * Start, enabling full USB 2.0 functionality ... usb 1.1 devices @@ -538,26 +550,23 @@ static int ehci_run (struct usb_hcd *hcd) * involved with the root hub. (Except where one is integrated, * and there's no companion controller unless maybe for USB OTG.) */ - if (first) { - ehci->reboot_notifier.notifier_call = ehci_reboot; - register_reboot_notifier (&ehci->reboot_notifier); - } - hcd->state = HC_STATE_RUNNING; writel (FLAG_CF, &ehci->regs->configured_flag); - readl (&ehci->regs->command); /* unblock posted write */ + readl (&ehci->regs->command); /* unblock posted writes */ temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, - "USB %x.%x %s, EHCI %x.%02x, driver %s\n", + "USB %x.%x started, EHCI %x.%02x, driver %s\n", ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - first ? "initialized" : "restarted", temp >> 8, temp & 0xff, DRIVER_VERSION); writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ - if (first) - create_debug_files (ehci); + /* GRR this is run-once init(), being done every time the HC starts. + * So long as they're part of class devices, we can't do it init() + * since the class device isn't created that early. + */ + create_debug_files(ehci); return 0; } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index b654e3f800b4..441c26064b44 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -58,15 +58,76 @@ static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap) return 0; } -/* called by khubd or root hub init threads */ +/* called after powerup, by probe or system-pm "wakeup" */ +static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) +{ + u32 temp; + int retval; + unsigned count = 256/4; + + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, 0x0a); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if ((temp & (3 << 13)) == (1 << 13)) { + temp &= 0x1fff; + ehci->debug = ehci_to_hcd(ehci)->regs + temp; + temp = readl(&ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(ehci->hcs_params), + (temp & DBGP_ENABLED) + ? " IN USE" + : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + + temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params)); + + /* EHCI 0.96 and later may have "extended capabilities" */ + while (temp && count--) { + u32 cap; + + pci_read_config_dword(pdev, temp, &cap); + ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp); + switch (cap & 0xff) { + case 1: /* BIOS/SMM/... handoff */ + if (bios_handoff(ehci, temp, cap) != 0) + return -EOPNOTSUPP; + break; + case 0: /* illegal reserved capability */ + ehci_dbg(ehci, "illegal capability!\n"); + cap = 0; + /* FALLTHROUGH */ + default: /* unknown */ + break; + } + temp = (cap >> 8) & 0xff; + } + if (!count) { + ehci_err(ehci, "bogus capabilities ... PCI problems!\n"); + return -EIO; + } + + /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ + retval = pci_set_mwi(pdev); + if (!retval) + ehci_dbg(ehci, "MWI active\n"); + + ehci_port_power(ehci, 0); + + return 0; +} + +/* called by khubd or root hub (re)init threads; leaves HC in halt state */ static int ehci_pci_reset(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 temp; - unsigned count = 256/4; - - spin_lock_init (&ehci->lock); + int retval; ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); @@ -76,6 +137,10 @@ static int ehci_pci_reset(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); + retval = ehci_halt(ehci); + if (retval) + return retval; + /* NOTE: only the parts below this line are PCI-specific */ switch (pdev->vendor) { @@ -111,57 +176,9 @@ static int ehci_pci_reset(struct usb_hcd *hcd) break; } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = readl(&ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - - temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params)); - - /* EHCI 0.96 and later may have "extended capabilities" */ - while (temp && count--) { - u32 cap; - - pci_read_config_dword(to_pci_dev(hcd->self.controller), - temp, &cap); - ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp); - switch (cap & 0xff) { - case 1: /* BIOS/SMM/... handoff */ - if (bios_handoff(ehci, temp, cap) != 0) - return -EOPNOTSUPP; - break; - case 0: /* illegal reserved capability */ - ehci_warn(ehci, "illegal capability!\n"); - cap = 0; - /* FALLTHROUGH */ - default: /* unknown */ - break; - } - temp = (cap >> 8) & 0xff; - } - if (!count) { - ehci_err(ehci, "bogus capabilities ... PCI problems!\n"); - return -EIO; - } if (ehci_is_TDI(ehci)) ehci_reset(ehci); - ehci_port_power(ehci, 0); - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; @@ -184,39 +201,15 @@ static int ehci_pci_reset(struct usb_hcd *hcd) } } - /* force HC to halt state */ - return ehci_halt(ehci); -} - -static int ehci_pci_start(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int result = 0; - struct pci_dev *pdev; - u16 port_wake; - - pdev = to_pci_dev(hcd->self.controller); - /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - /* port wake capability, reported by boot firmware */ - pci_read_config_word(pdev, 0x62, &port_wake); - hcd->can_wakeup = (port_wake & 1) != 0; + /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ - /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ - result = pci_set_mwi(pdev); - if (!result) - ehci_dbg(ehci, "MWI active\n"); + retval = ehci_pci_reinit(ehci, pdev); - return ehci_run(hcd); -} - -/* always called by thread; normally rmmod */ - -static void ehci_pci_stop(struct usb_hcd *hcd) -{ - ehci_stop(hcd); + /* finish init */ + return ehci_init(hcd); } /*-------------------------------------------------------------------------*/ @@ -250,6 +243,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned port; struct usb_device *root = hcd->self.root_hub; + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int retval = -EINVAL; // maybe restore FLADJ @@ -258,7 +252,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) msleep(100); /* If CF is clear, we lost PCI Vaux power and need to restart. */ - if (readl(&ehci->regs->configured_flag) != cpu_to_le32(FLAG_CF)) + if (readl(&ehci->regs->configured_flag) != FLAG_CF) goto restart; /* If any port is suspended (or owned by the companion), @@ -292,7 +286,7 @@ restart: */ (void) ehci_halt(ehci); (void) ehci_reset(ehci); - (void) ehci_pci_reset(hcd); + (void) ehci_pci_reinit(ehci, pdev); /* emptying the schedule aborts any urbs */ spin_lock_irq(&ehci->lock); @@ -304,9 +298,7 @@ restart: /* restart; khubd will disconnect devices */ retval = ehci_run(hcd); - /* here we "know" root ports should always stay powered; - * but some controllers may lose all power. - */ + /* here we "know" root ports should always stay powered */ ehci_port_power(ehci, 1); return retval; @@ -328,12 +320,12 @@ static const struct hc_driver ehci_pci_hc_driver = { * basic lifecycle operations */ .reset = ehci_pci_reset, - .start = ehci_pci_start, + .start = ehci_run, #ifdef CONFIG_PM .suspend = ehci_pci_suspend, .resume = ehci_pci_resume, #endif - .stop = ehci_pci_stop, + .stop = ehci_stop, /* * managing i/o requests and associated device resources From 21b1861fb2ba5b25b32c63bc540bbc7ca1d186f8 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 23 Nov 2005 15:45:42 -0800 Subject: [PATCH 081/101] [PATCH] USB: ohci, move ppc asic tweaks nearer pci This should fix a suspend/resume issues that appear with OHCI on some PPC hardware. The PCI layer should doesn't have the hooks needed for such ASIC-specific hooks (in this case, software clock gating), so this moves the code to do that into hcd-pci.c ... where it can be done after the relevant PCI PM state transition (to/from D3). Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/core/hcd-pci.c | 38 +++++++++++++++++++++++++++++++++++-- drivers/usb/host/ohci-pci.c | 36 ----------------------------------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 7feb829362d6..5131d88e8c5b 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -20,9 +20,17 @@ #include #include #include +#include + #include #include -#include + +#ifdef CONFIG_PPC_PMAC +#include +#include +#include +#include +#endif #include "usb.h" #include "hcd.h" @@ -277,8 +285,22 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) } done: - if (retval == 0) + if (retval == 0) { dev->dev.power.power_state = PMSG_SUSPEND; + +#ifdef CONFIG_PPC_PMAC + /* Disable ASIC clocks for USB */ + if (_machine == _MACH_Pmac) { + struct device_node *of_node; + + of_node = pci_device_to_OF_node (dev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, + of_node, 0, 0); + } +#endif + } + return retval; } EXPORT_SYMBOL (usb_hcd_pci_suspend); @@ -301,6 +323,18 @@ int usb_hcd_pci_resume (struct pci_dev *dev) return 0; } +#ifdef CONFIG_PPC_PMAC + /* Reenable ASIC clocks for USB */ + if (_machine == _MACH_Pmac) { + struct device_node *of_node; + + of_node = pci_device_to_OF_node (dev); + if (of_node) + pmac_call_feature (PMAC_FTR_USB_ENABLE, + of_node, 0, 1); + } +#endif + /* NOTE: chip docs cover clean "real suspend" cases (what Linux * calls "standby", "suspend to RAM", and so on). There are also * dirty cases when swsusp fakes a suspend in "shutdown" mode. diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index a59e536441e1..5f22e6590cd1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -14,15 +14,6 @@ * This file is licenced under the GPL. */ -#include - -#ifdef CONFIG_PPC_PMAC -#include -#include -#include -#include -#endif - #ifndef CONFIG_PCI #error "This file is PCI bus glue. CONFIG_PCI must be defined." #endif @@ -115,39 +106,12 @@ ohci_pci_start (struct usb_hcd *hcd) static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) { /* root hub was already suspended */ - - /* FIXME these PMAC things get called in the wrong places. ASIC - * clocks should be turned off AFTER entering D3, and on BEFORE - * trying to enter D0. Evidently the PCI layer doesn't currently - * provide the right sort of platform hooks for this ... - */ -#ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { - struct device_node *of_node; - - /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller)); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif /* CONFIG_PPC_PMAC */ return 0; } static int ohci_pci_resume (struct usb_hcd *hcd) { -#ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { - struct device_node *of_node; - - /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller)); - if (of_node) - pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); - } -#endif /* CONFIG_PPC_PMAC */ - usb_hcd_resume_root_hub(hcd); return 0; } From 63dc3ff3e019287e8cb4647808de1d93acddd006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=E4rdeman?= Date: Wed, 23 Nov 2005 15:45:49 -0800 Subject: [PATCH 082/101] [PATCH] USB: fix USB key generates ioctl_internal_command errors issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Wed, Nov 16, 2005 at 06:34:24PM -0800, Pete Zaitcev wrote: >On Wed, 16 Nov 2005 23:52:32 +0100, David Härdeman wrote: >> usb-storage: waiting for device to settle before scanning >> Vendor: I0MEGA Model: UMni1GB*IOM2K4 Rev: 1.01 >> Type: Direct-Access ANSI SCSI revision: 02 >> SCSI device sda: 2048000 512-byte hdwr sectors (1049 MB) >> sda: Write Protect is off >> sda: Mode Sense: 00 00 00 00 >> sda: assuming drive cache: write through >> ioctl_internal_command: <8 0 0 0> return code = 8000002 >> : Current: sense key=0x0 >> ASC=0x0 ASCQ=0x0 >> SCSI device sda: 2048000 512-byte hdwr sectors (1049 MB) > >I think it's harmless. I saw things like that, and initially I plugged >them with workarounds like this: Thanks for the pointer, and yes, it is harmless, but it floods the console with the messages which hides other (potentially important) messages...following your example I've made a patch which fixes the problem. Signed-off-by: David Härdeman Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/storage/unusual_devs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0a9858f69a9b..f5f47a34b168 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1118,6 +1118,15 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_GO_SLOW ), +/* + * David Härdeman + * The key makes the SCSI stack print confusing (but harmless) messages + */ +UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, + "Iomega", + "Micro Mini 1GB", + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), + #ifdef CONFIG_USB_STORAGE_SDDR55 UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, "Sandisk", From 8dd396ec7bf706fe85d8c6792b478ee6f09e8de6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 23 Nov 2005 15:45:53 -0800 Subject: [PATCH 083/101] [PATCH] USB: kernel-doc for linux/usb.h Fix kernel-doc warning in linux/usb.h. Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- include/linux/usb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/usb.h b/include/linux/usb.h index 856d232c7562..d81b050e5955 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -47,6 +47,7 @@ struct usb_driver; * @urb_list: urbs queued to this endpoint; maintained by usbcore * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH) * with one or more transfer descriptors (TDs) per urb + * @kobj: kobject for sysfs info * @extra: descriptors following this endpoint in the configuration * @extralen: how many bytes of "extra" are valid * From 569cfaadb0ea21bfcedac85dbc5147b4a9ed42d2 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Wed, 23 Nov 2005 15:45:58 -0800 Subject: [PATCH 084/101] [PATCH] usb serial: remove redundant include remove redundant include Signed-off-by: Nicolas Kaiser Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/serial/ipw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index a02fada85362..7744b8148bc5 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include "usb-serial.h" From cf65f1623dd005ddfb1cbba20af3423a6c638dbe Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 24 Nov 2005 21:41:14 +1100 Subject: [PATCH 085/101] drm: fix quiescent locking A fix for a locking bug which is triggered when a client tries to lock with flag DMA_QUIESCENT (typically the X server), but gets interrupted by a signal. The locking IOCTL should then return an error, but if DMA_QUIESCENT succeeds it returns 0, and the client falsely thinks it has the lock. In addition The client waits for DMA_QUISCENT and possibly DMA_READY without having the lock. From: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/char/drm/drm_lock.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index b276ae8a6633..b48a595d54ec 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c @@ -104,6 +104,10 @@ int drm_lock(struct inode *inode, struct file *filp, __set_current_state(TASK_RUNNING); remove_wait_queue(&dev->lock.lock_queue, &entry); + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + if (ret) + return ret; + sigemptyset(&dev->sigmask); sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGTSTP); @@ -116,8 +120,12 @@ int drm_lock(struct inode *inode, struct file *filp, if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY)) dev->driver->dma_ready(dev); - if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) - return dev->driver->dma_quiescent(dev); + if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) { + if (dev->driver->dma_quiescent(dev)) { + DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context); + return DRM_ERR(EBUSY); + } + } /* dev->driver->kernel_context_switch isn't used by any of the x86 * drivers but is used by the Sparc driver. @@ -128,9 +136,7 @@ int drm_lock(struct inode *inode, struct file *filp, dev->driver->kernel_context_switch(dev, dev->last_context, lock.context); } - DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); - - return ret; + return 0; } /** From 6d9885a8ce45cd9b7d36517ee823a480eaf95c02 Mon Sep 17 00:00:00 2001 From: Jasper Spaans Date: Thu, 24 Nov 2005 16:53:36 +0100 Subject: [PATCH 086/101] [PATCH] fbcon: fix obvious bug in fbcon logo rotation code This code fixes a tiny problem with the recent fbcon rotation changes: fb_prepare_logo doesn't check the return value of fb_find_logo and that causes a crash for my while booting. Obvious & working & tested fix is here. Signed-off-by: Jasper Spaans Acked-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 9f180096c896..6240aedb4154 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -452,13 +452,17 @@ int fb_prepare_logo(struct fb_info *info, int rotate) /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); + + if (!fb_logo.logo) { + return 0; + } if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) yres = info->var.yres; else yres = info->var.xres; - if (fb_logo.logo && fb_logo.logo->height > yres) { + if (fb_logo.logo->height > yres) { fb_logo.logo = NULL; return 0; } From 55b02d74e126df70fb6b92a0e4e4bed2f0a13fe4 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 25 Nov 2005 16:41:33 +1100 Subject: [PATCH 087/101] [XFS] Fix potential overflow in xfs_iomap_t delta for very large extents SGI-PV: 945311 SGI-Modid: xfs-linux-melb:xfs-kern:201708a Signed-off-by: Eric Sandeen Signed-off-by: Nathan Scott --- fs/xfs/xfs_iomap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index fcd6d63bb68b..3ce204a524b0 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -69,7 +69,7 @@ typedef struct xfs_iomap { xfs_buftarg_t *iomap_target; xfs_off_t iomap_offset; /* offset of mapping, bytes */ xfs_off_t iomap_bsize; /* size of mapping, bytes */ - size_t iomap_delta; /* offset into mapping, bytes */ + xfs_off_t iomap_delta; /* offset into mapping, bytes */ iomap_flags_t iomap_flags; } xfs_iomap_t; From f33c6797bccc695c4c85885f2c676ad4c8fed98d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 25 Nov 2005 16:41:47 +1100 Subject: [PATCH 088/101] [XFS] handle error returns from freeze_bdev SGI-PV: 945483 SGI-Modid: xfs-linux-melb:xfs-kern:201884a Signed-off-by: Christoph Hellwig Signed-off-by: Nathan Scott --- fs/xfs/xfs_fsops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 7ceabd0e2d9d..d1236d6f4045 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -550,7 +550,7 @@ xfs_fs_goingdown( struct vfs *vfsp = XFS_MTOVFS(mp); struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); - if (sb) { + if (sb && !IS_ERR(sb)) { xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); thaw_bdev(sb->s_bdev, sb); } From a4656391b76ed93faed724c5963f033164ee477e Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 25 Nov 2005 16:41:57 +1100 Subject: [PATCH 089/101] [XFS] Fix a 32 bit value wraparound when providing a mapping for a large direct write. SGI-PV: 944820 SGI-Modid: xfs-linux-melb:xfs-kern:24351a Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_aops.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c6108971b4e6..94d3cdfbf9b8 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -941,13 +941,12 @@ __linvfs_get_block( int retpbbm = 1; int error; - if (blocks) { - offset = blocks << inode->i_blkbits; /* 64 bit goodness */ - size = (ssize_t) min_t(xfs_off_t, offset, LONG_MAX); - } else { - size = 1 << inode->i_blkbits; - } offset = (xfs_off_t)iblock << inode->i_blkbits; + if (blocks) + size = (ssize_t) min_t(xfs_off_t, LONG_MAX, + (xfs_off_t)blocks << inode->i_blkbits); + else + size = 1 << inode->i_blkbits; VOP_BMAP(vp, offset, size, create ? flags : BMAPI_READ, &iomap, &retpbbm, error); @@ -1007,7 +1006,7 @@ __linvfs_get_block( ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0); offset = min_t(xfs_off_t, iomap.iomap_bsize - iomap.iomap_delta, - blocks << inode->i_blkbits); + (xfs_off_t)blocks << inode->i_blkbits); bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset); } From 6b2cf618cc8445a03640d1e5e36829352e297017 Mon Sep 17 00:00:00 2001 From: Felix Blyakher Date: Fri, 25 Nov 2005 16:42:13 +1100 Subject: [PATCH 090/101] [XFS] Tight loop in xfs_finish_reclaim_all prevented the xfslogd to run its queue of IO completion callbacks, thus creating the deadlock between umount and xfslogd. Breaking the loop solves the problem. SGI-PV: 943821 SGI-Modid: xfs-linux-melb:xfs-kern:202363a Signed-off-by: Felix Blyakher Signed-off-by: Nathan Scott --- fs/xfs/xfs_vnodeops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7c1f74531463..e03fa2a3d5ed 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -3958,8 +3958,9 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock) } } XFS_MOUNT_IUNLOCK(mp); - xfs_finish_reclaim(ip, noblock, - XFS_IFLUSH_DELWRI_ELSE_ASYNC); + if (xfs_finish_reclaim(ip, noblock, + XFS_IFLUSH_DELWRI_ELSE_ASYNC)) + delay(1); purged = 1; break; } From e0144ca55391556d781cb1c90fd6f00bb0c20760 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 25 Nov 2005 16:42:22 +1100 Subject: [PATCH 091/101] [XFS] Fix a case where attr2 format was being used unconditionally. SGI-PV: 941645 SGI-Modid: xfs-linux-melb:xfs-kern:24566a Signed-off-by: Nathan Scott --- fs/xfs/xfs_attr_leaf.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 35e557b00db2..1c7421840c18 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -310,7 +310,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) * Fix up the start offset of the attribute fork */ totsize -= size; - if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname) { + if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && + !(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { /* * Last attribute now removed, revert to original * inode format making all literal area available @@ -328,7 +329,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); ASSERT(dp->i_d.di_forkoff); - ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname); + ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || + (mp->m_flags & XFS_MOUNT_COMPAT_ATTR)); dp->i_afp->if_ext_max = XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); dp->i_df.if_ext_max = @@ -737,7 +739,8 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) + name_loc->namelen + INT_GET(name_loc->valuelen, ARCH_CONVERT); } - if (bytes == sizeof(struct xfs_attr_sf_hdr)) + if (!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR) && + (bytes == sizeof(struct xfs_attr_sf_hdr))) return(-1); return(xfs_attr_shortform_bytesfit(dp, bytes)); } @@ -775,6 +778,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) goto out; if (forkoff == -1) { + ASSERT(!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR)); + /* * Last attribute was removed, revert to original * inode format making all literal area available From 551c81e2d32c5867fb592091365d8c37e1509dce Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 25 Nov 2005 16:42:28 +1100 Subject: [PATCH 092/101] [XFS] Resolve the xlog_grant_log_space hang, revert inline to macro. SGI-PV: 946205 SGI-Modid: xfs-linux-melb:xfs-kern:24567a Signed-off-by: Nathan Scott --- fs/xfs/xfs_log_priv.h | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 8f285149681f..4518b188ade6 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -494,10 +494,8 @@ typedef struct log { #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) -#define XLOG_GRANT_SUB_SPACE(log,bytes,type) \ - xlog_grant_sub_space(log,bytes,type) -static inline void xlog_grant_sub_space(struct log *log, int bytes, int type) -{ +#define XLOG_GRANT_SUB_SPACE(log,bytes,type) \ + { \ if (type == 'w') { \ (log)->l_grant_write_bytes -= (bytes); \ if ((log)->l_grant_write_bytes < 0) { \ @@ -511,13 +509,9 @@ static inline void xlog_grant_sub_space(struct log *log, int bytes, int type) (log)->l_grant_reserve_cycle--; \ } \ } \ -} - -#define XLOG_GRANT_ADD_SPACE(log,bytes,type) \ - xlog_grant_add_space(log,bytes,type) -static inline void -xlog_grant_add_space(struct log *log, int bytes, int type) -{ + } +#define XLOG_GRANT_ADD_SPACE(log,bytes,type) \ + { \ if (type == 'w') { \ (log)->l_grant_write_bytes += (bytes); \ if ((log)->l_grant_write_bytes > (log)->l_logsize) { \ @@ -531,12 +525,9 @@ xlog_grant_add_space(struct log *log, int bytes, int type) (log)->l_grant_reserve_cycle++; \ } \ } \ -} - -#define XLOG_INS_TICKETQ(q, tic) xlog_ins_ticketq(q, tic) -static inline void -xlog_ins_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) -{ \ + } +#define XLOG_INS_TICKETQ(q, tic) \ + { \ if (q) { \ (tic)->t_next = (q); \ (tic)->t_prev = (q)->t_prev; \ @@ -547,12 +538,9 @@ xlog_ins_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) (q) = (tic); \ } \ (tic)->t_flags |= XLOG_TIC_IN_Q; \ -} - -#define XLOG_DEL_TICKETQ(q, tic) xlog_del_ticketq(q, tic) -static inline void -xlog_del_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) -{ \ + } +#define XLOG_DEL_TICKETQ(q, tic) \ + { \ if ((tic) == (tic)->t_next) { \ (q) = NULL; \ } else { \ @@ -562,7 +550,7 @@ xlog_del_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) } \ (tic)->t_next = (tic)->t_prev = NULL; \ (tic)->t_flags &= ~XLOG_TIC_IN_Q; \ -} + } /* common routines */ extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); From 55bb239e5464ecde046af3e45052ef06efda6444 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 22 Nov 2005 12:05:26 +1100 Subject: [PATCH 093/101] [PATCH] powerpc: remove arch/powerpc/include hack for 64 bit With the removal of include/asm-powerpc, we no longer need arch/powerpc/include/asm for the 64 bit build. We also do not need -Iarch/powerpc for the 64 bit build either. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/Makefile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 98f67c78d1bd..a13eb575f834 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -61,15 +61,17 @@ endif LDFLAGS_vmlinux := -Bstatic # The -Iarch/$(ARCH)/include is temporary while we are merging -CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include -AFLAGS += -Iarch/$(ARCH) -CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe +CPPFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -Iarch/$(ARCH)/include +AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc -CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple -CFLAGS += $(CFLAGS-y) +CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple +CPPFLAGS += $(CPPFLAGS-y) +AFLAGS += $(AFLAGS-y) +CFLAGS += -msoft-float -pipe $(CFLAGS-y) CPP = $(CC) -E $(CFLAGS) # Temporary hack until we have migrated to asm-powerpc -LINUXINCLUDE += -Iarch/$(ARCH)/include +LINUXINCLUDE-$(CONFIG_PPC32) := -Iarch/$(ARCH)/include +LINUXINCLUDE += $(LINUXINCLUDE-y) CHECKFLAGS += -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__ @@ -173,11 +175,13 @@ archclean: archprepare: checkbin +ifeq ($(CONFIG_PPC32),y) # Temporary hack until we have migrated to asm-powerpc include/asm: arch/$(ARCH)/include/asm arch/$(ARCH)/include/asm: FORCE $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi $(Q)ln -fsn $(srctree)/include/asm-$(OLDARCH) arch/$(ARCH)/include/asm +endif # Use the file '.tmp_gas_check' for binutils tests, as gas won't output # to stdout and these checks are run even on install targets. From 9a94c5793a7b44720f19ebb71b636bc9c31b44d8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Thu, 24 Nov 2005 13:34:56 +1100 Subject: [PATCH 094/101] [PATCH] powerpc: More hugepage boundary case fixes Blah. The patch [0] I recently sent fixing errors with in_hugepage_area() and prepare_hugepage_range() for powerpc itself has an off-by-one bug. Furthermore, the related functions touches_hugepage_*_range() and within_hugepage_*_range() are also buggy. Some of the bugs, like those addressed in [0] originated with commit 7d24f0b8a53261709938ffabe3e00f88f6498df9 where we tweaked the semantics of where hugepages are allowed. Other bugs have been there essentially forever, and are due to the undefined behaviour of '<<' with shift counts greater than the type width (LOW_ESID_MASK could return non-zero for high ranges with the right congruences). The good news is that I now have a testsuite which should pick up things like this if they creep in again. [0] "powerpc-fix-for-hugepage-areas-straddling-4gb-boundary" Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hugetlbpage.c | 2 +- include/asm-powerpc/page_64.h | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index f867bba893ca..6bc9dbad7dea 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -295,7 +295,7 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len) if (addr < 0x100000000UL) err = open_low_hpage_areas(current->mm, LOW_ESID_MASK(addr, len)); - if ((addr + len) >= 0x100000000UL) + if ((addr + len) > 0x100000000UL) err = open_high_hpage_areas(current->mm, HTLB_AREA_MASK(addr, len)); if (err) { diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h index 58a3dd9a79ec..6642c0125001 100644 --- a/include/asm-powerpc/page_64.h +++ b/include/asm-powerpc/page_64.h @@ -103,8 +103,9 @@ extern unsigned int HPAGE_SHIFT; #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) -#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ - - (1U << GET_ESID(addr))) & 0xffff) +#define LOW_ESID_MASK(addr, len) \ + (((1U << (GET_ESID(min((addr)+(len)-1, 0x100000000UL))+1)) \ + - (1U << GET_ESID(min((addr), 0x100000000UL)))) & 0xffff) #define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ - (1U << GET_HTLB_AREA(addr))) & 0xffff) @@ -113,17 +114,21 @@ extern unsigned int HPAGE_SHIFT; #define ARCH_HAS_SETCLEAR_HUGE_PTE #define touches_hugepage_low_range(mm, addr, len) \ - (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas) + (((addr) < 0x100000000UL) \ + && (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas)) #define touches_hugepage_high_range(mm, addr, len) \ - (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas) + ((((addr) + (len)) > 0x100000000UL) \ + && (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas)) #define __within_hugepage_low_range(addr, len, segmask) \ - ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) + ( (((addr)+(len)) <= 0x100000000UL) \ + && ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask))) #define within_hugepage_low_range(addr, len) \ __within_hugepage_low_range((addr), (len), \ current->mm->context.low_htlb_areas) #define __within_hugepage_high_range(addr, len, zonemask) \ - ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)) + ( ((addr) >= 0x100000000UL) \ + && ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask))) #define within_hugepage_high_range(addr, len) \ __within_hugepage_high_range((addr), (len), \ current->mm->context.high_htlb_areas) From 36f20c6df75d599393d79c7feb6283b20913e3d5 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 25 Nov 2005 17:09:57 -0500 Subject: [PATCH 095/101] NFSv4: Fix buggy nfs_wait_on_sequence() Signed-off-by: Trond Myklebust --- fs/nfs/nfs4state.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 0675f3215e0a..5ef4c57618fe 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -644,12 +644,15 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) { + struct rpc_sequence *sequence = counter->sequence; struct nfs_seqid *new; new = kmalloc(sizeof(*new), GFP_KERNEL); if (new != NULL) { new->sequence = counter; - INIT_LIST_HEAD(&new->list); + spin_lock(&sequence->lock); + list_add_tail(&new->list, &sequence->list); + spin_unlock(&sequence->lock); } return new; } @@ -658,12 +661,10 @@ void nfs_free_seqid(struct nfs_seqid *seqid) { struct rpc_sequence *sequence = seqid->sequence->sequence; - if (!list_empty(&seqid->list)) { - spin_lock(&sequence->lock); - list_del(&seqid->list); - spin_unlock(&sequence->lock); - } - rpc_wake_up_next(&sequence->wait); + spin_lock(&sequence->lock); + list_del(&seqid->list); + spin_unlock(&sequence->lock); + rpc_wake_up(&sequence->wait); kfree(seqid); } @@ -722,11 +723,10 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) if (sequence->list.next == &seqid->list) goto out; spin_lock(&sequence->lock); - if (!list_empty(&sequence->list)) { + if (sequence->list.next != &seqid->list) { rpc_sleep_on(&sequence->wait, task, NULL, NULL); status = -EAGAIN; - } else - list_add(&seqid->list, &sequence->list); + } spin_unlock(&sequence->lock); out: return status; From ff6040667ad5a21fa1090e02941ecefb94ebe32c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 25 Nov 2005 17:10:01 -0500 Subject: [PATCH 096/101] NFSv4: Fix typo in lock caching When caching locks due to holding a file delegation, we must always check against local locks before sending anything to the server. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 21482b2518f6..60e0dd800cc3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3071,15 +3071,15 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock struct nfs4_client *clp = state->owner->so_client; int status; - down_read(&clp->cl_sem); /* Is this a delegated open? */ - if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { + if (NFS_I(state->inode)->delegation_state != 0) { /* Yes: cache locks! */ status = do_vfs_lock(request->fl_file, request); /* ...but avoid races with delegation recall... */ if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) - goto out; + return status; } + down_read(&clp->cl_sem); status = nfs4_set_lock_state(state, request); if (status != 0) goto out; From b37b03b7051493c9f9a6b336c9c0f81334885b7d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 25 Nov 2005 17:10:06 -0500 Subject: [PATCH 097/101] NFS: Fix a spinlock recursion inside nfs_update_inode() In cases where the server has gone insane, nfs_update_inode() may end up calling nfs_invalidate_inode(), which again calls stuff that takes the inode->i_lock that we're already holding. In addition, given the sort of things we have in NFS these days that need to be cleaned up on inode release, I'm not sure we should ever be calling make_bad_inode(). Fix up spinlock recursion, and limit nfs_invalidate_inode() to clearing the caches, and marking the inode as being stale. Thanks to Steve Dickson for spotting this. Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6391d8964214..aaab1a5ac461 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -643,14 +643,11 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) /* * Invalidate the local caches */ -void -nfs_zap_caches(struct inode *inode) +static void nfs_zap_caches_locked(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); int mode = inode->i_mode; - spin_lock(&inode->i_lock); - NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); NFS_ATTRTIMEO_UPDATE(inode) = jiffies; @@ -659,7 +656,12 @@ nfs_zap_caches(struct inode *inode) nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; else nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; +} +void nfs_zap_caches(struct inode *inode) +{ + spin_lock(&inode->i_lock); + nfs_zap_caches_locked(inode); spin_unlock(&inode->i_lock); } @@ -676,16 +678,13 @@ static void nfs_zap_acl_cache(struct inode *inode) } /* - * Invalidate, but do not unhash, the inode + * Invalidate, but do not unhash, the inode. + * NB: must be called with inode->i_lock held! */ -static void -nfs_invalidate_inode(struct inode *inode) +static void nfs_invalidate_inode(struct inode *inode) { - umode_t save_mode = inode->i_mode; - - make_bad_inode(inode); - inode->i_mode = save_mode; - nfs_zap_caches(inode); + set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); + nfs_zap_caches_locked(inode); } struct nfs_find_desc { @@ -1528,14 +1527,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); #endif + out_err: /* * No need to worry about unhashing the dentry, as the * lookup validation will know that the inode is bad. * (But we fall through to invalidate the caches.) */ nfs_invalidate_inode(inode); - out_err: - set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); return -ESTALE; } From b3eb67a2ab4e14fc6cc035907400b86462d174db Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 25 Nov 2005 17:10:11 -0500 Subject: [PATCH 098/101] SUNRPC: Funny looking code in __rpc_purge_upcall In __rpc_purge_upcall (net/sunrpc/rpc_pipe.c), the newer code to clean up the in_upcall list has a typo. Thanks to Vince Busam for spotting this! Signed-off-by: Trond Myklebust --- net/sunrpc/rpc_pipe.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 81e00a6c19de..e3b242daf53c 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -38,24 +38,28 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly; #define RPC_UPCALL_TIMEOUT (30*HZ) +static void +__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err) +{ + struct rpc_pipe_msg *msg; + void (*destroy_msg)(struct rpc_pipe_msg *); + + destroy_msg = rpci->ops->destroy_msg; + while (!list_empty(head)) { + msg = list_entry(head->next, struct rpc_pipe_msg, list); + list_del_init(&msg->list); + msg->errno = err; + destroy_msg(msg); + } +} + static void __rpc_purge_upcall(struct inode *inode, int err) { struct rpc_inode *rpci = RPC_I(inode); - struct rpc_pipe_msg *msg; - while (!list_empty(&rpci->pipe)) { - msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list); - list_del_init(&msg->list); - msg->errno = err; - rpci->ops->destroy_msg(msg); - } - while (!list_empty(&rpci->in_upcall)) { - msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list); - list_del_init(&msg->list); - msg->errno = err; - rpci->ops->destroy_msg(msg); - } + __rpc_purge_list(rpci, &rpci->pipe, err); + __rpc_purge_list(rpci, &rpci->in_upcall, err); rpci->pipelen = 0; wake_up(&rpci->waitq); } From 16a631733135a625dd8bc83207553aaf34c0a72c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 27 Nov 2005 00:37:05 +0100 Subject: [PATCH 099/101] [PATCH] drivers/message/i2o/pci.c: fix a NULL pointer dereference The Coverity checker spotted this obvious NULL pointer dereference. Signed-off-by: Adrian Bunk Acked-by: Markus Lidel Signed-off-by: Linus Torvalds --- drivers/message/i2o/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 66c03e882570..81ef306cb124 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -421,8 +421,8 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, i2o_pci_free(c); free_controller: - i2o_iop_free(c); put_device(c->device.parent); + i2o_iop_free(c); disable: pci_disable_device(pdev); From 2012a116d9e6803fb072d0cfe1aae0cc4e6d6416 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 27 Nov 2005 00:37:36 +0100 Subject: [PATCH 100/101] [PATCH] drivers/infiniband/core/mad.c: fix use-after-release case The Coverity checker spotted this obvious use-after-release bug caused by a wrong order of the cleanups. Signed-off-by: Adrian Bunk Signed-off-by: Linus Torvalds --- drivers/infiniband/core/mad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 41d6b4017acb..d393b504bf26 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -355,9 +355,9 @@ error4: spin_unlock_irqrestore(&port_priv->reg_lock, flags); kfree(reg_req); error3: - kfree(mad_agent_priv); -error2: ib_dereg_mr(mad_agent_priv->agent.mr); +error2: + kfree(mad_agent_priv); error1: return ret; } From 458af5439fe7ae7d95ca14106844e61f0795166c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 27 Nov 2005 00:36:37 +0100 Subject: [PATCH 101/101] [PATCH] drivers/scsi/dpt_i2o.c: fix a NULL pointer dereference The Coverity checker spotted this obvious NULL pointer dereference. Signed-off-by: Adrian Bunk Acked-by: Mark Salyzyn Signed-off-by: Linus Torvalds --- drivers/scsi/dpt_i2o.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index c28e3aea1c3c..418fc7b896ac 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -816,7 +816,7 @@ static int adpt_hba_reset(adpt_hba* pHba) static void adpt_i2o_sys_shutdown(void) { adpt_hba *pHba, *pNext; - struct adpt_i2o_post_wait_data *p1, *p2; + struct adpt_i2o_post_wait_data *p1, *old; printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n"); printk(KERN_INFO" This could take a few minutes if there are many devices attached\n"); @@ -830,13 +830,14 @@ static void adpt_i2o_sys_shutdown(void) } /* Remove any timedout entries from the wait queue. */ - p2 = NULL; // spin_lock_irqsave(&adpt_post_wait_lock, flags); /* Nothing should be outstanding at this point so just * free them */ - for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p2->next) { - kfree(p1); + for(p1 = adpt_post_wait_queue; p1;) { + old = p1; + p1 = p1->next; + kfree(old); } // spin_unlock_irqrestore(&adpt_post_wait_lock, flags); adpt_post_wait_queue = NULL;