From 3abb92722ab1784b419dadb5444daf8ea9636905 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 28 Nov 2005 08:16:13 -0800 Subject: [PATCH 01/71] [CIFS] When file is deleted locally but later recreated on the server fix cifs negative dentries so they are freed faster (not requiring umount or readdir e.g.) so the client recognizes the new file on the server more quickly. Signed-off-by: Steve French --- fs/cifs/CHANGES | 8 +++++--- fs/cifs/dir.c | 25 ++++++++++++++++--------- fs/cifs/inode.c | 22 ++++++++++++++-------- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 6bded10c0d50..c40bd0df80ad 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,10 +1,12 @@ Version 1.39 ------------ -Defer close of a file handle slightly if pending writes depend on that file handle +Defer close of a file handle slightly if pending writes depend on that handle (this reduces the EBADF bad file handle errors that can be logged under heavy stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 -Fix SFU style symlinks and mknod needed for servers which do not support the CIFS -Unix Extensions. Fix setfacl/getfacl on bigendian. +Fix SFU style symlinks and mknod needed for servers which do not support the +CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative +dentries so files that the client sees as deleted but that later get created +on the server will be recognized. Version 1.38 ------------ diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 16b21522e8fe..aa4ea965b329 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -465,12 +465,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name direntry->d_op = &cifs_dentry_ops; d_add(direntry, newInode); - /* since paths are not looked up by component - the parent directories are presumed to be good here */ + /* since paths are not looked up by component - the parent + directories are presumed to be good here */ renew_parental_timestamps(direntry); } else if (rc == -ENOENT) { rc = 0; + direntry->d_time = jiffies; + if (pTcon->nocase) + direntry->d_op = &cifs_ci_dentry_ops; + else + direntry->d_op = &cifs_dentry_ops; d_add(direntry, NULL); + /* if it was once a directory (but how can we tell?) we could do + shrink_dcache_parent(direntry); */ } else { cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", rc,full_path)); @@ -489,21 +497,20 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) { int isValid = 1; -/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ - if (direntry->d_inode) { if (cifs_revalidate(direntry)) { - /* unlock_kernel(); */ return 0; } } else { - cFYI(1, - ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p", - direntry->d_name.name, direntry)); + cFYI(1, ("neg dentry 0x%p name = %s", + direntry, direntry->d_name.name)); + if(time_after(jiffies, direntry->d_time + HZ) || + !lookupCacheEnabled) { + d_drop(direntry); + isValid = 0; + } } -/* unlock_kernel(); */ - return isValid; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 05b525812adb..d34325c887c4 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1039,14 +1039,20 @@ int cifs_revalidate(struct dentry *direntry) filemap_fdatawrite(direntry->d_inode->i_mapping); } if (invalidate_inode) { - if (direntry->d_inode->i_mapping) - filemap_fdatawait(direntry->d_inode->i_mapping); - /* may eventually have to do this for open files too */ - if (list_empty(&(cifsInode->openFileList))) { - /* Has changed on server - flush read ahead pages */ - cFYI(1, ("Invalidating read ahead data on " - "closed file")); - invalidate_remote_inode(direntry->d_inode); + /* shrink_dcache not necessary now that cifs dentry ops + are exported for negative dentries */ +/* if(S_ISDIR(direntry->d_inode->i_mode)) + shrink_dcache_parent(direntry); */ + if (S_ISREG(direntry->d_inode->i_mode)) { + if (direntry->d_inode->i_mapping) + filemap_fdatawait(direntry->d_inode->i_mapping); + /* may eventually have to do this for open files too */ + if (list_empty(&(cifsInode->openFileList))) { + /* changed on server - flush read ahead pages */ + cFYI(1, ("Invalidating read ahead data on " + "closed file")); + invalidate_remote_inode(direntry->d_inode); + } } } /* up(&direntry->d_inode->i_sem); */ From 0e2d94f6a09d0a2d39c3b7d9529ac5c378098245 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 29 Nov 2005 08:02:24 +1100 Subject: [PATCH 02/71] [PATCH] ppc: Export symbol needed by MOL Export symbol needed to allow MOL to run. This was changed to be inline in past and forgot to be change here. Signed-off-by: Paul Mackerras --- arch/ppc/kernel/ppc_ksyms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 66073f775193..bb6a5c6a64be 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -184,7 +184,7 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(flush_instruction_cache); EXPORT_SYMBOL(giveup_fpu); -EXPORT_SYMBOL(flush_icache_range); +EXPORT_SYMBOL(__flush_icache_range); EXPORT_SYMBOL(flush_dcache_range); EXPORT_SYMBOL(flush_icache_user_range); EXPORT_SYMBOL(flush_dcache_page); From 666acb94d155106e494c6dfdd8b2fae44e0fad61 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 29 Nov 2005 15:50:58 +1100 Subject: [PATCH 03/71] powerpc: Export __flush_icache_range for 32-bit Both 32-bit and 64-bit use the same inline flush_icache_range definition now, so both need to export __flush_icache_range, not just 64-bit. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ppc_ksyms.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index af4d1bc9a2eb..94db25708456 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -163,15 +163,13 @@ EXPORT_SYMBOL(giveup_altivec); EXPORT_SYMBOL(giveup_spe); #endif /* CONFIG_SPE */ -#ifdef CONFIG_PPC64 -EXPORT_SYMBOL(__flush_icache_range); -#else +#ifndef CONFIG_PPC64 EXPORT_SYMBOL(flush_instruction_cache); -EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(flush_tlb_kernel_range); EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(_tlbie); #endif +EXPORT_SYMBOL(__flush_icache_range); EXPORT_SYMBOL(flush_dcache_range); #ifdef CONFIG_SMP From 220bbd748335f73aafb472a97716762a42cb0d58 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 28 Nov 2005 22:27:11 -0800 Subject: [PATCH 04/71] [IPV6]: Implement appropriate dummy rule 4 in ipv6_dev_get_saddr(). Ensure to update hiscore.rule in dummy rule 4 in ipv6_dev_get_saddr(). Pointed out by Yan Zheng . Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a16064ba0caf..76ff9f4fe89d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -985,6 +985,8 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, } /* Rule 4: Prefer home address -- not implemented yet */ + if (hiscore.rule < 4) + hiscore.rule++; /* Rule 5: Prefer outgoing interface */ if (hiscore.rule < 5) { From bc4117f8767203927e78b92e9e5b3ddb71d6a84d Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 29 Nov 2005 11:48:00 +0000 Subject: [PATCH 05/71] [MTD] RFD_FTL: Use lanana assigned major device number A major block device number is now assigned by lanana. Signed-off-by: Sean Young Signed-off-by: Thomas Gleixner --- drivers/mtd/rfd_ftl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 0ab8d29caeea..20ce212638fc 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -30,11 +30,9 @@ MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit s #define PREFIX "rfd_ftl: " -/* Major device # for FTL device */ - -/* A request for this major has been sent to device@lanana.org */ +/* This major has been assigned by device@lanana.org */ #ifndef RFD_FTL_MAJOR -#define RFD_FTL_MAJOR 95 +#define RFD_FTL_MAJOR 256 #endif /* Maximum number of partitions in an FTL region */ From fa2a455b028f3b6ca4dae129c6337d7edf21f12c Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 29 Nov 2005 18:43:17 +1100 Subject: [PATCH 06/71] [PATCH] Fix vma argument in get_usr_pages() for gate areas The system call gate area handling called vm_normal_page() with the wrong vma (which was always NULL, and caused an oops). Signed-off-by: Nick Piggin 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 9ab206b829a2..6c1eac92a316 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -988,7 +988,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, return i ? : -EFAULT; } if (pages) { - struct page *page = vm_normal_page(vma, start, *pte); + struct page *page = vm_normal_page(gate_vma, start, *pte); pages[i] = page; if (page) get_page(page); From 21eeb7aa116b1f59fc23339521173cbb13e57f1a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 29 Nov 2005 16:57:17 +0100 Subject: [PATCH 07/71] [JFFS2] Fix the slab cache constructor of 'struct jffs2_inode_info' objects. JFFS2 initialize f->sem mutex as "locked" in the slab constructor which is a bug. Objects are freed with unlocked f->sem mutex. So, when they allocated again, f->sem is unlocked because the slab cache constructor is not called for them. The constructor is called only once when memory pages are allocated for objects (namely, when the slab layer allocates new slabs). So, sometimes 'struct jffs2_inode_info' are allocated with unlocked f->sem, sometimes with locked. This is a bug. Instead, initialize f->sem as unlocked in the constructor. I.e., in the "constructed" state f->sem must be unlocked. From: Keijiro Yano Acked-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/fs.c | 2 ++ fs/jffs2/super.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 543420665c5b..d0fcc5f3497e 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -234,6 +234,7 @@ void jffs2_read_inode (struct inode *inode) c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); + down(&f->sem); ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); @@ -400,6 +401,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i f = JFFS2_INODE_INFO(inode); jffs2_init_inode_info(f); + down(&f->sem); memset(ri, 0, sizeof(*ri)); /* Set OS-specific defaults for new inodes */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9e0b5458d9c0..93883817cbd0 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -51,7 +51,7 @@ static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long f if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX_LOCKED(&ei->sem); + init_MUTEX(&ei->sem); inode_init_once(&ei->vfs_inode); } } From b77dae5293efba42ea1ff04d410ee68e66d5b0cf Mon Sep 17 00:00:00 2001 From: Dean Roe Date: Wed, 9 Nov 2005 14:25:06 -0600 Subject: [PATCH 08/71] [IA64] - Make pfn_valid more precise for SGI Altix systems A single SGI Altix system can be divided into multiple partitions, each running their own instance of the Linux kernel. pfn_valid() is currently not optimal for any but the first partition, since it does not compare the pfn with min_low_pfn before calling the more costly ia64_pfn_valid(). Signed-off-by: Dean Roe Signed-off-by: Tony Luck --- arch/ia64/kernel/ia64_ksyms.c | 1 + include/asm-ia64/page.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 01572814abe4..5db9d3bcbbcb 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -42,6 +42,7 @@ EXPORT_SYMBOL(clear_page); #ifdef CONFIG_VIRTUAL_MEM_MAP #include +EXPORT_SYMBOL(min_low_pfn); /* defined by bootmem.c, but not exported by generic code */ EXPORT_SYMBOL(max_low_pfn); /* defined by bootmem.c, but not exported by generic code */ #endif diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 9dd9da105278..5e6362a786b7 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -110,8 +110,9 @@ extern int ia64_pfn_valid (unsigned long pfn); # define pfn_to_page(pfn) (mem_map + (pfn)) #elif defined(CONFIG_DISCONTIGMEM) extern struct page *vmem_map; +extern unsigned long min_low_pfn; extern unsigned long max_low_pfn; -# define pfn_valid(pfn) (((pfn) < max_low_pfn) && ia64_pfn_valid(pfn)) +# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn) && ia64_pfn_valid(pfn)) # define page_to_pfn(page) ((unsigned long) (page - vmem_map)) # define pfn_to_page(pfn) (vmem_map + (pfn)) #endif From 5a94bcfd2a18edcf368b3128c7df07b58e529932 Mon Sep 17 00:00:00 2001 From: Keshavamurthy Anil S Date: Tue, 22 Nov 2005 14:15:49 -0800 Subject: [PATCH 09/71] [IA64] Remove getting break_num by decoding instruction break.b always sets cr.iim to 0 and the current code tries to get the break_num by decoding instruction. However, their seems to be a race condition while reading the regs->cr_iip, as on other cpu the break.b at regs->cr_iip might have been replaced with the original instruction as a result of unregister_kprobe() and hence decoding instruction to obtain break_num will result in wrong value in this case. Also includes changes to kprobes.c which now has to handle break number zero. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Tony Luck --- arch/ia64/kernel/kprobes.c | 2 +- arch/ia64/kernel/traps.c | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 801eeaeaf3de..2895d6e6062f 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -740,7 +740,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, switch(val) { case DIE_BREAK: /* err is break number from ia64_bad_break() */ - if (args->err == 0x80200 || args->err == 0x80300) + if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0) if (pre_kprobes_handler(args)) ret = NOTIFY_STOP; break; diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index fba5fdd1f968..d3e0ecb56d62 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -132,24 +132,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) siginfo_t siginfo; int sig, code; - /* break.b always sets cr.iim to 0, which causes problems for - * debuggers. Get the real break number from the original instruction, - * but only for kernel code. User space break.b is left alone, to - * preserve the existing behaviour. All break codings have the same - * format, so there is no need to check the slot type. - */ - if (break_num == 0 && !user_mode(regs)) { - struct ia64_psr *ipsr = ia64_psr(regs); - unsigned long *bundle = (unsigned long *)regs->cr_iip; - unsigned long slot; - switch (ipsr->ri) { - case 0: slot = (bundle[0] >> 5); break; - case 1: slot = (bundle[0] >> 46) | (bundle[1] << 18); break; - default: slot = (bundle[1] >> 23); break; - } - break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff); - } - /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_imm = break_num; From 3eb8ceac486ed9b6eceed098423f1ca6b180ec9d Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 14 Nov 2005 13:41:51 +0000 Subject: [PATCH 10/71] [MTD] devices/ms02-nv: phys/virt address fixups Merge from linux-mips: Use physical addresses at the interface level, letting drivers remap them as appropriate. Signed-off-by: Maciej W. Rozycki Signed-off-by: Thomas Gleixner --- drivers/mtd/devices/ms02-nv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index f5026cee087f..0ff2e4378244 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c @@ -6,7 +6,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: ms02-nv.c,v 1.10 2005/06/20 12:24:41 macro Exp $ + * $Id: ms02-nv.c,v 1.11 2005/11/14 13:41:47 macro Exp $ */ #include @@ -293,13 +293,13 @@ static int __init ms02nv_init(void) switch (mips_machtype) { case MACH_DS5000_200: - csr = (volatile u32 *)KN02_CSR_BASE; + csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR); if (*csr & KN02_CSR_BNK32M) stride = 2; break; case MACH_DS5000_2X0: case MACH_DS5900: - csr = (volatile u32 *)KN03_MCR_BASE; + csr = (volatile u32 *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_MCR); if (*csr & KN03_MCR_BNK32M) stride = 2; break; From 987d24018dc83d27e491674c50ff2272f51eb719 Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Tue, 15 Nov 2005 23:28:20 +0000 Subject: [PATCH 11/71] [MTD] CFI: Use 16-bit access to autoselect/read device id data Recent models of Intel/Sharp and Spansion CFI flash now have significant bits in the upper byte of device ID codes, read via what Spansion calls "autoselect" and Intel calls "read device identifier". Currently these values are truncated to the low 8 bits in the mtd data structures, as all CFI read query info has previously been read one byte at a time. Add a new method for reading 16-bit info, currently just manufacturer and device codes; datasheets hint at future uses for upper bytes in other fields. Signed-off-by: Todd Poynor Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_probe.c | 6 +++--- include/linux/mtd/cfi.h | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 90eb30e06b7c..d65ccdebbda4 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.84 2005/11/07 11:14:23 gleixner Exp $ + $Id: cfi_probe.c,v 1.85 2005/11/15 23:28:17 tpoynor Exp $ */ #include @@ -230,8 +230,8 @@ static int __xipram cfi_chip_setup(struct map_info *map, cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); - cfi->mfr = cfi_read_query(map, base); - cfi->id = cfi_read_query(map, base + ofs_factor); + cfi->mfr = cfi_read_query16(map, base); + cfi->id = cfi_read_query16(map, base + ofs_factor); /* Put it back into Read Mode */ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 3c9ea4b7adda..23a568910341 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.56 2005/11/07 11:14:54 gleixner Exp $ + * $Id: cfi.h,v 1.57 2005/11/15 23:28:17 tpoynor Exp $ */ #ifndef __MTD_CFI_H__ @@ -426,6 +426,22 @@ static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr) } } +static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr) +{ + map_word val = map_read(map, addr); + + if (map_bankwidth_is_1(map)) { + return val.x[0] & 0xff; + } else if (map_bankwidth_is_2(map)) { + return cfi16_to_cpu(val.x[0]); + } else { + /* No point in a 64-bit byteswap since that would just be + swapping the responses from different chips, and we are + only interested in one chip (a representative sample) */ + return cfi32_to_cpu(val.x[0]); + } +} + static inline void cfi_udelay(int us) { if (us >= 1000) { From 3c77354794939143fdf1dd669895a812f94f9a38 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 16 Nov 2005 16:23:25 +0000 Subject: [PATCH 12/71] [MTD] maps/ixp4xx: half-word boundary and little-endian fixups ixp4xx updates: - Handle reads that don't start on a half-word boundary. - Make it work when CPU is in little-endian mode. Signed-off-by: John Bowler Signed-off-by: Alessandro Zummo Signed-off-by: David Vrabel Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/ixp4xx.c | 78 +++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index a59f8027903c..986c58628390 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -1,5 +1,5 @@ /* - * $Id: ixp4xx.c,v 1.12 2005/11/07 11:14:27 gleixner Exp $ + * $Id: ixp4xx.c,v 1.13 2005/11/16 16:23:21 dvrabel Exp $ * * drivers/mtd/maps/ixp4xx.c * @@ -34,10 +34,55 @@ #include +/* + * Read/write a 16 bit word from flash address 'addr'. + * + * When the cpu is in little-endian mode it swizzles the address lines + * ('address coherency') so we need to undo the swizzling to ensure commands + * and the like end up on the correct flash address. + * + * To further complicate matters, due to the way the expansion bus controller + * handles 32 bit reads, the byte stream ABCD is stored on the flash as: + * D15 D0 + * +---+---+ + * | A | B | 0 + * +---+---+ + * | C | D | 2 + * +---+---+ + * This means that on LE systems each 16 bit word must be swapped. Note that + * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI + * data and other flash commands which are always in D7-D0. + */ #ifndef __ARMEB__ +#ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP +# error CONFIG_MTD_CFI_BE_BYTE_SWAP required +#endif + +static inline u16 flash_read16(void __iomem *addr) +{ + return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2))); +} + +static inline void flash_write16(u16 d, void __iomem *addr) +{ + __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2)); +} + #define BYTE0(h) ((h) & 0xFF) #define BYTE1(h) (((h) >> 8) & 0xFF) + #else + +static inline u16 flash_read16(const void __iomem *addr) +{ + return __raw_readw(addr); +} + +static inline void flash_write16(u16 d, void __iomem *addr) +{ + __raw_writew(d, addr); +} + #define BYTE0(h) (((h) >> 8) & 0xFF) #define BYTE1(h) ((h) & 0xFF) #endif @@ -45,7 +90,7 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) { map_word val; - val.x[0] = le16_to_cpu(readw(map->virt + ofs)); + val.x[0] = flash_read16(map->virt + ofs); return val; } @@ -57,19 +102,28 @@ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs) static void ixp4xx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - int i; u8 *dest = (u8 *) to; void __iomem *src = map->virt + from; - u16 data; - for (i = 0; i < (len / 2); i++) { - data = le16_to_cpu(readw(src + 2*i)); - dest[i * 2] = BYTE0(data); - dest[i * 2 + 1] = BYTE1(data); + if (len <= 0) + return; + + if (from & 1) { + *dest++ = BYTE1(flash_read16(src)); + src++; + --len; } - if (len & 1) - dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i))); + while (len >= 2) { + u16 data = flash_read16(src); + *dest++ = BYTE0(data); + *dest++ = BYTE1(data); + src += 2; + len -= 2; + } + + if (len > 0) + *dest++ = BYTE0(flash_read16(src)); } /* @@ -79,7 +133,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr) { if (!(adr & 1)) - writew(cpu_to_le16(d.x[0]), map->virt + adr); + flash_write16(d.x[0], map->virt + adr); } /* @@ -87,7 +141,7 @@ static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long */ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr) { - writew(cpu_to_le16(d.x[0]), map->virt + adr); + flash_write16(d.x[0], map->virt + adr); } struct ixp4xx_flash_info { From 7ac571f8d0f843fb818f7c70ec77784545e91bc4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 17 Nov 2005 08:20:31 +0000 Subject: [PATCH 13/71] [MTD] Make some tables 'const' so they can live in .rodata arjan: drivers/mtd/maps/sc520cdp.c:167: warning: par_table is never written to and should be declared 'const' arjan: drivers/mtd/maps/pci.c:105: warning: mtd_pci_map is never written to and should be declared 'const' arjan: mind fixing those up ? Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/pci.c | 4 ++-- drivers/mtd/maps/sc520cdp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 8b3570b09095..21822c2edbe4 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: pci.c,v 1.13 2005/11/07 11:14:27 gleixner Exp $ + * $Id: pci.c,v 1.14 2005/11/17 08:20:27 dwmw2 Exp $ * * Generic PCI memory map driver. We support the following boards: * - Intel IQ80310 ATU. @@ -102,7 +102,7 @@ static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void * memcpy_toio(map->base + map->translate(map, to), from, len); } -static struct map_info mtd_pci_map = { +static const struct map_info mtd_pci_map = { .phys = NO_XIP, .copy_from = mtd_pci_copyfrom, .copy_to = mtd_pci_copyto, diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 6fb9f3c57aab..ed92afadd8a9 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: sc520cdp.c,v 1.22 2005/11/07 11:14:28 gleixner Exp $ + * $Id: sc520cdp.c,v 1.23 2005/11/17 08:20:27 dwmw2 Exp $ * * * The SC520CDP is an evaluation board for the Elan SC520 processor available @@ -164,7 +164,7 @@ struct sc520_par_table unsigned long default_address; }; -static struct sc520_par_table par_table[NUM_FLASH_BANKS] = +static const struct sc520_par_table par_table[NUM_FLASH_BANKS] = { { /* Flash Bank #0: selected by ROMCS0 */ SC520_PAR_ROMCS0, From 8bc3b3804a6123e634be26359558aa998102506a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 23 Nov 2005 22:07:56 +0000 Subject: [PATCH 14/71] [MTD] cfi_cmdset_0001: relax locking rules for multi hardware partition support Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 143f01a4c170..69c04945591f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.185 2005/11/07 11:14:22 gleixner Exp $ + * $Id: cfi_cmdset_0001.c,v 1.186 2005/11/23 22:07:52 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -644,9 +644,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr * * - contension arbitration is handled in the owner's context. * - * The 'shared' struct can be read when its lock is taken. - * However any writes to it can only be made when the current - * owner's lock is also held. + * The 'shared' struct can be read and/or written only when + * its lock is taken. */ struct flchip_shared *shared = chip->priv; struct flchip *contender; @@ -675,14 +674,13 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr } timeo = jiffies + HZ; spin_lock(&shared->lock); + spin_unlock(contender->mutex); } /* We now own it */ shared->writing = chip; if (mode == FL_ERASING) shared->erasing = chip; - if (contender && contender != chip) - spin_unlock(contender->mutex); spin_unlock(&shared->lock); } From e2602b347aa6f62b61754c5f65191ef67ffd0dc7 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 29 Nov 2005 14:30:03 +0000 Subject: [PATCH 15/71] [MTD] maps: sparse fixup The patch below fixes the following sparse warning: drivers/mtd/maps/nettel.c:482:27: warning: Using plain integer as NULL pointer Signed-off-by: Luiz Capitulino Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/nettel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index f00ee7e54dba..632eb2aa968f 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -6,7 +6,7 @@ * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) * - * $Id: nettel.c,v 1.11 2005/11/07 11:14:27 gleixner Exp $ + * $Id: nettel.c,v 1.12 2005/11/29 14:30:00 gleixner Exp $ */ /****************************************************************************/ @@ -479,7 +479,7 @@ void __exit nettel_cleanup(void) } if (nettel_intel_map.virt) { iounmap(nettel_intel_map.virt); - nettel_intel_map.virt = 0; + nettel_intel_map.virt = NULL; } #endif } From 72af3b2c5a9946e78125e143b636f3d7217bcf08 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 28 Nov 2005 22:36:12 +0000 Subject: [PATCH 16/71] [MTD] Remove bogus PQ2FADS driver Remove disfunctional driver, which slipped through the review mechanism Signed-off-by: Thomas Gleixner --- drivers/mtd/maps/Kconfig | 6 ------ drivers/mtd/maps/Makefile | 1 - 2 files changed, 7 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 846a533323a8..452ccd5037c3 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -538,12 +538,6 @@ config MTD_MPC1211 This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02). If you have such a board, say 'Y'. -config MTD_PQ2FADS - tristate "JEDEC flash SIMM mapped on PQ2FADS and 8272ADS boards" - depends on (ADS8272 || PQ2FADS) && MTD_PARTITIONS && MTD_JEDECPROBE && MTD_PHYSMAP && MTD_CFI_GEOMETRY && MTD_CFI_INTELEXT - help - This enables access to flash SIMM on PQ2FADS-like boards - config MTD_OMAP_NOR tristate "TI OMAP board mappings" depends on MTD_CFI && ARCH_OMAP diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 7d9e940a1dcd..2f7e254912f0 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -70,6 +70,5 @@ obj-$(CONFIG_MTD_DMV182) += dmv182.o obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o -obj-$(CONFIG_MTD_PQ2FADS) += pq2fads.o obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o obj-$(CONFIG_MTD_TQM834x) += tqm834x.o From ee2d49de3e3a0b846ecedb36fec0e4a5ff222dcb Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 29 Nov 2005 14:28:31 +0000 Subject: [PATCH 17/71] [MTD] chips: make sharps driver usable again Update the pre-CFI Sharp driver sharps.c so it compiles. map_read32 / map_write32 no longer exist in the kernel so the driver is totally broken as it stands. The replacement functions use different parameters resulting in the other changes. Change collie to use this driver until someone works out why the cfi driver fails on that machine. Signed-off-by: Richard Purdie Tested-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/sharp.c | 123 ++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 2d26bdef82d5..36f61a6a766e 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -4,7 +4,7 @@ * Copyright 2000,2001 David A. Schleef * 2000,2001 Lineo, Inc. * - * $Id: sharp.c,v 1.16 2005/11/07 11:14:23 gleixner Exp $ + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $ * * Devices supported: * LH28F016SCT Symmetrical block flash memory, 2Mx8 @@ -160,22 +160,28 @@ struct mtd_info *sharp_probe(struct map_info *map) return mtd; } +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr) +{ + map_word map_cmd; + map_cmd.x[0] = cmd; + map_write(map, map_cmd, adr); +} + static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) { - unsigned long tmp; + map_word tmp, read0, read4; unsigned long base = 0; - u32 read0, read4; int width = 4; - tmp = map_read32(map, base+0); + tmp = map_read(map, base+0); - map_write32(map, CMD_READ_ID, base+0); + sharp_send_cmd(map, CMD_READ_ID, base+0); - read0=map_read32(map, base+0); - read4=map_read32(map, base+4); - if(read0 == 0x89898989){ + read0 = map_read(map, base+0); + read4 = map_read(map, base+4); + if(read0.x[0] == 0x89898989){ printk("Looks like sharp flash\n"); - switch(read4){ + switch(read4.x[0]){ case 0xaaaaaaaa: case 0xa0a0a0a0: /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/ @@ -197,16 +203,16 @@ static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) return width; #endif default: - printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n", - read0,read4); + printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); } - }else if((map_read32(map, base+0) == CMD_READ_ID)){ + }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){ /* RAM, probably */ printk("Looks like RAM\n"); - map_write32(map, tmp, base+0); + map_write(map, tmp, base+0); }else{ - printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n", - read0,read4); + printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); } return 0; @@ -215,7 +221,8 @@ static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) /* This function returns with the chip->mutex lock held. */ static int sharp_wait(struct map_info *map, struct flchip *chip) { - int status, i; + int i; + map_word status; unsigned long timeo = jiffies + HZ; DECLARE_WAITQUEUE(wait, current); int adr = 0; @@ -225,12 +232,12 @@ retry: switch(chip->state){ case FL_READY: - map_write32(map,CMD_READ_STATUS,adr); + sharp_send_cmd(map, CMD_READ_STATUS, adr); chip->state = FL_STATUS; case FL_STATUS: for(i=0;i<100;i++){ - status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY) break; udelay(1); } @@ -254,7 +261,7 @@ retry: goto retry; } - map_write32(map,CMD_RESET, adr); + sharp_send_cmd(map, CMD_RESET, adr); chip->state = FL_READY; @@ -351,37 +358,39 @@ static int sharp_write_oneword(struct map_info *map, struct flchip *chip, int timeo; int try; int i; - int status = 0; + map_word data, status; + status.x[0] = 0; ret = sharp_wait(map,chip); for(try=0;try<10;try++){ - map_write32(map,CMD_BYTE_WRITE,adr); + sharp_send_cmd(map, CMD_BYTE_WRITE, adr); /* cpu_to_le32 -> hack to fix the writel be->le conversion */ - map_write32(map,cpu_to_le32(datum),adr); + data.x[0] = cpu_to_le32(datum); + map_write(map, data, adr); chip->state = FL_WRITING; timeo = jiffies + (HZ/2); - map_write32(map,CMD_READ_STATUS,adr); + sharp_send_cmd(map, CMD_READ_STATUS, adr); for(i=0;i<100;i++){ - status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) break; } if(i==100){ printk("sharp: timed out writing\n"); } - if(!(status&SR_ERRORS)) + if(!(status.x[0] & SR_ERRORS)) break; - printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status); + printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]); - map_write32(map,CMD_CLEAR_STATUS,adr); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); } - map_write32(map,CMD_RESET,adr); + sharp_send_cmd(map, CMD_RESET, adr); chip->state = FL_READY; wake_up(&chip->wq); @@ -434,18 +443,18 @@ static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, { int ret; unsigned long timeo; - int status; + map_word status; DECLARE_WAITQUEUE(wait, current); - map_write32(map,CMD_READ_STATUS,adr); - status = map_read32(map,adr); + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); timeo = jiffies + HZ; while(time_before(jiffies, timeo)){ - map_write32(map,CMD_READ_STATUS,adr); - status = map_read32(map,adr); - if((status & SR_READY)==SR_READY){ + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY){ ret = 0; goto out; } @@ -476,7 +485,7 @@ static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, { int ret; //int timeo; - int status; + map_word status; //int i; //printk("sharp_erase_oneblock()\n"); @@ -486,26 +495,26 @@ static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, sharp_unlock_oneblock(map,chip,adr); #endif - map_write32(map,CMD_BLOCK_ERASE_1,adr); - map_write32(map,CMD_BLOCK_ERASE_2,adr); + sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr); + sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr); chip->state = FL_ERASING; ret = sharp_do_wait_for_ready(map,chip,adr); if(ret<0)return ret; - map_write32(map,CMD_READ_STATUS,adr); - status = map_read32(map,adr); + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); - if(!(status&SR_ERRORS)){ - map_write32(map,CMD_RESET,adr); + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); chip->state = FL_READY; //spin_unlock_bh(chip->mutex); return 0; } - printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status); - map_write32(map,CMD_CLEAR_STATUS,adr); + printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); //spin_unlock_bh(chip->mutex); @@ -517,20 +526,20 @@ static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) { int i; - int status; + map_word status; - map_write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); - map_write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr); + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr); udelay(100); - status = map_read32(map,adr); - printk("status=%08x\n",status); + status = map_read(map, adr); + printk("status=%08lx\n", status.x[0]); for(i=0;i<1000;i++){ - //map_write32(map,CMD_READ_STATUS,adr); - status = map_read32(map,adr); - if((status & SR_READY)==SR_READY) + //sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) break; udelay(100); } @@ -538,14 +547,14 @@ static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, printk("sharp: timed out unlocking block\n"); } - if(!(status&SR_ERRORS)){ - map_write32(map,CMD_RESET,adr); + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); chip->state = FL_READY; return; } - printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status); - map_write32(map,CMD_CLEAR_STATUS,adr); + printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); } #endif From 2b9175c174b83b8d97db9398efe948fa9092938f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 29 Nov 2005 14:49:38 +0000 Subject: [PATCH 18/71] [MTD] Make functions static, include header files with prototypes This patch contains the following possible cleanups: - every file should #include the headers containing the prototypes for it's global functions - make needlessly global functions static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_probe.c | 4 ++-- drivers/mtd/devices/block2mtd.c | 6 +++--- drivers/mtd/ftl.c | 6 +++--- drivers/mtd/maps/physmap.c | 3 ++- drivers/mtd/nand/nandsim.c | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index d65ccdebbda4..e636aa86bc24 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.85 2005/11/15 23:28:17 tpoynor Exp $ + $Id: cfi_probe.c,v 1.86 2005/11/29 14:48:31 gleixner Exp $ */ #include @@ -426,7 +426,7 @@ static struct mtd_chip_driver cfi_chipdrv = { .module = THIS_MODULE }; -int __init cfi_probe_init(void) +static int __init cfi_probe_init(void) { register_mtd_chip_driver(&cfi_chipdrv); return 0; diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 0aaa0ced9aba..7ff403b2a0a0 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -1,5 +1,5 @@ /* - * $Id: block2mtd.c,v 1.29 2005/11/07 11:14:24 gleixner Exp $ + * $Id: block2mtd.c,v 1.30 2005/11/29 14:48:32 gleixner Exp $ * * block2mtd.c - create an mtd from a block device * @@ -19,7 +19,7 @@ #include #include -#define VERSION "$Revision: 1.29 $" +#define VERSION "$Revision: 1.30 $" #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args) @@ -40,7 +40,7 @@ static LIST_HEAD(blkmtd_device_list); #define PAGE_READAHEAD 64 -void cache_readahead(struct address_space *mapping, int index) +static void cache_readahead(struct address_space *mapping, int index) { filler_t *filler = (filler_t*)mapping->a_ops->readpage; int i, pagei; diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index de7e231d6d18..8a878b34eca0 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c @@ -1,5 +1,5 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org - * $Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $ + * $Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $ * * Fixes: Arnaldo Carvalho de Melo * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups @@ -1084,9 +1084,9 @@ struct mtd_blktrans_ops ftl_tr = { .owner = THIS_MODULE, }; -int init_ftl(void) +static int init_ftl(void) { - DEBUG(0, "$Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $\n"); + DEBUG(0, "$Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $\n"); return register_mtd_blktrans(&ftl_tr); } diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 9ee760f97bc6..f49ebc3c4606 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -1,5 +1,5 @@ /* - * $Id: physmap.c,v 1.38 2005/11/07 11:14:28 gleixner Exp $ + * $Id: physmap.c,v 1.39 2005/11/29 14:49:36 gleixner Exp $ * * Normal mappings of chips in physical memory * @@ -19,6 +19,7 @@ #include #include #include +#include static struct mtd_info *mymtd; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index de4500395300..a0af92cc7efd 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -1486,7 +1486,7 @@ ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) /* * Module initialization function */ -int __init ns_init_module(void) +static int __init ns_init_module(void) { struct nand_chip *chip; struct nandsim *nand; From eca351336acb2fa943611e0846562ce3997ef53b Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Tue, 29 Nov 2005 11:45:26 -0800 Subject: [PATCH 19/71] [PATCH] Fix missing pfn variables caused by vm changes I image this showed up because of "unused var..." when the changes occured, because flush_cache_page() is a noop in most places. This showed up for me on parisc however, where flush_cache_page() is a real function. Signed-off-by: Linus Torvalds --- mm/memory.c | 4 ++-- mm/rmap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 6c1eac92a316..74839b3a3999 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1345,7 +1345,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, int reuse = can_share_swap_page(old_page); unlock_page(old_page); if (reuse) { - flush_cache_page(vma, address, pfn); + flush_cache_page(vma, address, pte_pfn(orig_pte)); entry = pte_mkyoung(orig_pte); entry = maybe_mkwrite(pte_mkdirty(entry), vma); ptep_set_access_flags(vma, address, page_table, entry, 1); @@ -1389,7 +1389,7 @@ gotten: } } else inc_mm_counter(mm, anon_rss); - flush_cache_page(vma, address, pfn); + flush_cache_page(vma, address, pte_pfn(orig_pte)); entry = mk_pte(new_page, vma->vm_page_prot); entry = maybe_mkwrite(pte_mkdirty(entry), vma); ptep_establish(vma, address, page_table, entry); diff --git a/mm/rmap.c b/mm/rmap.c index 491ac350048f..f853c6def159 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -641,7 +641,7 @@ static void try_to_unmap_cluster(unsigned long cursor, continue; /* Nuke the page table entry. */ - flush_cache_page(vma, address, pfn); + flush_cache_page(vma, address, pte_pfn(*pte)); pteval = ptep_clear_flush(vma, address, pte); /* If nonlinear, store the file page offset in the pte. */ From 238f58d898df941aa9d1cb390fb27ff4febe8965 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 29 Nov 2005 13:01:56 -0800 Subject: [PATCH 20/71] Support strange discontiguous PFN remappings These get created by some drivers that don't generally even want a pfn remapping at all, but would really mostly prefer to just map pages they've allocated individually instead. For now, create a helper function that turns such an incomplete PFN remapping call into a loop that does that explicit mapping. In the long run we almost certainly want to export a totally different interface for that, though. Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/memory.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 6a75a7a78bf1..74f90d7eb5ef 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -163,6 +163,7 @@ extern unsigned int kobjsize(const void *objp); #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ +#define VM_INCOMPLETE 0x02000000 /* Strange partial PFN mapping marker */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff --git a/mm/memory.c b/mm/memory.c index 74839b3a3999..990e7dc666f8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1146,6 +1146,95 @@ int zeromap_page_range(struct vm_area_struct *vma, return err; } +/* + * This is the old fallback for page remapping. + * + * For historical reasons, it only allows reserved pages. Only + * old drivers should use this, and they needed to mark their + * pages reserved for the old functions anyway. + */ +static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *page, pgprot_t prot) +{ + int retval; + pgd_t * pgd; + pud_t * pud; + pmd_t * pmd; + pte_t * pte; + spinlock_t *ptl; + + retval = -EINVAL; + if (PageAnon(page) || !PageReserved(page)) + goto out; + retval = -ENOMEM; + flush_dcache_page(page); + pgd = pgd_offset(mm, addr); + pud = pud_alloc(mm, pgd, addr); + if (!pud) + goto out; + pmd = pmd_alloc(mm, pud, addr); + if (!pmd) + goto out; + pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + if (!pte) + goto out; + retval = -EBUSY; + if (!pte_none(*pte)) + goto out_unlock; + + /* Ok, finally just insert the thing.. */ + get_page(page); + inc_mm_counter(mm, file_rss); + page_add_file_rmap(page); + set_pte_at(mm, addr, pte, mk_pte(page, prot)); + + retval = 0; +out_unlock: + pte_unmap_unlock(pte, ptl); +out: + return retval; +} + +/* + * Somebody does a pfn remapping that doesn't actually work as a vma. + * + * Do it as individual pages instead, and warn about it. It's bad form, + * and very inefficient. + */ +static int incomplete_pfn_remap(struct vm_area_struct *vma, + unsigned long start, unsigned long end, + unsigned long pfn, pgprot_t prot) +{ + static int warn = 10; + struct page *page; + int retval; + + if (!(vma->vm_flags & VM_INCOMPLETE)) { + if (warn) { + warn--; + printk("%s does an incomplete pfn remapping", current->comm); + dump_stack(); + } + } + vma->vm_flags |= VM_INCOMPLETE | VM_IO | VM_RESERVED; + + if (start < vma->vm_start || end > vma->vm_end) + return -EINVAL; + + if (!pfn_valid(pfn)) + return -EINVAL; + + retval = 0; + page = pfn_to_page(pfn); + while (start < end) { + retval = insert_page(vma->vm_mm, start, page, prot); + if (retval < 0) + break; + start += PAGE_SIZE; + page++; + } + return retval; +} + /* * maps a range of physical memory into the requested pages. the old * mappings are removed. any references to nonexistent pages results @@ -1220,6 +1309,9 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, struct mm_struct *mm = vma->vm_mm; int err; + if (addr != vma->vm_start || end != vma->vm_end) + return incomplete_pfn_remap(vma, addr, end, pfn, prot); + /* * Physically remapped pages are special. Tell the * rest of the world about it: From 238f9b063dcc9f23493a0d3fecca29fe332d4905 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Nov 2005 21:36:16 +0100 Subject: [PATCH 21/71] [PATCH] fix megaraid.c locking This fixes locking in megaraid.c, namely: (1) make sure megaraid_queue release the adapter lock by changing the code to have a single return (2) remove the errornous scsi_assign_lock call Testing by Burton Windle. Signed-off-by: Christoph Hellwig Acked-by: Burton Windle Signed-off-by: Linus Torvalds --- drivers/scsi/megaraid.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index dfea346b00a5..f9792528e33f 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -380,23 +380,23 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*done)(Scsi_Cmnd *)) spin_lock_irqsave(&adapter->lock, flags); scb = mega_build_cmd(adapter, scmd, &busy); + if (!scb) + goto out; - if(scb) { - scb->state |= SCB_PENDQ; - list_add_tail(&scb->list, &adapter->pending_list); + scb->state |= SCB_PENDQ; + list_add_tail(&scb->list, &adapter->pending_list); - /* - * Check if the HBA is in quiescent state, e.g., during a - * delete logical drive opertion. If it is, don't run - * the pending_list. - */ - if(atomic_read(&adapter->quiescent) == 0) { - mega_runpendq(adapter); - } - return 0; - } + /* + * Check if the HBA is in quiescent state, e.g., during a + * delete logical drive opertion. If it is, don't run + * the pending_list. + */ + if (atomic_read(&adapter->quiescent) == 0) + mega_runpendq(adapter); + + busy = 0; + out: spin_unlock_irqrestore(&adapter->lock, flags); - return busy; } @@ -4677,7 +4677,6 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) adapter->flag = flag; spin_lock_init(&adapter->lock); - scsi_assign_lock(host, &adapter->lock); host->cmd_per_lun = max_cmd_per_lun; host->max_sectors = max_sectors_per_io; From cab3f16febeaf1a60e38159ff578f609f9976544 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 29 Nov 2005 13:59:03 -0800 Subject: [PATCH 22/71] [SPARC64]: Fix >8K I/O mappings. Increment the PFN field of the PTE so that the tests on vm_pfn in mm/memory.c match up. The TLB ignores these lower bits for larger page sizes, so it's OK to set things like this. Signed-off-by: David S. Miller --- arch/sparc64/mm/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c index d9396c1721cd..580b63da836b 100644 --- a/arch/sparc64/mm/generic.c +++ b/arch/sparc64/mm/generic.c @@ -77,6 +77,7 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, BUG_ON(!pte_none(*pte)); set_pte_at(mm, address, pte, entry); address += PAGE_SIZE; + pte_val(entry) += PAGE_SIZE; pte++; } while (address < curend); } while (address < end); From c9cfcddfd65735437a4cb8563d6b66a6da8a5ed6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 29 Nov 2005 14:03:14 -0800 Subject: [PATCH 23/71] VM: add common helper function to create the page tables This logic was duplicated four times, for no good reason. Signed-off-by: Linus Torvalds --- fs/exec.c | 12 +----------- include/linux/mm.h | 2 ++ mm/fremap.c | 24 ++---------------------- mm/memory.c | 26 ++++++++++++++------------ 4 files changed, 19 insertions(+), 45 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 1f8a9fd2c9ed..22533cce0611 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -306,9 +306,6 @@ void install_arg_page(struct vm_area_struct *vma, struct page *page, unsigned long address) { struct mm_struct *mm = vma->vm_mm; - pgd_t * pgd; - pud_t * pud; - pmd_t * pmd; pte_t * pte; spinlock_t *ptl; @@ -316,14 +313,7 @@ void install_arg_page(struct vm_area_struct *vma, goto out; flush_dcache_page(page); - pgd = pgd_offset(mm, address); - pud = pud_alloc(mm, pgd, address); - if (!pud) - goto out; - pmd = pmd_alloc(mm, pud, address); - if (!pmd) - goto out; - pte = pte_alloc_map_lock(mm, pmd, address, &ptl); + pte = get_locked_pte(mm, address, &ptl); if (!pte) goto out; if (!pte_none(*pte)) { diff --git a/include/linux/mm.h b/include/linux/mm.h index 74f90d7eb5ef..0e73f1539d08 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -742,6 +742,8 @@ struct shrinker; extern struct shrinker *set_shrinker(int, shrinker_t); extern void remove_shrinker(struct shrinker *shrinker); +extern pte_t *FASTCALL(get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)); + int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address); int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address); diff --git a/mm/fremap.c b/mm/fremap.c index f851775e09c2..9f381e58bf44 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -55,20 +55,10 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, pgoff_t size; int err = -ENOMEM; pte_t *pte; - pmd_t *pmd; - pud_t *pud; - pgd_t *pgd; pte_t pte_val; spinlock_t *ptl; - pgd = pgd_offset(mm, addr); - pud = pud_alloc(mm, pgd, addr); - if (!pud) - goto out; - pmd = pmd_alloc(mm, pud, addr); - if (!pmd) - goto out; - pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + pte = get_locked_pte(mm, addr, &ptl); if (!pte) goto out; @@ -110,20 +100,10 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, { int err = -ENOMEM; pte_t *pte; - pmd_t *pmd; - pud_t *pud; - pgd_t *pgd; pte_t pte_val; spinlock_t *ptl; - pgd = pgd_offset(mm, addr); - pud = pud_alloc(mm, pgd, addr); - if (!pud) - goto out; - pmd = pmd_alloc(mm, pud, addr); - if (!pmd) - goto out; - pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + pte = get_locked_pte(mm, addr, &ptl); if (!pte) goto out; diff --git a/mm/memory.c b/mm/memory.c index 990e7dc666f8..74f95ae0510b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1146,6 +1146,18 @@ int zeromap_page_range(struct vm_area_struct *vma, return err; } +pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl) +{ + pgd_t * pgd = pgd_offset(mm, addr); + pud_t * pud = pud_alloc(mm, pgd, addr); + if (pud) { + pmd_t * pmd = pmd_alloc(mm, pgd, addr); + if (pmd) + return pte_alloc_map_lock(mm, pmd, addr, ptl); + } + return NULL; +} + /* * This is the old fallback for page remapping. * @@ -1156,10 +1168,7 @@ int zeromap_page_range(struct vm_area_struct *vma, static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *page, pgprot_t prot) { int retval; - pgd_t * pgd; - pud_t * pud; - pmd_t * pmd; - pte_t * pte; + pte_t *pte; spinlock_t *ptl; retval = -EINVAL; @@ -1167,14 +1176,7 @@ static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *pa goto out; retval = -ENOMEM; flush_dcache_page(page); - pgd = pgd_offset(mm, addr); - pud = pud_alloc(mm, pgd, addr); - if (!pud) - goto out; - pmd = pmd_alloc(mm, pud, addr); - if (!pmd) - goto out; - pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + pte = get_locked_pte(mm, addr, &ptl); if (!pte) goto out; retval = -EBUSY; From 5d2a2dbbc1025dbf7998b9289574d9592b8f21cc Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 29 Nov 2005 14:07:55 -0800 Subject: [PATCH 24/71] cow_user_page: fix page alignment High Dickins points out that the user virtual address passed to the page fault handler isn't necessarily page-aligned. Also, add a comment on why the copy could fail for the user address case. Signed-off-by: Linus Torvalds --- mm/memory.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 74f95ae0510b..745b3482e6c2 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1394,8 +1394,15 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo */ if (unlikely(!src)) { void *kaddr = kmap_atomic(dst, KM_USER0); - unsigned long left = __copy_from_user_inatomic(kaddr, (void __user *)va, PAGE_SIZE); - if (left) + void __user *uaddr = (void __user *)(va & PAGE_MASK); + + /* + * This really shouldn't fail, because the page is there + * in the page tables. But it might just be unreadable, + * in which case we just give up and fill the result with + * zeroes. + */ + if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) memset(kaddr, 0, PAGE_SIZE); kunmap_atomic(kaddr, KM_USER0); return; From e5bbe4dfc8dbfc50ef89f8641e020616d4d1e69e Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 29 Nov 2005 16:54:51 +0000 Subject: [PATCH 25/71] [PATCH] pfnmap: remove src_page from do_wp_page Clean away do_wp_page's "src_page": cow_user_page makes it unnecessary. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds --- mm/memory.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 745b3482e6c2..ae259b6e5a21 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1433,12 +1433,11 @@ 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, *src_page, *new_page; + struct page *old_page, *new_page; pte_t entry; int ret = VM_FAULT_MINOR; old_page = vm_normal_page(vma, address, orig_pte); - src_page = old_page; if (!old_page) goto gotten; @@ -1466,7 +1465,7 @@ gotten: if (unlikely(anon_vma_prepare(vma))) goto oom; - if (src_page == ZERO_PAGE(address)) { + if (old_page == ZERO_PAGE(address)) { new_page = alloc_zeroed_user_highpage(vma, address); if (!new_page) goto oom; @@ -1474,7 +1473,7 @@ gotten: new_page = alloc_page_vma(GFP_HIGHUSER, vma, address); if (!new_page) goto oom; - cow_user_page(new_page, src_page, address); + cow_user_page(new_page, old_page, address); } /* From 325f04dbca60a4cfe4ac25e7cf246edd07eb4c5f Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 29 Nov 2005 16:55:48 +0000 Subject: [PATCH 26/71] [PATCH] pfnmap: do_no_page BUG_ON again Use copy_user_highpage directly instead of cow_user_page in do_no_page: in the immediately following page_cache_release, and elsewhere, it is assuming that new_page is normal. If any VM_PFNMAP driver can get to do_no_page, it's just a BUG (but not in the case of do_anonymous_page). Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds --- mm/memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index ae259b6e5a21..5bfa52a98630 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2009,6 +2009,8 @@ 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_PFNMAP); + if (vma->vm_file) { mapping = vma->vm_file->f_mapping; sequence = mapping->truncate_count; @@ -2041,7 +2043,7 @@ retry: page = alloc_page_vma(GFP_HIGHUSER, vma, address); if (!page) goto oom; - cow_user_page(page, new_page, address); + copy_user_highpage(page, new_page, address); page_cache_release(new_page); new_page = page; anon = 1; From f747307ed1defcdfd37a3ef84c48e3138691cd26 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 29 Nov 2005 14:21:57 -0800 Subject: [PATCH 27/71] Revert "[PATCH] drivers/message/fusion/mptbase.c: make code static" This reverts commit 252ac865535e1ea9cc2d28be83f477d8d8b961a2. It impacts the LSI customers using the mptstm target mode drivers (source tar-ball at ftp://ftp.lsil.com/HostAdapterDrivers/linux/Fusion-MPT/mptstm-1.00.13-src.tar.gz for those who care). Signed-off-by: Linus Torvalds --- drivers/message/fusion/mptbase.c | 6 ++++-- drivers/message/fusion/mptbase.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 74022316fc63..65c2ec5c421b 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -91,9 +91,9 @@ static int mfcounter = 0; * Public data... */ int mpt_lan_index = -1; -static int mpt_stm_index = -1; +int mpt_stm_index = -1; -static struct proc_dir_entry *mpt_proc_root_dir; +struct proc_dir_entry *mpt_proc_root_dir; #define WHOINIT_UNKNOWN 0xAA @@ -6271,6 +6271,7 @@ EXPORT_SYMBOL(mpt_resume); EXPORT_SYMBOL(mpt_suspend); #endif EXPORT_SYMBOL(ioc_list); +EXPORT_SYMBOL(mpt_proc_root_dir); EXPORT_SYMBOL(mpt_register); EXPORT_SYMBOL(mpt_deregister); EXPORT_SYMBOL(mpt_event_register); @@ -6288,6 +6289,7 @@ EXPORT_SYMBOL(mpt_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); EXPORT_SYMBOL(mpt_lan_index); +EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); EXPORT_SYMBOL(mpt_toolbox); diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 8ad277a9afa1..5f5b3fb5b4d7 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -1006,8 +1006,10 @@ extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); * Public data decl's... */ extern struct list_head ioc_list; +extern struct proc_dir_entry *mpt_proc_root_dir; extern int mpt_lan_index; /* needed by mptlan.c */ +extern int mpt_stm_index; /* needed by mptstm.c */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* } __KERNEL__ */ From 18955cfcb2a5d75a08e0cb297f13ccfb6904de48 Mon Sep 17 00:00:00 2001 From: Mike Stroyan Date: Tue, 29 Nov 2005 16:12:55 -0800 Subject: [PATCH 28/71] [IPV4] tcp/route: Another look at hash table sizes The tcp_ehash hash table gets too big on systems with really big memory. It is worse on systems with pages larger than 4KB. It wastes memory that could be better used. It also makes the netstat command slow because reading /proc/net/tcp and /proc/net/tcp6 needs to go through the full hash table. The default value should not be larger for larger page sizes. It seems that the effect of page size is an unintended error dating back a long time. I also wonder if the default value really should be a larger fraction of memory for systems with more memory. While systems with really big ram can afford more space for hash tables, it is not clear to me that they benefit from increasing the allocation ratio for this table. The amount of memory allocated is determined by net/ipv4/tcp.c:tcp_init and mm/page_alloc.c:alloc_large_system_hash. tcp_init calls alloc_large_system_hash passing parameters- bucketsize=sizeof(struct tcp_ehash_bucket) numentries=thash_entries scale=(num_physpages >= 128 * 1024) ? (25-PAGE_SHIFT) : (27-PAGE_SHIFT) limit=0 On i386, PAGE_SHIFT is 12 for a page size of 4K On ia64, PAGE_SHIFT defaults to 14 for a page size of 16K The num_physpages test above makes the allocation take a larger fraction of the total memory on systems with larger memory. The threshold size for a i386 system is 512MB. For an ia64 system with 16KB pages the threshold is 2GB. For smaller memory systems- On i386, scale = (27 - 12) = 15 On ia64, scale = (27 - 14) = 13 For larger memory systems- On i386, scale = (25 - 12) = 13 On ia64, scale = (25 - 14) = 11 For the rest of this discussion, I'll just track the larger memory case. The default behavior has numentries=thash_entries=0, so the allocated size is determined by either scale or by the default limit of 1/16 of total memory. In alloc_large_system_hash- | numentries = (flags & HASH_HIGHMEM) ? nr_all_pages : nr_kernel_pages; | numentries += (1UL << (20 - PAGE_SHIFT)) - 1; | numentries >>= 20 - PAGE_SHIFT; | numentries <<= 20 - PAGE_SHIFT; At this point, numentries is pages for all of memory, rounded up to the nearest megabyte boundary. | /* limit to 1 bucket per 2^scale bytes of low memory */ | if (scale > PAGE_SHIFT) | numentries >>= (scale - PAGE_SHIFT); | else | numentries <<= (PAGE_SHIFT - scale); On i386, numentries >>= (13 - 12), so numentries is 1/8196 of bytes of total memory. On ia64, numentries <<= (14 - 11), so numentries is 1/2048 of bytes of total memory. | log2qty = long_log2(numentries); | | do { | size = bucketsize << log2qty; bucketsize is 16, so size is 16 times numentries, rounded down to a power of two. On i386, size is 1/512 of bytes of total memory. On ia64, size is 1/128 of bytes of total memory. For smaller systems the results are On i386, size is 1/2048 of bytes of total memory. On ia64, size is 1/512 of bytes of total memory. The large page effect can be removed by just replacing the use of PAGE_SHIFT with a constant of 12 in the calls to alloc_large_system_hash. That makes them more like the other uses of that function from fs/inode.c and fs/dcache.c Signed-off-by: David S. Miller --- net/ipv4/route.c | 3 +-- net/ipv4/tcp.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 381dd6a6aebb..e9c14f4a2eba 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -3149,8 +3149,7 @@ int __init ip_rt_init(void) sizeof(struct rt_hash_bucket), rhash_entries, (num_physpages >= 128 * 1024) ? - (27 - PAGE_SHIFT) : - (29 - PAGE_SHIFT), + 15 : 17, HASH_HIGHMEM, &rt_hash_log, &rt_hash_mask, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9ac7a4f46bd8..5e6bc4b32875 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2065,8 +2065,7 @@ void __init tcp_init(void) sizeof(struct inet_ehash_bucket), thash_entries, (num_physpages >= 128 * 1024) ? - (25 - PAGE_SHIFT) : - (27 - PAGE_SHIFT), + 13 : 15, HASH_HIGHMEM, &tcp_hashinfo.ehash_size, NULL, @@ -2082,8 +2081,7 @@ void __init tcp_init(void) sizeof(struct inet_bind_hashbucket), tcp_hashinfo.ehash_size, (num_physpages >= 128 * 1024) ? - (25 - PAGE_SHIFT) : - (27 - PAGE_SHIFT), + 13 : 15, HASH_HIGHMEM, &tcp_hashinfo.bhash_size, NULL, From c9933d0856d6d0ede6b4b30e5e7330614f5203af Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Tue, 29 Nov 2005 16:13:32 -0800 Subject: [PATCH 29/71] [ATM]: always return the first interface for ATM_ITF_ANY From: Mitchell Blank Jr Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- net/atm/common.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 63feea49fb13..83454e12317d 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -423,33 +423,23 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; - if (itf != ATM_ITF_ANY) { + if (likely(itf != ATM_ITF_ANY)) { dev = atm_dev_lookup(itf); - if (!dev) - return -ENODEV; - error = __vcc_connect(vcc, dev, vpi, vci); - if (error) { - atm_dev_put(dev); - return error; - } } else { - struct list_head *p, *next; - dev = NULL; spin_lock(&atm_dev_lock); - list_for_each_safe(p, next, &atm_devs) { - dev = list_entry(p, struct atm_dev, dev_list); + if (!list_empty(&atm_devs)) { + dev = list_entry(atm_devs.next, struct atm_dev, dev_list); atm_dev_hold(dev); - spin_unlock(&atm_dev_lock); - if (!__vcc_connect(vcc, dev, vpi, vci)) - break; - atm_dev_put(dev); - dev = NULL; - spin_lock(&atm_dev_lock); } spin_unlock(&atm_dev_lock); - if (!dev) - return -ENODEV; + } + if (!dev) + return -ENODEV; + error = __vcc_connect(vcc, dev, vpi, vci); + if (error) { + atm_dev_put(dev); + return error; } if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) set_bit(ATM_VF_PARTIAL,&vcc->flags); From c219750b2e667f4f79f4d8faca5057dad793db87 Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Tue, 29 Nov 2005 16:13:55 -0800 Subject: [PATCH 30/71] [ATM]: atm_pcr_goal() doesn't modify its argument's contents -- mark it as const Signed-off-by: Mitchell Blank Jr Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- include/linux/atmdev.h | 2 +- net/atm/atm_misc.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index e7d0593bb576..37e5ee485399 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -468,7 +468,7 @@ static inline void atm_dev_put(struct atm_dev *dev) int atm_charge(struct atm_vcc *vcc,int truesize); struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, gfp_t gfp_flags); -int atm_pcr_goal(struct atm_trafprm *tp); +int atm_pcr_goal(const struct atm_trafprm *tp); void vcc_release_async(struct atm_vcc *vcc, int reply); diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index 223c7ad5bd0f..02cc7e71efea 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c @@ -74,11 +74,14 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, */ -int atm_pcr_goal(struct atm_trafprm *tp) +int atm_pcr_goal(const struct atm_trafprm *tp) { - if (tp->pcr && tp->pcr != ATM_MAX_PCR) return -tp->pcr; - if (tp->min_pcr && !tp->pcr) return tp->min_pcr; - if (tp->max_pcr != ATM_MAX_PCR) return -tp->max_pcr; + if (tp->pcr && tp->pcr != ATM_MAX_PCR) + return -tp->pcr; + if (tp->min_pcr && !tp->pcr) + return tp->min_pcr; + if (tp->max_pcr != ATM_MAX_PCR) + return -tp->max_pcr; return 0; } From c22c28f69b1e28505bd0d26bd0f64554a9e66fe8 Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Tue, 29 Nov 2005 16:14:12 -0800 Subject: [PATCH 31/71] [ATM]: [lanai] better constification Signed-off-by: Mitchell Blank Jr Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/lanai.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 51ec14787293..36226271b83c 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -305,7 +305,7 @@ struct lanai_dev { * vci with their bit set */ static void vci_bitfield_iterate(struct lanai_dev *lanai, - /*const*/ unsigned long *lp, + const unsigned long *lp, void (*func)(struct lanai_dev *,vci_t vci)) { vci_t vci = find_first_bit(lp, NUM_VCI); @@ -951,7 +951,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai) /* read a big-endian 4-byte value out of eeprom */ static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address) { - return be32_to_cpup((u32 *) (&lanai->eeprom[address])); + return be32_to_cpup((const u32 *) &lanai->eeprom[address]); } /* Checksum/validate EEPROM contents */ @@ -1160,7 +1160,7 @@ static inline int vcc_tx_space(const struct lanai_vcc *lvcc, int endptr) } /* test if VCC is currently backlogged */ -static inline int vcc_is_backlogged(/*const*/ struct lanai_vcc *lvcc) +static inline int vcc_is_backlogged(const struct lanai_vcc *lvcc) { return !skb_queue_empty(&lvcc->tx.backlog); } @@ -1395,7 +1395,8 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr) { int size; struct sk_buff *skb; - /*const*/ u32 *x, *end = &lvcc->rx.buf.start[endptr * 4]; + const u32 *x; + u32 *end = &lvcc->rx.buf.start[endptr * 4]; int n = ((unsigned long) end) - ((unsigned long) lvcc->rx.buf.ptr); if (n < 0) n += lanai_buf_size(&lvcc->rx.buf); @@ -2111,7 +2112,7 @@ static int lanai_normalize_ci(struct lanai_dev *lanai, * shifted by that much as we compute * */ -static int pcr_to_cbricg(/*const*/ struct atm_qos *qos) +static int pcr_to_cbricg(const struct atm_qos *qos) { int rounddown = 0; /* 1 = Round PCR down, i.e. round ICG _up_ */ int x, icg, pcr = atm_pcr_goal(&qos->txtp); From fd22f1e037be33040f5583fe091d39d1e632e183 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 29 Nov 2005 16:14:33 -0800 Subject: [PATCH 32/71] [ATM]: [lanai] lanai missing unregister Signed-off-by: Dave Jones Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/lanai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 36226271b83c..2abf3edd0ffe 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2761,6 +2761,7 @@ static void __exit lanai_module_exit(void) * gone, so there isn't much to do */ DPRINTK("cleanup_module()\n"); + pci_unregister_driver(&lanai_driver); } module_init(lanai_module_init); From e91a73568b19b4a8145fc6e05314d522ee35a0b1 Mon Sep 17 00:00:00 2001 From: Jan Pieter Date: Tue, 29 Nov 2005 16:14:58 -0800 Subject: [PATCH 33/71] [ATM]: drivers/atm/atmdev_init.c no longer necessary From: Jan Pieter Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/atmdev_init.c | 54 --------------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 drivers/atm/atmdev_init.c diff --git a/drivers/atm/atmdev_init.c b/drivers/atm/atmdev_init.c deleted file mode 100644 index 0e09e5c28e3f..000000000000 --- a/drivers/atm/atmdev_init.c +++ /dev/null @@ -1,54 +0,0 @@ -/* drivers/atm/atmdev_init.c - ATM device driver initialization */ - -/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ - - -#include -#include - - -#ifdef CONFIG_ATM_ZATM -extern int zatm_detect(void); -#endif -#ifdef CONFIG_ATM_AMBASSADOR -extern int amb_detect(void); -#endif -#ifdef CONFIG_ATM_HORIZON -extern int hrz_detect(void); -#endif -#ifdef CONFIG_ATM_FORE200E -extern int fore200e_detect(void); -#endif -#ifdef CONFIG_ATM_LANAI -extern int lanai_detect(void); -#endif - - -/* - * For historical reasons, atmdev_init returns the number of devices found. - * Note that some detections may not go via atmdev_init (e.g. eni.c), so this - * number is meaningless. - */ - -int __init atmdev_init(void) -{ - int devs; - - devs = 0; -#ifdef CONFIG_ATM_ZATM - devs += zatm_detect(); -#endif -#ifdef CONFIG_ATM_AMBASSADOR - devs += amb_detect(); -#endif -#ifdef CONFIG_ATM_HORIZON - devs += hrz_detect(); -#endif -#ifdef CONFIG_ATM_FORE200E - devs += fore200e_detect(); -#endif -#ifdef CONFIG_ATM_LANAI - devs += lanai_detect(); -#endif - return devs; -} From 50accc9c428273501dd2a6295c84a533dd1fe645 Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Tue, 29 Nov 2005 16:15:18 -0800 Subject: [PATCH 34/71] [ATM]: attempt to autoload atm drivers From: Mitchell Blank Jr Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- net/atm/common.c | 2 +- net/atm/resources.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 83454e12317d..db9318fc6031 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -424,7 +424,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; if (likely(itf != ATM_ITF_ANY)) { - dev = atm_dev_lookup(itf); + dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); } else { dev = NULL; spin_lock(&atm_dev_lock); diff --git a/net/atm/resources.c b/net/atm/resources.c index 415d2615d475..35f3ceb76868 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -245,7 +245,8 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) if (get_user(number, &sioc->number)) return -EFAULT; - if (!(dev = atm_dev_lookup(number))) + if (!(dev = try_then_request_module(atm_dev_lookup(number), + "atm-device-%d", number))) return -ENODEV; switch (cmd) { From 5045b6d34c6a9efa4a8a1815265ca9fcf44d6a7c Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Tue, 29 Nov 2005 16:15:38 -0800 Subject: [PATCH 35/71] [ATM]: linux/config.h only needed for #ifdef __KERNEL__ section Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- include/linux/atmdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 37e5ee485399..8fadb073c834 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -7,7 +7,6 @@ #define LINUX_ATMDEV_H -#include #include #include #include @@ -210,6 +209,7 @@ struct atm_cirange { #ifdef __KERNEL__ +#include #include /* wait_queue_head_t */ #include /* struct timeval */ #include From 49693280262a149e5430d3401e263e464c88334a Mon Sep 17 00:00:00 2001 From: Mitchell Blank Jr Date: Tue, 29 Nov 2005 16:15:59 -0800 Subject: [PATCH 36/71] [ATM]: [lanai] kill lanai_ioctl() which just contains some old debugging code Signed-off-by: Mitchell Blank Jr Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/lanai.c | 90 +-------------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 2abf3edd0ffe..69f4c7ce9a63 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -39,7 +39,7 @@ * o lanai_change_qos() isn't written yet * * o There aren't any ioctl's yet -- I'd like to eventually support - * setting loopback and LED modes that way. (see lanai_ioctl) + * setting loopback and LED modes that way. * * o If the segmentation engine or DMA gets shut down we should restart * card as per section 17.0i. (see lanai_reset) @@ -2435,93 +2435,6 @@ static int lanai_open(struct atm_vcc *atmvcc) return result; } -#if 0 -/* ioctl operations for card */ -/* NOTE: these are all DEBUGGING ONLY currently */ -static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void __user *arg) -{ - int result = 0; - struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; - switch(cmd) { - case 2106275: - shutdown_atm_dev(atmdev); - return 0; - case 2200000: { - unsigned long flags; - spin_lock_irqsave(&lanai->servicelock, flags); - run_service(lanai); - spin_unlock_irqrestore(&lanai->servicelock, flags); - return 0; } - case 2200002: - get_statistics(lanai); - return 0; - case 2200003: { - unsigned int i; - for (i = 0; i <= 0x5C ; i += 4) { - if (i==0x48) /* Write-only butt reg */ - continue; - printk(KERN_CRIT DEV_LABEL " 0x%02X: " - "0x%08X\n", i, - (unsigned int) readl(lanai->base + i)); - barrier(); mb(); - pcistatus_check(lanai, 0); - barrier(); mb(); - } - return 0; } - case 2200004: { - u8 b; - u16 w; - u32 dw; - struct pci_dev *pci = lanai->pci; - (void) pci_read_config_word(pci, PCI_VENDOR_ID, &w); - DPRINTK("vendor = 0x%X\n", (unsigned int) w); - (void) pci_read_config_word(pci, PCI_DEVICE_ID, &w); - DPRINTK("device = 0x%X\n", (unsigned int) w); - (void) pci_read_config_word(pci, PCI_COMMAND, &w); - DPRINTK("command = 0x%X\n", (unsigned int) w); - (void) pci_read_config_word(pci, PCI_STATUS, &w); - DPRINTK("status = 0x%X\n", (unsigned int) w); - (void) pci_read_config_dword(pci, - PCI_CLASS_REVISION, &dw); - DPRINTK("class/revision = 0x%X\n", (unsigned int) dw); - (void) pci_read_config_byte(pci, - PCI_CACHE_LINE_SIZE, &b); - DPRINTK("cache line size = 0x%X\n", (unsigned int) b); - (void) pci_read_config_byte(pci, PCI_LATENCY_TIMER, &b); - DPRINTK("latency = %d (0x%X)\n", - (int) b, (unsigned int) b); - (void) pci_read_config_byte(pci, PCI_HEADER_TYPE, &b); - DPRINTK("header type = 0x%X\n", (unsigned int) b); - (void) pci_read_config_byte(pci, PCI_BIST, &b); - DPRINTK("bist = 0x%X\n", (unsigned int) b); - /* skipping a few here */ - (void) pci_read_config_byte(pci, - PCI_INTERRUPT_LINE, &b); - DPRINTK("pci_int_line = 0x%X\n", (unsigned int) b); - (void) pci_read_config_byte(pci, - PCI_INTERRUPT_PIN, &b); - DPRINTK("pci_int_pin = 0x%X\n", (unsigned int) b); - (void) pci_read_config_byte(pci, PCI_MIN_GNT, &b); - DPRINTK("min_gnt = 0x%X\n", (unsigned int) b); - (void) pci_read_config_byte(pci, PCI_MAX_LAT, &b); - DPRINTK("max_lat = 0x%X\n", (unsigned int) b); } - return 0; -#ifdef USE_POWERDOWN - case 2200005: - DPRINTK("Coming out of powerdown\n"); - lanai->conf1 &= ~CONFIG1_POWERDOWN; - conf1_write(lanai); - return 0; -#endif - default: - result = -ENOIOCTLCMD; - } - return result; -} -#else /* !0 */ -#define lanai_ioctl NULL -#endif /* 0 */ - static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb) { struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data; @@ -2679,7 +2592,6 @@ static const struct atmdev_ops ops = { .dev_close = lanai_dev_close, .open = lanai_open, .close = lanai_close, - .ioctl = lanai_ioctl, .getsockopt = NULL, .setsockopt = NULL, .send = lanai_send, From aaaaaadbe7a663d110814db50fcbe7d320eb4c32 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 29 Nov 2005 16:16:21 -0800 Subject: [PATCH 37/71] [ATM]: avoid race conditions related to atm_devs list Use semaphore to protect atm_devs list, as no one need access to it from interrupt context. Avoid race conditions between atm_dev_register(), atm_dev_lookup() and atm_dev_deregister(). Fix double spin_unlock() bug. Signed-off-by: Stanislaw Gruszka Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- net/atm/common.c | 4 ++-- net/atm/resources.c | 36 +++++++++++++++++------------------- net/atm/resources.h | 3 +-- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index db9318fc6031..9e016f404e14 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -427,12 +427,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); } else { dev = NULL; - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); if (!list_empty(&atm_devs)) { dev = list_entry(atm_devs.next, struct atm_dev, dev_list); atm_dev_hold(dev); } - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); } if (!dev) return -ENODEV; diff --git a/net/atm/resources.c b/net/atm/resources.c index 35f3ceb76868..ad533b02b84f 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -25,7 +25,7 @@ LIST_HEAD(atm_devs); -DEFINE_SPINLOCK(atm_dev_lock); +DECLARE_MUTEX(atm_dev_mutex); static struct atm_dev *__alloc_atm_dev(const char *type) { @@ -52,7 +52,7 @@ static struct atm_dev *__atm_dev_lookup(int number) list_for_each(p, &atm_devs) { dev = list_entry(p, struct atm_dev, dev_list); - if ((dev->ops) && (dev->number == number)) { + if (dev->number == number) { atm_dev_hold(dev); return dev; } @@ -64,9 +64,9 @@ struct atm_dev *atm_dev_lookup(int number) { struct atm_dev *dev; - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); dev = __atm_dev_lookup(number); - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); return dev; } @@ -81,11 +81,11 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, type); return NULL; } - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); if (number != -1) { if ((inuse = __atm_dev_lookup(number))) { atm_dev_put(inuse); - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); kfree(dev); return NULL; } @@ -105,19 +105,17 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, memset(&dev->flags, 0, sizeof(dev->flags)); memset(&dev->stats, 0, sizeof(dev->stats)); atomic_set(&dev->refcnt, 1); - list_add_tail(&dev->dev_list, &atm_devs); - spin_unlock(&atm_dev_lock); if (atm_proc_dev_register(dev) < 0) { printk(KERN_ERR "atm_dev_register: " "atm_proc_dev_register failed for dev %s\n", type); - spin_lock(&atm_dev_lock); - list_del(&dev->dev_list); - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); kfree(dev); return NULL; } + list_add_tail(&dev->dev_list, &atm_devs); + up(&atm_dev_mutex); return dev; } @@ -129,9 +127,9 @@ void atm_dev_deregister(struct atm_dev *dev) atm_proc_dev_deregister(dev); - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); list_del(&dev->dev_list); - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); warning_time = jiffies; while (atomic_read(&dev->refcnt) != 1) { @@ -211,16 +209,16 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) return -EFAULT; if (get_user(len, &iobuf->length)) return -EFAULT; - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); list_for_each(p, &atm_devs) size += sizeof(int); if (size > len) { - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); return -E2BIG; } tmp_buf = kmalloc(size, GFP_ATOMIC); if (!tmp_buf) { - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); return -ENOMEM; } tmp_p = tmp_buf; @@ -228,7 +226,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) dev = list_entry(p, struct atm_dev, dev_list); *tmp_p++ = dev->number; } - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); error = ((copy_to_user(buf, tmp_buf, size)) || put_user(size, &iobuf->length)) ? -EFAULT : 0; @@ -415,13 +413,13 @@ static __inline__ void *dev_get_idx(loff_t left) void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) { - spin_lock(&atm_dev_lock); + down(&atm_dev_mutex); return *pos ? dev_get_idx(*pos) : (void *) 1; } void atm_dev_seq_stop(struct seq_file *seq, void *v) { - spin_unlock(&atm_dev_lock); + up(&atm_dev_mutex); } void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) diff --git a/net/atm/resources.h b/net/atm/resources.h index 12910619dbb6..b7fb82a93b42 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -11,8 +11,7 @@ extern struct list_head atm_devs; -extern spinlock_t atm_dev_lock; - +extern struct semaphore atm_dev_mutex; int atm_dev_ioctl(unsigned int cmd, void __user *arg); From 64bf69ddff7637b7ed7acf9b2a823cc0ee519439 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 29 Nov 2005 16:16:41 -0800 Subject: [PATCH 38/71] [ATM]: deregistration removes device from atm_devs list immediately atm_dev_deregister() removes device from atm_dev list immediately to prevent operations on a phantom device. Decision to free device based only on ->refcnt now. Remove shutdown_atm_dev() use atm_dev_deregister() instead. atm_dev_deregister() also asynchronously releases all vccs related to device. Signed-off-by: Stanislaw Gruszka Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/atmtcp.c | 20 ++------------------ drivers/usb/atm/usbatm.c | 4 ++-- include/linux/atmdev.h | 14 +++++++------- net/atm/common.c | 30 +++++++++++++++++++++++++++--- net/atm/common.h | 2 ++ net/atm/resources.c | 37 +++++++++++-------------------------- 6 files changed, 51 insertions(+), 56 deletions(-) diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index 57f1810fdccd..fc518d85543d 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -246,10 +246,6 @@ static void atmtcp_c_close(struct atm_vcc *vcc) { struct atm_dev *atmtcp_dev; struct atmtcp_dev_data *dev_data; - struct sock *s; - struct hlist_node *node; - struct atm_vcc *walk; - int i; atmtcp_dev = (struct atm_dev *) vcc->dev_data; dev_data = PRIV(atmtcp_dev); @@ -257,20 +253,8 @@ static void atmtcp_c_close(struct atm_vcc *vcc) if (dev_data->persist) return; atmtcp_dev->dev_data = NULL; kfree(dev_data); - shutdown_atm_dev(atmtcp_dev); + atm_dev_deregister(atmtcp_dev); vcc->dev_data = NULL; - read_lock(&vcc_sklist_lock); - for(i = 0; i < VCC_HTABLE_SIZE; ++i) { - struct hlist_head *head = &vcc_hash[i]; - - sk_for_each(s, node, head) { - walk = atm_sk(s); - if (walk->dev != atmtcp_dev) - continue; - wake_up(s->sk_sleep); - } - } - read_unlock(&vcc_sklist_lock); module_put(THIS_MODULE); } @@ -450,7 +434,7 @@ static int atmtcp_remove_persistent(int itf) if (PRIV(dev)->vcc) return 0; kfree(dev_data); atm_dev_put(dev); - shutdown_atm_dev(dev); + atm_dev_deregister(dev); return 0; } diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index c466739428b2..2e6593e6c1bd 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -879,7 +879,7 @@ static int usbatm_atm_init(struct usbatm_data *instance) fail: instance->atm_dev = NULL; - shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */ + atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */ return ret; } @@ -1164,7 +1164,7 @@ void usbatm_usb_disconnect(struct usb_interface *intf) /* ATM finalize */ if (instance->atm_dev) - shutdown_atm_dev(instance->atm_dev); + atm_dev_deregister(instance->atm_dev); usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ } diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 8fadb073c834..b203ea82a0a8 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -274,7 +274,7 @@ enum { enum { - ATM_DF_CLOSE, /* close device when last VCC is closed */ + ATM_DF_REMOVED, /* device was removed from atm_devs list */ }; @@ -415,7 +415,6 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, int number,unsigned long *flags); /* number == -1: pick first available */ struct atm_dev *atm_dev_lookup(int number); void atm_dev_deregister(struct atm_dev *dev); -void shutdown_atm_dev(struct atm_dev *dev); void vcc_insert_socket(struct sock *sk); @@ -457,11 +456,12 @@ static inline void atm_dev_hold(struct atm_dev *dev) static inline void atm_dev_put(struct atm_dev *dev) { - atomic_dec(&dev->refcnt); - - if ((atomic_read(&dev->refcnt) == 1) && - test_bit(ATM_DF_CLOSE,&dev->flags)) - shutdown_atm_dev(dev); + if (atomic_dec_and_test(&dev->refcnt)) { + BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags)); + if (dev->ops->dev_close) + dev->ops->dev_close(dev); + kfree(dev); + } } diff --git a/net/atm/common.c b/net/atm/common.c index 9e016f404e14..6656b111cc05 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -221,6 +221,29 @@ void vcc_release_async(struct atm_vcc *vcc, int reply) EXPORT_SYMBOL(vcc_release_async); +void atm_dev_release_vccs(struct atm_dev *dev) +{ + int i; + + write_lock_irq(&vcc_sklist_lock); + for (i = 0; i < VCC_HTABLE_SIZE; i++) { + struct hlist_head *head = &vcc_hash[i]; + struct hlist_node *node, *tmp; + struct sock *s; + struct atm_vcc *vcc; + + sk_for_each_safe(s, node, tmp, head) { + vcc = atm_sk(s); + if (vcc->dev == dev) { + vcc_release_async(vcc, -EPIPE); + sk_del_node_init(s); + } + } + } + write_unlock_irq(&vcc_sklist_lock); +} + + static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) { int max_sdu; @@ -332,12 +355,13 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, return -EINVAL; if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE)) return -EPERM; - error = 0; + error = -ENODEV; if (!try_module_get(dev->ops->owner)) - return -ENODEV; + return error; vcc->dev = dev; write_lock_irq(&vcc_sklist_lock); - if ((error = find_ci(vcc, &vpi, &vci))) { + if (test_bit(ATM_DF_REMOVED, &dev->flags) || + (error = find_ci(vcc, &vpi, &vci))) { write_unlock_irq(&vcc_sklist_lock); goto fail_module_put; } diff --git a/net/atm/common.h b/net/atm/common.h index e49ed41c0e33..4887c317cefe 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -47,4 +47,6 @@ static inline void atm_proc_exit(void) /* SVC */ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); +void atm_dev_release_vccs(struct atm_dev *dev); + #endif diff --git a/net/atm/resources.c b/net/atm/resources.c index ad533b02b84f..c8c459fcb038 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -70,6 +70,7 @@ struct atm_dev *atm_dev_lookup(int number) return dev; } + struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, int number, unsigned long *flags) { @@ -123,37 +124,22 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, void atm_dev_deregister(struct atm_dev *dev) { - unsigned long warning_time; - - atm_proc_dev_deregister(dev); + BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags)); + set_bit(ATM_DF_REMOVED, &dev->flags); + /* + * if we remove current device from atm_devs list, new device + * with same number can appear, such we need deregister proc, + * release async all vccs and remove them from vccs list too + */ down(&atm_dev_mutex); list_del(&dev->dev_list); up(&atm_dev_mutex); - warning_time = jiffies; - while (atomic_read(&dev->refcnt) != 1) { - msleep(250); - if ((jiffies - warning_time) > 10 * HZ) { - printk(KERN_EMERG "atm_dev_deregister: waiting for " - "dev %d to become free. Usage count = %d\n", - dev->number, atomic_read(&dev->refcnt)); - warning_time = jiffies; - } - } + atm_dev_release_vccs(dev); + atm_proc_dev_deregister(dev); - kfree(dev); -} - -void shutdown_atm_dev(struct atm_dev *dev) -{ - if (atomic_read(&dev->refcnt) > 1) { - set_bit(ATM_DF_CLOSE, &dev->flags); - return; - } - if (dev->ops->dev_close) - dev->ops->dev_close(dev); - atm_dev_deregister(dev); + atm_dev_put(dev); } @@ -433,4 +419,3 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) EXPORT_SYMBOL(atm_dev_register); EXPORT_SYMBOL(atm_dev_deregister); EXPORT_SYMBOL(atm_dev_lookup); -EXPORT_SYMBOL(shutdown_atm_dev); From fb29644994744a63bc57186cefa79534b5d9b5a9 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Tue, 29 Nov 2005 16:17:11 -0800 Subject: [PATCH 39/71] [ATM]: [adummy] dummy ATM driver (similar to net/dummy) Signed-off-by: Chas Williams Signed-off-by: David S. Miller --- drivers/atm/Kconfig | 7 ++ drivers/atm/Makefile | 1 + drivers/atm/adummy.c | 168 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 drivers/atm/adummy.c diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index 489de81ea609..01a9f1cb7743 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig @@ -5,6 +5,13 @@ menu "ATM drivers" depends on NETDEVICES && ATM +config ATM_DUMMY + tristate "Dummy ATM driver" + depends on ATM + help + Dummy ATM driver. Useful for proxy signalling, testing, + and development. If unsure, say N. + config ATM_TCP tristate "ATM over TCP" depends on INET && ATM diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile index 5b77188527a9..b5077ce8cb40 100644 --- a/drivers/atm/Makefile +++ b/drivers/atm/Makefile @@ -31,6 +31,7 @@ ifeq ($(CONFIG_ATM_IDT77252_USE_SUNI),y) obj-$(CONFIG_ATM_IDT77252) += suni.o endif +obj-$(CONFIG_ATM_DUMMY) += adummy.o obj-$(CONFIG_ATM_TCP) += atmtcp.o obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o obj-$(CONFIG_ATM_LANAI) += lanai.o diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c new file mode 100644 index 000000000000..d15c194be44a --- /dev/null +++ b/drivers/atm/adummy.c @@ -0,0 +1,168 @@ +/* + * adummy.c: a dummy ATM driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* version definition */ + +#define DRV_VERSION "1.0" + +#define DEV_LABEL "adummy" + +#define ADUMMY_DEV(dev) ((struct adummy_dev *) (dev)->dev_data) + +struct adummy_dev { + struct atm_dev *atm_dev; + + struct list_head entry; +}; + +/* globals */ + +static LIST_HEAD(adummy_devs); + +static int __init +adummy_start(struct atm_dev *dev) +{ + dev->ci_range.vpi_bits = 4; + dev->ci_range.vci_bits = 12; + + return 0; +} + +static int +adummy_open(struct atm_vcc *vcc) +{ + short vpi = vcc->vpi; + int vci = vcc->vci; + + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) + return 0; + + set_bit(ATM_VF_ADDR, &vcc->flags); + set_bit(ATM_VF_READY, &vcc->flags); + + return 0; +} + +static void +adummy_close(struct atm_vcc *vcc) +{ + clear_bit(ATM_VF_READY, &vcc->flags); + clear_bit(ATM_VF_ADDR, &vcc->flags); +} + +static int +adummy_send(struct atm_vcc *vcc, struct sk_buff *skb) +{ + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); + atomic_inc(&vcc->stats->tx); + + return 0; +} + +static int +adummy_proc_read(struct atm_dev *dev, loff_t *pos, char *page) +{ + int left = *pos; + + if (!left--) + return sprintf(page, "version %s\n", DRV_VERSION); + + return 0; +} + +static struct atmdev_ops adummy_ops = +{ + .open = adummy_open, + .close = adummy_close, + .send = adummy_send, + .proc_read = adummy_proc_read, + .owner = THIS_MODULE +}; + +static int __init adummy_init(void) +{ + struct atm_dev *atm_dev; + struct adummy_dev *adummy_dev; + int err = 0; + + printk(KERN_ERR "adummy: version %s\n", DRV_VERSION); + + adummy_dev = (struct adummy_dev *) kmalloc(sizeof(struct adummy_dev), + GFP_KERNEL); + if (!adummy_dev) { + printk(KERN_ERR DEV_LABEL ": kmalloc() failed\n"); + err = -ENOMEM; + goto out; + } + memset(adummy_dev, 0, sizeof(struct adummy_dev)); + + atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, 0); + if (!atm_dev) { + printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); + err = -ENODEV; + goto out_kfree; + } + + adummy_dev->atm_dev = atm_dev; + atm_dev->dev_data = adummy_dev; + + if (adummy_start(atm_dev)) { + printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n"); + err = -ENODEV; + goto out_unregister; + } + + list_add(&adummy_dev->entry, &adummy_devs); +out: + return err; + +out_unregister: + atm_dev_deregister(atm_dev); +out_kfree: + kfree(adummy_dev); + goto out; +} + +static void __exit adummy_cleanup(void) +{ + struct adummy_dev *adummy_dev, *next; + + list_for_each_entry_safe(adummy_dev, next, &adummy_devs, entry) { + atm_dev_deregister(adummy_dev->atm_dev); + kfree(adummy_dev); + } +} + +module_init(adummy_init); +module_exit(adummy_cleanup); + +MODULE_AUTHOR("chas williams "); +MODULE_DESCRIPTION("dummy ATM driver"); +MODULE_LICENSE("GPL"); From 9b5b5cff9a6655dbb6d2e2be365bb95eec3950eb Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Tue, 29 Nov 2005 16:21:38 -0800 Subject: [PATCH 40/71] [NET]: Add const markers to various variables. the patch below marks various variables const in net/; the goal is to move them to the .rodata section so that they can't false-share cachelines with things that get written to, as well as potentially helping gcc a bit with optimisations. (these were found using a gcc patch to warn about such variables) Signed-off-by: Arjan van de Ven Signed-off-by: David S. Miller --- net/ipv4/fib_hash.c | 2 +- net/ipv4/fib_semantics.c | 2 +- net/ipv4/icmp.c | 4 ++-- net/ipv4/ipvs/ip_vs_conn.c | 2 +- net/ipv4/ipvs/ip_vs_ctl.c | 4 ++-- net/ipv4/ipvs/ip_vs_proto_tcp.c | 2 +- net/ipv4/netfilter/ip_conntrack_amanda.c | 2 +- net/ipv4/netfilter/ip_conntrack_ftp.c | 2 +- net/ipv4/netfilter/ip_conntrack_irc.c | 2 +- net/ipv4/netfilter/ip_conntrack_proto_icmp.c | 4 ++-- net/ipv4/netfilter/ip_conntrack_proto_sctp.c | 4 ++-- net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 6 +++--- net/ipv4/netfilter/ip_tables.c | 2 +- net/ipv4/netfilter/ipt_LOG.c | 2 +- net/ipv4/proc.c | 10 +++++----- net/ipv4/route.c | 2 +- net/ipv4/tcp.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/netfilter/ip6_tables.c | 2 +- 19 files changed, 29 insertions(+), 29 deletions(-) diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 2a8c9afc3695..7ea0209cb169 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -975,7 +975,7 @@ static void fib_seq_stop(struct seq_file *seq, void *v) static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi) { - static unsigned type2flags[RTN_MAX + 1] = { + static const unsigned type2flags[RTN_MAX + 1] = { [7] = RTF_REJECT, [8] = RTF_REJECT, }; unsigned flags = type2flags[type]; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 186f20c4a45e..6d2a6ac070e3 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -83,7 +83,7 @@ for (nhsel=0; nhsel < 1; nhsel++) #define endfor_nexthops(fi) } -static struct +static const struct { int error; u8 scope; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e3eceecd0496..92e23b2ad4d2 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -220,7 +220,7 @@ struct icmp_control { short error; /* This ICMP is classed as an error message */ }; -static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; +static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; /* * The ICMP socket(s). This is the most convenient way to flow control @@ -994,7 +994,7 @@ error: /* * This table is the definition of how we handle ICMP. */ -static struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { +static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { [ICMP_ECHOREPLY] = { .output_entry = ICMP_MIB_OUTECHOREPS, .input_entry = ICMP_MIB_INECHOREPS, diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index f828fa2eb7de..2a3a8c59c655 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -771,7 +771,7 @@ static inline int todrop_entry(struct ip_vs_conn *cp) * The drop rate array needs tuning for real environments. * Called from timer bh only => no locking */ - static char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + static const char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; static char todrop_counter[9] = {0}; int i; diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 2d66848e7aa0..9bdcf31b760e 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -1909,7 +1909,7 @@ static int ip_vs_set_timeout(struct ip_vs_timeout_user *u) #define DAEMON_ARG_LEN (sizeof(struct ip_vs_daemon_user)) #define MAX_ARG_LEN SVCDEST_ARG_LEN -static unsigned char set_arglen[SET_CMDID(IP_VS_SO_SET_MAX)+1] = { +static const unsigned char set_arglen[SET_CMDID(IP_VS_SO_SET_MAX)+1] = { [SET_CMDID(IP_VS_SO_SET_ADD)] = SERVICE_ARG_LEN, [SET_CMDID(IP_VS_SO_SET_EDIT)] = SERVICE_ARG_LEN, [SET_CMDID(IP_VS_SO_SET_DEL)] = SERVICE_ARG_LEN, @@ -2180,7 +2180,7 @@ __ip_vs_get_timeouts(struct ip_vs_timeout_user *u) #define GET_TIMEOUT_ARG_LEN (sizeof(struct ip_vs_timeout_user)) #define GET_DAEMON_ARG_LEN (sizeof(struct ip_vs_daemon_user) * 2) -static unsigned char get_arglen[GET_CMDID(IP_VS_SO_GET_MAX)+1] = { +static const unsigned char get_arglen[GET_CMDID(IP_VS_SO_GET_MAX)+1] = { [GET_CMDID(IP_VS_SO_GET_VERSION)] = 64, [GET_CMDID(IP_VS_SO_GET_INFO)] = GET_INFO_ARG_LEN, [GET_CMDID(IP_VS_SO_GET_SERVICES)] = GET_SERVICES_ARG_LEN, diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index c19408973c09..0e878fd6215c 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -251,7 +251,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) #define TCP_DIR_OUTPUT 4 #define TCP_DIR_INPUT_ONLY 8 -static int tcp_state_off[IP_VS_DIR_LAST] = { +static const int tcp_state_off[IP_VS_DIR_LAST] = { [IP_VS_DIR_INPUT] = TCP_DIR_INPUT, [IP_VS_DIR_OUTPUT] = TCP_DIR_OUTPUT, [IP_VS_DIR_INPUT_ONLY] = TCP_DIR_INPUT_ONLY, diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index fa3f914117ec..e52847fa10f5 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); module_param(master_timeout, int, 0600); MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); -static char *conns[] = { "DATA ", "MESG ", "INDEX " }; +static const char *conns[] = { "DATA ", "MESG ", "INDEX " }; /* This is slow, but it's simple. --RR */ static char *amanda_buffer; diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 59e12b02b22c..68b173bcda60 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -55,7 +55,7 @@ static int try_rfc959(const char *, size_t, u_int32_t [], char); static int try_eprt(const char *, size_t, u_int32_t [], char); static int try_epsv_response(const char *, size_t, u_int32_t [], char); -static struct ftp_search { +static const struct ftp_search { enum ip_conntrack_dir dir; const char *pattern; size_t plen; diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index 2dea1db14406..d7c40421d0d1 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c @@ -59,7 +59,7 @@ MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC module_param(dcc_timeout, int, 0400); MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); -static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " }; +static const char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " }; #define MINMATCHLEN 5 #if 0 diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index e4d6b268e8c4..5f9925db608e 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -51,7 +51,7 @@ static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple, const struct ip_conntrack_tuple *orig) { /* Add 1; spaces filled with 0. */ - static u_int8_t invmap[] + static const u_int8_t invmap[] = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, [ICMP_ECHOREPLY] = ICMP_ECHO + 1, [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, @@ -110,7 +110,7 @@ static int icmp_packet(struct ip_conntrack *ct, return NF_ACCEPT; } -static u_int8_t valid_new[] = { +static const u_int8_t valid_new[] = { [ICMP_ECHO] = 1, [ICMP_TIMESTAMP] = 1, [ICMP_INFO_REQUEST] = 1, diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 59a4a0111dd3..977fb59d4563 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -65,7 +65,7 @@ static unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000; static unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000; static unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS; -static unsigned long * sctp_timeouts[] +static const unsigned long * sctp_timeouts[] = { NULL, /* SCTP_CONNTRACK_NONE */ &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */ &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */ @@ -118,7 +118,7 @@ cookie echoed to closed. */ /* SCTP conntrack state transitions */ -static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { +static const enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { { /* ORIGINAL */ /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */ diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index ee3b7d6c4d2e..625981676776 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -99,7 +99,7 @@ unsigned long ip_ct_tcp_timeout_close = 10 SECS; to ~13-30min depending on RTO. */ unsigned long ip_ct_tcp_timeout_max_retrans = 5 MINS; -static unsigned long * tcp_timeouts[] +static const unsigned long * tcp_timeouts[] = { NULL, /* TCP_CONNTRACK_NONE */ &ip_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */ &ip_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */ @@ -170,7 +170,7 @@ enum tcp_bit_set { * if they are invalid * or we do not support the request (simultaneous open) */ -static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { +static const enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { { /* ORIGINAL */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */ @@ -817,7 +817,7 @@ void ip_conntrack_tcp_update(struct sk_buff *skb, #define TH_CWR 0x80 /* table of valid flag combinations - ECE and CWR are always valid */ -static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = +static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = { [TH_SYN] = 1, [TH_SYN|TH_ACK] = 1, diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 75c27e92f6ab..45886c8475e8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1892,7 +1892,7 @@ static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) return pos; } -static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = +static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = { { "ip_tables_names", ipt_get_tables }, { "ip_tables_targets", ipt_get_targets }, { "ip_tables_matches", ipt_get_matches }, diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 92ed050fac69..180d6ca04af6 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -197,7 +197,7 @@ static void dump_packet(const struct nf_loginfo *info, } case IPPROTO_ICMP: { struct icmphdr _icmph, *ich; - static size_t required_len[NR_ICMP_TYPES+1] + static const size_t required_len[NR_ICMP_TYPES+1] = { [ICMP_ECHOREPLY] = 4, [ICMP_DEST_UNREACH] = 8 + sizeof(struct iphdr), diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index a65e508fbd40..0d7dc668db46 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -98,7 +98,7 @@ fold_field(void *mib[], int offt) } /* snmp items */ -static struct snmp_mib snmp4_ipstats_list[] = { +static const struct snmp_mib snmp4_ipstats_list[] = { SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES), SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS), SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS), @@ -119,7 +119,7 @@ static struct snmp_mib snmp4_ipstats_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp4_icmp_list[] = { +static const struct snmp_mib snmp4_icmp_list[] = { SNMP_MIB_ITEM("InMsgs", ICMP_MIB_INMSGS), SNMP_MIB_ITEM("InErrors", ICMP_MIB_INERRORS), SNMP_MIB_ITEM("InDestUnreachs", ICMP_MIB_INDESTUNREACHS), @@ -149,7 +149,7 @@ static struct snmp_mib snmp4_icmp_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp4_tcp_list[] = { +static const struct snmp_mib snmp4_tcp_list[] = { SNMP_MIB_ITEM("RtoAlgorithm", TCP_MIB_RTOALGORITHM), SNMP_MIB_ITEM("RtoMin", TCP_MIB_RTOMIN), SNMP_MIB_ITEM("RtoMax", TCP_MIB_RTOMAX), @@ -167,7 +167,7 @@ static struct snmp_mib snmp4_tcp_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp4_udp_list[] = { +static const struct snmp_mib snmp4_udp_list[] = { SNMP_MIB_ITEM("InDatagrams", UDP_MIB_INDATAGRAMS), SNMP_MIB_ITEM("NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("InErrors", UDP_MIB_INERRORS), @@ -175,7 +175,7 @@ static struct snmp_mib snmp4_udp_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp4_net_list[] = { +static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("SyncookiesSent", LINUX_MIB_SYNCOOKIESSENT), SNMP_MIB_ITEM("SyncookiesRecv", LINUX_MIB_SYNCOOKIESRECV), SNMP_MIB_ITEM("SyncookiesFailed", LINUX_MIB_SYNCOOKIESFAILED), diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e9c14f4a2eba..f701a136a6ae 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1371,7 +1371,7 @@ out: kfree_skb(skb); * are needed for AMPRnet AX.25 paths. */ -static unsigned short mtu_plateau[] = +static const unsigned short mtu_plateau[] = {32000, 17914, 8166, 4352, 2002, 1492, 576, 296, 216, 128 }; static __inline__ unsigned short guess_mtu(unsigned short old_mtu) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5e6bc4b32875..ef98b14ac56d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1413,7 +1413,7 @@ recv_urg: * closed. */ -static unsigned char new_state[16] = { +static const unsigned char new_state[16] = { /* current state: new state: action: */ /* (Invalid) */ TCP_CLOSE, /* TCP_ESTABLISHED */ TCP_FIN_WAIT1 | TCP_ACTION_FIN, diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 1bdf0fb8bf8a..34a332225c17 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -751,7 +751,7 @@ void icmpv6_cleanup(void) inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); } -static struct icmp6_err { +static const struct icmp6_err { int err; int fatal; } tab_unreach[] = { diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7d492226c16e..95d469271c4d 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1972,7 +1972,7 @@ static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length return pos; } -static struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = +static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = { { "ip6_tables_names", ip6t_get_tables }, { "ip6_tables_targets", ip6t_get_targets }, { "ip6_tables_matches", ip6t_get_matches }, From 4b30b1c6a3e58dc74f2dbb0aa39f16a23cfcdd56 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 29 Nov 2005 16:27:20 -0800 Subject: [PATCH 41/71] [IPV4]: make two functions static This patch makes two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_output.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 4e9c74b54b15..a4c347c3b8e3 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1217,7 +1217,7 @@ static int ipgre_tunnel_init(struct net_device *dev) return 0; } -int __init ipgre_fb_tunnel_init(struct net_device *dev) +static int __init ipgre_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; struct iphdr *iph = &tunnel->parms.iph; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 11c2f68254f0..eba64e2bd397 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -690,7 +690,7 @@ csum_page(struct page *page, int offset, int copy) return csum; } -inline int ip_ufo_append_data(struct sock *sk, +static inline int ip_ufo_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int hh_len, int fragheaderlen, From d127e94a5cf1c9c996b8c67cd2595b96c3e35e4c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 29 Nov 2005 16:28:18 -0800 Subject: [PATCH 42/71] [NETFILTER] ipv4: small cleanups This patch contains the following cleanups: - make needlessly global code static - ip_conntrack_core.c: ip_conntrack_flush() -> ip_conntrack_flush(void) Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 4 ++-- net/ipv4/netfilter/ip_nat_core.c | 2 +- net/ipv4/netfilter/ipt_LOG.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 422ab68ee7fb..7a4ecddd597b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1354,7 +1354,7 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size) get_order(sizeof(struct list_head) * size)); } -void ip_conntrack_flush() +void ip_conntrack_flush(void) { /* This makes sure all current packets have passed through netfilter framework. Roll on, two-stage module @@ -1408,7 +1408,7 @@ static struct list_head *alloc_hashtable(int size, int *vmalloced) return hash; } -int set_hashsize(const char *val, struct kernel_param *kp) +static int set_hashsize(const char *val, struct kernel_param *kp) { int i, bucket, hashsize, vmalloced; int old_vmalloced, old_size; diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 762f4d93936b..c1a61462507f 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -49,7 +49,7 @@ static unsigned int ip_nat_htable_size; static struct list_head *bysource; #define MAX_IP_NAT_PROTO 256 -struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO]; +static struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO]; static inline struct ip_nat_protocol * __ip_nat_proto_find(u_int8_t protonum) diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 180d6ca04af6..30be0f1dae37 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -351,7 +351,7 @@ static void dump_packet(const struct nf_loginfo *info, /* maxlen = 230+ 91 + 230 + 252 = 803 */ } -struct nf_loginfo default_loginfo = { +static struct nf_loginfo default_loginfo = { .type = NF_LOG_TYPE_LOG, .u = { .log = { From 34a0b3cdc078746788ffc49e56da0db62b8b6ea4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 29 Nov 2005 16:28:56 -0800 Subject: [PATCH 43/71] [IPV6]: make two functions static This patch makes two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 3 ++- net/ipv6/ipv6_sockglue.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index c1fa693511a1..8523c76ebf76 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -774,7 +774,8 @@ out_err_release: *dst = NULL; return err; } -inline int ip6_ufo_append_data(struct sock *sk, + +static inline int ip6_ufo_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int hh_len, int fragheaderlen, diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 25757ade989f..3620718defe6 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -628,8 +628,8 @@ e_inval: return -EINVAL; } -int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, - char __user *optval, int len) +static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, + char __user *optval, int len) { if (!hdr) return 0; From 49c91fb01ff3948285608c65754b3ffbf57d50f2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 29 Nov 2005 19:27:22 -0500 Subject: [PATCH 44/71] [PATCH] VM: Fix typos in get_locked_pte Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds --- mm/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 5bfa52a98630..8d10b5540c73 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1146,12 +1146,12 @@ int zeromap_page_range(struct vm_area_struct *vma, return err; } -pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl) +pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl) { pgd_t * pgd = pgd_offset(mm, addr); pud_t * pud = pud_alloc(mm, pgd, addr); if (pud) { - pmd_t * pmd = pmd_alloc(mm, pgd, addr); + pmd_t * pmd = pmd_alloc(mm, pud, addr); if (pmd) return pte_alloc_map_lock(mm, pmd, addr, ptl); } From 8117ce76c28ef0cab8545b518fa0543f6d1437e6 Mon Sep 17 00:00:00 2001 From: Paolo Galtieri Date: Tue, 29 Nov 2005 14:26:47 -0800 Subject: [PATCH 45/71] [PATCH] ppc: fix floating point register corruption I recently discovered a bug on PPC which causes the floating point registers to get corrupted when CONFIG_PREEMPT=y. The problem occurred while running a multi threaded Java application that does floating point. The problem could be reproduced in anywhere from 2 to 6 hours. With the patch I have included below it ran for over a week without failure. Signed-off-by: Paolo Galtieri Cc: Kumar Gala Cc: Matt Porter Cc: Tom Rini Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc/kernel/process.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index cb1c7b92f8c6..25cbdc8d2941 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -417,6 +417,7 @@ void show_regs(struct pt_regs * regs) void exit_thread(void) { + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -425,10 +426,12 @@ void exit_thread(void) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); } void flush_thread(void) { + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -437,6 +440,7 @@ void flush_thread(void) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); } void @@ -535,6 +539,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) regs->nip = nip; regs->gpr[1] = sp; regs->msr = MSR_USER; + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -543,6 +548,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr.val = 0; #ifdef CONFIG_ALTIVEC From 48abec07cf8063184d397560a6a5f27eaf9caddf Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 30 Nov 2005 13:20:54 +1100 Subject: [PATCH 46/71] powerpc: Fix bug causing FP registers corruption on UP + preempt This fixes a bug noticed by Paolo Galtieri and fixed for ARCH=ppc in the previous commit (ppc: fix floating point register corruption). This fixes the arch/powerpc code by adding preempt_disable/enable, and also cleans it up a bit by pulling out the code that discards any lazily-switched CPU register state into a new function, rather than having that code repeated in three places. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 62 ++++++++++++++--------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index a5a7542a8ff3..105d5609ff57 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -201,6 +201,28 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) } #endif /* CONFIG_SPE */ +/* + * If we are doing lazy switching of CPU state (FP, altivec or SPE), + * and the current task has some state, discard it. + */ +static inline void discard_lazy_cpu_state(void) +{ +#ifndef CONFIG_SMP + preempt_disable(); + if (last_task_used_math == current) + last_task_used_math = NULL; +#ifdef CONFIG_ALTIVEC + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; +#endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_SPE + if (last_task_used_spe == current) + last_task_used_spe = NULL; +#endif + preempt_enable(); +#endif /* CONFIG_SMP */ +} + int set_dabr(unsigned long dabr) { if (ppc_md.set_dabr) @@ -434,19 +456,7 @@ void show_regs(struct pt_regs * regs) void exit_thread(void) { kprobe_flush_task(current); - -#ifndef CONFIG_SMP - if (last_task_used_math == current) - last_task_used_math = NULL; -#ifdef CONFIG_ALTIVEC - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif -#endif /* CONFIG_SMP */ + discard_lazy_cpu_state(); } void flush_thread(void) @@ -458,18 +468,7 @@ void flush_thread(void) t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); #endif -#ifndef CONFIG_SMP - if (last_task_used_math == current) - last_task_used_math = NULL; -#ifdef CONFIG_ALTIVEC - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif -#endif /* CONFIG_SMP */ + discard_lazy_cpu_state(); #ifdef CONFIG_PPC64 /* for now */ if (current->thread.dabr) { @@ -635,18 +634,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) } #endif -#ifndef CONFIG_SMP - if (last_task_used_math == current) - last_task_used_math = NULL; -#ifdef CONFIG_ALTIVEC - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#endif -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif -#endif /* CONFIG_SMP */ + discard_lazy_cpu_state(); memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr.val = 0; #ifdef CONFIG_ALTIVEC From ed1189b7e8cd8144f0b232c220aed4ee26d89463 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 29 Nov 2005 14:04:05 +0100 Subject: [PATCH 47/71] [PATCH] powerpc: prevent stack corruption in call_prom_ret Use the correct pointer to clear the memory of the return values, to prevent stack corruption in the callers stackframe. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 4ce0105c308e..bcdc209dca85 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -265,7 +265,7 @@ static int __init call_prom_ret(const char *service, int nargs, int nret, va_end(list); for (i = 0; i < nret; i++) - rets[nargs+i] = 0; + args.args[nargs+i] = 0; if (enter_prom(&args, RELOC(prom_entry)) < 0) return PROM_ERROR; From df69a60dc6afc2936d79054d30b481c1fd9720e5 Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Tue, 29 Nov 2005 19:34:31 -0800 Subject: [PATCH 48/71] [PATCH] process events connector: uid_t gid_t size issues The uid_t and gid_t fields appear to present a 32/64-bit userspace/kernel problem for some archs. This patch addresses the problem by fixing the size to the largest size for uid_t/gid_t used in the kernel. This preserves the total size of the event structure while ensuring that the layouts of the ID change event match in 32 and 64-bit kernels and applications. Signed-off-by: Matt Helsley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/cn_proc.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h index 70ab56317380..c948f678e04e 100644 --- a/include/linux/cn_proc.h +++ b/include/linux/cn_proc.h @@ -86,12 +86,12 @@ struct proc_event { pid_t process_pid; pid_t process_tgid; union { - uid_t ruid; /* current->uid */ - gid_t rgid; /* current->gid */ + __u32 ruid; /* task uid */ + __u32 rgid; /* task gid */ } r; union { - uid_t euid; - gid_t egid; + __u32 euid; + __u32 egid; } e; } id; From 5bd0190bf3d7e53043a048e809ffa29d41b9d6ac Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 29 Nov 2005 19:34:32 -0800 Subject: [PATCH 49/71] [PATCH] Fix crash when ptrace poking hugepage areas set_page_dirty() will not cope with being handed a page * which is part of a compound page, but not the master page in that compound page. This case can occur via access_process_vm() if you attemp to write to another process's hugepage memory area using ptrace() (causing an oops or hang). This patch fixes the bug by only calling set_page_dirty() from access_process_vm() if the page is not a compound page. We already use a similar fix in bio_set_pages_dirty() for the case of direct io to hugepages. Signed-off-by: David Gibson Acked-by: William Irwin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 17ee7e5a3451..656476eedb1b 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -241,7 +241,8 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in if (write) { copy_to_user_page(vma, page, addr, maddr + offset, buf, bytes); - set_page_dirty_lock(page); + if (!PageCompound(page)) + set_page_dirty_lock(page); } else { copy_from_user_page(vma, page, addr, buf, maddr + offset, bytes); From d91b14c463306eb6527550ba48617e7f5500d3ae Mon Sep 17 00:00:00 2001 From: Thierry Vignaud Date: Tue, 29 Nov 2005 19:34:35 -0800 Subject: [PATCH 50/71] [PATCH] fix rebooting on HP nc6120 laptop Anne NICOLAS and Andres Kaaber reported their HP laptop didn't reboot smoothly. Signed-off-by: Thierry Vignaud Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/reboot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 350ea6680f63..2afe0f8d555a 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -111,6 +111,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), }, }, + { /* Handle problems with rebooting on HP nc6120 */ + .callback = set_bios_reboot, + .ident = "HP Compaq nc6120", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"), + }, + }, { } }; From 123d3c13e2853a11b4d599d754b356acb12886e2 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 29 Nov 2005 19:34:37 -0800 Subject: [PATCH 51/71] [PATCH] fix swsusp on machines not supporting S4 Fix swsusp on machines not supporting S4. With recent changes, it is not possible to trigger it using /sys filesystem. Swsusp does not really need any support from low-level code, it is possible to reboot or halt at the end of suspend. Signed-off-by: Pavel Machek Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/main.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/kernel/power/main.c b/kernel/power/main.c index 6ee2cad530e8..d253f3ae2fa5 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -24,7 +24,7 @@ DECLARE_MUTEX(pm_sem); -struct pm_ops * pm_ops = NULL; +struct pm_ops *pm_ops; suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN; /** @@ -151,6 +151,18 @@ static char *pm_states[PM_SUSPEND_MAX] = { #endif }; +static inline int valid_state(suspend_state_t state) +{ + /* Suspend-to-disk does not really need low-level support. + * It can work with reboot if needed. */ + if (state == PM_SUSPEND_DISK) + return 1; + + if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) + return 0; + return 1; +} + /** * enter_state - Do common work of entering low-power state. @@ -167,7 +179,7 @@ static int enter_state(suspend_state_t state) { int error; - if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) + if (!valid_state(state)) return -ENODEV; if (down_trylock(&pm_sem)) return -EBUSY; @@ -238,9 +250,8 @@ static ssize_t state_show(struct subsystem * subsys, char * buf) char * s = buf; for (i = 0; i < PM_SUSPEND_MAX; i++) { - if (pm_states[i] && pm_ops && (!pm_ops->valid - ||(pm_ops->valid && pm_ops->valid(i)))) - s += sprintf(s,"%s ",pm_states[i]); + if (pm_states[i] && valid_state(i)) + s += sprintf(s,"%s ", pm_states[i]); } s += sprintf(s,"\n"); return (s - buf); From 9f232a125bf86b0dae09f8ea4a0553535cf6b658 Mon Sep 17 00:00:00 2001 From: Paolo Galtieri Date: Tue, 29 Nov 2005 19:34:38 -0800 Subject: [PATCH 52/71] [PATCH] ppc: fix floating point register corruption I recently discovered a bug on PPC which causes the floating point registers to get corrupted when CONFIG_PREEMPT=y. The problem occurred while running a multi threaded Java application that does floating point. The problem could be reproduced in anywhere from 2 to 6 hours. With the patch I have included below it ran for over a week without failure. Signed-off-by: Paolo Galtieri Cc: Kumar Gala Cc: Matt Porter Cc: Tom Rini Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/kernel/process.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index cb1c7b92f8c6..25cbdc8d2941 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -417,6 +417,7 @@ void show_regs(struct pt_regs * regs) void exit_thread(void) { + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -425,10 +426,12 @@ void exit_thread(void) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); } void flush_thread(void) { + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -437,6 +440,7 @@ void flush_thread(void) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); } void @@ -535,6 +539,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) regs->nip = nip; regs->gpr[1] = sp; regs->msr = MSR_USER; + preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; if (last_task_used_altivec == current) @@ -543,6 +548,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) if (last_task_used_spe == current) last_task_used_spe = NULL; #endif + preempt_enable(); memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr.val = 0; #ifdef CONFIG_ALTIVEC From 576f6d79564d0d2c1f43088e6805674d2e122935 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Tue, 29 Nov 2005 19:34:39 -0800 Subject: [PATCH 53/71] [PATCH] reiserfs: handle cnode allocation failure gracefully If an external device is used for a journal, by default it will use the entire device. The reiserfs journal code allocates structures per journal block when it mounts the file system. If the journal device is too large, and memory cannot be allocated for the structures, it will continue and ultimately panic when it can't pull one off the free list. This patch handles the allocation failure gracefully and prints an error message at mount time. Changes: Updated error message to be more descriptive to the user. Discussed and approved on ReiserFS Mailing List, Nov 28. Signed-off-by: Jeff Mahoney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 4b15761434bc..68b7b78638ff 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2757,6 +2757,15 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, journal->j_cnode_used = 0; journal->j_must_wait = 0; + if (journal->j_cnode_free == 0) { + reiserfs_warning(p_s_sb, "journal-2004: Journal cnode memory " + "allocation failed (%ld bytes). Journal is " + "too large for available memory. Usually " + "this is due to a journal that is too large.", + sizeof (struct reiserfs_journal_cnode) * num_cnodes); + goto free_and_return; + } + init_journal_hash(p_s_sb); jl = journal->j_current_jl; jl->j_list_bitmap = get_list_bitmap(p_s_sb, jl); From b0b623c3b22d57d6941b200321779d56c4e79e6b Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Tue, 29 Nov 2005 19:34:41 -0800 Subject: [PATCH 54/71] [PATCH] hfsplus: don't modify journaled volume Access to a journaled HFS+ volume is not officially supported under Linux, so mount such a volume read-only, but users can override this behaviour using the "force" mount option. The minimum requirement to relax this check is to at least check that the journal is empty and so nothing needs to be replayed to make sure the volume is consistent. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfsplus/hfsplus_fs.h | 1 + fs/hfsplus/hfsplus_raw.h | 12 +++++++----- fs/hfsplus/options.c | 6 +++++- fs/hfsplus/super.c | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index c60e5635498d..df16fcbff3fb 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -151,6 +151,7 @@ struct hfsplus_sb_info { #define HFSPLUS_SB_WRITEBACKUP 0x0001 #define HFSPLUS_SB_NODECOMPOSE 0x0002 +#define HFSPLUS_SB_FORCE 0x0004 struct hfsplus_inode_info { diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 5bad37cfdb29..b4fbed633219 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h @@ -123,11 +123,13 @@ struct hfsplus_vh { } __packed; /* HFS+ volume attributes */ -#define HFSPLUS_VOL_UNMNT (1 << 8) -#define HFSPLUS_VOL_SPARE_BLK (1 << 9) -#define HFSPLUS_VOL_NOCACHE (1 << 10) -#define HFSPLUS_VOL_INCNSTNT (1 << 11) -#define HFSPLUS_VOL_SOFTLOCK (1 << 15) +#define HFSPLUS_VOL_UNMNT (1 << 8) +#define HFSPLUS_VOL_SPARE_BLK (1 << 9) +#define HFSPLUS_VOL_NOCACHE (1 << 10) +#define HFSPLUS_VOL_INCNSTNT (1 << 11) +#define HFSPLUS_VOL_NODEID_REUSED (1 << 12) +#define HFSPLUS_VOL_JOURNALED (1 << 13) +#define HFSPLUS_VOL_SOFTLOCK (1 << 15) /* HFS+ BTree node descriptor */ struct hfs_bnode_desc { diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index cca0818aa4ca..935dafba0078 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -22,7 +22,7 @@ enum { opt_umask, opt_uid, opt_gid, opt_part, opt_session, opt_nls, opt_nodecompose, opt_decompose, - opt_err + opt_force, opt_err }; static match_table_t tokens = { @@ -36,6 +36,7 @@ static match_table_t tokens = { { opt_nls, "nls=%s" }, { opt_decompose, "decompose" }, { opt_nodecompose, "nodecompose" }, + { opt_force, "force" }, { opt_err, NULL } }; @@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) case opt_nodecompose: sbi->flags |= HFSPLUS_SB_NODECOMPOSE; break; + case opt_force: + sbi->flags |= HFSPLUS_SB_FORCE; + break; default: return 0; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0ce1c455ae55..8093351bd7c3 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -251,16 +251,28 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) return 0; if (!(*flags & MS_RDONLY)) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; + struct hfsplus_sb_info sbi; + + memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); + sbi.nls = HFSPLUS_SB(sb).nls; + if (!hfsplus_parse_options(data, &sbi)) + return -EINVAL; if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; + } else if (sbi.flags & HFSPLUS_SB_FORCE) { + /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; + } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { + printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n"); + sb->s_flags |= MS_RDONLY; + *flags |= MS_RDONLY; } } return 0; @@ -352,11 +364,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. mounting read-only.\n"); sb->s_flags |= MS_RDONLY; + } else if (sbi->flags & HFSPLUS_SB_FORCE) { + /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { if (!silent) printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; + } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { + if (!silent) + printk("HFS+-fs: write access to a jounaled filesystem is not supported, " + "use the force option at your own risk, mounting read-only.\n"); + sb->s_flags |= MS_RDONLY; } + sbi->flags &= ~HFSPLUS_SB_FORCE; /* Load metadata objects (B*Trees) */ HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); From fe655d3a06488c8a188461bca493e9f23fc8c448 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 29 Nov 2005 19:34:42 -0800 Subject: [PATCH 55/71] [PATCH] setting irq affinity is broken in ia32 with MSI enabled Setting irq affinity stops working when MSI is enabled. With MSI, move_irq is empty, so we can't change irq affinity. It appears a typo in Ashok's original commit for this issue. X86_64 actually is using move_native_irq. Signed-off-by: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/io_apic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index cc5d7ac5b2e7..22c8675c79f4 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2009,7 +2009,7 @@ static void ack_edge_ioapic_vector(unsigned int vector) { int irq = vector_to_irq(vector); - move_irq(vector); + move_native_irq(vector); ack_edge_ioapic_irq(irq); } @@ -2024,7 +2024,7 @@ static void end_level_ioapic_vector (unsigned int vector) { int irq = vector_to_irq(vector); - move_irq(vector); + move_native_irq(vector); end_level_ioapic_irq(irq); } From 49d5c7b08713c3a482d62b5a0ad41b4ec32905a5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 29 Nov 2005 19:34:43 -0800 Subject: [PATCH 56/71] [PATCH] fbdev: cirrusfb: Driver cleanup and bug fixes - pseudo_palette is only 16 entries long - the pseudo_palette, if using the generic drawing functions, must always be u32 regardless of bpp - the fillrect accelerator is using region->color regardless of the visual. region->color is the index to the pseudo_palette if visual is truecolor Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cirrusfb.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 2858c5c8ba3c..e0dbdfc0c8b4 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -404,7 +404,7 @@ struct cirrusfb_info { struct cirrusfb_regs currentmode; int blank_mode; - u32 pseudo_palette[17]; + u32 pseudo_palette[16]; struct { u8 red, green, blue, pad; } palette[256]; #ifdef CONFIG_ZORRO @@ -1603,14 +1603,14 @@ static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green, switch (info->var.bits_per_pixel) { case 8: - ((u8*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; case 16: - ((u16*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; case 24: case 32: - ((u32*)(info->pseudo_palette))[regno] = v; + cinfo->pseudo_palette[regno] = v; break; } return 0; @@ -2020,18 +2020,21 @@ static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo, const struct fb_fillrect *region) { int m; /* bytes per pixel */ + u32 color = (cinfo->info->fix.visual == FB_VISUAL_TRUECOLOR) ? + cinfo->pseudo_palette[region->color] : region->color; + if(cinfo->info->var.bits_per_pixel == 1) { cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, region->dx / 8, region->dy, region->width / 8, region->height, - region->color, + color, cinfo->currentmode.line_length); } else { m = ( cinfo->info->var.bits_per_pixel + 7 ) / 8; cirrusfb_RectFill(cinfo->regbase, cinfo->info->var.bits_per_pixel, region->dx * m, region->dy, region->width * m, region->height, - region->color, + color, cinfo->currentmode.line_length); } return; From 1a57198609615a936ff57da37b6957db9bafde83 Mon Sep 17 00:00:00 2001 From: Mark Fortescue Date: Tue, 29 Nov 2005 19:34:44 -0800 Subject: [PATCH 57/71] [PATCH] fbdev: cg3fb: Kconfig fix A cut and past error regarding the CG3 frame buffer needs to be fixed. It also affects Creator/Creator3D/Elite3D. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 25b6ca6ad081..3e470c8b4193 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -534,6 +534,12 @@ config FB_SUN3 bool "Sun3 framebuffer support" depends on (FB = y) && (SUN3 || SUN3X) && BROKEN +config FB_SBUS + bool "SBUS and UPA framebuffers" + depends on (FB = y) && (SPARC32 || SPARC64) + help + Say Y if you want support for SBUS or UPA based frame buffer device. + config FB_BW2 bool "BWtwo support" depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) @@ -546,6 +552,7 @@ config FB_BW2 config FB_CG3 bool "CGthree support" depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) + select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT help @@ -1210,12 +1217,6 @@ config FB_AU1100 source "drivers/video/geode/Kconfig" -config FB_SBUS - bool "SBUS and UPA framebuffers" - depends on (FB = y) && (SPARC32 || SPARC64) - help - Say Y if you want support for SBUS or UPA based frame buffer device. - config FB_FFB bool "Creator/Creator3D/Elite3D support" depends on FB_SBUS && SPARC64 From 6473a559c336d5c407f9df412ca2f55357767ff8 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Nov 2005 20:20:10 -0800 Subject: [PATCH 58/71] [CIFS] Fix missing permission check on setattr when noperm mount option is disabled. Also set mode, uid, gid better on mkdir and create for the case when Unix Extensions is not enabled and setuids is enabled. This is necessary to fix the hole in which chown could be allowed for non-root users in some cases if root mounted, and also to display the mode and uid properly in some cases. Signed-off-by: Steve French --- fs/cifs/CHANGES | 2 +- fs/cifs/README | 30 ++++++++++++++++++++++++------ fs/cifs/TODO | 4 ++-- fs/cifs/dir.c | 9 ++++++++- fs/cifs/inode.c | 28 +++++++++++++++++++++++++--- 5 files changed, 60 insertions(+), 13 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index c40bd0df80ad..943ef9b82244 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -6,7 +6,7 @@ stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 Fix SFU style symlinks and mknod needed for servers which do not support the CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative dentries so files that the client sees as deleted but that later get created -on the server will be recognized. +on the server will be recognized. Add client side permission check on setattr. Version 1.38 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index bb90941826ad..e5d09a2fc7a5 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -278,7 +278,9 @@ A partial list of the supported mount options follows: (such as Windows), permissions can also be checked at the client, and a crude form of client side permission checking can be enabled by specifying file_mode and dir_mode on - the client + the client. Note that the mount.cifs helper must be + at version 1.10 or higher to support specifying the uid + (or gid) in non-numberic form. gid If CIFS Unix extensions are not supported by the server this overrides the default gid for inodes. file_mode If CIFS Unix extensions are not supported by the server @@ -345,7 +347,10 @@ A partial list of the supported mount options follows: client system. It is typically only needed when the server supports the CIFS Unix Extensions but the UIDs/GIDs on the client and server system do not match closely enough to allow - access by the user doing the mount. + access by the user doing the mount, but it may be useful with + non CIFS Unix Extension mounts for cases in which the default + mode is specified on the mount but is not to be enforced on the + client (e.g. perhaps when MultiUserMount is enabled) Note that this does not affect the normal ACL check on the target machine done by the server software (of the server ACL against the user name provided at mount time). @@ -368,15 +373,21 @@ A partial list of the supported mount options follows: setuids If the CIFS Unix extensions are negotiated with the server the client will attempt to set the effective uid and gid of the local process on newly created files, directories, and - devices (create, mkdir, mknod). + devices (create, mkdir, mknod). If the CIFS Unix Extensions + are not negotiated, for newly created files and directories + instead of using the default uid and gid specified on the + the mount, cache the new file's uid and gid locally which means + that the uid for the file can change when the inode is + reloaded (or the user remounts the share). nosetuids The client will not attempt to set the uid and gid on on newly created files, directories, and devices (create, mkdir, mknod) which will result in the server setting the uid and gid to the default (usually the server uid of the user who mounted the share). Letting the server (rather than - the client) set the uid and gid is the default. This - parameter has no effect if the CIFS Unix Extensions are not - negotiated. + the client) set the uid and gid is the default. If the CIFS + Unix Extensions are not negotiated then the uid and gid for + new files will appear to be the uid (gid) of the mounter or the + uid (gid) parameter specified on the mount. netbiosname When mounting to servers via port 139, specifies the RFC1001 source name to use to represent the client netbios machine name when doing the RFC1001 netbios session initialize. @@ -418,6 +429,13 @@ A partial list of the supported mount options follows: byte range locks). remount remount the share (often used to change from ro to rw mounts or vice versa) + sfu When the CIFS Unix Extensions are not negotiated, attempt to + create device files and fifos in a format compatible with + Services for Unix (SFU). In addition retrieve bits 10-12 + of the mode via the SETFILEBITS extended attribute (as + SFU does). In the future the bottom 9 bits of the mode + mode also will be emulated using queries of the security + descriptor (ACL). The mount.cifs mount helper also accepts a few mount options before -o including: diff --git a/fs/cifs/TODO b/fs/cifs/TODO index c909298d11ed..fc34c74ec4be 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -version 1.37 October 9, 2005 +Version 1.39 November 30, 2005 A Partial List of Missing Features ================================== @@ -58,7 +58,7 @@ o) Improve performance of readpages by sending more than one read at a time when 8 pages or more are requested. In conjuntion add support for async_cifs_readpages. -p) Add support for storing symlink and fifo info to Windows servers +p) Add support for storing symlink info to Windows servers in the Extended Attribute format their SFU clients would recognize. q) Finish fcntl D_NOTIFY support so kde and gnome file list windows diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index aa4ea965b329..32cc96cafa3e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -228,8 +228,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else { rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,xid); - if(newinode) + if(newinode) { newinode->i_mode = mode; + if((oplock & CIFS_CREATE_ACTION) && + (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_SET_UID)) { + newinode->i_uid = current->fsuid; + newinode->i_gid = current->fsgid; + } + } } if (rc != 0) { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d34325c887c4..053c1cadf703 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -710,7 +710,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) char *full_path = NULL; struct inode *newinode = NULL; - cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); + cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); xid = GetXid(); @@ -768,7 +768,16 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) /* BB to be implemented via Windows secrty descriptors eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, -1, -1, local_nls); */ - } + if(direntry->d_inode) { + direntry->d_inode->i_mode = mode; + if(cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_SET_UID) { + direntry->d_inode->i_uid = + current->fsuid; + direntry->d_inode->i_gid = + current->fsgid; + } + } } kfree(full_path); FreeXid(xid); @@ -1111,9 +1120,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", direntry->d_name.name, attrs->ia_valid)); + cifs_sb = CIFS_SB(direntry->d_inode->i_sb); pTcon = cifs_sb->tcon; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM == 0) { + /* check if we have permission to change attrs */ + rc = inode_change_ok(direntry->d_inode, attrs); + if(rc < 0) { + FreeXid(xid); + return rc; + } else + rc = 0; + } + down(&direntry->d_sb->s_vfs_rename_sem); full_path = build_path_from_dentry(direntry); up(&direntry->d_sb->s_vfs_rename_sem); @@ -1153,7 +1173,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) 1 /* 45 seconds */); cFYI(1,("Wrt seteof rc %d", rc)); } - } + } else + rc = -EINVAL; + if (rc != 0) { /* Set file size by pathname rather than by handle either because no valid, writeable file handle for From 6ab16d249513a50bef3f1b275cea6aa8d3f51832 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Nov 2005 20:55:11 -0800 Subject: [PATCH 59/71] [CIFS] Fix umount --force to wake up the pending response queue, not just the request queue. Also periodically wakeup response_q so threads can check if stuck requests have timed out. Workaround Windows server illegal smb length on transact2 findfirst response. Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 23 ++++++++++++++++++++++- fs/cifs/cifssmb.c | 25 +++++++++++++++++++++++++ fs/cifs/misc.c | 17 ++++++++++++----- fs/cifs/netmisc.c | 4 ++-- fs/cifs/transport.c | 1 + 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 51548ed2e9cc..f4974b41e485 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "cifsfs.h" #include "cifspdu.h" #define DECLARE_GLOBALS_HERE @@ -429,6 +430,11 @@ static void cifs_umount_begin(struct super_block * sblock) { cFYI(1,("wake up tasks now - umount begin not complete")); wake_up_all(&tcon->ses->server->request_q); + wake_up_all(&tcon->ses->server->response_q); + msleep(1); /* yield */ + /* we have to kick the requests once more */ + wake_up_all(&tcon->ses->server->response_q); + msleep(1); } /* BB FIXME - finish add checks for tidStatus BB */ @@ -895,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg) static int cifs_dnotify_thread(void * dummyarg) { + struct list_head *tmp; + struct cifsSesInfo *ses; + daemonize("cifsdnotifyd"); allow_signal(SIGTERM); @@ -903,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg) if(try_to_freeze()) continue; set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(39*HZ); + schedule_timeout(15*HZ); + read_lock(&GlobalSMBSeslock); + /* check if any stuck requests that need + to be woken up and wakeq so the + thread can wake up and error out */ + list_for_each(tmp, &GlobalSMBSessionList) { + ses = list_entry(tmp, struct cifsSesInfo, + cifsSessionList); + if(ses && ses->server && + atomic_read(&ses->server->inSend)) + wake_up_all(&ses->server->response_q); + } + read_unlock(&GlobalSMBSeslock); } while(!signal_pending(current)); complete_and_exit (&cifs_dnotify_exited, 0); } diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d179b0c3eee4..6867e556d37e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, check for tcp and smb session status done differently for those three - in the calling routine */ if(tcon) { + if(tcon->tidStatus == CifsExiting) { + /* only tree disconnect, open, and write, + (and ulogoff which does not have tcon) + are allowed as we start force umount */ + if((smb_command != SMB_COM_WRITE_ANDX) && + (smb_command != SMB_COM_OPEN_ANDX) && + (smb_command != SMB_COM_TREE_DISCONNECT)) { + cFYI(1,("can not send cmd %d while umounting", + smb_command)); + return -ENODEV; + } + } if((tcon->ses) && (tcon->ses->status != CifsExiting) && (tcon->ses->server)){ struct nls_table *nls_codepage; @@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, check for tcp and smb session status done differently for those three - in the calling routine */ if(tcon) { + if(tcon->tidStatus == CifsExiting) { + /* only tree disconnect, open, and write, + (and ulogoff which does not have tcon) + are allowed as we start force umount */ + if((smb_command != SMB_COM_WRITE_ANDX) && + (smb_command != SMB_COM_OPEN_ANDX) && + (smb_command != SMB_COM_TREE_DISCONNECT)) { + cFYI(1,("can not send cmd %d while umounting", + smb_command)); + return -ENODEV; + } + } + if((tcon->ses) && (tcon->ses->status != CifsExiting) && (tcon->ses->server)){ struct nls_table *nls_codepage; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index ca27a82c54cd..94baf6c8ecbd 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -397,12 +397,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) if(smb->Command == SMB_COM_LOCKING_ANDX) return 0; else - cERROR(1, ("Rcvd Request not response ")); + cERROR(1, ("Rcvd Request not response")); } } else { /* bad signature or mid */ if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) cERROR(1, - ("Bad protocol string signature header %x ", + ("Bad protocol string signature header %x", *(unsigned int *) smb->Protocol)); if (mid != smb->Mid) cERROR(1, ("Mids do not match")); @@ -417,7 +417,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) __u32 len = smb->smb_buf_length; __u32 clc_len; /* calculated length */ cFYI(0, - ("Entering checkSMB with Length: %x, smb_buf_length: %x ", + ("Entering checkSMB with Length: %x, smb_buf_length: %x", length, len)); if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { @@ -451,9 +451,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); /* Windows XP can return a few bytes too much, presumably an illegal pad, at the end of byte range lock responses - so we allow for up to eight byte pad, as long as actual + so we allow for that three byte pad, as long as actual received length is as long or longer than calculated length */ - if((4+len > clc_len) && (len <= clc_len + 3)) + /* We have now had to extend this more, since there is a + case in which it needs to be bigger still to handle a + malformed response to transact2 findfirst from WinXP when + access denied is returned and thus bcc and wct are zero + but server says length is 0x21 bytes too long as if the server + forget to reset the smb rfc1001 length when it reset the + wct and bcc to minimum size and drop the t2 parms and data */ + if((4+len > clc_len) && (len <= clc_len + 512)) return 0; else return 1; diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f7814689844b..5de74d216fdd 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -330,7 +330,7 @@ static const struct { ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { - ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { + ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { @@ -676,7 +676,7 @@ static const struct { ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { - ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, { + ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, { ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 41a9659c16bc..f8871196098c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -515,6 +515,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, *pbytes_returned = in_buf->smb_buf_length; /* BB special case reconnect tid and uid here? */ + /* BB special case Errbadpassword and pwdexpired here */ rc = map_smb_to_linux_error(in_buf); /* convert ByteCount if necessary */ From 2a138ebb012ac42c082ae8b40c87c1f265664391 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Nov 2005 21:22:19 -0800 Subject: [PATCH 60/71] [CIFS] Missing parenthesis and typo in previous fix Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- fs/cifs/inode.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f4974b41e485..2a13a2bac8f1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -921,7 +921,7 @@ static int cifs_dnotify_thread(void * dummyarg) ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); if(ses && ses->server && - atomic_read(&ses->server->inSend)) + atomic_read(&ses->server->inFlight)) wake_up_all(&ses->server->response_q); } read_unlock(&GlobalSMBSeslock); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 053c1cadf703..e8773461c7f7 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -778,6 +778,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) current->fsgid; } } + } } kfree(full_path); FreeXid(xid); @@ -1124,7 +1125,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) cifs_sb = CIFS_SB(direntry->d_inode->i_sb); pTcon = cifs_sb->tcon; - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM == 0) { + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { /* check if we have permission to change attrs */ rc = inode_change_ok(direntry->d_inode, attrs); if(rc < 0) { From 9632051963cb6e6f7412990f8b962209b9334e13 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 29 Nov 2005 22:27:14 +0100 Subject: [PATCH 61/71] [PATCH] hwmon: w83792d fix unused fan pins 1. This patch add check for fan4,5,6,7 and do not create device file if their pins are not configured as fan. 2. Fix the issue that can not set fan divisor to 128. 3. Fix the index out of bounds bug in w83792d_detect function. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 4be59dbb78c4..1ba072630361 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -193,6 +193,7 @@ static const u8 W83792D_REG_LEVELS[3][4] = { 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */ }; +#define W83792D_REG_GPIO_EN 0x1A #define W83792D_REG_CONFIG 0x40 #define W83792D_REG_VID_FANDIV 0x47 #define W83792D_REG_CHIPID 0x49 @@ -257,7 +258,7 @@ DIV_TO_REG(long val) { int i; val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { if (val == 0) break; val >>= 1; @@ -1282,8 +1283,8 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) w83792d_init_client(new_client); /* A few vars need to be filled upon startup */ - for (i = 1; i <= 7; i++) { - data->fan_min[i - 1] = w83792d_read_value(new_client, + for (i = 0; i < 7; i++) { + data->fan_min[i] = w83792d_read_value(new_client, W83792D_REG_FAN_MIN[i]); } @@ -1306,10 +1307,20 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file_fan(new_client, 1); device_create_file_fan(new_client, 2); device_create_file_fan(new_client, 3); - device_create_file_fan(new_client, 4); - device_create_file_fan(new_client, 5); - device_create_file_fan(new_client, 6); - device_create_file_fan(new_client, 7); + + /* Read GPIO enable register to check if pins for fan 4,5 are used as + GPIO */ + val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); + if (!(val1 & 0x40)) + device_create_file_fan(new_client, 4); + if (!(val1 & 0x20)) + device_create_file_fan(new_client, 5); + + val1 = w83792d_read_value(new_client, W83792D_REG_PIN); + if (val1 & 0x40) + device_create_file_fan(new_client, 6); + if (val1 & 0x04) + device_create_file_fan(new_client, 7); device_create_file_temp1(new_client); /* Temp1 */ device_create_file_temp_add(new_client, 2); /* Temp2 */ From c9d6073fb3cda856132dd544d537679f9715436c Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Thu, 24 Nov 2005 20:41:06 +1100 Subject: [PATCH 62/71] [PATCH] pci_ids.h: remove duplicate entries G'day Albert, Andrew, commit 4fb80634d30f5e639a92b78c8f215f96a61ba8c7 Author: Albert Lee Date: Thu May 12 15:49:21 2005 -0400 duplicates symbols already appearing in pci_ids.h, appended patch removes them again :o) From: Grant Coady pci_ids: commit 4fb80634d30f5e639a92b78c8f215f96a61ba8c7 duplicated a couple existing symbols in pci_ids.h, remove them. Signed-off-by: Grant Coady Signed-off-by: Greg Kroah-Hartman --- include/linux/pci_ids.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1e737e269db9..53e3293051d4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -387,7 +387,6 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 @@ -489,8 +488,6 @@ #define PCI_DEVICE_ID_AMD_8151_0 0x7454 #define PCI_DEVICE_ID_AMD_8131_APIC 0x7450 -#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A - #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 From 620948a01c71060a32611bc2f792f58a88cf28b1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 28 Nov 2005 15:22:55 -0500 Subject: [PATCH 63/71] [PATCH] USB: documentation update This patch (as611) fixes a minor mistake and misspelling in the USB documentation. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/error-codes.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt index 1e36f1661cd0..867f4c38f356 100644 --- a/Documentation/usb/error-codes.txt +++ b/Documentation/usb/error-codes.txt @@ -46,8 +46,9 @@ USB-specific: -EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable in the current interface altsetting. - (b) ISO packet is biger than endpoint maxpacket - (c) requested data transfer size is invalid (negative) + (b) ISO packet is larger than the endpoint maxpacket. + (c) requested data transfer length is invalid: negative + or too large for the host controller. -ENOSPC This request would overcommit the usb bandwidth reserved for periodic transfers (interrupt, isochronous). From d3420ba4930d61f4ec4abc046765de274182b4ed Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 28 Nov 2005 13:44:52 -0500 Subject: [PATCH 64/71] [PATCH] Additional device ID for Conexant AccessRunner USB driver Reported as working in Fedora bugzilla by Petr. From: Petr Tuma Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 79861ee12a29..9d59dc62e6d2 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -787,6 +787,9 @@ static const struct usb_device_id cxacru_usb_ids[] = { { /* V = Conexant P = ADSL modem (Hasbani project) */ USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00 }, + { /* V = Conexant P = ADSL modem (Well PTI-800 */ + USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00 + }, { /* V = Conexant P = ADSL modem */ USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 }, From 8de98402652c01839ae321be6cb3054cf5735d83 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 25 Nov 2005 09:59:46 +1100 Subject: [PATCH 65/71] [PATCH] USB: Fix USB suspend/resume crasher (#2) This patch closes the IRQ race and makes various other OHCI & EHCI code path safer vs. suspend/resume. I've been able to (finally !) successfully suspend and resume various Mac models, with or without USB mouse plugged, or plugging while asleep, or unplugging while asleep etc... all without a crash. Alan, please verify the UHCI bit I did, I only verified that it builds. It's very simple so I wouldn't expect any issue there. If you aren't confident, then just drop the hunks that change uhci-hcd.c I also made the patch a little bit more "safer" by making sure the store to the interrupt register that disables interrupts is not posted before I set the flag and drop the spinlock. Without this patch, you cannot reliably sleep/wakeup any recent Mac, and I suspect PCs have some more sneaky issues too (they don't frankly crash with machine checks because x86 tend to silently swallow PCI errors but that won't last afaik, at least PCI Express will blow up in those situations, but the USB code may still misbehave). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 3 ++- drivers/usb/core/hcd.c | 15 ++++++++++----- drivers/usb/core/hcd.h | 7 ++++++- drivers/usb/host/ehci-pci.c | 27 ++++++++++++++++++++++++++- drivers/usb/host/ehci-q.c | 24 ++++++++++++++++-------- drivers/usb/host/ehci-sched.c | 18 ++++++++++++++++-- drivers/usb/host/ohci-hcd.c | 6 +++++- drivers/usb/host/ohci-hub.c | 24 ++++++++++++++++++++---- drivers/usb/host/ohci-pci.c | 27 +++++++++++++++++++++++++-- drivers/usb/host/uhci-hcd.c | 6 ++++++ 10 files changed, 132 insertions(+), 25 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5131d88e8c5b..29b5b2a6e183 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -219,6 +219,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) goto done; } } + synchronize_irq(dev->irq); /* FIXME until the generic PM interfaces change a lot more, this * can't use PCI D1 and D2 states. For example, the confusion @@ -392,7 +393,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) dev->dev.power.power_state = PMSG_ON; - hcd->saw_irq = 0; + clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); if (hcd->driver->resume) { retval = hcd->driver->resume(hcd); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5e5f65a475ab..da24c31ee00d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1315,11 +1315,12 @@ static int hcd_unlink_urb (struct urb *urb, int status) * finish unlinking the initial failed usb_set_address() * or device descriptor fetch. */ - if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { + if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) + && hcd->self.root_hub != urb->dev) { dev_warn (hcd->self.controller, "Unlink after no-IRQ? " "Controller is probably using the wrong IRQ." "\n"); - hcd->saw_irq = 1; + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); } urb->status = status; @@ -1649,13 +1650,15 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) struct usb_hcd *hcd = __hcd; int start = hcd->state; - if (start == HC_STATE_HALT) + if (unlikely(start == HC_STATE_HALT || + !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) return IRQ_NONE; if (hcd->driver->irq (hcd, r) == IRQ_NONE) return IRQ_NONE; - hcd->saw_irq = 1; - if (hcd->state == HC_STATE_HALT) + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (unlikely(hcd->state == HC_STATE_HALT)) usb_hc_died (hcd); return IRQ_HANDLED; } @@ -1768,6 +1771,8 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_info(hcd->self.controller, "%s\n", hcd->product_desc); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* till now HC has been in an indeterminate state ... */ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { dev_err(hcd->self.controller, "can't reset\n"); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 24a62a2ff86d..c8a1b350e2cf 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -72,7 +72,12 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ * hardware info/state */ const struct hc_driver *driver; /* hw-specific hooks */ - unsigned saw_irq : 1; + + /* Flags that need to be manipulated atomically */ + unsigned long flags; +#define HCD_FLAG_HW_ACCESSIBLE 0x00000001 +#define HCD_FLAG_SAW_IRQ 0x00000002 + unsigned can_wakeup:1; /* hw supports wakeup? */ unsigned remote_wakeup:1;/* sw should use wakeup? */ unsigned rh_registered:1;/* is root hub registered? */ diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 441c26064b44..14fff5714c1e 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -228,14 +228,36 @@ static int ehci_pci_reset(struct usb_hcd *hcd) static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; + int rc = 0; if (time_before(jiffies, ehci->next_statechange)) msleep(10); + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave (&ehci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + writel (0, &ehci->regs->intr_enable); + (void)readl(&ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ehci->lock, flags); + // could save FLADJ in case of Vaux power loss // ... we'd only use it to handle clock skew - return 0; + return rc; } static int ehci_pci_resume(struct usb_hcd *hcd) @@ -251,6 +273,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd) if (time_before(jiffies, ehci->next_statechange)) msleep(100); + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* If CF is clear, we lost PCI Vaux power and need to restart. */ if (readl(&ehci->regs->configured_flag) != FLAG_CF) goto restart; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5bb872c3496d..bf03ec0d8ee2 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -912,6 +912,7 @@ submit_async ( int epnum; unsigned long flags; struct ehci_qh *qh = NULL; + int rc = 0; qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); epnum = ep->desc.bEndpointAddress; @@ -926,21 +927,28 @@ submit_async ( #endif spin_lock_irqsave (&ehci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) { + rc = -ESHUTDOWN; + goto done; + } + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); + if (unlikely(qh == NULL)) { + rc = -ENOMEM; + goto done; + } /* Control/bulk operations through TTs don't need scheduling, * the HC and TT handle it when the TT has a buffer ready. */ - if (likely (qh != NULL)) { - if (likely (qh->qh_state == QH_STATE_IDLE)) - qh_link_async (ehci, qh_get (qh)); - } + if (likely (qh->qh_state == QH_STATE_IDLE)) + qh_link_async (ehci, qh_get (qh)); + done: spin_unlock_irqrestore (&ehci->lock, flags); - if (unlikely (qh == NULL)) { + if (unlikely (qh == NULL)) qtd_list_free (ehci, urb, qtd_list); - return -ENOMEM; - } - return 0; + return rc; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f0c8aa1ccd5d..57e77374d228 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -602,6 +602,12 @@ static int intr_submit ( spin_lock_irqsave (&ehci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) { + status = -ESHUTDOWN; + goto done; + } + /* get qh and force any scheduling errors */ INIT_LIST_HEAD (&empty); qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); @@ -1456,7 +1462,11 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - status = iso_stream_schedule (ehci, urb, stream); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) + status = -ESHUTDOWN; + else + status = iso_stream_schedule (ehci, urb, stream); if (likely (status == 0)) itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); spin_unlock_irqrestore (&ehci->lock, flags); @@ -1815,7 +1825,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - status = iso_stream_schedule (ehci, urb, stream); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) + status = -ESHUTDOWN; + else + status = iso_stream_schedule (ehci, urb, stream); if (status == 0) sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); spin_unlock_irqrestore (&ehci->lock, flags); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5c0c6c8a7a82..bf1d9abc07ac 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -115,7 +115,7 @@ /*-------------------------------------------------------------------------*/ -// #define OHCI_VERBOSE_DEBUG /* not always helpful */ +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR @@ -253,6 +253,10 @@ static int ohci_urb_enqueue ( spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + retval = -ENODEV; + goto fail; + } if (!HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; goto fail; diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index e01e77bc324b..72e3b12a1926 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -53,6 +53,11 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) spin_lock_irqsave (&ohci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + spin_unlock_irqrestore (&ohci->lock, flags); + return -ESHUTDOWN; + } + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_RESUME: @@ -140,11 +145,19 @@ static int ohci_bus_resume (struct usb_hcd *hcd) struct ohci_hcd *ohci = hcd_to_ohci (hcd); u32 temp, enables; int status = -EINPROGRESS; + unsigned long flags; if (time_before (jiffies, ohci->next_statechange)) msleep(5); - spin_lock_irq (&ohci->lock); + spin_lock_irqsave (&ohci->lock, flags); + + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + spin_unlock_irqrestore (&ohci->lock, flags); + return -ESHUTDOWN; + } + + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { @@ -179,7 +192,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) ohci_dbg (ohci, "lost power\n"); status = -EBUSY; } - spin_unlock_irq (&ohci->lock); + spin_unlock_irqrestore (&ohci->lock, flags); if (status == -EBUSY) { (void) ohci_init (ohci); return ohci_restart (ohci); @@ -297,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER - || !HC_IS_RUNNING(hcd->state)) { + if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER + || !HC_IS_RUNNING(hcd->state))) { can_suspend = 0; goto done; } @@ -508,6 +521,9 @@ static int ohci_hub_control ( u32 temp; int retval = 0; + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + return -ESHUTDOWN; + switch (typeReq) { case ClearHubFeature: switch (wValue) { diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 5f22e6590cd1..1b09dde068e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -105,13 +105,36 @@ 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 */ - return 0; + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + int rc = 0; + + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave (&ohci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ohci->lock, flags); + + return rc; } static int ohci_pci_resume (struct usb_hcd *hcd) { + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); usb_hcd_resume_root_hub(hcd); return 0; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d33ce3982a5f..ed550132db0b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -717,6 +717,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) * at the source, so we must turn off PIRQ. */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); uhci->hc_inaccessible = 1; hcd->poll_rh = 0; @@ -733,6 +734,11 @@ static int uhci_resume(struct usb_hcd *hcd) dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); + /* We aren't in D3 state anymore, we do that even if dead as I + * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0 + */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ return 0; spin_lock_irq(&uhci->lock); From 8926bfa7462d4c3f8b05cca929e0c4bcde93ae38 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 28 Nov 2005 08:40:38 -0800 Subject: [PATCH 66/71] [PATCH] USB: ehci fixups Rename the EHCI "reset" routine so it better matches what it does (setup); and move the one-time data structure setup earlier, before doing anything that implicitly relies on it having been completed already. From: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 14fff5714c1e..13f73a836e45 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -121,8 +121,8 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) 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) +/* called during probe() after chip reset completes */ +static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); @@ -141,6 +141,11 @@ static int ehci_pci_reset(struct usb_hcd *hcd) if (retval) return retval; + /* data structure init */ + retval = ehci_init(hcd); + if (retval) + return retval; + /* NOTE: only the parts below this line are PCI-specific */ switch (pdev->vendor) { @@ -154,7 +159,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) /* AMD8111 EHCI doesn't work, according to AMD errata */ if (pdev->device == 0x7463) { ehci_info(ehci, "ignoring AMD8111 (errata)\n"); - return -EIO; + retval = -EIO; + goto done; } break; case PCI_VENDOR_ID_NVIDIA: @@ -207,9 +213,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ retval = ehci_pci_reinit(ehci, pdev); - - /* finish init */ - return ehci_init(hcd); +done: + return retval; } /*-------------------------------------------------------------------------*/ @@ -344,7 +349,7 @@ static const struct hc_driver ehci_pci_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_pci_reset, + .reset = ehci_pci_setup, .start = ehci_run, #ifdef CONFIG_PM .suspend = ehci_pci_suspend, From 25741b3e43151bc207dd2b850b0bb157c442682b Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 29 Nov 2005 22:38:43 -0800 Subject: [PATCH 67/71] [CIFS] For previous fix, mode on mkdir needed S_IFDIR left out. Signed-off-by: Steve French --- fs/cifs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e8773461c7f7..411c1f7f84da 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -770,6 +770,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) -1, -1, local_nls); */ if(direntry->d_inode) { direntry->d_inode->i_mode = mode; + direntry->d_inode->i_mode |= S_IFDIR; if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { direntry->d_inode->i_uid = From c801147c5a103eec864afee348c4ee3fdb0f380c Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 30 Nov 2005 15:32:59 +0100 Subject: [PATCH 68/71] [PATCH] SiS DRM: Fix possible NULL dereference This fixes a NULL pointer reference in DRM. The SiS driver tries to allocate a big chunk of memory, but the return value is never checked. Reported in Novell bugzilla #132271: https://bugzilla.novell.com/show_bug.cgi?id=132271 Signed-off-by: Takashi Iwai Signed-off-by: Linus Torvalds --- drivers/char/drm/drm_context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index bdd168d88f49..bd958d69a2ac 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c @@ -432,7 +432,10 @@ int drm_addctx(struct inode *inode, struct file *filp, if (ctx.handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_ctor) - dev->driver->context_ctor(dev, ctx.handle); + if (!dev->driver->context_ctor(dev, ctx.handle)) { + DRM_DEBUG( "Running out of ctxs or memory.\n"); + return -ENOMEM; + } } ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST); From a145dd411eb28c83ee4bb68b66f62c326c0f764e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 30 Nov 2005 09:35:19 -0800 Subject: [PATCH 69/71] VM: add "vm_insert_page()" function This is what a lot of drivers will actually want to use to insert individual pages into a user VMA. It doesn't have the old PageReserved restrictions of remap_pfn_range(), and it doesn't complain about partial remappings. The page you insert needs to be a nice clean kernel allocation, so you can't insert arbitrary page mappings with this, but that's not what people want. Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/memory.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0e73f1539d08..29f02d8513f6 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -956,6 +956,7 @@ struct page *vmalloc_to_page(void *addr); unsigned long vmalloc_to_pfn(void *addr); int remap_pfn_range(struct vm_area_struct *, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t); +int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *); struct page *follow_page(struct vm_area_struct *, unsigned long address, unsigned int foll_flags); diff --git a/mm/memory.c b/mm/memory.c index 8d10b5540c73..4b4fc3a7ea48 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1172,7 +1172,7 @@ static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *pa spinlock_t *ptl; retval = -EINVAL; - if (PageAnon(page) || !PageReserved(page)) + if (PageAnon(page)) goto out; retval = -ENOMEM; flush_dcache_page(page); @@ -1196,6 +1196,35 @@ out: return retval; } +/* + * This allows drivers to insert individual pages they've allocated + * into a user vma. + * + * The page has to be a nice clean _individual_ kernel allocation. + * If you allocate a compound page, you need to have marked it as + * such (__GFP_COMP), or manually just split the page up yourself + * (which is mainly an issue of doing "set_page_count(page, 1)" for + * each sub-page, and then freeing them one by one when you free + * them rather than freeing it as a compound page). + * + * NOTE! Traditionally this was done with "remap_pfn_range()" which + * took an arbitrary page protection parameter. This doesn't allow + * that. Your vma protection will have to be set up correctly, which + * means that if you want a shared writable mapping, you'd better + * ask for a shared writable mapping! + * + * The page does not need to be reserved. + */ +int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *page) +{ + if (addr < vma->vm_start || addr >= vma->vm_end) + return -EFAULT; + if (!page_count(page)) + return -EINVAL; + return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); +} +EXPORT_SYMBOL_GPL(vm_insert_page); + /* * Somebody does a pfn remapping that doesn't actually work as a vma. * @@ -1225,8 +1254,11 @@ static int incomplete_pfn_remap(struct vm_area_struct *vma, if (!pfn_valid(pfn)) return -EINVAL; - retval = 0; page = pfn_to_page(pfn); + if (!PageReserved(page)) + return -EINVAL; + + retval = 0; while (start < end) { retval = insert_page(vma->vm_mm, start, page, prot); if (retval < 0) From 346f7dbb17cb7d84317b4410df2e8f7bf2e57f44 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 30 Nov 2005 10:22:30 -0800 Subject: [PATCH 70/71] Revert "[PATCH] pci_ids.h: remove duplicate entries" This reverts commit c9d6073fb3cda856132dd544d537679f9715436c. It was totally bogus. Signed-off-by: Linus Torvalds --- include/linux/pci_ids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 53e3293051d4..1e737e269db9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -387,6 +387,7 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 +#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 @@ -488,6 +489,8 @@ #define PCI_DEVICE_ID_AMD_8151_0 0x7454 #define PCI_DEVICE_ID_AMD_8131_APIC 0x7450 +#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A + #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 From 5666c0947ede0432ba5148570aa66ffb9febff5b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 30 Nov 2005 22:25:15 -0800 Subject: [PATCH 71/71] Linux v2.6.15-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5187fee78080..4643d579fc87 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 15 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc4 NAME=Affluent Albatross # *DOCUMENTATION*