diff --git a/[refs] b/[refs] index a2bda0618850..c2b1f52bdfe1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c34752bc8b3196aee3115d1aa41972604ab0aea8 +refs/heads/master: 20f77f5654042cf484d8964b618faf9d620f639b diff --git a/trunk/Documentation/ide/ide.txt b/trunk/Documentation/ide/ide.txt index e77bebfa7b0d..0c78f4b1d9d9 100644 --- a/trunk/Documentation/ide/ide.txt +++ b/trunk/Documentation/ide/ide.txt @@ -216,8 +216,6 @@ Other kernel parameters for ide_core are: * "noflush=[interface_number.device_number]" to disable flush requests -* "nohpa=[interface_number.device_number]" to disable Host Protected Area - * "noprobe=[interface_number.device_number]" to skip probing * "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 0bf8a882ee9e..7bcdebffdab3 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -887,8 +887,11 @@ and is between 256 and 4096 characters. It is defined in the file ide-core.nodma= [HW] (E)IDE subsystem Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc - .vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr - .cdrom .chs .ignore_cable are additional options + .vlb_clock .pci_clock .noflush .noprobe .nowerr .cdrom + .chs .ignore_cable are additional options + See Documentation/ide/ide.txt. + + idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed See Documentation/ide/ide.txt. ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem diff --git a/trunk/arch/alpha/mm/extable.c b/trunk/arch/alpha/mm/extable.c index 813c9b63c0e1..62dc379d301a 100644 --- a/trunk/arch/alpha/mm/extable.c +++ b/trunk/arch/alpha/mm/extable.c @@ -48,27 +48,6 @@ void sort_extable(struct exception_table_entry *start, cmp_ex, swap_ex); } -#ifdef CONFIG_MODULES -/* - * Any entry referring to the module init will be at the beginning or - * the end. - */ -void trim_init_extable(struct module *m) -{ - /*trim the beginning*/ - while (m->num_exentries && - within_module_init(ex_to_addr(&m->extable[0]), m)) { - m->extable++; - m->num_exentries--; - } - /*trim the end*/ - while (m->num_exentries && - within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), - m)) - m->num_exentries--; -} -#endif /* CONFIG_MODULES */ - const struct exception_table_entry * search_extable(const struct exception_table_entry *first, const struct exception_table_entry *last, diff --git a/trunk/arch/avr32/kernel/module.c b/trunk/arch/avr32/kernel/module.c index 98f94d041d9c..1167fe9cf6c4 100644 --- a/trunk/arch/avr32/kernel/module.c +++ b/trunk/arch/avr32/kernel/module.c @@ -32,6 +32,8 @@ void module_free(struct module *mod, void *module_region) mod->arch.syminfo = NULL; vfree(module_region); + /* FIXME: if module_region == mod->init_region, trim exception + * table entries. */ } static inline int check_rela(Elf32_Rela *rela, struct module *module, diff --git a/trunk/arch/cris/kernel/module.c b/trunk/arch/cris/kernel/module.c index abc13e368b90..a187833febc8 100644 --- a/trunk/arch/cris/kernel/module.c +++ b/trunk/arch/cris/kernel/module.c @@ -48,6 +48,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { FREE_MODULE(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/frv/kernel/module.c b/trunk/arch/frv/kernel/module.c index 711763c8a6f3..850d168f69fc 100644 --- a/trunk/arch/frv/kernel/module.c +++ b/trunk/arch/frv/kernel/module.c @@ -35,6 +35,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/h8300/kernel/module.c b/trunk/arch/h8300/kernel/module.c index 0865e291c20d..cfc9127d2ced 100644 --- a/trunk/arch/h8300/kernel/module.c +++ b/trunk/arch/h8300/kernel/module.c @@ -23,6 +23,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/ia64/mm/extable.c b/trunk/arch/ia64/mm/extable.c index e95d5ad9285d..71c50dd8f870 100644 --- a/trunk/arch/ia64/mm/extable.c +++ b/trunk/arch/ia64/mm/extable.c @@ -53,32 +53,6 @@ void sort_extable (struct exception_table_entry *start, cmp_ex, swap_ex); } -static inline unsigned long ex_to_addr(const struct exception_table_entry *x) -{ - return (unsigned long)&x->insn + x->insn; -} - -#ifdef CONFIG_MODULES -/* - * Any entry referring to the module init will be at the beginning or - * the end. - */ -void trim_init_extable(struct module *m) -{ - /*trim the beginning*/ - while (m->num_exentries && - within_module_init(ex_to_addr(&m->extable[0]), m)) { - m->extable++; - m->num_exentries--; - } - /*trim the end*/ - while (m->num_exentries && - within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), - m)) - m->num_exentries--; -} -#endif /* CONFIG_MODULES */ - const struct exception_table_entry * search_extable (const struct exception_table_entry *first, const struct exception_table_entry *last, diff --git a/trunk/arch/m32r/kernel/module.c b/trunk/arch/m32r/kernel/module.c index cb5f37d78d49..8d4205794380 100644 --- a/trunk/arch/m32r/kernel/module.c +++ b/trunk/arch/m32r/kernel/module.c @@ -44,6 +44,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/m68k/kernel/module.c b/trunk/arch/m68k/kernel/module.c index cd6bcb1c957e..774862bc6977 100644 --- a/trunk/arch/m68k/kernel/module.c +++ b/trunk/arch/m68k/kernel/module.c @@ -31,6 +31,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/m68knommu/kernel/module.c b/trunk/arch/m68knommu/kernel/module.c index d11ffae7956a..3b1a2ff61ddc 100644 --- a/trunk/arch/m68knommu/kernel/module.c +++ b/trunk/arch/m68knommu/kernel/module.c @@ -23,6 +23,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/mips/kernel/module.c b/trunk/arch/mips/kernel/module.c index 3e9100dcc12d..1f60e27523d9 100644 --- a/trunk/arch/mips/kernel/module.c +++ b/trunk/arch/mips/kernel/module.c @@ -68,6 +68,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, diff --git a/trunk/arch/mn10300/kernel/module.c b/trunk/arch/mn10300/kernel/module.c index 4fa0e3648d8e..6b287f2e8e84 100644 --- a/trunk/arch/mn10300/kernel/module.c +++ b/trunk/arch/mn10300/kernel/module.c @@ -48,6 +48,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + * table entries. */ } /* diff --git a/trunk/arch/parisc/kernel/module.c b/trunk/arch/parisc/kernel/module.c index ef5caf2e6ed0..ecd1c5024447 100644 --- a/trunk/arch/parisc/kernel/module.c +++ b/trunk/arch/parisc/kernel/module.c @@ -267,6 +267,8 @@ void module_free(struct module *mod, void *module_region) mod->arch.section = NULL; vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* Additional bytes needed in front of individual sections */ diff --git a/trunk/arch/powerpc/kernel/module.c b/trunk/arch/powerpc/kernel/module.c index 477c663e0140..43e7e3a7f130 100644 --- a/trunk/arch/powerpc/kernel/module.c +++ b/trunk/arch/powerpc/kernel/module.c @@ -43,6 +43,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, diff --git a/trunk/arch/s390/kernel/module.c b/trunk/arch/s390/kernel/module.c index ab2e3ed28abc..eed4a00cb676 100644 --- a/trunk/arch/s390/kernel/module.c +++ b/trunk/arch/s390/kernel/module.c @@ -56,6 +56,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } static void diff --git a/trunk/arch/sh/kernel/module.c b/trunk/arch/sh/kernel/module.c index c2efdcde266f..c19b0f7d2cc1 100644 --- a/trunk/arch/sh/kernel/module.c +++ b/trunk/arch/sh/kernel/module.c @@ -46,6 +46,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* We don't need anything special. */ diff --git a/trunk/arch/sparc/include/asm/uaccess_32.h b/trunk/arch/sparc/include/asm/uaccess_32.h index 8303ac481034..47d5619d43fa 100644 --- a/trunk/arch/sparc/include/asm/uaccess_32.h +++ b/trunk/arch/sparc/include/asm/uaccess_32.h @@ -17,9 +17,6 @@ #ifndef __ASSEMBLY__ -#define ARCH_HAS_SORT_EXTABLE -#define ARCH_HAS_SEARCH_EXTABLE - /* Sparc is not segmented, however we need to be able to fool access_ok() * when doing system calls from kernel mode legitimately. * diff --git a/trunk/arch/sparc/kernel/module.c b/trunk/arch/sparc/kernel/module.c index 0ee642f63234..90273765e81f 100644 --- a/trunk/arch/sparc/kernel/module.c +++ b/trunk/arch/sparc/kernel/module.c @@ -75,6 +75,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ diff --git a/trunk/arch/sparc/mm/extable.c b/trunk/arch/sparc/mm/extable.c index a61c349448e1..16cc28935e39 100644 --- a/trunk/arch/sparc/mm/extable.c +++ b/trunk/arch/sparc/mm/extable.c @@ -28,10 +28,6 @@ search_extable(const struct exception_table_entry *start, * word 3: last insn address + 4 bytes * word 4: fixup code address * - * Deleted entries are encoded as: - * word 1: unused - * word 2: -1 - * * See asm/uaccess.h for more details. */ @@ -43,10 +39,6 @@ search_extable(const struct exception_table_entry *start, continue; } - /* A deleted entry; see trim_init_extable */ - if (walk->fixup == -1) - continue; - if (walk->insn == value) return walk; } @@ -65,27 +57,6 @@ search_extable(const struct exception_table_entry *start, return NULL; } -#ifdef CONFIG_MODULES -/* We could memmove them around; easier to mark the trimmed ones. */ -void trim_init_extable(struct module *m) -{ - unsigned int i; - bool range; - - for (i = 0; i < m->num_exentries; i += range ? 2 : 1) { - range = m->extable[i].fixup == 0; - - if (within_module_init(m->extable[i].insn, m)) { - m->extable[i].fixup = -1; - if (range) - m->extable[i+1].fixup = -1; - } - if (range) - i++; - } -} -#endif /* CONFIG_MODULES */ - /* Special extable search, which handles ranges. Returns fixup */ unsigned long search_extables_range(unsigned long addr, unsigned long *g2) { diff --git a/trunk/arch/um/include/asm/pgtable.h b/trunk/arch/um/include/asm/pgtable.h index 9ce3f165111a..58da2480a7f4 100644 --- a/trunk/arch/um/include/asm/pgtable.h +++ b/trunk/arch/um/include/asm/pgtable.h @@ -53,21 +53,16 @@ extern unsigned long end_iomem; #else # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) #endif -#define MODULES_VADDR VMALLOC_START -#define MODULES_END VMALLOC_END -#define MODULES_LEN (MODULES_VADDR - MODULES_END) #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -#define __PAGE_KERNEL_EXEC \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) -#define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) /* * The i386 can't do page protection for execute, and considers that the same diff --git a/trunk/arch/um/sys-i386/Makefile b/trunk/arch/um/sys-i386/Makefile index 1b549bca4645..598b5c1903af 100644 --- a/trunk/arch/um/sys-i386/Makefile +++ b/trunk/arch/um/sys-i386/Makefile @@ -8,7 +8,7 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ subarch-obj-y = lib/semaphore_32.o lib/string_32.o subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o -subarch-obj-$(CONFIG_MODULES) += kernel/module.o +subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o USER_OBJS := bugs.o ptrace_user.o fault.o diff --git a/trunk/arch/um/sys-x86_64/Makefile b/trunk/arch/um/sys-x86_64/Makefile index 2201e9c20e4a..c8b4cce9cfe1 100644 --- a/trunk/arch/um/sys-x86_64/Makefile +++ b/trunk/arch/um/sys-x86_64/Makefile @@ -8,8 +8,10 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ sysrq.o ksyms.o tls.o +obj-$(CONFIG_MODULES) += um_module.o + subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o -subarch-obj-$(CONFIG_MODULES) += kernel/module.o +subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o ldt-y = ../sys-i386/ldt.o diff --git a/trunk/arch/um/sys-x86_64/um_module.c b/trunk/arch/um/sys-x86_64/um_module.c new file mode 100644 index 000000000000..3dead392a415 --- /dev/null +++ b/trunk/arch/um/sys-x86_64/um_module.c @@ -0,0 +1,21 @@ +#include +#include + +/* Copied from i386 arch/i386/kernel/module.c */ +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc_exec(size); +} + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* + * FIXME: If module_region == mod->init_region, trim exception + * table entries. + */ +} + diff --git a/trunk/arch/x86/include/asm/pgtable_32_types.h b/trunk/arch/x86/include/asm/pgtable_32_types.h index 5e67c1532314..2733fad45f98 100644 --- a/trunk/arch/x86/include/asm/pgtable_32_types.h +++ b/trunk/arch/x86/include/asm/pgtable_32_types.h @@ -46,10 +46,6 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) #endif -#define MODULES_VADDR VMALLOC_START -#define MODULES_END VMALLOC_END -#define MODULES_LEN (MODULES_VADDR - MODULES_END) - #define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) #endif /* _ASM_X86_PGTABLE_32_DEFS_H */ diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index f3477bb84566..4f78bd682125 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -73,7 +73,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_MODULES) += module_$(BITS).o obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o obj-$(CONFIG_KGDB) += kgdb.o diff --git a/trunk/arch/x86/kernel/module_32.c b/trunk/arch/x86/kernel/module_32.c new file mode 100644 index 000000000000..0edd819050e7 --- /dev/null +++ b/trunk/arch/x86/kernel/module_32.c @@ -0,0 +1,152 @@ +/* Kernel module help for i386. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc_exec(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* We don't need anything special. */ +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_386_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_386_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, + *para = NULL; + char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { + if (!strcmp(".text", secstrings + s->sh_name)) + text = s; + if (!strcmp(".altinstructions", secstrings + s->sh_name)) + alt = s; + if (!strcmp(".smp_locks", secstrings + s->sh_name)) + locks = s; + if (!strcmp(".parainstructions", secstrings + s->sh_name)) + para = s; + } + + if (alt) { + /* patch .altinstructions */ + void *aseg = (void *)alt->sh_addr; + apply_alternatives(aseg, aseg + alt->sh_size); + } + if (locks && text) { + void *lseg = (void *)locks->sh_addr; + void *tseg = (void *)text->sh_addr; + alternatives_smp_module_add(me, me->name, + lseg, lseg + locks->sh_size, + tseg, tseg + text->sh_size); + } + + if (para) { + void *pseg = (void *)para->sh_addr; + apply_paravirt(pseg, pseg + para->sh_size); + } + + return module_bug_finalize(hdr, sechdrs, me); +} + +void module_arch_cleanup(struct module *mod) +{ + alternatives_smp_module_del(mod); + module_bug_cleanup(mod); +} diff --git a/trunk/arch/x86/kernel/module.c b/trunk/arch/x86/kernel/module_64.c similarity index 74% rename from trunk/arch/x86/kernel/module.c rename to trunk/arch/x86/kernel/module_64.c index 89f386f044e4..c23880b90b5c 100644 --- a/trunk/arch/x86/kernel/module.c +++ b/trunk/arch/x86/kernel/module_64.c @@ -1,5 +1,6 @@ -/* Kernel module help for x86. +/* Kernel module help for x86-64 Copyright (C) 2001 Rusty Russell. + Copyright (C) 2002,2003 Andi Kleen, SuSE Labs. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,18 +22,23 @@ #include #include #include -#include #include +#include +#include #include #include #include -#if 0 -#define DEBUGP printk -#else #define DEBUGP(fmt...) -#endif + +#ifndef CONFIG_UML +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} void *module_alloc(unsigned long size) { @@ -48,15 +54,9 @@ void *module_alloc(unsigned long size) if (!area) return NULL; - return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM, - PAGE_KERNEL_EXEC); -} - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); + return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); } +#endif /* We don't need anything special. */ int module_frob_arch_sections(Elf_Ehdr *hdr, @@ -67,58 +67,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, return 0; } -#ifdef CONFIG_X86_32 -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - uint32_t *location; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_386_32: - /* We add the value into the location given */ - *location += sym->st_value; - break; - case R_386_PC32: - /* Add the value, subtract its postition */ - *location += sym->st_value - (uint32_t)location; - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - return 0; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; -} -#else /*X86_64*/ int apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, @@ -199,8 +147,6 @@ int apply_relocate(Elf_Shdr *sechdrs, return -ENOSYS; } -#endif - int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) diff --git a/trunk/arch/x86/kernel/setup.c b/trunk/arch/x86/kernel/setup.c index be5ae80f897f..d1c636bf31a7 100644 --- a/trunk/arch/x86/kernel/setup.c +++ b/trunk/arch/x86/kernel/setup.c @@ -301,13 +301,15 @@ static void __init reserve_brk(void) #ifdef CONFIG_BLK_DEV_INITRD +#ifdef CONFIG_X86_32 + #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) static void __init relocate_initrd(void) { u64 ramdisk_image = boot_params.hdr.ramdisk_image; u64 ramdisk_size = boot_params.hdr.ramdisk_size; - u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; + u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT; u64 ramdisk_here; unsigned long slop, clen, mapaddr; char *p, *q; @@ -363,13 +365,14 @@ static void __init relocate_initrd(void) ramdisk_image, ramdisk_image + ramdisk_size - 1, ramdisk_here, ramdisk_here + ramdisk_size - 1); } +#endif static void __init reserve_initrd(void) { u64 ramdisk_image = boot_params.hdr.ramdisk_image; u64 ramdisk_size = boot_params.hdr.ramdisk_size; u64 ramdisk_end = ramdisk_image + ramdisk_size; - u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; + u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT; if (!boot_params.hdr.type_of_loader || !ramdisk_image || !ramdisk_size) @@ -399,8 +402,14 @@ static void __init reserve_initrd(void) return; } +#ifdef CONFIG_X86_32 relocate_initrd(); - +#else + printk(KERN_ERR "initrd extends beyond end of memory " + "(0x%08llx > 0x%08llx)\ndisabling initrd\n", + ramdisk_end, end_of_lowmem); + initrd_start = 0; +#endif free_early(ramdisk_image, ramdisk_end); } #else diff --git a/trunk/arch/x86/kernel/vmlinux.lds.S b/trunk/arch/x86/kernel/vmlinux.lds.S index 367e87882041..4c85b2e2bb65 100644 --- a/trunk/arch/x86/kernel/vmlinux.lds.S +++ b/trunk/arch/x86/kernel/vmlinux.lds.S @@ -108,8 +108,6 @@ SECTIONS /* Data */ . = ALIGN(PAGE_SIZE); .data : AT(ADDR(.data) - LOAD_OFFSET) { - /* Start of data section */ - _sdata = .; DATA_DATA CONSTRUCTORS diff --git a/trunk/arch/xtensa/kernel/module.c b/trunk/arch/xtensa/kernel/module.c index c1accea8cb56..3981a466c779 100644 --- a/trunk/arch/xtensa/kernel/module.c +++ b/trunk/arch/xtensa/kernel/module.c @@ -34,6 +34,8 @@ void *module_alloc(unsigned long size) void module_free(struct module *mod, void *module_region) { vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ } int module_frob_arch_sections(Elf32_Ehdr *hdr, diff --git a/trunk/drivers/ide/at91_ide.c b/trunk/drivers/ide/at91_ide.c index fc0949a8cfde..403d0e4265db 100644 --- a/trunk/drivers/ide/at91_ide.c +++ b/trunk/drivers/ide/at91_ide.c @@ -216,7 +216,6 @@ static const struct ide_port_info at91_ide_port_info __initdata = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, .pio_mask = ATA_PIO6, - .chipset = ide_generic, }; /* @@ -247,7 +246,8 @@ irqreturn_t at91_irq_handler(int irq, void *dev_id) static int __init at91_ide_probe(struct platform_device *pdev) { int ret; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; unsigned long tf_base = 0, ctl_base = 0; @@ -304,9 +304,10 @@ static int __init at91_ide_probe(struct platform_device *pdev) ide_std_init_ports(&hw, tf_base, ctl_base + 6); hw.irq = board->irq_pin; + hw.chipset = ide_generic; hw.dev = &pdev->dev; - host = ide_host_alloc(&at91_ide_port_info, hws, 1); + host = ide_host_alloc(&at91_ide_port_info, hws); if (!host) { perr("failed to allocate ide host\n"); return -ENOMEM; diff --git a/trunk/drivers/ide/au1xxx-ide.c b/trunk/drivers/ide/au1xxx-ide.c index 58121bd6c115..46013644c965 100644 --- a/trunk/drivers/ide/au1xxx-ide.c +++ b/trunk/drivers/ide/au1xxx-ide.c @@ -449,7 +449,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) } #endif -static void auide_setup_ports(struct ide_hw *hw, _auide_hwif *ahwif) +static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) { int i; unsigned long *ata_regs = hw->io_ports_array; @@ -499,7 +499,6 @@ static const struct ide_port_info au1xxx_port_info = { #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA .mwdma_mask = ATA_MWDMA2, #endif - .chipset = ide_au1xxx, }; static int au_ide_probe(struct platform_device *dev) @@ -508,7 +507,7 @@ static int au_ide_probe(struct platform_device *dev) struct resource *res; struct ide_host *host; int ret = 0; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) char *mode = "MWDMA2"; @@ -549,8 +548,9 @@ static int au_ide_probe(struct platform_device *dev) auide_setup_ports(&hw, ahwif); hw.irq = ahwif->irq; hw.dev = &dev->dev; + hw.chipset = ide_au1xxx; - ret = ide_host_add(&au1xxx_port_info, hws, 1, &host); + ret = ide_host_add(&au1xxx_port_info, hws, &host); if (ret) goto out; diff --git a/trunk/drivers/ide/buddha.c b/trunk/drivers/ide/buddha.c index e3c6a5913305..d028f8864bc1 100644 --- a/trunk/drivers/ide/buddha.c +++ b/trunk/drivers/ide/buddha.c @@ -121,7 +121,7 @@ static int xsurf_ack_intr(ide_hwif_t *hwif) return 1; } -static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, unsigned long ctl, unsigned long irq_port, ide_ack_intr_t *ack_intr) { @@ -139,12 +139,13 @@ static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info buddha_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -160,7 +161,7 @@ static int __init buddha_init(void) while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { unsigned long board; - struct ide_hw hw[MAX_NUM_HWIFS], *hws[MAX_NUM_HWIFS]; + hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { buddha_num_hwifs = BUDDHA_NUM_HWIFS; @@ -224,7 +225,7 @@ static int __init buddha_init(void) hws[i] = &hw[i]; } - ide_host_add(&buddha_port_info, hws, i, NULL); + ide_host_add(&buddha_port_info, hws, NULL); } return 0; diff --git a/trunk/drivers/ide/cmd640.c b/trunk/drivers/ide/cmd640.c index 1683ed5c7329..8890276fef7f 100644 --- a/trunk/drivers/ide/cmd640.c +++ b/trunk/drivers/ide/cmd640.c @@ -708,7 +708,7 @@ static int __init cmd640x_init(void) int second_port_cmd640 = 0, rc; const char *bus_type, *port2; u8 b, cfr; - struct ide_hw hw[2], *hws[2]; + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; if (cmd640_vlb && probe_for_cmd640_vlb()) { bus_type = "VLB"; @@ -762,9 +762,11 @@ static int __init cmd640x_init(void) ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); hw[0].irq = 14; + hw[0].chipset = ide_cmd640; ide_std_init_ports(&hw[1], 0x170, 0x376); hw[1].irq = 15; + hw[1].chipset = ide_cmd640; printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); @@ -822,8 +824,7 @@ static int __init cmd640x_init(void) cmd640_dump_regs(); #endif - return ide_host_add(&cmd640_port_info, hws, second_port_cmd640 ? 2 : 1, - NULL); + return ide_host_add(&cmd640_port_info, hws, NULL); } module_param_named(probe_vlb, cmd640_vlb, bool, 0); diff --git a/trunk/drivers/ide/cs5520.c b/trunk/drivers/ide/cs5520.c index bd066bb9d611..87987a7d36c9 100644 --- a/trunk/drivers/ide/cs5520.c +++ b/trunk/drivers/ide/cs5520.c @@ -110,7 +110,7 @@ static const struct ide_port_info cyrix_chipset __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { const struct ide_port_info *d = &cyrix_chipset; - struct ide_hw hw[2], *hws[] = { NULL, NULL }; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; ide_setup_pci_noise(dev, d); @@ -136,7 +136,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); hw[0].irq = 14; - return ide_host_add(d, hws, 2, NULL); + return ide_host_add(d, hws, NULL); } static const struct pci_device_id cs5520_pci_tbl[] = { diff --git a/trunk/drivers/ide/delkin_cb.c b/trunk/drivers/ide/delkin_cb.c index 1e10eba62ceb..f153b95619bb 100644 --- a/trunk/drivers/ide/delkin_cb.c +++ b/trunk/drivers/ide/delkin_cb.c @@ -68,7 +68,6 @@ static const struct ide_port_info delkin_cb_port_info = { IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, .init_chipset = delkin_cb_init_chipset, - .chipset = ide_pci, }; static int __devinit @@ -77,7 +76,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) struct ide_host *host; unsigned long base; int rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; rc = pci_enable_device(dev); if (rc) { @@ -98,8 +97,9 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) ide_std_init_ports(&hw, base + 0x10, base + 0x1e); hw.irq = dev->irq; hw.dev = &dev->dev; + hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_host_add(&delkin_cb_port_info, hws, 1, &host); + rc = ide_host_add(&delkin_cb_port_info, hws, &host); if (rc) goto out_disable; diff --git a/trunk/drivers/ide/falconide.c b/trunk/drivers/ide/falconide.c index 22fa27389c3b..0e2df6755ec9 100644 --- a/trunk/drivers/ide/falconide.c +++ b/trunk/drivers/ide/falconide.c @@ -111,10 +111,9 @@ static const struct ide_port_info falconide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; -static void __init falconide_setup_ports(struct ide_hw *hw) +static void __init falconide_setup_ports(hw_regs_t *hw) { int i; @@ -129,6 +128,8 @@ static void __init falconide_setup_ports(struct ide_hw *hw) hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; + + hw->chipset = ide_generic; } /* @@ -138,7 +139,7 @@ static void __init falconide_setup_ports(struct ide_hw *hw) static int __init falconide_init(void) { struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int rc; if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) @@ -153,7 +154,7 @@ static int __init falconide_init(void) falconide_setup_ports(&hw); - host = ide_host_alloc(&falconide_port_info, hws, 1); + host = ide_host_alloc(&falconide_port_info, hws); if (host == NULL) { rc = -ENOMEM; goto err; diff --git a/trunk/drivers/ide/gayle.c b/trunk/drivers/ide/gayle.c index 4451a6a5dfe0..c7119516c5a7 100644 --- a/trunk/drivers/ide/gayle.c +++ b/trunk/drivers/ide/gayle.c @@ -88,7 +88,7 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif) return 1; } -static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, unsigned long ctl, unsigned long irq_port, ide_ack_intr_t *ack_intr) { @@ -106,13 +106,14 @@ static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = IRQ_AMIGA_PORTS; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info gayle_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -125,7 +126,7 @@ static int __init gayle_init(void) unsigned long base, ctrlport, irqport; ide_ack_intr_t *ack_intr; int a4000, i, rc; - struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; + hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (!MACH_IS_AMIGA) return -ENODEV; @@ -170,7 +171,7 @@ static int __init gayle_init(void) hws[i] = &hw[i]; } - rc = ide_host_add(&gayle_port_info, hws, i, NULL); + rc = ide_host_add(&gayle_port_info, hws, NULL); if (rc) release_mem_region(res_start, res_n); diff --git a/trunk/drivers/ide/hpt366.c b/trunk/drivers/ide/hpt366.c index 7ce68ef6b904..0feb66c720e1 100644 --- a/trunk/drivers/ide/hpt366.c +++ b/trunk/drivers/ide/hpt366.c @@ -138,6 +138,14 @@ #undef HPT_RESET_STATE_ENGINE #undef HPT_DELAY_INTERRUPT +static const char *quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + static const char *bad_ata100_5[] = { "IBM-DTLA-307075", "IBM-DTLA-307060", @@ -721,13 +729,27 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) hpt3xx_set_mode(drive, XFER_PIO_0 + pio); } +static void hpt3xx_quirkproc(ide_drive_t *drive) +{ + char *m = (char *)&drive->id[ATA_ID_PROD]; + const char **list = quirk_drives; + + while (*list) + if (strstr(m, *list++)) { + drive->quirk_list = 1; + return; + } + + drive->quirk_list = 0; +} + static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = to_pci_dev(hwif->dev); struct hpt_info *info = hpt3xx_get_info(hwif->dev); - if ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) + if (drive->quirk_list == 0) return; if (info->chip_type >= HPT370) { @@ -1382,6 +1404,7 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) static const struct ide_port_ops hpt3xx_port_ops = { .set_pio_mode = hpt3xx_set_pio_mode, .set_dma_mode = hpt3xx_set_mode, + .quirkproc = hpt3xx_quirkproc, .maskproc = hpt3xx_maskproc, .mdma_filter = hpt3xx_mdma_filter, .udma_filter = hpt3xx_udma_filter, diff --git a/trunk/drivers/ide/icside.c b/trunk/drivers/ide/icside.c index 5af3d0ffaf0a..36da913cc553 100644 --- a/trunk/drivers/ide/icside.c +++ b/trunk/drivers/ide/icside.c @@ -65,6 +65,8 @@ static struct cardinfo icside_cardinfo_v6_2 = { }; struct icside_state { + unsigned int channel; + unsigned int enabled; void __iomem *irq_port; void __iomem *ioc_base; unsigned int sel; @@ -114,11 +116,18 @@ static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) struct icside_state *state = ec->irq_data; void __iomem *base = state->irq_port; - writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); - readb(base + ICS_ARCIN_V6_INTROFFSET_2); + state->enabled = 1; - writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); - readb(base + ICS_ARCIN_V6_INTROFFSET_1); + switch (state->channel) { + case 0: + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); + readb(base + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); + readb(base + ICS_ARCIN_V6_INTROFFSET_1); + break; + } } /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) @@ -128,6 +137,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) { struct icside_state *state = ec->irq_data; + state->enabled = 0; + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); } @@ -149,6 +160,44 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = { .irqpending = icside_irqpending_arcin_v6, }; +/* + * Handle routing of interrupts. This is called before + * we write the command to the drive. + */ +static void icside_maskproc(ide_drive_t *drive, int mask) +{ + ide_hwif_t *hwif = drive->hwif; + struct expansion_card *ec = ECARD_DEV(hwif->dev); + struct icside_state *state = ecard_get_drvdata(ec); + unsigned long flags; + + local_irq_save(flags); + + state->channel = hwif->channel; + + if (state->enabled && !mask) { + switch (hwif->channel) { + case 0: + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + break; + case 1: + writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + break; + } + } else { + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); + readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); + } + + local_irq_restore(flags); +} + +static const struct ide_port_ops icside_v6_no_dma_port_ops = { + .maskproc = icside_maskproc, +}; + #ifdef CONFIG_BLK_DEV_IDEDMA_ICS /* * SG-DMA support. @@ -226,6 +275,7 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) static const struct ide_port_ops icside_v6_port_ops = { .set_dma_mode = icside_set_dma_mode, + .maskproc = icside_maskproc, }; static void icside_dma_host_set(ide_drive_t *drive, int on) @@ -269,6 +319,11 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) */ BUG_ON(dma_channel_active(ec->dma)); + /* + * Ensure that we have the right interrupt routed. + */ + icside_maskproc(drive, 0); + /* * Route the DMA signals to the correct interface. */ @@ -326,7 +381,7 @@ static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) return -EOPNOTSUPP; } -static void icside_setup_ports(struct ide_hw *hw, void __iomem *base, +static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, struct cardinfo *info, struct expansion_card *ec) { unsigned long port = (unsigned long)base + info->dataoffset; @@ -343,11 +398,11 @@ static void icside_setup_ports(struct ide_hw *hw, void __iomem *base, hw->irq = ec->irq; hw->dev = &ec->dev; + hw->chipset = ide_acorn; } static const struct ide_port_info icside_v5_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_acorn, }; static int __devinit @@ -355,7 +410,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) { void __iomem *base; struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int ret; base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); @@ -376,7 +431,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); - host = ide_host_alloc(&icside_v5_port_info, hws, 1); + host = ide_host_alloc(&icside_v5_port_info, hws); if (host == NULL) return -ENODEV; @@ -397,11 +452,11 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) static const struct ide_port_info icside_v6_port_info __initdata = { .init_dma = icside_dma_off_init, + .port_ops = &icside_v6_no_dma_port_ops, .dma_ops = &icside_v6_dma_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, - .chipset = ide_acorn, }; static int __devinit @@ -411,7 +466,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) struct ide_host *host; unsigned int sel = 0; int ret; - struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] }; + hw_regs_t hw[2], *hws[] = { &hw[0], &hw[1], NULL, NULL }; struct ide_port_info d = icside_v6_port_info; ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); @@ -451,7 +506,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); - host = ide_host_alloc(&d, hws, 2); + host = ide_host_alloc(&d, hws); if (host == NULL) return -ENODEV; diff --git a/trunk/drivers/ide/ide-4drives.c b/trunk/drivers/ide/ide-4drives.c index 979d342c338a..78aca75a2c48 100644 --- a/trunk/drivers/ide/ide-4drives.c +++ b/trunk/drivers/ide/ide-4drives.c @@ -25,13 +25,12 @@ static const struct ide_port_info ide_4drives_port_info = { .port_ops = &ide_4drives_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA | IDE_HFLAG_4DRIVES, - .chipset = ide_4drives, }; static int __init ide_4drives_init(void) { unsigned long base = 0x1f0, ctl = 0x3f6; - struct ide_hw hw, *hws[] = { &hw, &hw }; + hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL }; if (probe_4drives == 0) return -ENODEV; @@ -53,8 +52,9 @@ static int __init ide_4drives_init(void) ide_std_init_ports(&hw, base, ctl); hw.irq = 14; + hw.chipset = ide_4drives; - return ide_host_add(&ide_4drives_port_info, hws, 2, NULL); + return ide_host_add(&ide_4drives_port_info, hws, NULL); } module_init(ide_4drives_init); diff --git a/trunk/drivers/ide/ide-atapi.c b/trunk/drivers/ide/ide-atapi.c index bbdd2547f12a..757e5956b132 100644 --- a/trunk/drivers/ide/ide-atapi.c +++ b/trunk/drivers/ide/ide-atapi.c @@ -259,7 +259,7 @@ void ide_retry_pc(ide_drive_t *drive) pc->req_xfer = blk_rq_bytes(sense_rq); if (drive->media == ide_tape) - drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; + set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); /* * Push back the failed request and put request sense on top diff --git a/trunk/drivers/ide/ide-cs.c b/trunk/drivers/ide/ide-cs.c index 527908ff298c..9e47f3529d55 100644 --- a/trunk/drivers/ide/ide-cs.c +++ b/trunk/drivers/ide/ide-cs.c @@ -155,7 +155,6 @@ static const struct ide_port_info idecs_port_info = { .port_ops = &idecs_port_ops, .host_flags = IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_pci, }; static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, @@ -164,7 +163,7 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, struct ide_host *host; ide_hwif_t *hwif; int i, rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; if (!request_region(io, 8, DRV_NAME)) { printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", @@ -182,9 +181,10 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, io, ctl); hw.irq = irq; + hw.chipset = ide_pci; hw.dev = &handle->dev; - rc = ide_host_add(&idecs_port_info, hws, 1, &host); + rc = ide_host_add(&idecs_port_info, hws, &host); if (rc) goto out_release; diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 6a1de2169709..c6f7fcfb9d67 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -302,12 +302,14 @@ static const struct drive_list_entry hpa_list[] = { { NULL, NULL } }; -static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48) +static void idedisk_check_hpa(ide_drive_t *drive) { - u64 capacity, set_max; + unsigned long long capacity, set_max; + int lba48 = ata_id_lba48_enabled(drive->id); capacity = drive->capacity64; - set_max = idedisk_read_native_max_address(drive, lba48); + + set_max = idedisk_read_native_max_address(drive, lba48); if (ide_in_drive_list(drive->id, hpa_list)) { /* @@ -318,31 +320,9 @@ static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48) set_max--; } - return set_max; -} - -static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48) -{ - set_max = idedisk_set_max_address(drive, set_max, lba48); - if (set_max) - drive->capacity64 = set_max; - - return set_max; -} - -static void idedisk_check_hpa(ide_drive_t *drive) -{ - u64 capacity, set_max; - int lba48 = ata_id_lba48_enabled(drive->id); - - capacity = drive->capacity64; - set_max = ide_disk_hpa_get_native_capacity(drive, lba48); - if (set_max <= capacity) return; - drive->probed_capacity = set_max; - printk(KERN_INFO "%s: Host Protected Area detected.\n" "\tcurrent capacity is %llu sectors (%llu MB)\n" "\tnative capacity is %llu sectors (%llu MB)\n", @@ -350,13 +330,13 @@ static void idedisk_check_hpa(ide_drive_t *drive) capacity, sectors_to_MB(capacity), set_max, sectors_to_MB(set_max)); - if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0) - return; + set_max = idedisk_set_max_address(drive, set_max, lba48); - set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48); - if (set_max) + if (set_max) { + drive->capacity64 = set_max; printk(KERN_INFO "%s: Host Protected Area disabled.\n", drive->name); + } } static int ide_disk_get_capacity(ide_drive_t *drive) @@ -378,8 +358,6 @@ static int ide_disk_get_capacity(ide_drive_t *drive) drive->capacity64 = drive->cyl * drive->head * drive->sect; } - drive->probed_capacity = drive->capacity64; - if (lba) { drive->dev_flags |= IDE_DFLAG_LBA; @@ -398,7 +376,7 @@ static int ide_disk_get_capacity(ide_drive_t *drive) "%llu sectors (%llu MB)\n", drive->name, (unsigned long long)drive->capacity64, sectors_to_MB(drive->capacity64)); - drive->probed_capacity = drive->capacity64 = 1ULL << 28; + drive->capacity64 = 1ULL << 28; } if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && @@ -414,34 +392,6 @@ static int ide_disk_get_capacity(ide_drive_t *drive) return 0; } -static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity) -{ - u64 set = min(capacity, drive->probed_capacity); - u16 *id = drive->id; - int lba48 = ata_id_lba48_enabled(id); - - if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 || - ata_id_hpa_enabled(id) == 0) - goto out; - - /* - * according to the spec the SET MAX ADDRESS command shall be - * immediately preceded by a READ NATIVE MAX ADDRESS command - */ - capacity = ide_disk_hpa_get_native_capacity(drive, lba48); - if (capacity == 0) - goto out; - - set = ide_disk_hpa_set_capacity(drive, set, lba48); - if (set) { - /* needed for ->resume to disable HPA */ - drive->dev_flags |= IDE_DFLAG_NOHPA; - return set; - } -out: - return drive->capacity64; -} - static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) { ide_drive_t *drive = q->queuedata; @@ -478,14 +428,14 @@ static int set_multcount(ide_drive_t *drive, int arg) if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) return -EINVAL; - if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) + if (drive->special.b.set_multmode) return -EBUSY; rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_ATA_TASKFILE; drive->mult_req = arg; - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; error = blk_execute_rq(drive->queue, NULL, rq, 0); blk_put_request(rq); @@ -790,7 +740,6 @@ static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, const struct ide_disk_ops ide_ata_disk_ops = { .check = ide_disk_check, - .set_capacity = ide_disk_set_capacity, .get_capacity = ide_disk_get_capacity, .setup = ide_disk_setup, .flush = ide_disk_flush, diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index 219e6fb78dc6..001f68f0bb28 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -347,6 +347,7 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) return mode; } +EXPORT_SYMBOL_GPL(ide_find_dma_mode); static int ide_tune_dma(ide_drive_t *drive) { diff --git a/trunk/drivers/ide/ide-eh.c b/trunk/drivers/ide/ide-eh.c index 2b9141979613..5d5fb961b5ce 100644 --- a/trunk/drivers/ide/ide-eh.c +++ b/trunk/drivers/ide/ide-eh.c @@ -52,7 +52,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, } if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special_flags |= IDE_SFLAG_RECALIBRATE; + drive->special.b.recalibrate = 1; ++rq->errors; @@ -268,8 +268,9 @@ static void ide_disk_pre_reset(ide_drive_t *drive) { int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; - drive->special_flags = - legacy ? (IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE) : 0; + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; drive->mult_count = 0; drive->dev_flags &= ~IDE_DFLAG_PARKED; @@ -279,7 +280,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive) drive->mult_req = 0; if (drive->mult_req != drive->mult_count) - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; } static void pre_reset(ide_drive_t *drive) @@ -407,9 +408,8 @@ static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) /* more than enough time */ udelay(10); /* clear SRST, leave nIEN (unless device is on the quirk list) */ - tp_ops->write_devctl(hwif, - ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) ? 0 : ATA_NIEN) | - ATA_DEVCTL_OBS); + tp_ops->write_devctl(hwif, (drive->quirk_list == 2 ? 0 : ATA_NIEN) | + ATA_DEVCTL_OBS); /* more than enough time */ udelay(10); hwif->poll_timeout = jiffies + WAIT_WORSTCASE; diff --git a/trunk/drivers/ide/ide-gd.c b/trunk/drivers/ide/ide-gd.c index 214119026b3f..4b6b71e2cdf5 100644 --- a/trunk/drivers/ide/ide-gd.c +++ b/trunk/drivers/ide/ide-gd.c @@ -287,19 +287,6 @@ static int ide_gd_media_changed(struct gendisk *disk) return ret; } -static unsigned long long ide_gd_set_capacity(struct gendisk *disk, - unsigned long long capacity) -{ - struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); - ide_drive_t *drive = idkp->drive; - const struct ide_disk_ops *disk_ops = drive->disk_ops; - - if (disk_ops->set_capacity) - return disk_ops->set_capacity(drive, capacity); - - return drive->capacity64; -} - static int ide_gd_revalidate_disk(struct gendisk *disk) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); @@ -328,7 +315,6 @@ static struct block_device_operations ide_gd_ops = { .locked_ioctl = ide_gd_ioctl, .getgeo = ide_gd_getgeo, .media_changed = ide_gd_media_changed, - .set_capacity = ide_gd_set_capacity, .revalidate_disk = ide_gd_revalidate_disk }; diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c index 54d7c4685d23..7812ca0be13b 100644 --- a/trunk/drivers/ide/ide-generic.c +++ b/trunk/drivers/ide/ide-generic.c @@ -29,7 +29,6 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); static const struct ide_port_info ide_generic_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; #ifdef CONFIG_ARM @@ -86,7 +85,7 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) static int __init ide_generic_init(void) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; unsigned long io_addr; int i, rc = 0, primary = 0, secondary = 0; @@ -133,7 +132,9 @@ static int __init ide_generic_init(void) #else hw.irq = legacy_irqs[i]; #endif - rc = ide_host_add(&ide_generic_port_info, hws, 1, NULL); + hw.chipset = ide_generic; + + rc = ide_host_add(&ide_generic_port_info, hws, NULL); if (rc) { release_region(io_addr + 0x206, 1); release_region(io_addr, 8); diff --git a/trunk/drivers/ide/ide-h8300.c b/trunk/drivers/ide/ide-h8300.c index 520f42c5445a..c06ebdc4a130 100644 --- a/trunk/drivers/ide/ide-h8300.c +++ b/trunk/drivers/ide/ide-h8300.c @@ -64,26 +64,26 @@ static const struct ide_tp_ops h8300_tp_ops = { #define H8300_IDE_GAP (2) -static inline void hw_setup(struct ide_hw *hw) +static inline void hw_setup(hw_regs_t *hw) { int i; - memset(hw, 0, sizeof(*hw)); + memset(hw, 0, sizeof(hw_regs_t)); for (i = 0; i <= 7; i++) hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; + hw->chipset = ide_generic; } static const struct ide_port_info h8300_port_info = { .tp_ops = &h8300_tp_ops, .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int __init h8300_ide_init(void) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); @@ -96,7 +96,7 @@ static int __init h8300_ide_init(void) hw_setup(&hw); - return ide_host_add(&h8300_port_info, hws, 1, NULL); + return ide_host_add(&h8300_port_info, hws, NULL); out_busy: printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index 272cc38f6dbe..bba4297f2f03 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -184,42 +184,29 @@ static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) tf->command = ATA_CMD_SET_MULTI; } -/** - * do_special - issue some special commands - * @drive: drive the command is for - * - * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, - * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. - */ - -static ide_startstop_t do_special(ide_drive_t *drive) +static ide_startstop_t ide_disk_special(ide_drive_t *drive) { + special_t *s = &drive->special; struct ide_cmd cmd; -#ifdef DEBUG - printk(KERN_DEBUG "%s: %s: 0x%02x\n", drive->name, __func__, - drive->special_flags); -#endif - if (drive->media != ide_disk) { - drive->special_flags = 0; - drive->mult_req = 0; - return ide_stopped; - } - memset(&cmd, 0, sizeof(cmd)); cmd.protocol = ATA_PROT_NODATA; - if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) { - drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY; + if (s->b.set_geometry) { + s->b.set_geometry = 0; ide_tf_set_specify_cmd(drive, &cmd.tf); - } else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) { - drive->special_flags &= ~IDE_SFLAG_RECALIBRATE; + } else if (s->b.recalibrate) { + s->b.recalibrate = 0; ide_tf_set_restore_cmd(drive, &cmd.tf); - } else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) { - drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE; + } else if (s->b.set_multmode) { + s->b.set_multmode = 0; ide_tf_set_setmult_cmd(drive, &cmd.tf); - } else - BUG(); + } else if (s->all) { + int special = s->all; + s->all = 0; + printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); + return ide_stopped; + } cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; @@ -230,6 +217,31 @@ static ide_startstop_t do_special(ide_drive_t *drive) return ide_started; } +/** + * do_special - issue some special commands + * @drive: drive the command is for + * + * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, + * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. + * + * It used to do much more, but has been scaled back. + */ + +static ide_startstop_t do_special (ide_drive_t *drive) +{ + special_t *s = &drive->special; + +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", drive->name, s->all); +#endif + if (drive->media == ide_disk) + return ide_disk_special(drive); + + s->all = 0; + drive->mult_req = 0; + return ide_stopped; +} + void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) { ide_hwif_t *hwif = drive->hwif; @@ -339,8 +351,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) printk(KERN_ERR "%s: drive not ready for command\n", drive->name); return startstop; } - - if (drive->special_flags == 0) { + if (!drive->special.all) { struct ide_driver *drv; /* @@ -488,15 +499,11 @@ void do_ide_request(struct request_queue *q) if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && hwif != prev_port) { - ide_drive_t *cur_dev = - prev_port ? prev_port->cur_dev : NULL; - /* * set nIEN for previous port, drives in the - * quirk list may not like intr setups/cleanups + * quirk_list may not like intr setups/cleanups */ - if (cur_dev && - (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) + if (prev_port && prev_port->cur_dev->quirk_list == 0) prev_port->tp_ops->write_devctl(prev_port, ATA_NIEN | ATA_DEVCTL_OBS); diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index fa047150a1c6..06fe002116ec 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -282,29 +282,6 @@ u8 eighty_ninty_three(ide_drive_t *drive) return 0; } -static const char *nien_quirk_list[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP KA9.1", - "QUANTUM FIREBALLP KX13.6", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -void ide_check_nien_quirk_list(ide_drive_t *drive) -{ - const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; - - for (list = nien_quirk_list; *list != NULL; list++) - if (strstr(m, *list) != NULL) { - drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK; - return; - } -} - int ide_driveid_update(ide_drive_t *drive) { u16 *id; @@ -334,6 +311,7 @@ int ide_driveid_update(ide_drive_t *drive) return 1; out_err: + SELECT_MASK(drive, 0); if (rc == 2) printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); kfree(id); @@ -387,7 +365,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); - if (drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) + if (drive->quirk_list == 2) tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); error = __ide_wait_stat(drive, drive->ready_stat, diff --git a/trunk/drivers/ide/ide-legacy.c b/trunk/drivers/ide/ide-legacy.c index b9654a7bb7be..8c5dcbf22547 100644 --- a/trunk/drivers/ide/ide-legacy.c +++ b/trunk/drivers/ide/ide-legacy.c @@ -1,7 +1,7 @@ #include #include -static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, +static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, u8 port_no, const struct ide_port_info *d, unsigned long config) { @@ -33,6 +33,7 @@ static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, ide_std_init_ports(hw, base, ctl); hw->irq = irq; + hw->chipset = d->chipset; hw->config = config; hws[port_no] = hw; @@ -40,7 +41,7 @@ static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) { - struct ide_hw hw[2], *hws[] = { NULL, NULL }; + hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; memset(&hw, 0, sizeof(hw)); @@ -52,6 +53,6 @@ int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) (d->host_flags & IDE_HFLAG_SINGLE)) return -ENOENT; - return ide_host_add(d, hws, 2, NULL); + return ide_host_add(d, hws, NULL); } EXPORT_SYMBOL_GPL(ide_legacy_device_add); diff --git a/trunk/drivers/ide/ide-pnp.c b/trunk/drivers/ide/ide-pnp.c index 017b1df3b805..6e80b774e88a 100644 --- a/trunk/drivers/ide/ide-pnp.c +++ b/trunk/drivers/ide/ide-pnp.c @@ -29,7 +29,6 @@ static struct pnp_device_id idepnp_devices[] = { static const struct ide_port_info ide_pnp_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) @@ -37,7 +36,7 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) struct ide_host *host; unsigned long base, ctl; int rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n"); @@ -63,8 +62,9 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, base, ctl); hw.irq = pnp_irq(dev, 0); + hw.chipset = ide_generic; - rc = ide_host_add(&ide_pnp_port_info, hws, 1, &host); + rc = ide_host_add(&ide_pnp_port_info, hws, &host); if (rc) goto out; diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index f371b0de314f..c895ed52b2e8 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -97,7 +97,7 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; if (drive->mult_req) - drive->special_flags |= IDE_SFLAG_SET_MULTMODE; + drive->special.b.set_multmode = 1; } } @@ -465,8 +465,23 @@ static u8 probe_for_drive(ide_drive_t *drive) int rc; u8 cmd; + /* + * In order to keep things simple we have an id + * block for all drives at all times. If the device + * is pre ATA or refuses ATA/ATAPI identify we + * will add faked data to this. + * + * Also note that 0 everywhere means "can't do X" + */ + drive->dev_flags &= ~IDE_DFLAG_ID_READ; + drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); + if (drive->id == NULL) { + printk(KERN_ERR "ide: out of memory for id data.\n"); + return 0; + } + m = (char *)&drive->id[ATA_ID_PROD]; strcpy(m, "UNKNOWN"); @@ -482,7 +497,7 @@ static u8 probe_for_drive(ide_drive_t *drive) } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - return 0; + goto out_free; /* identification failed? */ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { @@ -506,7 +521,7 @@ static u8 probe_for_drive(ide_drive_t *drive) } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - return 0; + goto out_free; /* The drive wasn't being helpful. Add generic info only */ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { @@ -520,6 +535,9 @@ static u8 probe_for_drive(ide_drive_t *drive) } return 1; +out_free: + kfree(drive->id); + return 0; } static void hwif_release_dev(struct device *dev) @@ -684,14 +702,8 @@ static int ide_probe_port(ide_hwif_t *hwif) if (irqd) disable_irq(hwif->irq); - rc = ide_port_wait_ready(hwif); - if (rc == -ENODEV) { - printk(KERN_INFO "%s: no devices on the port\n", hwif->name); - goto out; - } else if (rc == -EBUSY) - printk(KERN_ERR "%s: not ready before the probe\n", hwif->name); - else - rc = -ENODEV; + if (ide_port_wait_ready(hwif) == -EBUSY) + printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); /* * Second drive should only exist if first drive was found, @@ -702,7 +714,7 @@ static int ide_probe_port(ide_hwif_t *hwif) if (drive->dev_flags & IDE_DFLAG_PRESENT) rc = 0; } -out: + /* * Use cached IRQ number. It might be (and is...) changed by probe * code above @@ -720,8 +732,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) int i; ide_port_for_each_present_dev(i, drive, hwif) { - ide_check_nien_quirk_list(drive); - if (port_ops && port_ops->quirkproc) port_ops->quirkproc(drive); } @@ -807,6 +817,8 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) if (ide_init_queue(drive)) { printk(KERN_ERR "ide: failed to init %s\n", drive->name); + kfree(drive->id); + drive->id = NULL; drive->dev_flags &= ~IDE_DFLAG_PRESENT; continue; } @@ -935,6 +947,9 @@ static void drive_release_dev (struct device *dev) blk_cleanup_queue(drive->queue); drive->queue = NULL; + kfree(drive->id); + drive->id = NULL; + drive->dev_flags &= ~IDE_DFLAG_PRESENT; complete(&drive->gendev_rel_comp); @@ -1020,15 +1035,6 @@ static void ide_port_init_devices(ide_hwif_t *hwif) if (port_ops && port_ops->init_dev) port_ops->init_dev(drive); } - - ide_port_for_each_dev(i, drive, hwif) { - /* - * default to PIO Mode 0 before we figure out - * the most suited mode for the attached device - */ - if (port_ops && port_ops->set_pio_mode) - port_ops->set_pio_mode(drive, 0); - } } static void ide_init_port(ide_hwif_t *hwif, unsigned int port, @@ -1036,7 +1042,8 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, { hwif->channel = port; - hwif->chipset = d->chipset ? d->chipset : ide_pci; + if (d->chipset) + hwif->chipset = d->chipset; if (d->init_iops) d->init_iops(hwif); @@ -1117,19 +1124,16 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) ide_port_for_each_dev(i, drive, hwif) { u8 j = (hwif->index * MAX_DRIVES) + i; - u16 *saved_id = drive->id; memset(drive, 0, sizeof(*drive)); - memset(saved_id, 0, SECTOR_SIZE); - drive->id = saved_id; drive->media = ide_disk; drive->select = (i << 4) | ATA_DEVICE_OBS; drive->hwif = hwif; drive->ready_stat = ATA_DRDY; drive->bad_wstat = BAD_W_STAT; - drive->special_flags = IDE_SFLAG_RECALIBRATE | - IDE_SFLAG_SET_GEOMETRY; + drive->special.b.recalibrate = 1; + drive->special.b.set_geometry = 1; drive->name[0] = 'h'; drive->name[1] = 'd'; drive->name[2] = 'a' + j; @@ -1164,10 +1168,11 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) ide_port_init_devices_data(hwif); } -static void ide_init_port_hw(ide_hwif_t *hwif, struct ide_hw *hw) +static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) { memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); hwif->irq = hw->irq; + hwif->chipset = hw->chipset; hwif->dev = hw->dev; hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; hwif->ack_intr = hw->ack_intr; @@ -1228,10 +1233,8 @@ static void ide_port_free_devices(ide_hwif_t *hwif) ide_drive_t *drive; int i; - ide_port_for_each_dev(i, drive, hwif) { - kfree(drive->id); + ide_port_for_each_dev(i, drive, hwif) kfree(drive); - } } static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) @@ -1245,18 +1248,6 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) if (drive == NULL) goto out_nomem; - /* - * In order to keep things simple we have an id - * block for all drives at all times. If the device - * is pre ATA or refuses ATA/ATAPI identify we - * will add faked data to this. - * - * Also note that 0 everywhere means "can't do X" - */ - drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node); - if (drive->id == NULL) - goto out_nomem; - hwif->devices[i] = drive; } return 0; @@ -1266,8 +1257,7 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) return -ENOMEM; } -struct ide_host *ide_host_alloc(const struct ide_port_info *d, - struct ide_hw **hws, unsigned int n_ports) +struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) { struct ide_host *host; struct device *dev = hws[0] ? hws[0]->dev : NULL; @@ -1278,7 +1268,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, if (host == NULL) return NULL; - for (i = 0; i < n_ports; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { ide_hwif_t *hwif; int idx; @@ -1298,7 +1288,6 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, if (idx < 0) { printk(KERN_ERR "%s: no free slot for interface\n", d ? d->name : "ide"); - ide_port_free_devices(hwif); kfree(hwif); continue; } @@ -1355,7 +1344,7 @@ static void ide_disable_port(ide_hwif_t *hwif) } int ide_host_register(struct ide_host *host, const struct ide_port_info *d, - struct ide_hw **hws) + hw_regs_t **hws) { ide_hwif_t *hwif, *mate = NULL; int i, j = 0; @@ -1449,13 +1438,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } EXPORT_SYMBOL_GPL(ide_host_register); -int ide_host_add(const struct ide_port_info *d, struct ide_hw **hws, - unsigned int n_ports, struct ide_host **hostp) +int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws, + struct ide_host **hostp) { struct ide_host *host; int rc; - host = ide_host_alloc(d, hws, n_ports); + host = ide_host_alloc(d, hws); if (host == NULL) return -ENOMEM; diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c index 4b447a8a49d4..d9764f0bc82f 100644 --- a/trunk/drivers/ide/ide-tape.c +++ b/trunk/drivers/ide/ide-tape.c @@ -240,27 +240,18 @@ static struct class *idetape_sysfs_class; static void ide_tape_release(struct device *); -static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES]; - -static struct ide_tape_obj *ide_tape_get(struct gendisk *disk, bool cdev, - unsigned int i) +static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) { struct ide_tape_obj *tape = NULL; mutex_lock(&idetape_ref_mutex); - - if (cdev) - tape = idetape_devs[i]; - else - tape = ide_drv_g(disk, ide_tape_obj); - + tape = ide_drv_g(disk, ide_tape_obj); if (tape) { if (ide_device_get(tape->drive)) tape = NULL; else get_device(&tape->dev); } - mutex_unlock(&idetape_ref_mutex); return tape; } @@ -275,6 +266,24 @@ static void ide_tape_put(struct ide_tape_obj *tape) mutex_unlock(&idetape_ref_mutex); } +/* + * The variables below are used for the character device interface. Additional + * state variables are defined in our ide_drive_t structure. + */ +static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES]; + +static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) +{ + struct ide_tape_obj *tape = NULL; + + mutex_lock(&idetape_ref_mutex); + tape = idetape_devs[i]; + if (tape) + get_device(&tape->dev); + mutex_unlock(&idetape_ref_mutex); + return tape; +} + /* * called on each failed packet command retry to analyze the request sense. We * currently do not utilize this information. @@ -388,8 +397,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) if (readpos[0] & 0x4) { printk(KERN_INFO "ide-tape: Block location is unknown" "to the tape\n"); - clear_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), - &drive->atapi_flags); + clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); uptodate = 0; err = IDE_DRV_ERROR_GENERAL; } else { @@ -398,8 +406,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) tape->partition = readpos[1]; tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]); - set_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), - &drive->atapi_flags); + set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); } } @@ -649,15 +656,15 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 && (rq->cmd[13] & REQ_IDETAPE_PC2) == 0) - drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; + set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); if (drive->dev_flags & IDE_DFLAG_POST_RESET) { - drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; + set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); drive->dev_flags &= ~IDE_DFLAG_POST_RESET; } - if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) && - !(stat & ATA_DSC)) { + if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) && + (stat & ATA_DSC) == 0) { if (postponed_rq == NULL) { tape->dsc_polling_start = jiffies; tape->dsc_poll_freq = tape->best_dsc_rw_freq; @@ -677,9 +684,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW; idetape_postpone_request(drive); return ide_stopped; - } else - drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC; - + } if (rq->cmd[13] & REQ_IDETAPE_READ) { pc = &tape->queued_pc; ide_tape_create_rw_cmd(tape, pc, rq, READ_6); @@ -739,7 +744,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) int load_attempted = 0; /* Wait for the tape to become ready */ - set_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), &drive->atapi_flags); + set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); timeout += jiffies; while (time_before(jiffies, timeout)) { if (ide_do_test_unit_ready(drive, disk) == 0) @@ -815,7 +820,7 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) if (tape->chrdev_dir != IDETAPE_DIR_READ) return; - clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags); + clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); tape->valid = 0; if (tape->buf != NULL) { kfree(tape->buf); @@ -1108,8 +1113,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, if (tape->chrdev_dir == IDETAPE_DIR_READ) { tape->valid = 0; - if (test_and_clear_bit(ilog2(IDE_AFLAG_FILEMARK), - &drive->atapi_flags)) + if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) ++count; ide_tape_discard_merge_buffer(drive, 0); } @@ -1164,7 +1168,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); if (tape->chrdev_dir != IDETAPE_DIR_READ) { - if (test_bit(ilog2(IDE_AFLAG_DETECT_BS), &drive->atapi_flags)) + if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags)) if (count > tape->blk_size && (count % tape->blk_size) == 0) tape->user_bs_factor = count / tape->blk_size; @@ -1180,8 +1184,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, /* refill if staging buffer is empty */ if (!tape->valid) { /* If we are at a filemark, nothing more to read */ - if (test_bit(ilog2(IDE_AFLAG_FILEMARK), - &drive->atapi_flags)) + if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) break; /* read */ if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, @@ -1199,7 +1202,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, done += todo; } - if (!done && test_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags)) { + if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); idetape_space_over_filemarks(drive, MTFSF, 1); @@ -1333,8 +1336,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) ide_tape_discard_merge_buffer(drive, 0); retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK); if (!retval) - clear_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), - &drive->atapi_flags); + clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); return retval; case MTNOP: ide_tape_discard_merge_buffer(drive, 0); @@ -1356,11 +1358,9 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) mt_count % tape->blk_size) return -EIO; tape->user_bs_factor = mt_count / tape->blk_size; - clear_bit(ilog2(IDE_AFLAG_DETECT_BS), - &drive->atapi_flags); + clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags); } else - set_bit(ilog2(IDE_AFLAG_DETECT_BS), - &drive->atapi_flags); + set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags); return 0; case MTSEEK: ide_tape_discard_merge_buffer(drive, 0); @@ -1486,7 +1486,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) return -ENXIO; lock_kernel(); - tape = ide_tape_get(NULL, true, i); + tape = ide_tape_chrdev_get(i); if (!tape) { unlock_kernel(); return -ENXIO; @@ -1505,20 +1505,20 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) filp->private_data = tape; - if (test_and_set_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags)) { + if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) { retval = -EBUSY; goto out_put_tape; } retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { - clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); + clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); goto out_put_tape; } idetape_read_position(drive); - if (!test_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), &drive->atapi_flags)) + if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags)) (void)idetape_rewind_tape(drive); /* Read block size and write protect status from drive. */ @@ -1534,7 +1534,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) if (tape->write_prot) { if ((filp->f_flags & O_ACCMODE) == O_WRONLY || (filp->f_flags & O_ACCMODE) == O_RDWR) { - clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); + clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); retval = -EROFS; goto out_put_tape; } @@ -1591,17 +1591,15 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) ide_tape_discard_merge_buffer(drive, 1); } - if (minor < 128 && test_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), - &drive->atapi_flags)) + if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags)) (void) idetape_rewind_tape(drive); - if (tape->chrdev_dir == IDETAPE_DIR_NONE) { if (tape->door_locked == DOOR_LOCKED) { if (!ide_set_media_lock(drive, tape->disk, 0)) tape->door_locked = DOOR_UNLOCKED; } } - clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); + clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); ide_tape_put(tape); unlock_kernel(); return 0; @@ -1907,7 +1905,7 @@ static const struct file_operations idetape_fops = { static int idetape_open(struct block_device *bdev, fmode_t mode) { - struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk, false, 0); + struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk); if (!tape) return -ENXIO; diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 75b85a8cd2d4..a0c3e1b2f73c 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -98,6 +98,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { ide_tf_dump(drive->name, cmd); tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); + SELECT_MASK(drive, 0); if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { u8 data[2] = { cmd->tf.data, cmd->hob.data }; @@ -165,7 +166,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { if (custom && tf->command == ATA_CMD_SET_MULTI) { drive->mult_req = drive->mult_count = 0; - drive->special_flags |= IDE_SFLAG_RECALIBRATE; + drive->special.b.recalibrate = 1; (void)ide_dump_status(drive, __func__, stat); return ide_stopped; } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index 16d056939f9f..92c9b90931e7 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -211,11 +211,6 @@ static unsigned int ide_noflush; module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); MODULE_PARM_DESC(noflush, "disable flush requests for a device"); -static unsigned int ide_nohpa; - -module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0); -MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); - static unsigned int ide_noprobe; module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); @@ -286,11 +281,6 @@ static void ide_dev_apply_params(ide_drive_t *drive, u8 unit) drive->name); drive->dev_flags |= IDE_DFLAG_NOFLUSH; } - if (ide_nohpa & (1 << i)) { - printk(KERN_INFO "ide: disabling Host Protected Area for %s\n", - drive->name); - drive->dev_flags |= IDE_DFLAG_NOHPA; - } if (ide_noprobe & (1 << i)) { printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); drive->dev_flags |= IDE_DFLAG_NOPROBE; diff --git a/trunk/drivers/ide/ide_platform.c b/trunk/drivers/ide/ide_platform.c index ee9b55ecc62b..051b4ab0f359 100644 --- a/trunk/drivers/ide/ide_platform.c +++ b/trunk/drivers/ide/ide_platform.c @@ -21,7 +21,7 @@ #include #include -static void __devinit plat_ide_setup_ports(struct ide_hw *hw, +static void __devinit plat_ide_setup_ports(hw_regs_t *hw, void __iomem *base, void __iomem *ctrl, struct pata_platform_info *pdata, @@ -40,11 +40,12 @@ static void __devinit plat_ide_setup_ports(struct ide_hw *hw, hw->io_ports.ctl_addr = (unsigned long)ctrl; hw->irq = irq; + + hw->chipset = ide_generic; } static const struct ide_port_info platform_ide_port_info = { .host_flags = IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; static int __devinit plat_ide_probe(struct platform_device *pdev) @@ -54,7 +55,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) struct pata_platform_info *pdata; struct ide_host *host; int ret = 0, mmio = 0; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; struct ide_port_info d = platform_ide_port_info; pdata = pdev->dev.platform_data; @@ -98,7 +99,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) if (mmio) d.host_flags |= IDE_HFLAG_MMIO; - ret = ide_host_add(&d, hws, 1, &host); + ret = ide_host_add(&d, hws, &host); if (ret) goto out; diff --git a/trunk/drivers/ide/macide.c b/trunk/drivers/ide/macide.c index 1447c8c90565..4b1718e83283 100644 --- a/trunk/drivers/ide/macide.c +++ b/trunk/drivers/ide/macide.c @@ -62,7 +62,7 @@ int macide_ack_intr(ide_hwif_t* hwif) return 0; } -static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, +static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, int irq, ide_ack_intr_t *ack_intr) { int i; @@ -76,12 +76,13 @@ static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static const struct ide_port_info macide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; static const char *mac_ide_name[] = @@ -96,7 +97,7 @@ static int __init macide_init(void) ide_ack_intr_t *ack_intr; unsigned long base; int irq; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; if (!MACH_IS_MAC) return -ENODEV; @@ -126,7 +127,7 @@ static int __init macide_init(void) macide_setup_ports(&hw, base, irq, ack_intr); - return ide_host_add(&macide_port_info, hws, 1, NULL); + return ide_host_add(&macide_port_info, hws, NULL); } module_init(macide_init); diff --git a/trunk/drivers/ide/palm_bk3710.c b/trunk/drivers/ide/palm_bk3710.c index 3c1dc0152153..09d813d313f4 100644 --- a/trunk/drivers/ide/palm_bk3710.c +++ b/trunk/drivers/ide/palm_bk3710.c @@ -306,7 +306,6 @@ static struct ide_port_info __devinitdata palm_bk3710_port_info = { .host_flags = IDE_HFLAG_MMIO, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, - .chipset = ide_palm3710, }; static int __init palm_bk3710_probe(struct platform_device *pdev) @@ -316,7 +315,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) void __iomem *base; unsigned long rate, mem_size; int i, rc; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; clk = clk_get(&pdev->dev, "IDECLK"); if (IS_ERR(clk)) @@ -364,12 +363,13 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) (base + IDE_PALM_ATA_PRI_CTL_OFFSET); hw.irq = irq->start; hw.dev = &pdev->dev; + hw.chipset = ide_palm3710; palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5; /* Register the IDE interface with Linux */ - rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL); + rc = ide_host_add(&palm_bk3710_port_info, hws, NULL); if (rc) goto out; diff --git a/trunk/drivers/ide/pdc202xx_new.c b/trunk/drivers/ide/pdc202xx_new.c index 65ba8239e7b5..b68906c3c17e 100644 --- a/trunk/drivers/ide/pdc202xx_new.c +++ b/trunk/drivers/ide/pdc202xx_new.c @@ -40,6 +40,18 @@ #define DBG(fmt, args...) #endif +static const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + static u8 max_dma_rate(struct pci_dev *pdev) { u8 mode; @@ -188,6 +200,19 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA80; } +static void pdcnew_quirkproc(ide_drive_t *drive) +{ + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(m, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; +} + static void pdcnew_reset(ide_drive_t *drive) { /* @@ -448,6 +473,7 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) static const struct ide_port_ops pdcnew_port_ops = { .set_pio_mode = pdcnew_set_pio_mode, .set_dma_mode = pdcnew_set_dma_mode, + .quirkproc = pdcnew_quirkproc, .resetproc = pdcnew_reset, .cable_detect = pdcnew_cable_detect, }; diff --git a/trunk/drivers/ide/pdc202xx_old.c b/trunk/drivers/ide/pdc202xx_old.c index b6abf7e52cac..e24ecc87a9b1 100644 --- a/trunk/drivers/ide/pdc202xx_old.c +++ b/trunk/drivers/ide/pdc202xx_old.c @@ -23,6 +23,18 @@ #define PDC202XX_DEBUG_DRIVE_INFO 0 +static const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP KA9.1", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX13.6", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + static void pdc_old_disable_66MHz_clock(ide_hwif_t *); static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) @@ -139,6 +151,19 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); } +static void pdc202xx_quirkproc(ide_drive_t *drive) +{ + const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(m, *list) != NULL) { + drive->quirk_list = 2; + return; + } + + drive->quirk_list = 0; +} + static void pdc202xx_dma_start(ide_drive_t *drive) { if (drive->current_speed > XFER_UDMA_2) @@ -178,6 +203,52 @@ static int pdc202xx_dma_end(ide_drive_t *drive) return ide_dma_end(drive); } +static int pdc202xx_dma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned long high_16 = hwif->extra_base - 16; + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); + u8 sc1d = inb(high_16 + 0x001d); + + if (hwif->channel) { + /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ + if ((sc1d & 0x50) == 0x50) + goto somebody_else; + else if ((sc1d & 0x40) == 0x40) + return (dma_stat & 4) == 4; + } else { + /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */ + if ((sc1d & 0x05) == 0x05) + goto somebody_else; + else if ((sc1d & 0x04) == 0x04) + return (dma_stat & 4) == 4; + } +somebody_else: + return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ +} + +static void pdc202xx_reset(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + unsigned long high_16 = hwif->extra_base - 16; + u8 udma_speed_flag = inb(high_16 | 0x001f); + + printk(KERN_WARNING "PDC202xx: software reset...\n"); + + outb(udma_speed_flag | 0x10, high_16 | 0x001f); + mdelay(100); + outb(udma_speed_flag & ~0x10, high_16 | 0x001f); + mdelay(2000); /* 2 seconds ?! */ + + ide_set_max_pio(drive); +} + +static void pdc202xx_dma_lost_irq(ide_drive_t *drive) +{ + pdc202xx_reset(drive); + ide_dma_lost_irq(drive); +} + static int init_chipset_pdc202xx(struct pci_dev *dev) { unsigned long dmabase = pci_resource_start(dev, 4); @@ -231,22 +302,37 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, static const struct ide_port_ops pdc20246_port_ops = { .set_pio_mode = pdc202xx_set_pio_mode, .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, }; static const struct ide_port_ops pdc2026x_port_ops = { .set_pio_mode = pdc202xx_set_pio_mode, .set_dma_mode = pdc202xx_set_mode, + .quirkproc = pdc202xx_quirkproc, + .resetproc = pdc202xx_reset, .cable_detect = pdc2026x_cable_detect, }; +static const struct ide_dma_ops pdc20246_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_start = ide_dma_start, + .dma_end = ide_dma_end, + .dma_test_irq = pdc202xx_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timer_expiry = ide_dma_sff_timer_expiry, + .dma_sff_read_status = ide_dma_sff_read_status, +}; + static const struct ide_dma_ops pdc2026x_dma_ops = { .dma_host_set = ide_dma_host_set, .dma_setup = ide_dma_setup, .dma_start = pdc202xx_dma_start, .dma_end = pdc202xx_dma_end, - .dma_test_irq = ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, + .dma_test_irq = pdc202xx_dma_test_irq, + .dma_lost_irq = pdc202xx_dma_lost_irq, .dma_timer_expiry = ide_dma_sff_timer_expiry, + .dma_clear = pdc202xx_reset, .dma_sff_read_status = ide_dma_sff_read_status, }; @@ -268,7 +354,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_pdc202xx, .port_ops = &pdc20246_port_ops, - .dma_ops = &sff_dma_ops, + .dma_ops = &pdc20246_dma_ops, .host_flags = IDE_HFLAGS_PDC202XX, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, diff --git a/trunk/drivers/ide/pmac.c b/trunk/drivers/ide/pmac.c index 97642a7a79c4..f76e4e6b408f 100644 --- a/trunk/drivers/ide/pmac.c +++ b/trunk/drivers/ide/pmac.c @@ -1023,14 +1023,13 @@ static const struct ide_port_info pmac_port_info = { * Setup, register & probe an IDE channel driven by this driver, this is * called by one of the 2 probe functions (macio or PCI). */ -static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, - struct ide_hw *hw) +static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) { struct device_node *np = pmif->node; const int *bidp; struct ide_host *host; ide_hwif_t *hwif; - struct ide_hw *hws[] = { hw }; + hw_regs_t *hws[] = { hw, NULL, NULL, NULL }; struct ide_port_info d = pmac_port_info; int rc; @@ -1078,7 +1077,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, /* Make sure we have sane timings */ sanitize_timings(pmif); - host = ide_host_alloc(&d, hws, 1); + host = ide_host_alloc(&d, hws); if (host == NULL) return -ENOMEM; hwif = host->ports[0]; @@ -1125,7 +1124,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, return 0; } -static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) +static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) { int i; @@ -1145,7 +1144,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) unsigned long regbase; pmac_ide_hwif_t *pmif; int irq, rc; - struct ide_hw hw; + hw_regs_t hw; pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); if (pmif == NULL) @@ -1269,7 +1268,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) void __iomem *base; unsigned long rbase, rlen; int rc; - struct ide_hw hw; + hw_regs_t hw; np = pci_device_to_OF_node(pdev); if (np == NULL) { diff --git a/trunk/drivers/ide/q40ide.c b/trunk/drivers/ide/q40ide.c index ab49a97023d9..c79346679244 100644 --- a/trunk/drivers/ide/q40ide.c +++ b/trunk/drivers/ide/q40ide.c @@ -51,11 +51,11 @@ static int q40ide_default_irq(unsigned long base) /* * Addresses are pretranslated for Q40 ISA access. */ -static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, +static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, ide_ack_intr_t *ack_intr, int irq) { - memset(hw, 0, sizeof(*hw)); + memset(hw, 0, sizeof(hw_regs_t)); /* BIG FAT WARNING: assumption: only DATA port is ever used in 16 bit mode */ hw->io_ports.data_addr = Q40_ISA_IO_W(base); @@ -70,6 +70,8 @@ static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, hw->irq = irq; hw->ack_intr = ack_intr; + + hw->chipset = ide_generic; } static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, @@ -117,7 +119,6 @@ static const struct ide_port_info q40ide_port_info = { .tp_ops = &q40ide_tp_ops, .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, .irq_flags = IRQF_SHARED, - .chipset = ide_generic, }; /* @@ -135,7 +136,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ static int __init q40ide_init(void) { int i; - struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL }; + hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; if (!MACH_IS_Q40) return -ENODEV; @@ -162,7 +163,7 @@ static int __init q40ide_init(void) hws[i] = &hw[i]; } - return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL); + return ide_host_add(&q40ide_port_info, hws, NULL); } module_init(q40ide_init); diff --git a/trunk/drivers/ide/rapide.c b/trunk/drivers/ide/rapide.c index 00f54248f41f..d5003ca69801 100644 --- a/trunk/drivers/ide/rapide.c +++ b/trunk/drivers/ide/rapide.c @@ -13,10 +13,9 @@ static const struct ide_port_info rapide_port_info = { .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, - .chipset = ide_generic, }; -static void rapide_setup_ports(struct ide_hw *hw, void __iomem *base, +static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) { unsigned long port = (unsigned long)base; @@ -36,7 +35,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) void __iomem *base; struct ide_host *host; int ret; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; ret = ecard_request_resources(ec); if (ret) @@ -50,9 +49,10 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) memset(&hw, 0, sizeof(hw)); rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); + hw.chipset = ide_generic; hw.dev = &ec->dev; - ret = ide_host_add(&rapide_port_info, hws, 1, &host); + ret = ide_host_add(&rapide_port_info, hws, &host); if (ret) goto release; diff --git a/trunk/drivers/ide/scc_pata.c b/trunk/drivers/ide/scc_pata.c index 1104bb301eb9..5be41f25204f 100644 --- a/trunk/drivers/ide/scc_pata.c +++ b/trunk/drivers/ide/scc_pata.c @@ -559,7 +559,7 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, { struct scc_ports *ports = pci_get_drvdata(dev); struct ide_host *host; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int i, rc; memset(&hw, 0, sizeof(hw)); @@ -567,8 +567,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; hw.irq = dev->irq; hw.dev = &dev->dev; + hw.chipset = ide_pci; - rc = ide_host_add(d, hws, 1, &host); + rc = ide_host_add(d, hws, &host); if (rc) return rc; @@ -822,7 +823,6 @@ static const struct ide_port_info scc_chipset __devinitdata = { .host_flags = IDE_HFLAG_SINGLE, .irq_flags = IRQF_SHARED, .pio_mask = ATA_PIO4, - .chipset = ide_pci, }; /** diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index ab3db61d2ba0..7a3a12d6e638 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -1,7 +1,7 @@ /* * Copyright (C) 1998-2000 Andre Hedrick * Copyright (C) 1995-1998 Mark Lord - * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public License */ @@ -301,11 +301,11 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * } /** - * ide_hw_configure - configure a struct ide_hw instance + * ide_hw_configure - configure a hw_regs_t instance * @dev: PCI device holding interface * @d: IDE port info * @port: port number - * @hw: struct ide_hw instance corresponding to this port + * @hw: hw_regs_t instance corresponding to this port * * Perform the initial set up for the hardware interface structure. This * is done per interface port rather than per PCI device. There may be @@ -315,7 +315,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * */ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, - unsigned int port, struct ide_hw *hw) + unsigned int port, hw_regs_t *hw) { unsigned long ctl = 0, base = 0; @@ -344,6 +344,7 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, memset(hw, 0, sizeof(*hw)); hw->dev = &dev->dev; + hw->chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(hw, base, ctl | 2); return 0; @@ -445,8 +446,8 @@ static int ide_setup_pci_controller(struct pci_dev *dev, * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device * @d: IDE port info - * @hw: struct ide_hw instances corresponding to this PCI IDE device - * @hws: struct ide_hw pointers table to update + * @hw: hw_regs_t instances corresponding to this PCI IDE device + * @hws: hw_regs_t pointers table to update * * Scan the interfaces attached to this device and do any * necessary per port setup. Attach the devices and ask the @@ -458,7 +459,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev, */ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, - struct ide_hw *hw, struct ide_hw **hws) + hw_regs_t *hw, hw_regs_t **hws) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; u8 tmp; @@ -534,15 +535,61 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, return ret; } +int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, + void *priv) +{ + struct ide_host *host; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; + int ret; + + ret = ide_setup_pci_controller(dev, d, 1); + if (ret < 0) + goto out; + + ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); + + host = ide_host_alloc(d, hws); + if (host == NULL) { + ret = -ENOMEM; + goto out; + } + + host->dev[0] = &dev->dev; + + host->host_priv = priv; + + host->irq_flags = IRQF_SHARED; + + pci_set_drvdata(dev, host); + + ret = do_ide_setup_pci_device(dev, d, 1); + if (ret < 0) + goto out; + + /* fixup IRQ */ + if (ide_pci_is_in_compatibility_mode(dev)) { + hw[0].irq = pci_get_legacy_ide_irq(dev, 0); + hw[1].irq = pci_get_legacy_ide_irq(dev, 1); + } else + hw[1].irq = hw[0].irq = ret; + + ret = ide_host_register(host, d, hws); + if (ret) + ide_host_free(host); +out: + return ret; +} +EXPORT_SYMBOL_GPL(ide_pci_init_one); + int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, const struct ide_port_info *d, void *priv) { struct pci_dev *pdev[] = { dev1, dev2 }; struct ide_host *host; - int ret, i, n_ports = dev2 ? 4 : 2; - struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; + int ret, i; + hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; - for (i = 0; i < n_ports / 2; i++) { + for (i = 0; i < 2; i++) { ret = ide_setup_pci_controller(pdev[i], d, !i); if (ret < 0) goto out; @@ -550,24 +597,23 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } - host = ide_host_alloc(d, hws, n_ports); + host = ide_host_alloc(d, hws); if (host == NULL) { ret = -ENOMEM; goto out; } host->dev[0] = &dev1->dev; - if (dev2) - host->dev[1] = &dev2->dev; + host->dev[1] = &dev2->dev; host->host_priv = priv; + host->irq_flags = IRQF_SHARED; pci_set_drvdata(pdev[0], host); - if (dev2) - pci_set_drvdata(pdev[1], host); + pci_set_drvdata(pdev[1], host); - for (i = 0; i < n_ports / 2; i++) { + for (i = 0; i < 2; i++) { ret = do_ide_setup_pci_device(pdev[i], d, !i); /* @@ -593,13 +639,6 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, } EXPORT_SYMBOL_GPL(ide_pci_init_two); -int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, - void *priv) -{ - return ide_pci_init_two(dev, NULL, d, priv); -} -EXPORT_SYMBOL_GPL(ide_pci_init_one); - void ide_pci_remove(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); diff --git a/trunk/drivers/ide/sgiioc4.c b/trunk/drivers/ide/sgiioc4.c index 5f37f168f944..e5d2a48a84de 100644 --- a/trunk/drivers/ide/sgiioc4.c +++ b/trunk/drivers/ide/sgiioc4.c @@ -91,7 +91,7 @@ typedef struct { static void -sgiioc4_init_hwif_ports(struct ide_hw *hw, unsigned long data_port, +sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, unsigned long ctrl_port, unsigned long irq_port) { unsigned long reg = data_port; @@ -546,7 +546,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) unsigned long cmd_base, irqport; unsigned long bar0, cmd_phys_base, ctl; void __iomem *virt_base; - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; int rc; /* Get the CmdBlk and CtrlBlk Base Registers */ @@ -575,12 +575,13 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) memset(&hw, 0, sizeof(hw)); sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); hw.irq = dev->irq; + hw.chipset = ide_pci; hw.dev = &dev->dev; /* Initializing chipset IRQ Registers */ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); - rc = ide_host_add(&sgiioc4_port_info, hws, 1, NULL); + rc = ide_host_add(&sgiioc4_port_info, hws, NULL); if (!rc) return 0; diff --git a/trunk/drivers/ide/siimage.c b/trunk/drivers/ide/siimage.c index bd82d228608c..e4973cd1fba9 100644 --- a/trunk/drivers/ide/siimage.c +++ b/trunk/drivers/ide/siimage.c @@ -451,8 +451,8 @@ static int sil_sata_reset_poll(ide_drive_t *drive) static void sil_sata_pre_reset(ide_drive_t *drive) { if (drive->media == ide_disk) { - drive->special_flags &= - ~(IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE); + drive->special.b.set_geometry = 0; + drive->special.b.recalibrate = 0; } } diff --git a/trunk/drivers/ide/sl82c105.c b/trunk/drivers/ide/sl82c105.c index 0924abff52ff..b0a460625335 100644 --- a/trunk/drivers/ide/sl82c105.c +++ b/trunk/drivers/ide/sl82c105.c @@ -10,7 +10,7 @@ * with the timing registers setup. * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org * - * Copyright (C) 2006-2007,2009 MontaVista Software, Inc. + * Copyright (C) 2006-2007 MontaVista Software, Inc. * Copyright (C) 2007 Bartlomiej Zolnierkiewicz */ @@ -146,15 +146,14 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive) u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; u8 dma_cmd; - printk(KERN_WARNING "sl82c105: lost IRQ, resetting host\n"); + printk("sl82c105: lost IRQ, resetting host\n"); /* * Check the raw interrupt from the drive. */ pci_read_config_dword(dev, 0x40, &val); if (val & mask) - printk(KERN_INFO "sl82c105: drive was requesting IRQ, " - "but host lost it\n"); + printk("sl82c105: drive was requesting IRQ, but host lost it\n"); /* * Was DMA enabled? If so, disable it - we're resetting the @@ -163,7 +162,7 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive) dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); if (dma_cmd & 1) { outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); - printk(KERN_INFO "sl82c105: DMA was enabled\n"); + printk("sl82c105: DMA was enabled\n"); } sl82c105_reset_host(dev); diff --git a/trunk/drivers/ide/tx4938ide.c b/trunk/drivers/ide/tx4938ide.c index ea89fddeed91..e33d764e2945 100644 --- a/trunk/drivers/ide/tx4938ide.c +++ b/trunk/drivers/ide/tx4938ide.c @@ -130,7 +130,8 @@ static const struct ide_port_info tx4938ide_port_info __initdata = { static int __init tx4938ide_probe(struct platform_device *pdev) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; @@ -182,7 +183,7 @@ static int __init tx4938ide_probe(struct platform_device *pdev) tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); else d.port_ops = NULL; - ret = ide_host_add(&d, hws, 1, &host); + ret = ide_host_add(&d, hws, &host); if (!ret) platform_set_drvdata(pdev, host); return ret; diff --git a/trunk/drivers/ide/tx4939ide.c b/trunk/drivers/ide/tx4939ide.c index 64b58ecc3f0e..5ca76224f6d1 100644 --- a/trunk/drivers/ide/tx4939ide.c +++ b/trunk/drivers/ide/tx4939ide.c @@ -537,7 +537,8 @@ static const struct ide_port_info tx4939ide_port_info __initdata = { static int __init tx4939ide_probe(struct platform_device *pdev) { - struct ide_hw hw, *hws[] = { &hw }; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; struct ide_host *host; struct resource *res; int irq, ret; @@ -580,7 +581,7 @@ static int __init tx4939ide_probe(struct platform_device *pdev) hw.dev = &pdev->dev; pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq); - host = ide_host_alloc(&tx4939ide_port_info, hws, 1); + host = ide_host_alloc(&tx4939ide_port_info, hws); if (!host) return -ENOMEM; /* use extra_base for base address of the all registers */ diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index e4e4d433b007..35e8eb02b9e9 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -354,7 +354,7 @@ static int default_crt_on __devinitdata = 0; static int default_lcd_on __devinitdata = 1; #ifdef CONFIG_MTRR -static bool mtrr = true; +static int mtrr = 1; #endif #ifdef CONFIG_PMAC_BACKLIGHT diff --git a/trunk/drivers/video/cyber2000fb.c b/trunk/drivers/video/cyber2000fb.c index da7c01b39be2..83c5cefc266c 100644 --- a/trunk/drivers/video/cyber2000fb.c +++ b/trunk/drivers/video/cyber2000fb.c @@ -1736,8 +1736,10 @@ static int __init cyber2000fb_init(void) #ifdef CONFIG_ARCH_SHARK err = cyberpro_vl_probe(); - if (!err) + if (!err) { ret = 0; + __module_get(THIS_MODULE); + } #endif #ifdef CONFIG_PCI err = pci_register_driver(&cyberpro_driver); @@ -1747,15 +1749,14 @@ static int __init cyber2000fb_init(void) return ret ? err : 0; } -module_init(cyber2000fb_init); -#ifndef CONFIG_ARCH_SHARK static void __exit cyberpro_exit(void) { pci_unregister_driver(&cyberpro_driver); } + +module_init(cyber2000fb_init); module_exit(cyberpro_exit); -#endif MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); diff --git a/trunk/drivers/video/uvesafb.c b/trunk/drivers/video/uvesafb.c index ca5b4643a401..421770b5e6ab 100644 --- a/trunk/drivers/video/uvesafb.c +++ b/trunk/drivers/video/uvesafb.c @@ -45,7 +45,7 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = { static int mtrr __devinitdata = 3; /* enable mtrr by default */ static int blank = 1; /* enable blanking by default */ static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ -static bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */ +static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */ static int nocrtc __devinitdata; /* ignore CRTC settings */ static int noedid __devinitdata; /* don't try DDC transfers */ static int vram_remap __devinitdata; /* set amt. of memory to be used */ @@ -2002,7 +2002,11 @@ static void __devexit uvesafb_exit(void) module_exit(uvesafb_exit); -#define param_get_scroll NULL +static int param_get_scroll(char *buffer, struct kernel_param *kp) +{ + return 0; +} + static int param_set_scroll(const char *val, struct kernel_param *kp) { ypan = 0; @@ -2013,8 +2017,6 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) ypan = 1; else if (!strcmp(val, "ywrap")) ypan = 2; - else - return -EINVAL; return 0; } diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index 525da2e8f73b..9f7270f36b2a 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -62,16 +62,6 @@ source "fs/autofs/Kconfig" source "fs/autofs4/Kconfig" source "fs/fuse/Kconfig" -config CUSE - tristate "Character device in Userpace support" - depends on FUSE_FS - help - This FUSE extension allows character devices to be - implemented in userspace. - - If you want to develop or use userspace character device - based on CUSE, answer Y or M. - config GENERIC_ACL bool select FS_POSIX_ACL diff --git a/trunk/fs/fuse/Makefile b/trunk/fs/fuse/Makefile index e95eeb445e58..72437065f6ad 100644 --- a/trunk/fs/fuse/Makefile +++ b/trunk/fs/fuse/Makefile @@ -3,6 +3,5 @@ # obj-$(CONFIG_FUSE_FS) += fuse.o -obj-$(CONFIG_CUSE) += cuse.o fuse-objs := dev.o dir.o file.o inode.o control.o diff --git a/trunk/fs/fuse/cuse.c b/trunk/fs/fuse/cuse.c deleted file mode 100644 index de792dcf3274..000000000000 --- a/trunk/fs/fuse/cuse.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * CUSE: Character device in Userspace - * - * Copyright (C) 2008-2009 SUSE Linux Products GmbH - * Copyright (C) 2008-2009 Tejun Heo - * - * This file is released under the GPLv2. - * - * CUSE enables character devices to be implemented from userland much - * like FUSE allows filesystems. On initialization /dev/cuse is - * created. By opening the file and replying to the CUSE_INIT request - * userland CUSE server can create a character device. After that the - * operation is very similar to FUSE. - * - * A CUSE instance involves the following objects. - * - * cuse_conn : contains fuse_conn and serves as bonding structure - * channel : file handle connected to the userland CUSE server - * cdev : the implemented character device - * dev : generic device for cdev - * - * Note that 'channel' is what 'dev' is in FUSE. As CUSE deals with - * devices, it's called 'channel' to reduce confusion. - * - * channel determines when the character device dies. When channel is - * closed, everything begins to destruct. The cuse_conn is taken off - * the lookup table preventing further access from cdev, cdev and - * generic device are removed and the base reference of cuse_conn is - * put. - * - * On each open, the matching cuse_conn is looked up and if found an - * additional reference is taken which is released when the file is - * closed. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fuse_i.h" - -#define CUSE_CONNTBL_LEN 64 - -struct cuse_conn { - struct list_head list; /* linked on cuse_conntbl */ - struct fuse_conn fc; /* fuse connection */ - struct cdev *cdev; /* associated character device */ - struct device *dev; /* device representing @cdev */ - - /* init parameters, set once during initialization */ - bool unrestricted_ioctl; -}; - -static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ -static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; -static struct class *cuse_class; - -static struct cuse_conn *fc_to_cc(struct fuse_conn *fc) -{ - return container_of(fc, struct cuse_conn, fc); -} - -static struct list_head *cuse_conntbl_head(dev_t devt) -{ - return &cuse_conntbl[(MAJOR(devt) + MINOR(devt)) % CUSE_CONNTBL_LEN]; -} - - -/************************************************************************** - * CUSE frontend operations - * - * These are file operations for the character device. - * - * On open, CUSE opens a file from the FUSE mnt and stores it to - * private_data of the open file. All other ops call FUSE ops on the - * FUSE file. - */ - -static ssize_t cuse_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - loff_t pos = 0; - - return fuse_direct_io(file, buf, count, &pos, 0); -} - -static ssize_t cuse_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - loff_t pos = 0; - /* - * No locking or generic_write_checks(), the server is - * responsible for locking and sanity checks. - */ - return fuse_direct_io(file, buf, count, &pos, 1); -} - -static int cuse_open(struct inode *inode, struct file *file) -{ - dev_t devt = inode->i_cdev->dev; - struct cuse_conn *cc = NULL, *pos; - int rc; - - /* look up and get the connection */ - spin_lock(&cuse_lock); - list_for_each_entry(pos, cuse_conntbl_head(devt), list) - if (pos->dev->devt == devt) { - fuse_conn_get(&pos->fc); - cc = pos; - break; - } - spin_unlock(&cuse_lock); - - /* dead? */ - if (!cc) - return -ENODEV; - - /* - * Generic permission check is already done against the chrdev - * file, proceed to open. - */ - rc = fuse_do_open(&cc->fc, 0, file, 0); - if (rc) - fuse_conn_put(&cc->fc); - return rc; -} - -static int cuse_release(struct inode *inode, struct file *file) -{ - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; - - fuse_sync_release(ff, file->f_flags); - fuse_conn_put(fc); - - return 0; -} - -static long cuse_file_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct fuse_file *ff = file->private_data; - struct cuse_conn *cc = fc_to_cc(ff->fc); - unsigned int flags = 0; - - if (cc->unrestricted_ioctl) - flags |= FUSE_IOCTL_UNRESTRICTED; - - return fuse_do_ioctl(file, cmd, arg, flags); -} - -static long cuse_file_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct fuse_file *ff = file->private_data; - struct cuse_conn *cc = fc_to_cc(ff->fc); - unsigned int flags = FUSE_IOCTL_COMPAT; - - if (cc->unrestricted_ioctl) - flags |= FUSE_IOCTL_UNRESTRICTED; - - return fuse_do_ioctl(file, cmd, arg, flags); -} - -static const struct file_operations cuse_frontend_fops = { - .owner = THIS_MODULE, - .read = cuse_read, - .write = cuse_write, - .open = cuse_open, - .release = cuse_release, - .unlocked_ioctl = cuse_file_ioctl, - .compat_ioctl = cuse_file_compat_ioctl, - .poll = fuse_file_poll, -}; - - -/************************************************************************** - * CUSE channel initialization and destruction - */ - -struct cuse_devinfo { - const char *name; -}; - -/** - * cuse_parse_one - parse one key=value pair - * @pp: i/o parameter for the current position - * @end: points to one past the end of the packed string - * @keyp: out parameter for key - * @valp: out parameter for value - * - * *@pp points to packed strings - "key0=val0\0key1=val1\0" which ends - * at @end - 1. This function parses one pair and set *@keyp to the - * start of the key and *@valp to the start of the value. Note that - * the original string is modified such that the key string is - * terminated with '\0'. *@pp is updated to point to the next string. - * - * RETURNS: - * 1 on successful parse, 0 on EOF, -errno on failure. - */ -static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) -{ - char *p = *pp; - char *key, *val; - - while (p < end && *p == '\0') - p++; - if (p == end) - return 0; - - if (end[-1] != '\0') { - printk(KERN_ERR "CUSE: info not properly terminated\n"); - return -EINVAL; - } - - key = val = p; - p += strlen(p); - - if (valp) { - strsep(&val, "="); - if (!val) - val = key + strlen(key); - key = strstrip(key); - val = strstrip(val); - } else - key = strstrip(key); - - if (!strlen(key)) { - printk(KERN_ERR "CUSE: zero length info key specified\n"); - return -EINVAL; - } - - *pp = p; - *keyp = key; - if (valp) - *valp = val; - - return 1; -} - -/** - * cuse_parse_dev_info - parse device info - * @p: device info string - * @len: length of device info string - * @devinfo: out parameter for parsed device info - * - * Parse @p to extract device info and store it into @devinfo. String - * pointed to by @p is modified by parsing and @devinfo points into - * them, so @p shouldn't be freed while @devinfo is in use. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) -{ - char *end = p + len; - char *key, *val; - int rc; - - while (true) { - rc = cuse_parse_one(&p, end, &key, &val); - if (rc < 0) - return rc; - if (!rc) - break; - if (strcmp(key, "DEVNAME") == 0) - devinfo->name = val; - else - printk(KERN_WARNING "CUSE: unknown device info \"%s\"\n", - key); - } - - if (!devinfo->name || !strlen(devinfo->name)) { - printk(KERN_ERR "CUSE: DEVNAME unspecified\n"); - return -EINVAL; - } - - return 0; -} - -static void cuse_gendev_release(struct device *dev) -{ - kfree(dev); -} - -/** - * cuse_process_init_reply - finish initializing CUSE channel - * - * This function creates the character device and sets up all the - * required data structures for it. Please read the comment at the - * top of this file for high level overview. - */ -static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) -{ - struct cuse_conn *cc = fc_to_cc(fc); - struct cuse_init_out *arg = &req->misc.cuse_init_out; - struct page *page = req->pages[0]; - struct cuse_devinfo devinfo = { }; - struct device *dev; - struct cdev *cdev; - dev_t devt; - int rc; - - if (req->out.h.error || - arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { - goto err; - } - - fc->minor = arg->minor; - fc->max_read = max_t(unsigned, arg->max_read, 4096); - fc->max_write = max_t(unsigned, arg->max_write, 4096); - - /* parse init reply */ - cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL; - - rc = cuse_parse_devinfo(page_address(page), req->out.args[1].size, - &devinfo); - if (rc) - goto err; - - /* determine and reserve devt */ - devt = MKDEV(arg->dev_major, arg->dev_minor); - if (!MAJOR(devt)) - rc = alloc_chrdev_region(&devt, MINOR(devt), 1, devinfo.name); - else - rc = register_chrdev_region(devt, 1, devinfo.name); - if (rc) { - printk(KERN_ERR "CUSE: failed to register chrdev region\n"); - goto err; - } - - /* devt determined, create device */ - rc = -ENOMEM; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - goto err_region; - - device_initialize(dev); - dev_set_uevent_suppress(dev, 1); - dev->class = cuse_class; - dev->devt = devt; - dev->release = cuse_gendev_release; - dev_set_drvdata(dev, cc); - dev_set_name(dev, "%s", devinfo.name); - - rc = device_add(dev); - if (rc) - goto err_device; - - /* register cdev */ - rc = -ENOMEM; - cdev = cdev_alloc(); - if (!cdev) - goto err_device; - - cdev->owner = THIS_MODULE; - cdev->ops = &cuse_frontend_fops; - - rc = cdev_add(cdev, devt, 1); - if (rc) - goto err_cdev; - - cc->dev = dev; - cc->cdev = cdev; - - /* make the device available */ - spin_lock(&cuse_lock); - list_add(&cc->list, cuse_conntbl_head(devt)); - spin_unlock(&cuse_lock); - - /* announce device availability */ - dev_set_uevent_suppress(dev, 0); - kobject_uevent(&dev->kobj, KOBJ_ADD); -out: - __free_page(page); - return; - -err_cdev: - cdev_del(cdev); -err_device: - put_device(dev); -err_region: - unregister_chrdev_region(devt, 1); -err: - fc->conn_error = 1; - goto out; -} - -static int cuse_send_init(struct cuse_conn *cc) -{ - int rc; - struct fuse_req *req; - struct page *page; - struct fuse_conn *fc = &cc->fc; - struct cuse_init_in *arg; - - BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); - - req = fuse_get_req(fc); - if (IS_ERR(req)) { - rc = PTR_ERR(req); - goto err; - } - - rc = -ENOMEM; - page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!page) - goto err_put_req; - - arg = &req->misc.cuse_init_in; - arg->major = FUSE_KERNEL_VERSION; - arg->minor = FUSE_KERNEL_MINOR_VERSION; - arg->flags |= CUSE_UNRESTRICTED_IOCTL; - req->in.h.opcode = CUSE_INIT; - req->in.numargs = 1; - req->in.args[0].size = sizeof(struct cuse_init_in); - req->in.args[0].value = arg; - req->out.numargs = 2; - req->out.args[0].size = sizeof(struct cuse_init_out); - req->out.args[0].value = &req->misc.cuse_init_out; - req->out.args[1].size = CUSE_INIT_INFO_MAX; - req->out.argvar = 1; - req->out.argpages = 1; - req->pages[0] = page; - req->num_pages = 1; - req->end = cuse_process_init_reply; - fuse_request_send_background(fc, req); - - return 0; - -err_put_req: - fuse_put_request(fc, req); -err: - return rc; -} - -static void cuse_fc_release(struct fuse_conn *fc) -{ - struct cuse_conn *cc = fc_to_cc(fc); - kfree(cc); -} - -/** - * cuse_channel_open - open method for /dev/cuse - * @inode: inode for /dev/cuse - * @file: file struct being opened - * - * Userland CUSE server can create a CUSE device by opening /dev/cuse - * and replying to the initilaization request kernel sends. This - * function is responsible for handling CUSE device initialization. - * Because the fd opened by this function is used during - * initialization, this function only creates cuse_conn and sends - * init. The rest is delegated to a kthread. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -static int cuse_channel_open(struct inode *inode, struct file *file) -{ - struct cuse_conn *cc; - int rc; - - /* set up cuse_conn */ - cc = kzalloc(sizeof(*cc), GFP_KERNEL); - if (!cc) - return -ENOMEM; - - fuse_conn_init(&cc->fc); - - INIT_LIST_HEAD(&cc->list); - cc->fc.release = cuse_fc_release; - - cc->fc.connected = 1; - cc->fc.blocked = 0; - rc = cuse_send_init(cc); - if (rc) { - fuse_conn_put(&cc->fc); - return rc; - } - file->private_data = &cc->fc; /* channel owns base reference to cc */ - - return 0; -} - -/** - * cuse_channel_release - release method for /dev/cuse - * @inode: inode for /dev/cuse - * @file: file struct being closed - * - * Disconnect the channel, deregister CUSE device and initiate - * destruction by putting the default reference. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -static int cuse_channel_release(struct inode *inode, struct file *file) -{ - struct cuse_conn *cc = fc_to_cc(file->private_data); - int rc; - - /* remove from the conntbl, no more access from this point on */ - spin_lock(&cuse_lock); - list_del_init(&cc->list); - spin_unlock(&cuse_lock); - - /* remove device */ - if (cc->dev) - device_unregister(cc->dev); - if (cc->cdev) { - unregister_chrdev_region(cc->cdev->dev, 1); - cdev_del(cc->cdev); - } - - /* kill connection and shutdown channel */ - fuse_conn_kill(&cc->fc); - rc = fuse_dev_release(inode, file); /* puts the base reference */ - - return rc; -} - -static struct file_operations cuse_channel_fops; /* initialized during init */ - - -/************************************************************************** - * Misc stuff and module initializatiion - * - * CUSE exports the same set of attributes to sysfs as fusectl. - */ - -static ssize_t cuse_class_waiting_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cuse_conn *cc = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting)); -} - -static ssize_t cuse_class_abort_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cuse_conn *cc = dev_get_drvdata(dev); - - fuse_abort_conn(&cc->fc); - return count; -} - -static struct device_attribute cuse_class_dev_attrs[] = { - __ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL), - __ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store), - { } -}; - -static struct miscdevice cuse_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "cuse", - .fops = &cuse_channel_fops, -}; - -static int __init cuse_init(void) -{ - int i, rc; - - /* init conntbl */ - for (i = 0; i < CUSE_CONNTBL_LEN; i++) - INIT_LIST_HEAD(&cuse_conntbl[i]); - - /* inherit and extend fuse_dev_operations */ - cuse_channel_fops = fuse_dev_operations; - cuse_channel_fops.owner = THIS_MODULE; - cuse_channel_fops.open = cuse_channel_open; - cuse_channel_fops.release = cuse_channel_release; - - cuse_class = class_create(THIS_MODULE, "cuse"); - if (IS_ERR(cuse_class)) - return PTR_ERR(cuse_class); - - cuse_class->dev_attrs = cuse_class_dev_attrs; - - rc = misc_register(&cuse_miscdev); - if (rc) { - class_destroy(cuse_class); - return rc; - } - - return 0; -} - -static void __exit cuse_exit(void) -{ - misc_deregister(&cuse_miscdev); - class_destroy(cuse_class); -} - -module_init(cuse_init); -module_exit(cuse_exit); - -MODULE_AUTHOR("Tejun Heo "); -MODULE_DESCRIPTION("Character device in Userspace"); -MODULE_LICENSE("GPL"); diff --git a/trunk/fs/fuse/dev.c b/trunk/fs/fuse/dev.c index 8fed2ed12f38..ba76b68c52ff 100644 --- a/trunk/fs/fuse/dev.c +++ b/trunk/fs/fuse/dev.c @@ -46,7 +46,6 @@ struct fuse_req *fuse_request_alloc(void) fuse_request_init(req); return req; } -EXPORT_SYMBOL_GPL(fuse_request_alloc); struct fuse_req *fuse_request_alloc_nofs(void) { @@ -125,7 +124,6 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc) atomic_dec(&fc->num_waiting); return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(fuse_get_req); /* * Return request in fuse_file->reserved_req. However that may @@ -210,7 +208,6 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) fuse_request_free(req); } } -EXPORT_SYMBOL_GPL(fuse_put_request); static unsigned len_args(unsigned numargs, struct fuse_arg *args) { @@ -285,7 +282,7 @@ __releases(&fc->lock) wake_up_all(&fc->blocked_waitq); } if (fc->num_background == FUSE_CONGESTION_THRESHOLD && - fc->connected && fc->bdi_initialized) { + fc->connected) { clear_bdi_congested(&fc->bdi, READ); clear_bdi_congested(&fc->bdi, WRITE); } @@ -403,7 +400,6 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) } spin_unlock(&fc->lock); } -EXPORT_SYMBOL_GPL(fuse_request_send); static void fuse_request_send_nowait_locked(struct fuse_conn *fc, struct fuse_req *req) @@ -412,8 +408,7 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, fc->num_background++; if (fc->num_background == FUSE_MAX_BACKGROUND) fc->blocked = 1; - if (fc->num_background == FUSE_CONGESTION_THRESHOLD && - fc->bdi_initialized) { + if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { set_bdi_congested(&fc->bdi, READ); set_bdi_congested(&fc->bdi, WRITE); } @@ -444,7 +439,6 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) req->isreply = 1; fuse_request_send_nowait(fc, req); } -EXPORT_SYMBOL_GPL(fuse_request_send_background); /* * Called under fc->lock @@ -1111,9 +1105,8 @@ void fuse_abort_conn(struct fuse_conn *fc) } spin_unlock(&fc->lock); } -EXPORT_SYMBOL_GPL(fuse_abort_conn); -int fuse_dev_release(struct inode *inode, struct file *file) +static int fuse_dev_release(struct inode *inode, struct file *file) { struct fuse_conn *fc = fuse_get_conn(file); if (fc) { @@ -1127,7 +1120,6 @@ int fuse_dev_release(struct inode *inode, struct file *file) return 0; } -EXPORT_SYMBOL_GPL(fuse_dev_release); static int fuse_dev_fasync(int fd, struct file *file, int on) { @@ -1150,7 +1142,6 @@ const struct file_operations fuse_dev_operations = { .release = fuse_dev_release, .fasync = fuse_dev_fasync, }; -EXPORT_SYMBOL_GPL(fuse_dev_operations); static struct miscdevice fuse_miscdevice = { .minor = FUSE_MINOR, diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index b3089a083d30..8b8eebc5614b 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -361,6 +361,19 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, return ERR_PTR(err); } +/* + * Synchronous release for the case when something goes wrong in CREATE_OPEN + */ +static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, int flags) +{ + fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE); + ff->reserved_req->force = 1; + fuse_request_send(fc, ff->reserved_req); + fuse_put_request(fc, ff->reserved_req); + kfree(ff); +} + /* * Atomic create+open operation * @@ -432,14 +445,12 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, goto out_free_ff; fuse_put_request(fc, req); - ff->fh = outopen.fh; - ff->nodeid = outentry.nodeid; - ff->open_flags = outopen.open_flags; inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, &outentry.attr, entry_attr_timeout(&outentry), 0); if (!inode) { flags &= ~(O_CREAT | O_EXCL | O_TRUNC); - fuse_sync_release(ff, flags); + ff->fh = outopen.fh; + fuse_sync_release(fc, ff, outentry.nodeid, flags); fuse_send_forget(fc, forget_req, outentry.nodeid, 1); return -ENOMEM; } @@ -449,11 +460,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, fuse_invalidate_attr(dir); file = lookup_instantiate_filp(nd, entry, generic_file_open); if (IS_ERR(file)) { - fuse_sync_release(ff, flags); + ff->fh = outopen.fh; + fuse_sync_release(fc, ff, outentry.nodeid, flags); return PTR_ERR(file); } - file->private_data = fuse_file_get(ff); - fuse_finish_open(inode, file); + fuse_finish_open(inode, file, ff, &outopen); return 0; out_free_ff: @@ -1024,7 +1035,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) req->out.argpages = 1; req->num_pages = 1; req->pages[0] = page; - fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); + fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); fuse_request_send(fc, req); nbytes = req->out.args[0].size; err = req->out.h.error; @@ -1090,14 +1101,12 @@ static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) static int fuse_dir_open(struct inode *inode, struct file *file) { - return fuse_open_common(inode, file, true); + return fuse_open_common(inode, file, 1); } static int fuse_dir_release(struct inode *inode, struct file *file) { - fuse_release_common(file, FUSE_RELEASEDIR); - - return 0; + return fuse_release_common(inode, file, 1); } static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index fce6ce694fde..06f30e965676 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -12,13 +12,13 @@ #include #include #include -#include static const struct file_operations fuse_direct_io_file_operations; -static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, - int opcode, struct fuse_open_out *outargp) +static int fuse_send_open(struct inode *inode, struct file *file, int isdir, + struct fuse_open_out *outargp) { + struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_open_in inarg; struct fuse_req *req; int err; @@ -31,8 +31,8 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); if (!fc->atomic_o_trunc) inarg.flags &= ~O_TRUNC; - req->in.h.opcode = opcode; - req->in.h.nodeid = nodeid; + req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -49,27 +49,22 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) { struct fuse_file *ff; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); - if (unlikely(!ff)) - return NULL; - - ff->fc = fc; - ff->reserved_req = fuse_request_alloc(); - if (unlikely(!ff->reserved_req)) { - kfree(ff); - return NULL; + if (ff) { + ff->reserved_req = fuse_request_alloc(); + if (!ff->reserved_req) { + kfree(ff); + return NULL; + } else { + INIT_LIST_HEAD(&ff->write_entry); + atomic_set(&ff->count, 0); + spin_lock(&fc->lock); + ff->kh = ++fc->khctr; + spin_unlock(&fc->lock); + } + RB_CLEAR_NODE(&ff->polled_node); + init_waitqueue_head(&ff->poll_wait); } - - INIT_LIST_HEAD(&ff->write_entry); - atomic_set(&ff->count, 0); - RB_CLEAR_NODE(&ff->polled_node); - init_waitqueue_head(&ff->poll_wait); - - spin_lock(&fc->lock); - ff->kh = ++fc->khctr; - spin_unlock(&fc->lock); - return ff; } @@ -79,7 +74,7 @@ void fuse_file_free(struct fuse_file *ff) kfree(ff); } -struct fuse_file *fuse_file_get(struct fuse_file *ff) +static struct fuse_file *fuse_file_get(struct fuse_file *ff) { atomic_inc(&ff->count); return ff; @@ -87,65 +82,40 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) { - path_put(&req->misc.release.path); + dput(req->misc.release.dentry); + mntput(req->misc.release.vfsmount); } static void fuse_file_put(struct fuse_file *ff) { if (atomic_dec_and_test(&ff->count)) { struct fuse_req *req = ff->reserved_req; - + struct inode *inode = req->misc.release.dentry->d_inode; + struct fuse_conn *fc = get_fuse_conn(inode); req->end = fuse_release_end; - fuse_request_send_background(ff->fc, req); + fuse_request_send_background(fc, req); kfree(ff); } } -int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, - bool isdir) +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg) { - struct fuse_open_out outarg; - struct fuse_file *ff; - int err; - int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; - - ff = fuse_file_alloc(fc); - if (!ff) - return -ENOMEM; - - err = fuse_send_open(fc, nodeid, file, opcode, &outarg); - if (err) { - fuse_file_free(ff); - return err; - } - - if (isdir) - outarg.open_flags &= ~FOPEN_DIRECT_IO; - - ff->fh = outarg.fh; - ff->nodeid = nodeid; - ff->open_flags = outarg.open_flags; - file->private_data = fuse_file_get(ff); - - return 0; -} -EXPORT_SYMBOL_GPL(fuse_do_open); - -void fuse_finish_open(struct inode *inode, struct file *file) -{ - struct fuse_file *ff = file->private_data; - - if (ff->open_flags & FOPEN_DIRECT_IO) + if (outarg->open_flags & FOPEN_DIRECT_IO) file->f_op = &fuse_direct_io_file_operations; - if (!(ff->open_flags & FOPEN_KEEP_CACHE)) + if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) invalidate_inode_pages2(inode->i_mapping); - if (ff->open_flags & FOPEN_NONSEEKABLE) + if (outarg->open_flags & FOPEN_NONSEEKABLE) nonseekable_open(inode, file); + ff->fh = outarg->fh; + file->private_data = fuse_file_get(ff); } -int fuse_open_common(struct inode *inode, struct file *file, bool isdir) +int fuse_open_common(struct inode *inode, struct file *file, int isdir) { struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_open_out outarg; + struct fuse_file *ff; int err; /* VFS checks this, but only _after_ ->open() */ @@ -156,85 +126,78 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) if (err) return err; - err = fuse_do_open(fc, get_node_id(inode), file, isdir); - if (err) - return err; + ff = fuse_file_alloc(fc); + if (!ff) + return -ENOMEM; - fuse_finish_open(inode, file); + err = fuse_send_open(inode, file, isdir, &outarg); + if (err) + fuse_file_free(ff); + else { + if (isdir) + outarg.open_flags &= ~FOPEN_DIRECT_IO; + fuse_finish_open(inode, file, ff, &outarg); + } - return 0; + return err; } -static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) +void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode) { - struct fuse_conn *fc = ff->fc; struct fuse_req *req = ff->reserved_req; struct fuse_release_in *inarg = &req->misc.release.in; - spin_lock(&fc->lock); - list_del(&ff->write_entry); - if (!RB_EMPTY_NODE(&ff->polled_node)) - rb_erase(&ff->polled_node, &fc->polled_files); - spin_unlock(&fc->lock); - - wake_up_interruptible_sync(&ff->poll_wait); - inarg->fh = ff->fh; inarg->flags = flags; req->in.h.opcode = opcode; - req->in.h.nodeid = ff->nodeid; + req->in.h.nodeid = nodeid; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; } -void fuse_release_common(struct file *file, int opcode) +int fuse_release_common(struct inode *inode, struct file *file, int isdir) { - struct fuse_file *ff; - struct fuse_req *req; + struct fuse_file *ff = file->private_data; + if (ff) { + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req = ff->reserved_req; - ff = file->private_data; - if (unlikely(!ff)) - return; + fuse_release_fill(ff, get_node_id(inode), file->f_flags, + isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); - req = ff->reserved_req; - fuse_prepare_release(ff, file->f_flags, opcode); + /* Hold vfsmount and dentry until release is finished */ + req->misc.release.vfsmount = mntget(file->f_path.mnt); + req->misc.release.dentry = dget(file->f_path.dentry); + + spin_lock(&fc->lock); + list_del(&ff->write_entry); + if (!RB_EMPTY_NODE(&ff->polled_node)) + rb_erase(&ff->polled_node, &fc->polled_files); + spin_unlock(&fc->lock); - /* Hold vfsmount and dentry until release is finished */ - path_get(&file->f_path); - req->misc.release.path = file->f_path; + wake_up_interruptible_sync(&ff->poll_wait); + /* + * Normally this will send the RELEASE request, + * however if some asynchronous READ or WRITE requests + * are outstanding, the sending will be delayed + */ + fuse_file_put(ff); + } - /* - * Normally this will send the RELEASE request, however if - * some asynchronous READ or WRITE requests are outstanding, - * the sending will be delayed. - */ - fuse_file_put(ff); + /* Return value is ignored by VFS */ + return 0; } static int fuse_open(struct inode *inode, struct file *file) { - return fuse_open_common(inode, file, false); + return fuse_open_common(inode, file, 0); } static int fuse_release(struct inode *inode, struct file *file) { - fuse_release_common(file, FUSE_RELEASE); - - /* return value is ignored by VFS */ - return 0; -} - -void fuse_sync_release(struct fuse_file *ff, int flags) -{ - WARN_ON(atomic_read(&ff->count) > 1); - fuse_prepare_release(ff, flags, FUSE_RELEASE); - ff->reserved_req->force = 1; - fuse_request_send(ff->fc, ff->reserved_req); - fuse_put_request(ff->fc, ff->reserved_req); - kfree(ff); + return fuse_release_common(inode, file, 0); } -EXPORT_SYMBOL_GPL(fuse_sync_release); /* * Scramble the ID space with XTEA, so that the value of the files_struct @@ -408,8 +371,8 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) return fuse_fsync_common(file, de, datasync, 0); } -void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, - size_t count, int opcode) +void fuse_read_fill(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count, int opcode) { struct fuse_read_in *inarg = &req->misc.read.in; struct fuse_file *ff = file->private_data; @@ -419,7 +382,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, inarg->size = count; inarg->flags = file->f_flags; req->in.h.opcode = opcode; - req->in.h.nodeid = ff->nodeid; + req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_read_in); req->in.args[0].value = inarg; @@ -429,12 +392,12 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, } static size_t fuse_send_read(struct fuse_req *req, struct file *file, - loff_t pos, size_t count, fl_owner_t owner) + struct inode *inode, loff_t pos, size_t count, + fl_owner_t owner) { - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; + struct fuse_conn *fc = get_fuse_conn(inode); - fuse_read_fill(req, file, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (owner != NULL) { struct fuse_read_in *inarg = &req->misc.read.in; @@ -492,7 +455,7 @@ static int fuse_readpage(struct file *file, struct page *page) req->out.argpages = 1; req->num_pages = 1; req->pages[0] = page; - num_read = fuse_send_read(req, file, pos, count, NULL); + num_read = fuse_send_read(req, file, inode, pos, count, NULL); err = req->out.h.error; fuse_put_request(fc, req); @@ -541,18 +504,19 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) fuse_file_put(req->ff); } -static void fuse_send_readpages(struct fuse_req *req, struct file *file) +static void fuse_send_readpages(struct fuse_req *req, struct file *file, + struct inode *inode) { - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; + struct fuse_conn *fc = get_fuse_conn(inode); loff_t pos = page_offset(req->pages[0]); size_t count = req->num_pages << PAGE_CACHE_SHIFT; req->out.argpages = 1; req->out.page_zeroing = 1; - fuse_read_fill(req, file, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); req->misc.read.attr_ver = fuse_get_attr_version(fc); if (fc->async_read) { + struct fuse_file *ff = file->private_data; req->ff = fuse_file_get(ff); req->end = fuse_readpages_end; fuse_request_send_background(fc, req); @@ -582,7 +546,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || req->pages[req->num_pages - 1]->index + 1 != page->index)) { - fuse_send_readpages(req, data->file); + fuse_send_readpages(req, data->file, inode); data->req = req = fuse_get_req(fc); if (IS_ERR(req)) { unlock_page(page); @@ -616,7 +580,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { if (data.req->num_pages) - fuse_send_readpages(data.req, file); + fuse_send_readpages(data.req, file, inode); else fuse_put_request(fc, data.req); } @@ -643,19 +607,24 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, return generic_file_aio_read(iocb, iov, nr_segs, pos); } -static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, - loff_t pos, size_t count) +static void fuse_write_fill(struct fuse_req *req, struct file *file, + struct fuse_file *ff, struct inode *inode, + loff_t pos, size_t count, int writepage) { + struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_write_in *inarg = &req->misc.write.in; struct fuse_write_out *outarg = &req->misc.write.out; + memset(inarg, 0, sizeof(struct fuse_write_in)); inarg->fh = ff->fh; inarg->offset = pos; inarg->size = count; + inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; + inarg->flags = file ? file->f_flags : 0; req->in.h.opcode = FUSE_WRITE; - req->in.h.nodeid = ff->nodeid; + req->in.h.nodeid = get_node_id(inode); req->in.numargs = 2; - if (ff->fc->minor < 9) + if (fc->minor < 9) req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; else req->in.args[0].size = sizeof(struct fuse_write_in); @@ -667,15 +636,13 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, } static size_t fuse_send_write(struct fuse_req *req, struct file *file, - loff_t pos, size_t count, fl_owner_t owner) + struct inode *inode, loff_t pos, size_t count, + fl_owner_t owner) { - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; - struct fuse_write_in *inarg = &req->misc.write.in; - - fuse_write_fill(req, ff, pos, count); - inarg->flags = file->f_flags; + struct fuse_conn *fc = get_fuse_conn(inode); + fuse_write_fill(req, file, file->private_data, inode, pos, count, 0); if (owner != NULL) { + struct fuse_write_in *inarg = &req->misc.write.in; inarg->write_flags |= FUSE_WRITE_LOCKOWNER; inarg->lock_owner = fuse_lock_owner_id(fc, owner); } @@ -733,7 +700,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, req->num_pages = 1; req->pages[0] = page; req->page_offset = offset; - nres = fuse_send_write(req, file, pos, count, NULL); + nres = fuse_send_write(req, file, inode, pos, count, NULL); err = req->out.h.error; fuse_put_request(fc, req); if (!err && !nres) @@ -774,7 +741,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, for (i = 0; i < req->num_pages; i++) fuse_wait_on_page_writeback(inode, req->pages[i]->index); - res = fuse_send_write(req, file, pos, count, NULL); + res = fuse_send_write(req, file, inode, pos, count, NULL); offset = req->page_offset; count = res; @@ -1012,23 +979,25 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, return 0; } -ssize_t fuse_direct_io(struct file *file, const char __user *buf, - size_t count, loff_t *ppos, int write) +static ssize_t fuse_direct_io(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, int write) { - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; + struct inode *inode = file->f_path.dentry->d_inode; + struct fuse_conn *fc = get_fuse_conn(inode); size_t nmax = write ? fc->max_write : fc->max_read; loff_t pos = *ppos; ssize_t res = 0; struct fuse_req *req; + if (is_bad_inode(inode)) + return -EIO; + req = fuse_get_req(fc); if (IS_ERR(req)) return PTR_ERR(req); while (count) { size_t nres; - fl_owner_t owner = current->files; size_t nbytes = min(count, nmax); int err = fuse_get_user_pages(req, buf, &nbytes, write); if (err) { @@ -1037,10 +1006,11 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, } if (write) - nres = fuse_send_write(req, file, pos, nbytes, owner); + nres = fuse_send_write(req, file, inode, pos, nbytes, + current->files); else - nres = fuse_send_read(req, file, pos, nbytes, owner); - + nres = fuse_send_read(req, file, inode, pos, nbytes, + current->files); fuse_release_user_pages(req, !write); if (req->out.h.error) { if (!res) @@ -1064,27 +1034,20 @@ ssize_t fuse_direct_io(struct file *file, const char __user *buf, } } fuse_put_request(fc, req); - if (res > 0) + if (res > 0) { + if (write) + fuse_write_update_size(inode, pos); *ppos = pos; + } + fuse_invalidate_attr(inode); return res; } -EXPORT_SYMBOL_GPL(fuse_direct_io); static ssize_t fuse_direct_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ssize_t res; - struct inode *inode = file->f_path.dentry->d_inode; - - if (is_bad_inode(inode)) - return -EIO; - - res = fuse_direct_io(file, buf, count, ppos, 0); - - fuse_invalidate_attr(inode); - - return res; + return fuse_direct_io(file, buf, count, ppos, 0); } static ssize_t fuse_direct_write(struct file *file, const char __user *buf, @@ -1092,22 +1055,12 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, { struct inode *inode = file->f_path.dentry->d_inode; ssize_t res; - - if (is_bad_inode(inode)) - return -EIO; - /* Don't allow parallel writes to the same file */ mutex_lock(&inode->i_mutex); res = generic_write_checks(file, ppos, &count, 0); - if (!res) { + if (!res) res = fuse_direct_io(file, buf, count, ppos, 1); - if (res > 0) - fuse_write_update_size(inode, *ppos); - } mutex_unlock(&inode->i_mutex); - - fuse_invalidate_attr(inode); - return res; } @@ -1224,10 +1177,9 @@ static int fuse_writepage_locked(struct page *page) req->ff = fuse_file_get(ff); spin_unlock(&fc->lock); - fuse_write_fill(req, ff, page_offset(page), 0); + fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); copy_highpage(tmp_page, page); - req->misc.write.in.write_flags |= FUSE_WRITE_CACHE; req->in.argpages = 1; req->num_pages = 1; req->pages[0] = tmp_page; @@ -1651,11 +1603,12 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, * limits ioctl data transfers to well-formed ioctls and is the forced * behavior for all FUSE servers. */ -long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, - unsigned int flags) +static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, unsigned int flags) { + struct inode *inode = file->f_dentry->d_inode; struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; + struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_ioctl_in inarg = { .fh = ff->fh, .cmd = cmd, @@ -1674,6 +1627,13 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, /* assume all the iovs returned by client always fits in a page */ BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); + if (!fuse_allow_task(fc, current)) + return -EACCES; + + err = -EIO; + if (is_bad_inode(inode)) + goto out; + err = -ENOMEM; pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); iov_page = alloc_page(GFP_KERNEL); @@ -1734,7 +1694,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, /* okay, let's send it to the client */ req->in.h.opcode = FUSE_IOCTL; - req->in.h.nodeid = ff->nodeid; + req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -1817,33 +1777,17 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, return err ? err : outarg.result; } -EXPORT_SYMBOL_GPL(fuse_do_ioctl); - -static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, - unsigned long arg, unsigned int flags) -{ - struct inode *inode = file->f_dentry->d_inode; - struct fuse_conn *fc = get_fuse_conn(inode); - - if (!fuse_allow_task(fc, current)) - return -EACCES; - - if (is_bad_inode(inode)) - return -EIO; - - return fuse_do_ioctl(file, cmd, arg, flags); -} static long fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return fuse_file_ioctl_common(file, cmd, arg, 0); + return fuse_file_do_ioctl(file, cmd, arg, 0); } static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); + return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT); } /* @@ -1897,10 +1841,11 @@ static void fuse_register_polled_file(struct fuse_conn *fc, spin_unlock(&fc->lock); } -unsigned fuse_file_poll(struct file *file, poll_table *wait) +static unsigned fuse_file_poll(struct file *file, poll_table *wait) { + struct inode *inode = file->f_dentry->d_inode; struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; + struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; struct fuse_poll_out outarg; struct fuse_req *req; @@ -1925,7 +1870,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) return PTR_ERR(req); req->in.h.opcode = FUSE_POLL; - req->in.h.nodeid = ff->nodeid; + req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; req->in.args[0].size = sizeof(inarg); req->in.args[0].value = &inarg; @@ -1944,7 +1889,6 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) } return POLLERR; } -EXPORT_SYMBOL_GPL(fuse_file_poll); /* * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index aaf2f9ff970e..6fc5aedaa0d5 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -97,13 +97,8 @@ struct fuse_inode { struct list_head writepages; }; -struct fuse_conn; - /** FUSE specific file data */ struct fuse_file { - /** Fuse connection for this file */ - struct fuse_conn *fc; - /** Request reserved for flush and release */ struct fuse_req *reserved_req; @@ -113,15 +108,9 @@ struct fuse_file { /** File handle used by userspace */ u64 fh; - /** Node id of this file */ - u64 nodeid; - /** Refcount */ atomic_t count; - /** FOPEN_* flags returned by open */ - u32 open_flags; - /** Entry on inode's write_files list */ struct list_head write_entry; @@ -196,6 +185,8 @@ enum fuse_req_state { FUSE_REQ_FINISHED }; +struct fuse_conn; + /** * A request to the client */ @@ -257,12 +248,11 @@ struct fuse_req { struct fuse_forget_in forget_in; struct { struct fuse_release_in in; - struct path path; + struct vfsmount *vfsmount; + struct dentry *dentry; } release; struct fuse_init_in init_in; struct fuse_init_out init_out; - struct cuse_init_in cuse_init_in; - struct cuse_init_out cuse_init_out; struct { struct fuse_read_in in; u64 attr_ver; @@ -396,9 +386,6 @@ struct fuse_conn { /** Filesystem supports NFS exporting. Only set in INIT */ unsigned export_support:1; - /** Set if bdi is valid */ - unsigned bdi_initialized:1; - /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction @@ -528,24 +515,25 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, * Initialize READ or READDIR request */ void fuse_read_fill(struct fuse_req *req, struct file *file, - loff_t pos, size_t count, int opcode); + struct inode *inode, loff_t pos, size_t count, int opcode); /** * Send OPEN or OPENDIR request */ -int fuse_open_common(struct inode *inode, struct file *file, bool isdir); +int fuse_open_common(struct inode *inode, struct file *file, int isdir); struct fuse_file *fuse_file_alloc(struct fuse_conn *fc); -struct fuse_file *fuse_file_get(struct fuse_file *ff); void fuse_file_free(struct fuse_file *ff); -void fuse_finish_open(struct inode *inode, struct file *file); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg); -void fuse_sync_release(struct fuse_file *ff, int flags); +/** Fill in ff->reserved_req with a RELEASE request */ +void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode); /** * Send RELEASE or RELEASEDIR request */ -void fuse_release_common(struct file *file, int opcode); +int fuse_release_common(struct inode *inode, struct file *file, int isdir); /** * Send FSYNC or FSYNCDIR request @@ -664,12 +652,10 @@ void fuse_invalidate_entry_cache(struct dentry *entry); */ struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); -void fuse_conn_kill(struct fuse_conn *fc); - /** * Initialize fuse_conn */ -void fuse_conn_init(struct fuse_conn *fc); +int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb); /** * Release reference to fuse_conn @@ -708,13 +694,4 @@ void fuse_release_nowrite(struct inode *inode); u64 fuse_get_attr_version(struct fuse_conn *fc); -int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, - bool isdir); -ssize_t fuse_direct_io(struct file *file, const char __user *buf, - size_t count, loff_t *ppos, int write); -long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, - unsigned int flags); -unsigned fuse_file_poll(struct file *file, poll_table *wait); -int fuse_dev_release(struct inode *inode, struct file *file); - #endif /* _FS_FUSE_I_H */ diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index f0df55a52929..91f7c85f1ffd 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -277,14 +277,11 @@ static void fuse_send_destroy(struct fuse_conn *fc) } } -static void fuse_bdi_destroy(struct fuse_conn *fc) +static void fuse_put_super(struct super_block *sb) { - if (fc->bdi_initialized) - bdi_destroy(&fc->bdi); -} + struct fuse_conn *fc = get_fuse_conn_super(sb); -void fuse_conn_kill(struct fuse_conn *fc) -{ + fuse_send_destroy(fc); spin_lock(&fc->lock); fc->connected = 0; fc->blocked = 0; @@ -298,16 +295,7 @@ void fuse_conn_kill(struct fuse_conn *fc) list_del(&fc->entry); fuse_ctl_remove_conn(fc); mutex_unlock(&fuse_mutex); - fuse_bdi_destroy(fc); -} -EXPORT_SYMBOL_GPL(fuse_conn_kill); - -static void fuse_put_super(struct super_block *sb) -{ - struct fuse_conn *fc = get_fuse_conn_super(sb); - - fuse_send_destroy(fc); - fuse_conn_kill(fc); + bdi_destroy(&fc->bdi); fuse_conn_put(fc); } @@ -478,8 +466,10 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } -void fuse_conn_init(struct fuse_conn *fc) +int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) { + int err; + memset(fc, 0, sizeof(*fc)); spin_lock_init(&fc->lock); mutex_init(&fc->inst_mutex); @@ -494,12 +484,49 @@ void fuse_conn_init(struct fuse_conn *fc) INIT_LIST_HEAD(&fc->bg_queue); INIT_LIST_HEAD(&fc->entry); atomic_set(&fc->num_waiting, 0); + fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; + fc->bdi.unplug_io_fn = default_unplug_io_fn; + /* fuse does it's own writeback accounting */ + fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; fc->khctr = 0; fc->polled_files = RB_ROOT; + fc->dev = sb->s_dev; + err = bdi_init(&fc->bdi); + if (err) + goto error_mutex_destroy; + if (sb->s_bdev) { + err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", + MAJOR(fc->dev), MINOR(fc->dev)); + } else { + err = bdi_register_dev(&fc->bdi, fc->dev); + } + if (err) + goto error_bdi_destroy; + /* + * For a single fuse filesystem use max 1% of dirty + + * writeback threshold. + * + * This gives about 1M of write buffer for memory maps on a + * machine with 1G and 10% dirty_ratio, which should be more + * than enough. + * + * Privileged users can raise it by writing to + * + * /sys/class/bdi//max_ratio + */ + bdi_set_max_ratio(&fc->bdi, 1); fc->reqctr = 0; fc->blocked = 1; fc->attr_version = 1; get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); + + return 0; + + error_bdi_destroy: + bdi_destroy(&fc->bdi); + error_mutex_destroy: + mutex_destroy(&fc->inst_mutex); + return err; } EXPORT_SYMBOL_GPL(fuse_conn_init); @@ -512,14 +539,12 @@ void fuse_conn_put(struct fuse_conn *fc) fc->release(fc); } } -EXPORT_SYMBOL_GPL(fuse_conn_put); struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) { atomic_inc(&fc->count); return fc; } -EXPORT_SYMBOL_GPL(fuse_conn_get); static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) { @@ -772,48 +797,6 @@ static void fuse_free_conn(struct fuse_conn *fc) kfree(fc); } -static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) -{ - int err; - - fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; - fc->bdi.unplug_io_fn = default_unplug_io_fn; - /* fuse does it's own writeback accounting */ - fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; - - err = bdi_init(&fc->bdi); - if (err) - return err; - - fc->bdi_initialized = 1; - - if (sb->s_bdev) { - err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", - MAJOR(fc->dev), MINOR(fc->dev)); - } else { - err = bdi_register_dev(&fc->bdi, fc->dev); - } - - if (err) - return err; - - /* - * For a single fuse filesystem use max 1% of dirty + - * writeback threshold. - * - * This gives about 1M of write buffer for memory maps on a - * machine with 1G and 10% dirty_ratio, which should be more - * than enough. - * - * Privileged users can raise it by writing to - * - * /sys/class/bdi//max_ratio - */ - bdi_set_max_ratio(&fc->bdi, 1); - - return 0; -} - static int fuse_fill_super(struct super_block *sb, void *data, int silent) { struct fuse_conn *fc; @@ -860,12 +843,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (!fc) goto err_fput; - fuse_conn_init(fc); - - fc->dev = sb->s_dev; - err = fuse_bdi_init(fc, sb); - if (err) - goto err_put_conn; + err = fuse_conn_init(fc, sb); + if (err) { + kfree(fc); + goto err_fput; + } fc->release = fuse_free_conn; fc->flags = d.flags; @@ -929,7 +911,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) err_put_root: dput(root_dentry); err_put_conn: - fuse_bdi_destroy(fc); + bdi_destroy(&fc->bdi); fuse_conn_put(fc); err_fput: fput(file); diff --git a/trunk/fs/partitions/check.c b/trunk/fs/partitions/check.c index 1a9c7878f864..0af36085eb28 100644 --- a/trunk/fs/partitions/check.c +++ b/trunk/fs/partitions/check.c @@ -556,49 +556,27 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) /* add partitions */ for (p = 1; p < state->limit; p++) { - sector_t size, from; -try_scan: - size = state->parts[p].size; + sector_t size = state->parts[p].size; + sector_t from = state->parts[p].from; if (!size) continue; - - from = state->parts[p].from; if (from >= get_capacity(disk)) { printk(KERN_WARNING "%s: p%d ignored, start %llu is behind the end of the disk\n", disk->disk_name, p, (unsigned long long) from); continue; } - if (from + size > get_capacity(disk)) { - struct block_device_operations *bdops = disk->fops; - unsigned long long capacity; - + /* + * we can not ignore partitions of broken tables + * created by for example camera firmware, but we + * limit them to the end of the disk to avoid + * creating invalid block devices + */ printk(KERN_WARNING - "%s: p%d size %llu exceeds device capacity, ", + "%s: p%d size %llu limited to end of disk\n", disk->disk_name, p, (unsigned long long) size); - - if (bdops->set_capacity && - (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) { - printk(KERN_CONT "enabling native capacity\n"); - capacity = bdops->set_capacity(disk, ~0ULL); - disk->flags |= GENHD_FL_NATIVE_CAPACITY; - if (capacity > get_capacity(disk)) { - set_capacity(disk, capacity); - check_disk_size_change(disk, bdev); - bdev->bd_invalidated = 0; - } - goto try_scan; - } else { - /* - * we can not ignore partitions of broken tables - * created by for example camera firmware, but - * we limit them to the end of the disk to avoid - * creating invalid block devices - */ - printk(KERN_CONT "limited to end of disk\n"); - size = get_capacity(disk) - from; - } + size = get_capacity(disk) - from; } part = add_partition(disk, p, from, size, state->parts[p].flags); diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 0b1a6cae9de1..ebdfde8fe556 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -1226,8 +1226,6 @@ struct block_device_operations { int (*direct_access) (struct block_device *, sector_t, void **, unsigned long *); int (*media_changed) (struct gendisk *); - unsigned long long (*set_capacity) (struct gendisk *, - unsigned long long); int (*revalidate_disk) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); struct module *owner; diff --git a/trunk/include/linux/compiler.h b/trunk/include/linux/compiler.h index 04fb5135b4e1..37bcb50a4d7c 100644 --- a/trunk/include/linux/compiler.h +++ b/trunk/include/linux/compiler.h @@ -261,11 +261,6 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define __section(S) __attribute__ ((__section__(#S))) #endif -/* Are two types/vars the same type (ignoring qualifiers)? */ -#ifndef __same_type -# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) -#endif - /* * Prevent the compiler from merging or refetching accesses. The compiler * is also forbidden from reordering successive instances of ACCESS_ONCE(), diff --git a/trunk/include/linux/fuse.h b/trunk/include/linux/fuse.h index d41ed593f79f..162e5defe683 100644 --- a/trunk/include/linux/fuse.h +++ b/trunk/include/linux/fuse.h @@ -120,13 +120,6 @@ struct fuse_file_lock { #define FUSE_EXPORT_SUPPORT (1 << 4) #define FUSE_BIG_WRITES (1 << 5) -/** - * CUSE INIT request/reply flags - * - * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl - */ -#define CUSE_UNRESTRICTED_IOCTL (1 << 0) - /** * Release flags */ @@ -217,9 +210,6 @@ enum fuse_opcode { FUSE_DESTROY = 38, FUSE_IOCTL = 39, FUSE_POLL = 40, - - /* CUSE specific operations */ - CUSE_INIT = 4096, }; enum fuse_notify_code { @@ -411,27 +401,6 @@ struct fuse_init_out { __u32 max_write; }; -#define CUSE_INIT_INFO_MAX 4096 - -struct cuse_init_in { - __u32 major; - __u32 minor; - __u32 unused; - __u32 flags; -}; - -struct cuse_init_out { - __u32 major; - __u32 minor; - __u32 unused; - __u32 flags; - __u32 max_read; - __u32 max_write; - __u32 dev_major; /* chardev major */ - __u32 dev_minor; /* chardev minor */ - __u32 spare[10]; -}; - struct fuse_interrupt_in { __u64 unique; }; diff --git a/trunk/include/linux/genhd.h b/trunk/include/linux/genhd.h index 7cbd38d363a2..149fda264c86 100644 --- a/trunk/include/linux/genhd.h +++ b/trunk/include/linux/genhd.h @@ -114,7 +114,6 @@ struct hd_struct { #define GENHD_FL_UP 16 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ -#define GENHD_FL_NATIVE_CAPACITY 128 #define BLK_SCSI_MAX_CMDS (256) #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index a6c6a2fad7c8..867cb68d8461 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -178,7 +178,7 @@ typedef u8 hwif_chipset_t; /* * Structure to hold all information about the location of this port */ -struct ide_hw { +typedef struct hw_regs_s { union { struct ide_io_ports io_ports; unsigned long io_ports_array[IDE_NR_PORTS]; @@ -186,11 +186,12 @@ struct ide_hw { int irq; /* our irq number */ ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ + hwif_chipset_t chipset; struct device *dev, *parent; unsigned long config; -}; +} hw_regs_t; -static inline void ide_std_init_ports(struct ide_hw *hw, +static inline void ide_std_init_ports(hw_regs_t *hw, unsigned long io_addr, unsigned long ctl_addr) { @@ -217,12 +218,21 @@ static inline void ide_std_init_ports(struct ide_hw *hw, /* * Special Driver Flags + * + * set_geometry : respecify drive geometry + * recalibrate : seek to cyl 0 + * set_multmode : set multmode count + * reserved : unused */ -enum { - IDE_SFLAG_SET_GEOMETRY = (1 << 0), - IDE_SFLAG_RECALIBRATE = (1 << 1), - IDE_SFLAG_SET_MULTMODE = (1 << 2), -}; +typedef union { + unsigned all : 8; + struct { + unsigned set_geometry : 1; + unsigned recalibrate : 1; + unsigned set_multmode : 1; + unsigned reserved : 5; + } b; +} special_t; /* * Status returned from various ide_ functions @@ -381,7 +391,6 @@ struct ide_drive_s; struct ide_disk_ops { int (*check)(struct ide_drive_s *, const char *); int (*get_capacity)(struct ide_drive_s *); - u64 (*set_capacity)(struct ide_drive_s *, u64); void (*setup)(struct ide_drive_s *); void (*flush)(struct ide_drive_s *); int (*init_media)(struct ide_drive_s *, struct gendisk *); @@ -459,8 +468,6 @@ enum { IDE_DFLAG_NICE1 = (1 << 5), /* device is physically present */ IDE_DFLAG_PRESENT = (1 << 6), - /* disable Host Protected Area */ - IDE_DFLAG_NOHPA = (1 << 7), /* id read from device (synthetic if not set) */ IDE_DFLAG_ID_READ = (1 << 8), IDE_DFLAG_NOPROBE = (1 << 9), @@ -499,7 +506,6 @@ enum { /* write protect */ IDE_DFLAG_WP = (1 << 29), IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), - IDE_DFLAG_NIEN_QUIRK = (1 << 31), }; struct ide_drive_s { @@ -524,13 +530,14 @@ struct ide_drive_s { unsigned long sleep; /* sleep until this time */ unsigned long timeout; /* max time to wait for irq */ - u8 special_flags; /* special action flags */ + special_t special; /* special action flags */ u8 select; /* basic drive/head select reg value */ u8 retry_pio; /* retrying dma capable host in pio */ u8 waiting_for_dma; /* dma currently in progress */ u8 dma; /* atapi dma flag */ + u8 quirk_list; /* considered quirky, set for a specific host */ u8 init_speed; /* transfer rate set at boot */ u8 current_speed; /* current transfer rate set */ u8 desired_speed; /* desired transfer rate set */ @@ -555,7 +562,8 @@ struct ide_drive_s { unsigned int drive_data; /* used by set_pio_mode/dev_select() */ unsigned int failures; /* current failure count */ unsigned int max_failures; /* maximum allowed failure count */ - u64 probed_capacity;/* initial/native media capacity */ + u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */ + u64 capacity64; /* total number of sectors */ int lun; /* logical unit */ @@ -1214,7 +1222,7 @@ static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev) } void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, - struct ide_hw *, struct ide_hw **); + hw_regs_t *, hw_regs_t **); void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); #ifdef CONFIG_BLK_DEV_IDEDMA_PCI @@ -1453,18 +1461,16 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {} void ide_register_region(struct gendisk *); void ide_unregister_region(struct gendisk *); -void ide_check_nien_quirk_list(ide_drive_t *); void ide_undecoded_slave(ide_drive_t *); void ide_port_apply_params(ide_hwif_t *); int ide_sysfs_register_port(ide_hwif_t *); -struct ide_host *ide_host_alloc(const struct ide_port_info *, struct ide_hw **, - unsigned int); +struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); void ide_host_free(struct ide_host *); int ide_host_register(struct ide_host *, const struct ide_port_info *, - struct ide_hw **); -int ide_host_add(const struct ide_port_info *, struct ide_hw **, unsigned int, + hw_regs_t **); +int ide_host_add(const struct ide_port_info *, hw_regs_t **, struct ide_host **); void ide_host_remove(struct ide_host *); int ide_legacy_device_add(const struct ide_port_info *, unsigned long); diff --git a/trunk/include/linux/module.h b/trunk/include/linux/module.h index a7bc6e7b43a7..a8f2c0aa4c32 100644 --- a/trunk/include/linux/module.h +++ b/trunk/include/linux/module.h @@ -77,7 +77,6 @@ search_extable(const struct exception_table_entry *first, void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish); void sort_main_extable(void); -void trim_init_extable(struct module *m); #ifdef MODULE #define MODULE_GENERIC_TABLE(gtype,name) \ diff --git a/trunk/include/linux/moduleparam.h b/trunk/include/linux/moduleparam.h index 6547c3cdbc4c..a4f0b931846c 100644 --- a/trunk/include/linux/moduleparam.h +++ b/trunk/include/linux/moduleparam.h @@ -36,14 +36,9 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp); /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); -/* Flag bits for kernel_param.flags */ -#define KPARAM_KMALLOCED 1 -#define KPARAM_ISBOOL 2 - struct kernel_param { const char *name; - u16 perm; - u16 flags; + unsigned int perm; param_set_fn set; param_get_fn get; union { @@ -84,7 +79,7 @@ struct kparam_array parameters. perm sets the visibility in sysfs: 000 means it's not there, read bits mean it's readable, write bits mean it's writable. */ -#define __module_param_call(prefix, name, set, get, arg, isbool, perm) \ +#define __module_param_call(prefix, name, set, get, arg, perm) \ /* Default value instead of permissions? */ \ static int __param_perm_check_##name __attribute__((unused)) = \ BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ @@ -93,13 +88,10 @@ struct kparam_array static struct kernel_param __moduleparam_const __param_##name \ __used \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ - = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \ - set, get, { arg } } + = { __param_str_##name, perm, set, get, { arg } } #define module_param_call(name, set, get, arg, perm) \ - __module_param_call(MODULE_PARAM_PREFIX, \ - name, set, get, arg, \ - __same_type(*(arg), bool), perm) + __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm) /* Helper functions: type is byte, short, ushort, int, uint, long, ulong, charp, bool or invbool, or XXX if you define param_get_XXX, @@ -128,16 +120,15 @@ struct kparam_array #define core_param(name, var, type, perm) \ param_check_##type(name, &(var)); \ __module_param_call("", name, param_set_##type, param_get_##type, \ - &var, __same_type(var, bool), perm) + &var, perm) #endif /* !MODULE */ /* Actually copy string: maxlen param is usually sizeof(string). */ #define module_param_string(name, string, len, perm) \ static const struct kparam_string __param_string_##name \ = { len, string }; \ - __module_param_call(MODULE_PARAM_PREFIX, name, \ - param_set_copystring, param_get_string, \ - .str = &__param_string_##name, 0, perm); \ + module_param_call(name, param_set_copystring, param_get_string, \ + .str = &__param_string_##name, perm); \ __MODULE_PARM_TYPE(name, "string") /* Called on module insert or kernel boot */ @@ -195,30 +186,21 @@ extern int param_set_charp(const char *val, struct kernel_param *kp); extern int param_get_charp(char *buffer, struct kernel_param *kp); #define param_check_charp(name, p) __param_check(name, p, char *) -/* For historical reasons "bool" parameters can be (unsigned) "int". */ extern int param_set_bool(const char *val, struct kernel_param *kp); extern int param_get_bool(char *buffer, struct kernel_param *kp); -#define param_check_bool(name, p) \ - static inline void __check_##name(void) \ - { \ - BUILD_BUG_ON(!__same_type(*(p), bool) && \ - !__same_type(*(p), unsigned int) && \ - !__same_type(*(p), int)); \ - } +#define param_check_bool(name, p) __param_check(name, p, int) extern int param_set_invbool(const char *val, struct kernel_param *kp); extern int param_get_invbool(char *buffer, struct kernel_param *kp); -#define param_check_invbool(name, p) __param_check(name, p, bool) +#define param_check_invbool(name, p) __param_check(name, p, int) /* Comma-separated array: *nump is set to number they actually specified. */ #define module_param_array_named(name, array, type, nump, perm) \ static const struct kparam_array __param_arr_##name \ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ sizeof(array[0]), array }; \ - __module_param_call(MODULE_PARAM_PREFIX, name, \ - param_array_set, param_array_get, \ - .arr = &__param_arr_##name, \ - __same_type(array[0], bool), perm); \ + module_param_call(name, param_array_set, param_array_get, \ + .arr = &__param_arr_##name, perm); \ __MODULE_PARM_TYPE(name, "array of " #type) #define module_param_array(name, type, nump, perm) \ diff --git a/trunk/include/linux/virtio.h b/trunk/include/linux/virtio.h index 06005fa9e982..9410394bbf96 100644 --- a/trunk/include/linux/virtio.h +++ b/trunk/include/linux/virtio.h @@ -99,8 +99,7 @@ void unregister_virtio_device(struct virtio_device *dev); * @id_table: the ids serviced by this driver. * @feature_table: an array of feature numbers supported by this device. * @feature_table_size: number of entries in the feature table array. - * @probe: the function to call when a device is found. Returns a token for - * remove, or PTR_ERR(). + * @probe: the function to call when a device is found. Returns 0 or -errno. * @remove: the function when a device is removed. * @config_changed: optional function to call when the device configuration * changes; may be called in interrupt context. diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index e4ab36ce7672..35f7de00bf0d 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -2455,7 +2455,6 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, mutex_lock(&module_mutex); /* Drop initial reference. */ module_put(mod); - trim_init_extable(mod); module_free(mod, mod->module_init); mod->module_init = NULL; mod->init_size = 0; diff --git a/trunk/kernel/params.c b/trunk/kernel/params.c index 7f6912ced2ba..de273ec85bd2 100644 --- a/trunk/kernel/params.c +++ b/trunk/kernel/params.c @@ -24,6 +24,9 @@ #include #include +/* We abuse the high bits of "perm" to record whether we kmalloc'ed. */ +#define KPARAM_KMALLOCED 0x80000000 + #if 0 #define DEBUGP printk #else @@ -217,13 +220,13 @@ int param_set_charp(const char *val, struct kernel_param *kp) return -ENOSPC; } - if (kp->flags & KPARAM_KMALLOCED) + if (kp->perm & KPARAM_KMALLOCED) kfree(*(char **)kp->arg); /* This is a hack. We can't need to strdup in early boot, and we * don't need to; this mangled commandline is preserved. */ if (slab_is_available()) { - kp->flags |= KPARAM_KMALLOCED; + kp->perm |= KPARAM_KMALLOCED; *(char **)kp->arg = kstrdup(val, GFP_KERNEL); if (!kp->arg) return -ENOMEM; @@ -238,63 +241,44 @@ int param_get_charp(char *buffer, struct kernel_param *kp) return sprintf(buffer, "%s", *((char **)kp->arg)); } -/* Actually could be a bool or an int, for historical reasons. */ int param_set_bool(const char *val, struct kernel_param *kp) { - bool v; - /* No equals means "set"... */ if (!val) val = "1"; /* One of =[yYnN01] */ switch (val[0]) { case 'y': case 'Y': case '1': - v = true; - break; + *(int *)kp->arg = 1; + return 0; case 'n': case 'N': case '0': - v = false; - break; - default: - return -EINVAL; + *(int *)kp->arg = 0; + return 0; } - - if (kp->flags & KPARAM_ISBOOL) - *(bool *)kp->arg = v; - else - *(int *)kp->arg = v; - return 0; + return -EINVAL; } int param_get_bool(char *buffer, struct kernel_param *kp) { - bool val; - if (kp->flags & KPARAM_ISBOOL) - val = *(bool *)kp->arg; - else - val = *(int *)kp->arg; - /* Y and N chosen as being relatively non-coder friendly */ - return sprintf(buffer, "%c", val ? 'Y' : 'N'); + return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N'); } -/* This one must be bool. */ int param_set_invbool(const char *val, struct kernel_param *kp) { - int ret; - bool boolval; + int boolval, ret; struct kernel_param dummy; dummy.arg = &boolval; - dummy.flags = KPARAM_ISBOOL; ret = param_set_bool(val, &dummy); if (ret == 0) - *(bool *)kp->arg = !boolval; + *(int *)kp->arg = !boolval; return ret; } int param_get_invbool(char *buffer, struct kernel_param *kp) { - return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); + return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'N' : 'Y'); } /* We break the rule and mangle the string. */ @@ -607,7 +591,7 @@ void destroy_params(const struct kernel_param *params, unsigned num) unsigned int i; for (i = 0; i < num; i++) - if (params[i].flags & KPARAM_KMALLOCED) + if (params[i].perm & KPARAM_KMALLOCED) kfree(*(char **)params[i].arg); } diff --git a/trunk/lib/extable.c b/trunk/lib/extable.c index 4cac81ec225e..179c08745595 100644 --- a/trunk/lib/extable.c +++ b/trunk/lib/extable.c @@ -39,26 +39,7 @@ void sort_extable(struct exception_table_entry *start, sort(start, finish - start, sizeof(struct exception_table_entry), cmp_ex, NULL); } - -#ifdef CONFIG_MODULES -/* - * If the exception table is sorted, any referring to the module init - * will be at the beginning or the end. - */ -void trim_init_extable(struct module *m) -{ - /*trim the beginning*/ - while (m->num_exentries && within_module_init(m->extable[0].insn, m)) { - m->extable++; - m->num_exentries--; - } - /*trim the end*/ - while (m->num_exentries && - within_module_init(m->extable[m->num_exentries-1].insn, m)) - m->num_exentries--; -} -#endif /* CONFIG_MODULES */ -#endif /* !ARCH_HAS_SORT_EXTABLE */ +#endif #ifndef ARCH_HAS_SEARCH_EXTABLE /*