diff options
95 files changed, 1683 insertions, 1068 deletions
diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 0c78f4b1d9d9..e77bebfa7b0d 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt | |||
@@ -216,6 +216,8 @@ Other kernel parameters for ide_core are: | |||
216 | 216 | ||
217 | * "noflush=[interface_number.device_number]" to disable flush requests | 217 | * "noflush=[interface_number.device_number]" to disable flush requests |
218 | 218 | ||
219 | * "nohpa=[interface_number.device_number]" to disable Host Protected Area | ||
220 | |||
219 | * "noprobe=[interface_number.device_number]" to skip probing | 221 | * "noprobe=[interface_number.device_number]" to skip probing |
220 | 222 | ||
221 | * "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit | 223 | * "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 7bcdebffdab3..0bf8a882ee9e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -887,11 +887,8 @@ and is between 256 and 4096 characters. It is defined in the file | |||
887 | 887 | ||
888 | ide-core.nodma= [HW] (E)IDE subsystem | 888 | ide-core.nodma= [HW] (E)IDE subsystem |
889 | Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc | 889 | Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc |
890 | .vlb_clock .pci_clock .noflush .noprobe .nowerr .cdrom | 890 | .vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr |
891 | .chs .ignore_cable are additional options | 891 | .cdrom .chs .ignore_cable are additional options |
892 | See Documentation/ide/ide.txt. | ||
893 | |||
894 | idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed | ||
895 | See Documentation/ide/ide.txt. | 892 | See Documentation/ide/ide.txt. |
896 | 893 | ||
897 | ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem | 894 | ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem |
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 62dc379d301a..813c9b63c0e1 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c | |||
@@ -48,6 +48,27 @@ void sort_extable(struct exception_table_entry *start, | |||
48 | cmp_ex, swap_ex); | 48 | cmp_ex, swap_ex); |
49 | } | 49 | } |
50 | 50 | ||
51 | #ifdef CONFIG_MODULES | ||
52 | /* | ||
53 | * Any entry referring to the module init will be at the beginning or | ||
54 | * the end. | ||
55 | */ | ||
56 | void trim_init_extable(struct module *m) | ||
57 | { | ||
58 | /*trim the beginning*/ | ||
59 | while (m->num_exentries && | ||
60 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
61 | m->extable++; | ||
62 | m->num_exentries--; | ||
63 | } | ||
64 | /*trim the end*/ | ||
65 | while (m->num_exentries && | ||
66 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
67 | m)) | ||
68 | m->num_exentries--; | ||
69 | } | ||
70 | #endif /* CONFIG_MODULES */ | ||
71 | |||
51 | const struct exception_table_entry * | 72 | const struct exception_table_entry * |
52 | search_extable(const struct exception_table_entry *first, | 73 | search_extable(const struct exception_table_entry *first, |
53 | const struct exception_table_entry *last, | 74 | const struct exception_table_entry *last, |
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 1167fe9cf6c4..98f94d041d9c 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c | |||
@@ -32,8 +32,6 @@ void module_free(struct module *mod, void *module_region) | |||
32 | mod->arch.syminfo = NULL; | 32 | mod->arch.syminfo = NULL; |
33 | 33 | ||
34 | vfree(module_region); | 34 | vfree(module_region); |
35 | /* FIXME: if module_region == mod->init_region, trim exception | ||
36 | * table entries. */ | ||
37 | } | 35 | } |
38 | 36 | ||
39 | static inline int check_rela(Elf32_Rela *rela, struct module *module, | 37 | static inline int check_rela(Elf32_Rela *rela, struct module *module, |
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index a187833febc8..abc13e368b90 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
@@ -48,8 +48,6 @@ void *module_alloc(unsigned long size) | |||
48 | void module_free(struct module *mod, void *module_region) | 48 | void module_free(struct module *mod, void *module_region) |
49 | { | 49 | { |
50 | FREE_MODULE(module_region); | 50 | FREE_MODULE(module_region); |
51 | /* FIXME: If module_region == mod->init_region, trim exception | ||
52 | table entries. */ | ||
53 | } | 51 | } |
54 | 52 | ||
55 | /* We don't need anything special. */ | 53 | /* We don't need anything special. */ |
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c index 850d168f69fc..711763c8a6f3 100644 --- a/arch/frv/kernel/module.c +++ b/arch/frv/kernel/module.c | |||
@@ -35,8 +35,6 @@ void *module_alloc(unsigned long size) | |||
35 | void module_free(struct module *mod, void *module_region) | 35 | void module_free(struct module *mod, void *module_region) |
36 | { | 36 | { |
37 | vfree(module_region); | 37 | vfree(module_region); |
38 | /* FIXME: If module_region == mod->init_region, trim exception | ||
39 | table entries. */ | ||
40 | } | 38 | } |
41 | 39 | ||
42 | /* We don't need anything special. */ | 40 | /* We don't need anything special. */ |
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c index cfc9127d2ced..0865e291c20d 100644 --- a/arch/h8300/kernel/module.c +++ b/arch/h8300/kernel/module.c | |||
@@ -23,8 +23,6 @@ void *module_alloc(unsigned long size) | |||
23 | void module_free(struct module *mod, void *module_region) | 23 | void module_free(struct module *mod, void *module_region) |
24 | { | 24 | { |
25 | vfree(module_region); | 25 | vfree(module_region); |
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | 26 | } |
29 | 27 | ||
30 | /* We don't need anything special. */ | 28 | /* We don't need anything special. */ |
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 71c50dd8f870..e95d5ad9285d 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c | |||
@@ -53,6 +53,32 @@ void sort_extable (struct exception_table_entry *start, | |||
53 | cmp_ex, swap_ex); | 53 | cmp_ex, swap_ex); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
57 | { | ||
58 | return (unsigned long)&x->insn + x->insn; | ||
59 | } | ||
60 | |||
61 | #ifdef CONFIG_MODULES | ||
62 | /* | ||
63 | * Any entry referring to the module init will be at the beginning or | ||
64 | * the end. | ||
65 | */ | ||
66 | void trim_init_extable(struct module *m) | ||
67 | { | ||
68 | /*trim the beginning*/ | ||
69 | while (m->num_exentries && | ||
70 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
71 | m->extable++; | ||
72 | m->num_exentries--; | ||
73 | } | ||
74 | /*trim the end*/ | ||
75 | while (m->num_exentries && | ||
76 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
77 | m)) | ||
78 | m->num_exentries--; | ||
79 | } | ||
80 | #endif /* CONFIG_MODULES */ | ||
81 | |||
56 | const struct exception_table_entry * | 82 | const struct exception_table_entry * |
57 | search_extable (const struct exception_table_entry *first, | 83 | search_extable (const struct exception_table_entry *first, |
58 | const struct exception_table_entry *last, | 84 | const struct exception_table_entry *last, |
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c index 8d4205794380..cb5f37d78d49 100644 --- a/arch/m32r/kernel/module.c +++ b/arch/m32r/kernel/module.c | |||
@@ -44,8 +44,6 @@ void *module_alloc(unsigned long size) | |||
44 | void module_free(struct module *mod, void *module_region) | 44 | void module_free(struct module *mod, void *module_region) |
45 | { | 45 | { |
46 | vfree(module_region); | 46 | vfree(module_region); |
47 | /* FIXME: If module_region == mod->init_region, trim exception | ||
48 | table entries. */ | ||
49 | } | 47 | } |
50 | 48 | ||
51 | /* We don't need anything special. */ | 49 | /* We don't need anything special. */ |
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c index 774862bc6977..cd6bcb1c957e 100644 --- a/arch/m68k/kernel/module.c +++ b/arch/m68k/kernel/module.c | |||
@@ -31,8 +31,6 @@ void *module_alloc(unsigned long size) | |||
31 | void module_free(struct module *mod, void *module_region) | 31 | void module_free(struct module *mod, void *module_region) |
32 | { | 32 | { |
33 | vfree(module_region); | 33 | vfree(module_region); |
34 | /* FIXME: If module_region == mod->init_region, trim exception | ||
35 | table entries. */ | ||
36 | } | 34 | } |
37 | 35 | ||
38 | /* We don't need anything special. */ | 36 | /* We don't need anything special. */ |
diff --git a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c index 3b1a2ff61ddc..d11ffae7956a 100644 --- a/arch/m68knommu/kernel/module.c +++ b/arch/m68knommu/kernel/module.c | |||
@@ -23,8 +23,6 @@ void *module_alloc(unsigned long size) | |||
23 | void module_free(struct module *mod, void *module_region) | 23 | void module_free(struct module *mod, void *module_region) |
24 | { | 24 | { |
25 | vfree(module_region); | 25 | vfree(module_region); |
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | 26 | } |
29 | 27 | ||
30 | /* We don't need anything special. */ | 28 | /* We don't need anything special. */ |
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index 1f60e27523d9..3e9100dcc12d 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c | |||
@@ -68,8 +68,6 @@ void *module_alloc(unsigned long size) | |||
68 | void module_free(struct module *mod, void *module_region) | 68 | void module_free(struct module *mod, void *module_region) |
69 | { | 69 | { |
70 | vfree(module_region); | 70 | vfree(module_region); |
71 | /* FIXME: If module_region == mod->init_region, trim exception | ||
72 | table entries. */ | ||
73 | } | 71 | } |
74 | 72 | ||
75 | int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, | 73 | int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, |
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c index 6b287f2e8e84..4fa0e3648d8e 100644 --- a/arch/mn10300/kernel/module.c +++ b/arch/mn10300/kernel/module.c | |||
@@ -48,8 +48,6 @@ void *module_alloc(unsigned long size) | |||
48 | void module_free(struct module *mod, void *module_region) | 48 | void module_free(struct module *mod, void *module_region) |
49 | { | 49 | { |
50 | vfree(module_region); | 50 | vfree(module_region); |
51 | /* FIXME: If module_region == mod->init_region, trim exception | ||
52 | * table entries. */ | ||
53 | } | 51 | } |
54 | 52 | ||
55 | /* | 53 | /* |
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index ecd1c5024447..ef5caf2e6ed0 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -267,8 +267,6 @@ void module_free(struct module *mod, void *module_region) | |||
267 | mod->arch.section = NULL; | 267 | mod->arch.section = NULL; |
268 | 268 | ||
269 | vfree(module_region); | 269 | vfree(module_region); |
270 | /* FIXME: If module_region == mod->init_region, trim exception | ||
271 | table entries. */ | ||
272 | } | 270 | } |
273 | 271 | ||
274 | /* Additional bytes needed in front of individual sections */ | 272 | /* Additional bytes needed in front of individual sections */ |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 43e7e3a7f130..477c663e0140 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -43,8 +43,6 @@ void *module_alloc(unsigned long size) | |||
43 | void module_free(struct module *mod, void *module_region) | 43 | void module_free(struct module *mod, void *module_region) |
44 | { | 44 | { |
45 | vfree(module_region); | 45 | vfree(module_region); |
46 | /* FIXME: If module_region == mod->init_region, trim exception | ||
47 | table entries. */ | ||
48 | } | 46 | } |
49 | 47 | ||
50 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | 48 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, |
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index eed4a00cb676..ab2e3ed28abc 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c | |||
@@ -56,8 +56,6 @@ void *module_alloc(unsigned long size) | |||
56 | void module_free(struct module *mod, void *module_region) | 56 | void module_free(struct module *mod, void *module_region) |
57 | { | 57 | { |
58 | vfree(module_region); | 58 | vfree(module_region); |
59 | /* FIXME: If module_region == mod->init_region, trim exception | ||
60 | table entries. */ | ||
61 | } | 59 | } |
62 | 60 | ||
63 | static void | 61 | static void |
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index c19b0f7d2cc1..c2efdcde266f 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c | |||
@@ -46,8 +46,6 @@ void *module_alloc(unsigned long size) | |||
46 | void module_free(struct module *mod, void *module_region) | 46 | void module_free(struct module *mod, void *module_region) |
47 | { | 47 | { |
48 | vfree(module_region); | 48 | vfree(module_region); |
49 | /* FIXME: If module_region == mod->init_region, trim exception | ||
50 | table entries. */ | ||
51 | } | 49 | } |
52 | 50 | ||
53 | /* We don't need anything special. */ | 51 | /* We don't need anything special. */ |
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 47d5619d43fa..8303ac481034 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h | |||
@@ -17,6 +17,9 @@ | |||
17 | 17 | ||
18 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
19 | 19 | ||
20 | #define ARCH_HAS_SORT_EXTABLE | ||
21 | #define ARCH_HAS_SEARCH_EXTABLE | ||
22 | |||
20 | /* Sparc is not segmented, however we need to be able to fool access_ok() | 23 | /* Sparc is not segmented, however we need to be able to fool access_ok() |
21 | * when doing system calls from kernel mode legitimately. | 24 | * when doing system calls from kernel mode legitimately. |
22 | * | 25 | * |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 90273765e81f..0ee642f63234 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
@@ -75,8 +75,6 @@ void *module_alloc(unsigned long size) | |||
75 | void module_free(struct module *mod, void *module_region) | 75 | void module_free(struct module *mod, void *module_region) |
76 | { | 76 | { |
77 | vfree(module_region); | 77 | vfree(module_region); |
78 | /* FIXME: If module_region == mod->init_region, trim exception | ||
79 | table entries. */ | ||
80 | } | 78 | } |
81 | 79 | ||
82 | /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ | 80 | /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ |
diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c index 16cc28935e39..a61c349448e1 100644 --- a/arch/sparc/mm/extable.c +++ b/arch/sparc/mm/extable.c | |||
@@ -28,6 +28,10 @@ search_extable(const struct exception_table_entry *start, | |||
28 | * word 3: last insn address + 4 bytes | 28 | * word 3: last insn address + 4 bytes |
29 | * word 4: fixup code address | 29 | * word 4: fixup code address |
30 | * | 30 | * |
31 | * Deleted entries are encoded as: | ||
32 | * word 1: unused | ||
33 | * word 2: -1 | ||
34 | * | ||
31 | * See asm/uaccess.h for more details. | 35 | * See asm/uaccess.h for more details. |
32 | */ | 36 | */ |
33 | 37 | ||
@@ -39,6 +43,10 @@ search_extable(const struct exception_table_entry *start, | |||
39 | continue; | 43 | continue; |
40 | } | 44 | } |
41 | 45 | ||
46 | /* A deleted entry; see trim_init_extable */ | ||
47 | if (walk->fixup == -1) | ||
48 | continue; | ||
49 | |||
42 | if (walk->insn == value) | 50 | if (walk->insn == value) |
43 | return walk; | 51 | return walk; |
44 | } | 52 | } |
@@ -57,6 +65,27 @@ search_extable(const struct exception_table_entry *start, | |||
57 | return NULL; | 65 | return NULL; |
58 | } | 66 | } |
59 | 67 | ||
68 | #ifdef CONFIG_MODULES | ||
69 | /* We could memmove them around; easier to mark the trimmed ones. */ | ||
70 | void trim_init_extable(struct module *m) | ||
71 | { | ||
72 | unsigned int i; | ||
73 | bool range; | ||
74 | |||
75 | for (i = 0; i < m->num_exentries; i += range ? 2 : 1) { | ||
76 | range = m->extable[i].fixup == 0; | ||
77 | |||
78 | if (within_module_init(m->extable[i].insn, m)) { | ||
79 | m->extable[i].fixup = -1; | ||
80 | if (range) | ||
81 | m->extable[i+1].fixup = -1; | ||
82 | } | ||
83 | if (range) | ||
84 | i++; | ||
85 | } | ||
86 | } | ||
87 | #endif /* CONFIG_MODULES */ | ||
88 | |||
60 | /* Special extable search, which handles ranges. Returns fixup */ | 89 | /* Special extable search, which handles ranges. Returns fixup */ |
61 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) | 90 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) |
62 | { | 91 | { |
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 58da2480a7f4..9ce3f165111a 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h | |||
@@ -53,16 +53,21 @@ extern unsigned long end_iomem; | |||
53 | #else | 53 | #else |
54 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) | 54 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) |
55 | #endif | 55 | #endif |
56 | #define MODULES_VADDR VMALLOC_START | ||
57 | #define MODULES_END VMALLOC_END | ||
58 | #define MODULES_LEN (MODULES_VADDR - MODULES_END) | ||
56 | 59 | ||
57 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) | 60 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) |
58 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | 61 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) |
59 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 62 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
60 | 63 | #define __PAGE_KERNEL_EXEC \ | |
64 | (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) | ||
61 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) | 65 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) |
62 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) | 66 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) |
63 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 67 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) |
64 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 68 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) |
65 | #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) | 69 | #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) |
70 | #define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) | ||
66 | 71 | ||
67 | /* | 72 | /* |
68 | * The i386 can't do page protection for execute, and considers that the same | 73 | * The i386 can't do page protection for execute, and considers that the same |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 598b5c1903af..1b549bca4645 100644 --- a/arch/um/sys-i386/Makefile +++ b/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 \ | |||
8 | 8 | ||
9 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o | 9 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o |
10 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o | 10 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o |
11 | subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o | 11 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
12 | 12 | ||
13 | USER_OBJS := bugs.o ptrace_user.o fault.o | 13 | USER_OBJS := bugs.o ptrace_user.o fault.o |
14 | 14 | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c8b4cce9cfe1..2201e9c20e4a 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -8,10 +8,8 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | |||
8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ | 8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ |
9 | sysrq.o ksyms.o tls.o | 9 | sysrq.o ksyms.o tls.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODULES) += um_module.o | ||
12 | |||
13 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o | 11 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o |
14 | subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o | 12 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
15 | 13 | ||
16 | ldt-y = ../sys-i386/ldt.o | 14 | ldt-y = ../sys-i386/ldt.o |
17 | 15 | ||
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c deleted file mode 100644 index 3dead392a415..000000000000 --- a/arch/um/sys-x86_64/um_module.c +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | #include <linux/vmalloc.h> | ||
2 | #include <linux/moduleloader.h> | ||
3 | |||
4 | /* Copied from i386 arch/i386/kernel/module.c */ | ||
5 | void *module_alloc(unsigned long size) | ||
6 | { | ||
7 | if (size == 0) | ||
8 | return NULL; | ||
9 | return vmalloc_exec(size); | ||
10 | } | ||
11 | |||
12 | /* Free memory returned from module_alloc */ | ||
13 | void module_free(struct module *mod, void *module_region) | ||
14 | { | ||
15 | vfree(module_region); | ||
16 | /* | ||
17 | * FIXME: If module_region == mod->init_region, trim exception | ||
18 | * table entries. | ||
19 | */ | ||
20 | } | ||
21 | |||
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h index 2733fad45f98..5e67c1532314 100644 --- a/arch/x86/include/asm/pgtable_32_types.h +++ b/arch/x86/include/asm/pgtable_32_types.h | |||
@@ -46,6 +46,10 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ | |||
46 | # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) | 46 | # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define MODULES_VADDR VMALLOC_START | ||
50 | #define MODULES_END VMALLOC_END | ||
51 | #define MODULES_LEN (MODULES_VADDR - MODULES_END) | ||
52 | |||
49 | #define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) | 53 | #define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) |
50 | 54 | ||
51 | #endif /* _ASM_X86_PGTABLE_32_DEFS_H */ | 55 | #endif /* _ASM_X86_PGTABLE_32_DEFS_H */ |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4f78bd682125..f3477bb84566 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -73,7 +73,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o | |||
73 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o | 73 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o |
74 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o | 74 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o |
75 | obj-$(CONFIG_KPROBES) += kprobes.o | 75 | obj-$(CONFIG_KPROBES) += kprobes.o |
76 | obj-$(CONFIG_MODULES) += module_$(BITS).o | 76 | obj-$(CONFIG_MODULES) += module.o |
77 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 77 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
78 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | 78 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o |
79 | obj-$(CONFIG_KGDB) += kgdb.o | 79 | obj-$(CONFIG_KGDB) += kgdb.o |
diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module.c index c23880b90b5c..89f386f044e4 100644 --- a/arch/x86/kernel/module_64.c +++ b/arch/x86/kernel/module.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* Kernel module help for x86-64 | 1 | /* Kernel module help for x86. |
2 | Copyright (C) 2001 Rusty Russell. | 2 | Copyright (C) 2001 Rusty Russell. |
3 | Copyright (C) 2002,2003 Andi Kleen, SuSE Labs. | ||
4 | 3 | ||
5 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
@@ -22,23 +21,18 @@ | |||
22 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
23 | #include <linux/string.h> | 22 | #include <linux/string.h> |
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/mm.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/bug.h> | 24 | #include <linux/bug.h> |
25 | #include <linux/mm.h> | ||
28 | 26 | ||
29 | #include <asm/system.h> | 27 | #include <asm/system.h> |
30 | #include <asm/page.h> | 28 | #include <asm/page.h> |
31 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
32 | 30 | ||
31 | #if 0 | ||
32 | #define DEBUGP printk | ||
33 | #else | ||
33 | #define DEBUGP(fmt...) | 34 | #define DEBUGP(fmt...) |
34 | 35 | #endif | |
35 | #ifndef CONFIG_UML | ||
36 | void module_free(struct module *mod, void *module_region) | ||
37 | { | ||
38 | vfree(module_region); | ||
39 | /* FIXME: If module_region == mod->init_region, trim exception | ||
40 | table entries. */ | ||
41 | } | ||
42 | 36 | ||
43 | void *module_alloc(unsigned long size) | 37 | void *module_alloc(unsigned long size) |
44 | { | 38 | { |
@@ -54,9 +48,15 @@ void *module_alloc(unsigned long size) | |||
54 | if (!area) | 48 | if (!area) |
55 | return NULL; | 49 | return NULL; |
56 | 50 | ||
57 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); | 51 | return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM, |
52 | PAGE_KERNEL_EXEC); | ||
53 | } | ||
54 | |||
55 | /* Free memory returned from module_alloc */ | ||
56 | void module_free(struct module *mod, void *module_region) | ||
57 | { | ||
58 | vfree(module_region); | ||
58 | } | 59 | } |
59 | #endif | ||
60 | 60 | ||
61 | /* We don't need anything special. */ | 61 | /* We don't need anything special. */ |
62 | int module_frob_arch_sections(Elf_Ehdr *hdr, | 62 | int module_frob_arch_sections(Elf_Ehdr *hdr, |
@@ -67,6 +67,58 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | #ifdef CONFIG_X86_32 | ||
71 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
72 | const char *strtab, | ||
73 | unsigned int symindex, | ||
74 | unsigned int relsec, | ||
75 | struct module *me) | ||
76 | { | ||
77 | unsigned int i; | ||
78 | Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; | ||
79 | Elf32_Sym *sym; | ||
80 | uint32_t *location; | ||
81 | |||
82 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
83 | sechdrs[relsec].sh_info); | ||
84 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
85 | /* This is where to make the change */ | ||
86 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
87 | + rel[i].r_offset; | ||
88 | /* This is the symbol it is referring to. Note that all | ||
89 | undefined symbols have been resolved. */ | ||
90 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
91 | + ELF32_R_SYM(rel[i].r_info); | ||
92 | |||
93 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
94 | case R_386_32: | ||
95 | /* We add the value into the location given */ | ||
96 | *location += sym->st_value; | ||
97 | break; | ||
98 | case R_386_PC32: | ||
99 | /* Add the value, subtract its postition */ | ||
100 | *location += sym->st_value - (uint32_t)location; | ||
101 | break; | ||
102 | default: | ||
103 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
104 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
105 | return -ENOEXEC; | ||
106 | } | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
112 | const char *strtab, | ||
113 | unsigned int symindex, | ||
114 | unsigned int relsec, | ||
115 | struct module *me) | ||
116 | { | ||
117 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", | ||
118 | me->name); | ||
119 | return -ENOEXEC; | ||
120 | } | ||
121 | #else /*X86_64*/ | ||
70 | int apply_relocate_add(Elf64_Shdr *sechdrs, | 122 | int apply_relocate_add(Elf64_Shdr *sechdrs, |
71 | const char *strtab, | 123 | const char *strtab, |
72 | unsigned int symindex, | 124 | unsigned int symindex, |
@@ -147,6 +199,8 @@ int apply_relocate(Elf_Shdr *sechdrs, | |||
147 | return -ENOSYS; | 199 | return -ENOSYS; |
148 | } | 200 | } |
149 | 201 | ||
202 | #endif | ||
203 | |||
150 | int module_finalize(const Elf_Ehdr *hdr, | 204 | int module_finalize(const Elf_Ehdr *hdr, |
151 | const Elf_Shdr *sechdrs, | 205 | const Elf_Shdr *sechdrs, |
152 | struct module *me) | 206 | struct module *me) |
diff --git a/arch/x86/kernel/module_32.c b/arch/x86/kernel/module_32.c deleted file mode 100644 index 0edd819050e7..000000000000 --- a/arch/x86/kernel/module_32.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* Kernel module help for i386. | ||
2 | Copyright (C) 2001 Rusty Russell. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #include <linux/moduleloader.h> | ||
19 | #include <linux/elf.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/bug.h> | ||
25 | |||
26 | #if 0 | ||
27 | #define DEBUGP printk | ||
28 | #else | ||
29 | #define DEBUGP(fmt...) | ||
30 | #endif | ||
31 | |||
32 | void *module_alloc(unsigned long size) | ||
33 | { | ||
34 | if (size == 0) | ||
35 | return NULL; | ||
36 | return vmalloc_exec(size); | ||
37 | } | ||
38 | |||
39 | |||
40 | /* Free memory returned from module_alloc */ | ||
41 | void module_free(struct module *mod, void *module_region) | ||
42 | { | ||
43 | vfree(module_region); | ||
44 | /* FIXME: If module_region == mod->init_region, trim exception | ||
45 | table entries. */ | ||
46 | } | ||
47 | |||
48 | /* We don't need anything special. */ | ||
49 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
50 | Elf_Shdr *sechdrs, | ||
51 | char *secstrings, | ||
52 | struct module *mod) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
58 | const char *strtab, | ||
59 | unsigned int symindex, | ||
60 | unsigned int relsec, | ||
61 | struct module *me) | ||
62 | { | ||
63 | unsigned int i; | ||
64 | Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; | ||
65 | Elf32_Sym *sym; | ||
66 | uint32_t *location; | ||
67 | |||
68 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
69 | sechdrs[relsec].sh_info); | ||
70 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
71 | /* This is where to make the change */ | ||
72 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
73 | + rel[i].r_offset; | ||
74 | /* This is the symbol it is referring to. Note that all | ||
75 | undefined symbols have been resolved. */ | ||
76 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
77 | + ELF32_R_SYM(rel[i].r_info); | ||
78 | |||
79 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
80 | case R_386_32: | ||
81 | /* We add the value into the location given */ | ||
82 | *location += sym->st_value; | ||
83 | break; | ||
84 | case R_386_PC32: | ||
85 | /* Add the value, subtract its postition */ | ||
86 | *location += sym->st_value - (uint32_t)location; | ||
87 | break; | ||
88 | default: | ||
89 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
90 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
91 | return -ENOEXEC; | ||
92 | } | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
98 | const char *strtab, | ||
99 | unsigned int symindex, | ||
100 | unsigned int relsec, | ||
101 | struct module *me) | ||
102 | { | ||
103 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", | ||
104 | me->name); | ||
105 | return -ENOEXEC; | ||
106 | } | ||
107 | |||
108 | int module_finalize(const Elf_Ehdr *hdr, | ||
109 | const Elf_Shdr *sechdrs, | ||
110 | struct module *me) | ||
111 | { | ||
112 | const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, | ||
113 | *para = NULL; | ||
114 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
115 | |||
116 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { | ||
117 | if (!strcmp(".text", secstrings + s->sh_name)) | ||
118 | text = s; | ||
119 | if (!strcmp(".altinstructions", secstrings + s->sh_name)) | ||
120 | alt = s; | ||
121 | if (!strcmp(".smp_locks", secstrings + s->sh_name)) | ||
122 | locks = s; | ||
123 | if (!strcmp(".parainstructions", secstrings + s->sh_name)) | ||
124 | para = s; | ||
125 | } | ||
126 | |||
127 | if (alt) { | ||
128 | /* patch .altinstructions */ | ||
129 | void *aseg = (void *)alt->sh_addr; | ||
130 | apply_alternatives(aseg, aseg + alt->sh_size); | ||
131 | } | ||
132 | if (locks && text) { | ||
133 | void *lseg = (void *)locks->sh_addr; | ||
134 | void *tseg = (void *)text->sh_addr; | ||
135 | alternatives_smp_module_add(me, me->name, | ||
136 | lseg, lseg + locks->sh_size, | ||
137 | tseg, tseg + text->sh_size); | ||
138 | } | ||
139 | |||
140 | if (para) { | ||
141 | void *pseg = (void *)para->sh_addr; | ||
142 | apply_paravirt(pseg, pseg + para->sh_size); | ||
143 | } | ||
144 | |||
145 | return module_bug_finalize(hdr, sechdrs, me); | ||
146 | } | ||
147 | |||
148 | void module_arch_cleanup(struct module *mod) | ||
149 | { | ||
150 | alternatives_smp_module_del(mod); | ||
151 | module_bug_cleanup(mod); | ||
152 | } | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d1c636bf31a7..be5ae80f897f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -301,15 +301,13 @@ static void __init reserve_brk(void) | |||
301 | 301 | ||
302 | #ifdef CONFIG_BLK_DEV_INITRD | 302 | #ifdef CONFIG_BLK_DEV_INITRD |
303 | 303 | ||
304 | #ifdef CONFIG_X86_32 | ||
305 | |||
306 | #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) | 304 | #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) |
307 | static void __init relocate_initrd(void) | 305 | static void __init relocate_initrd(void) |
308 | { | 306 | { |
309 | 307 | ||
310 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; | 308 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; |
311 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; | 309 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; |
312 | u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT; | 310 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; |
313 | u64 ramdisk_here; | 311 | u64 ramdisk_here; |
314 | unsigned long slop, clen, mapaddr; | 312 | unsigned long slop, clen, mapaddr; |
315 | char *p, *q; | 313 | char *p, *q; |
@@ -365,14 +363,13 @@ static void __init relocate_initrd(void) | |||
365 | ramdisk_image, ramdisk_image + ramdisk_size - 1, | 363 | ramdisk_image, ramdisk_image + ramdisk_size - 1, |
366 | ramdisk_here, ramdisk_here + ramdisk_size - 1); | 364 | ramdisk_here, ramdisk_here + ramdisk_size - 1); |
367 | } | 365 | } |
368 | #endif | ||
369 | 366 | ||
370 | static void __init reserve_initrd(void) | 367 | static void __init reserve_initrd(void) |
371 | { | 368 | { |
372 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; | 369 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; |
373 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; | 370 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; |
374 | u64 ramdisk_end = ramdisk_image + ramdisk_size; | 371 | u64 ramdisk_end = ramdisk_image + ramdisk_size; |
375 | u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT; | 372 | u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; |
376 | 373 | ||
377 | if (!boot_params.hdr.type_of_loader || | 374 | if (!boot_params.hdr.type_of_loader || |
378 | !ramdisk_image || !ramdisk_size) | 375 | !ramdisk_image || !ramdisk_size) |
@@ -402,14 +399,8 @@ static void __init reserve_initrd(void) | |||
402 | return; | 399 | return; |
403 | } | 400 | } |
404 | 401 | ||
405 | #ifdef CONFIG_X86_32 | ||
406 | relocate_initrd(); | 402 | relocate_initrd(); |
407 | #else | 403 | |
408 | printk(KERN_ERR "initrd extends beyond end of memory " | ||
409 | "(0x%08llx > 0x%08llx)\ndisabling initrd\n", | ||
410 | ramdisk_end, end_of_lowmem); | ||
411 | initrd_start = 0; | ||
412 | #endif | ||
413 | free_early(ramdisk_image, ramdisk_end); | 404 | free_early(ramdisk_image, ramdisk_end); |
414 | } | 405 | } |
415 | #else | 406 | #else |
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 4c85b2e2bb65..367e87882041 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
@@ -108,6 +108,8 @@ SECTIONS | |||
108 | /* Data */ | 108 | /* Data */ |
109 | . = ALIGN(PAGE_SIZE); | 109 | . = ALIGN(PAGE_SIZE); |
110 | .data : AT(ADDR(.data) - LOAD_OFFSET) { | 110 | .data : AT(ADDR(.data) - LOAD_OFFSET) { |
111 | /* Start of data section */ | ||
112 | _sdata = .; | ||
111 | DATA_DATA | 113 | DATA_DATA |
112 | CONSTRUCTORS | 114 | CONSTRUCTORS |
113 | 115 | ||
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c index 3981a466c779..c1accea8cb56 100644 --- a/arch/xtensa/kernel/module.c +++ b/arch/xtensa/kernel/module.c | |||
@@ -34,8 +34,6 @@ void *module_alloc(unsigned long size) | |||
34 | void module_free(struct module *mod, void *module_region) | 34 | void module_free(struct module *mod, void *module_region) |
35 | { | 35 | { |
36 | vfree(module_region); | 36 | vfree(module_region); |
37 | /* FIXME: If module_region == mod->init_region, trim exception | ||
38 | table entries. */ | ||
39 | } | 37 | } |
40 | 38 | ||
41 | int module_frob_arch_sections(Elf32_Ehdr *hdr, | 39 | int module_frob_arch_sections(Elf32_Ehdr *hdr, |
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c index 403d0e4265db..fc0949a8cfde 100644 --- a/drivers/ide/at91_ide.c +++ b/drivers/ide/at91_ide.c | |||
@@ -216,6 +216,7 @@ static const struct ide_port_info at91_ide_port_info __initdata = { | |||
216 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | | 216 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | |
217 | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, | 217 | IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, |
218 | .pio_mask = ATA_PIO6, | 218 | .pio_mask = ATA_PIO6, |
219 | .chipset = ide_generic, | ||
219 | }; | 220 | }; |
220 | 221 | ||
221 | /* | 222 | /* |
@@ -246,8 +247,7 @@ irqreturn_t at91_irq_handler(int irq, void *dev_id) | |||
246 | static int __init at91_ide_probe(struct platform_device *pdev) | 247 | static int __init at91_ide_probe(struct platform_device *pdev) |
247 | { | 248 | { |
248 | int ret; | 249 | int ret; |
249 | hw_regs_t hw; | 250 | struct ide_hw hw, *hws[] = { &hw }; |
250 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
251 | struct ide_host *host; | 251 | struct ide_host *host; |
252 | struct resource *res; | 252 | struct resource *res; |
253 | unsigned long tf_base = 0, ctl_base = 0; | 253 | unsigned long tf_base = 0, ctl_base = 0; |
@@ -304,10 +304,9 @@ static int __init at91_ide_probe(struct platform_device *pdev) | |||
304 | ide_std_init_ports(&hw, tf_base, ctl_base + 6); | 304 | ide_std_init_ports(&hw, tf_base, ctl_base + 6); |
305 | 305 | ||
306 | hw.irq = board->irq_pin; | 306 | hw.irq = board->irq_pin; |
307 | hw.chipset = ide_generic; | ||
308 | hw.dev = &pdev->dev; | 307 | hw.dev = &pdev->dev; |
309 | 308 | ||
310 | host = ide_host_alloc(&at91_ide_port_info, hws); | 309 | host = ide_host_alloc(&at91_ide_port_info, hws, 1); |
311 | if (!host) { | 310 | if (!host) { |
312 | perr("failed to allocate ide host\n"); | 311 | perr("failed to allocate ide host\n"); |
313 | return -ENOMEM; | 312 | return -ENOMEM; |
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c index 46013644c965..58121bd6c115 100644 --- a/drivers/ide/au1xxx-ide.c +++ b/drivers/ide/au1xxx-ide.c | |||
@@ -449,7 +449,7 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
449 | } | 449 | } |
450 | #endif | 450 | #endif |
451 | 451 | ||
452 | static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) | 452 | static void auide_setup_ports(struct ide_hw *hw, _auide_hwif *ahwif) |
453 | { | 453 | { |
454 | int i; | 454 | int i; |
455 | unsigned long *ata_regs = hw->io_ports_array; | 455 | unsigned long *ata_regs = hw->io_ports_array; |
@@ -499,6 +499,7 @@ static const struct ide_port_info au1xxx_port_info = { | |||
499 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA | 499 | #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA |
500 | .mwdma_mask = ATA_MWDMA2, | 500 | .mwdma_mask = ATA_MWDMA2, |
501 | #endif | 501 | #endif |
502 | .chipset = ide_au1xxx, | ||
502 | }; | 503 | }; |
503 | 504 | ||
504 | static int au_ide_probe(struct platform_device *dev) | 505 | static int au_ide_probe(struct platform_device *dev) |
@@ -507,7 +508,7 @@ static int au_ide_probe(struct platform_device *dev) | |||
507 | struct resource *res; | 508 | struct resource *res; |
508 | struct ide_host *host; | 509 | struct ide_host *host; |
509 | int ret = 0; | 510 | int ret = 0; |
510 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 511 | struct ide_hw hw, *hws[] = { &hw }; |
511 | 512 | ||
512 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) | 513 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) |
513 | char *mode = "MWDMA2"; | 514 | char *mode = "MWDMA2"; |
@@ -548,9 +549,8 @@ static int au_ide_probe(struct platform_device *dev) | |||
548 | auide_setup_ports(&hw, ahwif); | 549 | auide_setup_ports(&hw, ahwif); |
549 | hw.irq = ahwif->irq; | 550 | hw.irq = ahwif->irq; |
550 | hw.dev = &dev->dev; | 551 | hw.dev = &dev->dev; |
551 | hw.chipset = ide_au1xxx; | ||
552 | 552 | ||
553 | ret = ide_host_add(&au1xxx_port_info, hws, &host); | 553 | ret = ide_host_add(&au1xxx_port_info, hws, 1, &host); |
554 | if (ret) | 554 | if (ret) |
555 | goto out; | 555 | goto out; |
556 | 556 | ||
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c index d028f8864bc1..e3c6a5913305 100644 --- a/drivers/ide/buddha.c +++ b/drivers/ide/buddha.c | |||
@@ -121,7 +121,7 @@ static int xsurf_ack_intr(ide_hwif_t *hwif) | |||
121 | return 1; | 121 | return 1; |
122 | } | 122 | } |
123 | 123 | ||
124 | static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, | 124 | static void __init buddha_setup_ports(struct ide_hw *hw, unsigned long base, |
125 | unsigned long ctl, unsigned long irq_port, | 125 | unsigned long ctl, unsigned long irq_port, |
126 | ide_ack_intr_t *ack_intr) | 126 | ide_ack_intr_t *ack_intr) |
127 | { | 127 | { |
@@ -139,13 +139,12 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base, | |||
139 | 139 | ||
140 | hw->irq = IRQ_AMIGA_PORTS; | 140 | hw->irq = IRQ_AMIGA_PORTS; |
141 | hw->ack_intr = ack_intr; | 141 | hw->ack_intr = ack_intr; |
142 | |||
143 | hw->chipset = ide_generic; | ||
144 | } | 142 | } |
145 | 143 | ||
146 | static const struct ide_port_info buddha_port_info = { | 144 | static const struct ide_port_info buddha_port_info = { |
147 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | 145 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, |
148 | .irq_flags = IRQF_SHARED, | 146 | .irq_flags = IRQF_SHARED, |
147 | .chipset = ide_generic, | ||
149 | }; | 148 | }; |
150 | 149 | ||
151 | /* | 150 | /* |
@@ -161,7 +160,7 @@ static int __init buddha_init(void) | |||
161 | 160 | ||
162 | while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { | 161 | while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { |
163 | unsigned long board; | 162 | unsigned long board; |
164 | hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; | 163 | struct ide_hw hw[MAX_NUM_HWIFS], *hws[MAX_NUM_HWIFS]; |
165 | 164 | ||
166 | if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { | 165 | if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { |
167 | buddha_num_hwifs = BUDDHA_NUM_HWIFS; | 166 | buddha_num_hwifs = BUDDHA_NUM_HWIFS; |
@@ -225,7 +224,7 @@ fail_base2: | |||
225 | hws[i] = &hw[i]; | 224 | hws[i] = &hw[i]; |
226 | } | 225 | } |
227 | 226 | ||
228 | ide_host_add(&buddha_port_info, hws, NULL); | 227 | ide_host_add(&buddha_port_info, hws, i, NULL); |
229 | } | 228 | } |
230 | 229 | ||
231 | return 0; | 230 | return 0; |
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c index 8890276fef7f..1683ed5c7329 100644 --- a/drivers/ide/cmd640.c +++ b/drivers/ide/cmd640.c | |||
@@ -708,7 +708,7 @@ static int __init cmd640x_init(void) | |||
708 | int second_port_cmd640 = 0, rc; | 708 | int second_port_cmd640 = 0, rc; |
709 | const char *bus_type, *port2; | 709 | const char *bus_type, *port2; |
710 | u8 b, cfr; | 710 | u8 b, cfr; |
711 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; | 711 | struct ide_hw hw[2], *hws[2]; |
712 | 712 | ||
713 | if (cmd640_vlb && probe_for_cmd640_vlb()) { | 713 | if (cmd640_vlb && probe_for_cmd640_vlb()) { |
714 | bus_type = "VLB"; | 714 | bus_type = "VLB"; |
@@ -762,11 +762,9 @@ static int __init cmd640x_init(void) | |||
762 | 762 | ||
763 | ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); | 763 | ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); |
764 | hw[0].irq = 14; | 764 | hw[0].irq = 14; |
765 | hw[0].chipset = ide_cmd640; | ||
766 | 765 | ||
767 | ide_std_init_ports(&hw[1], 0x170, 0x376); | 766 | ide_std_init_ports(&hw[1], 0x170, 0x376); |
768 | hw[1].irq = 15; | 767 | hw[1].irq = 15; |
769 | hw[1].chipset = ide_cmd640; | ||
770 | 768 | ||
771 | printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" | 769 | printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" |
772 | "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); | 770 | "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); |
@@ -824,7 +822,8 @@ static int __init cmd640x_init(void) | |||
824 | cmd640_dump_regs(); | 822 | cmd640_dump_regs(); |
825 | #endif | 823 | #endif |
826 | 824 | ||
827 | return ide_host_add(&cmd640_port_info, hws, NULL); | 825 | return ide_host_add(&cmd640_port_info, hws, second_port_cmd640 ? 2 : 1, |
826 | NULL); | ||
828 | } | 827 | } |
829 | 828 | ||
830 | module_param_named(probe_vlb, cmd640_vlb, bool, 0); | 829 | module_param_named(probe_vlb, cmd640_vlb, bool, 0); |
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index 87987a7d36c9..bd066bb9d611 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c | |||
@@ -110,7 +110,7 @@ static const struct ide_port_info cyrix_chipset __devinitdata = { | |||
110 | static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 110 | static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) |
111 | { | 111 | { |
112 | const struct ide_port_info *d = &cyrix_chipset; | 112 | const struct ide_port_info *d = &cyrix_chipset; |
113 | hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; | 113 | struct ide_hw hw[2], *hws[] = { NULL, NULL }; |
114 | 114 | ||
115 | ide_setup_pci_noise(dev, d); | 115 | ide_setup_pci_noise(dev, d); |
116 | 116 | ||
@@ -136,7 +136,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic | |||
136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); | 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); |
137 | hw[0].irq = 14; | 137 | hw[0].irq = 14; |
138 | 138 | ||
139 | return ide_host_add(d, hws, NULL); | 139 | return ide_host_add(d, hws, 2, NULL); |
140 | } | 140 | } |
141 | 141 | ||
142 | static const struct pci_device_id cs5520_pci_tbl[] = { | 142 | static const struct pci_device_id cs5520_pci_tbl[] = { |
diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c index f153b95619bb..1e10eba62ceb 100644 --- a/drivers/ide/delkin_cb.c +++ b/drivers/ide/delkin_cb.c | |||
@@ -68,6 +68,7 @@ static const struct ide_port_info delkin_cb_port_info = { | |||
68 | IDE_HFLAG_NO_DMA, | 68 | IDE_HFLAG_NO_DMA, |
69 | .irq_flags = IRQF_SHARED, | 69 | .irq_flags = IRQF_SHARED, |
70 | .init_chipset = delkin_cb_init_chipset, | 70 | .init_chipset = delkin_cb_init_chipset, |
71 | .chipset = ide_pci, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | static int __devinit | 74 | static int __devinit |
@@ -76,7 +77,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) | |||
76 | struct ide_host *host; | 77 | struct ide_host *host; |
77 | unsigned long base; | 78 | unsigned long base; |
78 | int rc; | 79 | int rc; |
79 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 80 | struct ide_hw hw, *hws[] = { &hw }; |
80 | 81 | ||
81 | rc = pci_enable_device(dev); | 82 | rc = pci_enable_device(dev); |
82 | if (rc) { | 83 | if (rc) { |
@@ -97,9 +98,8 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) | |||
97 | ide_std_init_ports(&hw, base + 0x10, base + 0x1e); | 98 | ide_std_init_ports(&hw, base + 0x10, base + 0x1e); |
98 | hw.irq = dev->irq; | 99 | hw.irq = dev->irq; |
99 | hw.dev = &dev->dev; | 100 | hw.dev = &dev->dev; |
100 | hw.chipset = ide_pci; /* this enables IRQ sharing */ | ||
101 | 101 | ||
102 | rc = ide_host_add(&delkin_cb_port_info, hws, &host); | 102 | rc = ide_host_add(&delkin_cb_port_info, hws, 1, &host); |
103 | if (rc) | 103 | if (rc) |
104 | goto out_disable; | 104 | goto out_disable; |
105 | 105 | ||
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c index 0e2df6755ec9..22fa27389c3b 100644 --- a/drivers/ide/falconide.c +++ b/drivers/ide/falconide.c | |||
@@ -111,9 +111,10 @@ static const struct ide_port_info falconide_port_info = { | |||
111 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | | 111 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | |
112 | IDE_HFLAG_NO_DMA, | 112 | IDE_HFLAG_NO_DMA, |
113 | .irq_flags = IRQF_SHARED, | 113 | .irq_flags = IRQF_SHARED, |
114 | .chipset = ide_generic, | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | static void __init falconide_setup_ports(hw_regs_t *hw) | 117 | static void __init falconide_setup_ports(struct ide_hw *hw) |
117 | { | 118 | { |
118 | int i; | 119 | int i; |
119 | 120 | ||
@@ -128,8 +129,6 @@ static void __init falconide_setup_ports(hw_regs_t *hw) | |||
128 | 129 | ||
129 | hw->irq = IRQ_MFP_IDE; | 130 | hw->irq = IRQ_MFP_IDE; |
130 | hw->ack_intr = NULL; | 131 | hw->ack_intr = NULL; |
131 | |||
132 | hw->chipset = ide_generic; | ||
133 | } | 132 | } |
134 | 133 | ||
135 | /* | 134 | /* |
@@ -139,7 +138,7 @@ static void __init falconide_setup_ports(hw_regs_t *hw) | |||
139 | static int __init falconide_init(void) | 138 | static int __init falconide_init(void) |
140 | { | 139 | { |
141 | struct ide_host *host; | 140 | struct ide_host *host; |
142 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 141 | struct ide_hw hw, *hws[] = { &hw }; |
143 | int rc; | 142 | int rc; |
144 | 143 | ||
145 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) | 144 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE)) |
@@ -154,7 +153,7 @@ static int __init falconide_init(void) | |||
154 | 153 | ||
155 | falconide_setup_ports(&hw); | 154 | falconide_setup_ports(&hw); |
156 | 155 | ||
157 | host = ide_host_alloc(&falconide_port_info, hws); | 156 | host = ide_host_alloc(&falconide_port_info, hws, 1); |
158 | if (host == NULL) { | 157 | if (host == NULL) { |
159 | rc = -ENOMEM; | 158 | rc = -ENOMEM; |
160 | goto err; | 159 | goto err; |
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index c7119516c5a7..4451a6a5dfe0 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c | |||
@@ -88,7 +88,7 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif) | |||
88 | return 1; | 88 | return 1; |
89 | } | 89 | } |
90 | 90 | ||
91 | static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, | 91 | static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, |
92 | unsigned long ctl, unsigned long irq_port, | 92 | unsigned long ctl, unsigned long irq_port, |
93 | ide_ack_intr_t *ack_intr) | 93 | ide_ack_intr_t *ack_intr) |
94 | { | 94 | { |
@@ -106,14 +106,13 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, | |||
106 | 106 | ||
107 | hw->irq = IRQ_AMIGA_PORTS; | 107 | hw->irq = IRQ_AMIGA_PORTS; |
108 | hw->ack_intr = ack_intr; | 108 | hw->ack_intr = ack_intr; |
109 | |||
110 | hw->chipset = ide_generic; | ||
111 | } | 109 | } |
112 | 110 | ||
113 | static const struct ide_port_info gayle_port_info = { | 111 | static const struct ide_port_info gayle_port_info = { |
114 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | | 112 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | |
115 | IDE_HFLAG_NO_DMA, | 113 | IDE_HFLAG_NO_DMA, |
116 | .irq_flags = IRQF_SHARED, | 114 | .irq_flags = IRQF_SHARED, |
115 | .chipset = ide_generic, | ||
117 | }; | 116 | }; |
118 | 117 | ||
119 | /* | 118 | /* |
@@ -126,7 +125,7 @@ static int __init gayle_init(void) | |||
126 | unsigned long base, ctrlport, irqport; | 125 | unsigned long base, ctrlport, irqport; |
127 | ide_ack_intr_t *ack_intr; | 126 | ide_ack_intr_t *ack_intr; |
128 | int a4000, i, rc; | 127 | int a4000, i, rc; |
129 | hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; | 128 | struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; |
130 | 129 | ||
131 | if (!MACH_IS_AMIGA) | 130 | if (!MACH_IS_AMIGA) |
132 | return -ENODEV; | 131 | return -ENODEV; |
@@ -171,7 +170,7 @@ found: | |||
171 | hws[i] = &hw[i]; | 170 | hws[i] = &hw[i]; |
172 | } | 171 | } |
173 | 172 | ||
174 | rc = ide_host_add(&gayle_port_info, hws, NULL); | 173 | rc = ide_host_add(&gayle_port_info, hws, i, NULL); |
175 | if (rc) | 174 | if (rc) |
176 | release_mem_region(res_start, res_n); | 175 | release_mem_region(res_start, res_n); |
177 | 176 | ||
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 0feb66c720e1..7ce68ef6b904 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c | |||
@@ -138,14 +138,6 @@ | |||
138 | #undef HPT_RESET_STATE_ENGINE | 138 | #undef HPT_RESET_STATE_ENGINE |
139 | #undef HPT_DELAY_INTERRUPT | 139 | #undef HPT_DELAY_INTERRUPT |
140 | 140 | ||
141 | static const char *quirk_drives[] = { | ||
142 | "QUANTUM FIREBALLlct08 08", | ||
143 | "QUANTUM FIREBALLP KA6.4", | ||
144 | "QUANTUM FIREBALLP LM20.4", | ||
145 | "QUANTUM FIREBALLP LM20.5", | ||
146 | NULL | ||
147 | }; | ||
148 | |||
149 | static const char *bad_ata100_5[] = { | 141 | static const char *bad_ata100_5[] = { |
150 | "IBM-DTLA-307075", | 142 | "IBM-DTLA-307075", |
151 | "IBM-DTLA-307060", | 143 | "IBM-DTLA-307060", |
@@ -729,27 +721,13 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
729 | hpt3xx_set_mode(drive, XFER_PIO_0 + pio); | 721 | hpt3xx_set_mode(drive, XFER_PIO_0 + pio); |
730 | } | 722 | } |
731 | 723 | ||
732 | static void hpt3xx_quirkproc(ide_drive_t *drive) | ||
733 | { | ||
734 | char *m = (char *)&drive->id[ATA_ID_PROD]; | ||
735 | const char **list = quirk_drives; | ||
736 | |||
737 | while (*list) | ||
738 | if (strstr(m, *list++)) { | ||
739 | drive->quirk_list = 1; | ||
740 | return; | ||
741 | } | ||
742 | |||
743 | drive->quirk_list = 0; | ||
744 | } | ||
745 | |||
746 | static void hpt3xx_maskproc(ide_drive_t *drive, int mask) | 724 | static void hpt3xx_maskproc(ide_drive_t *drive, int mask) |
747 | { | 725 | { |
748 | ide_hwif_t *hwif = drive->hwif; | 726 | ide_hwif_t *hwif = drive->hwif; |
749 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 727 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
750 | struct hpt_info *info = hpt3xx_get_info(hwif->dev); | 728 | struct hpt_info *info = hpt3xx_get_info(hwif->dev); |
751 | 729 | ||
752 | if (drive->quirk_list == 0) | 730 | if ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) |
753 | return; | 731 | return; |
754 | 732 | ||
755 | if (info->chip_type >= HPT370) { | 733 | if (info->chip_type >= HPT370) { |
@@ -1404,7 +1382,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) | |||
1404 | static const struct ide_port_ops hpt3xx_port_ops = { | 1382 | static const struct ide_port_ops hpt3xx_port_ops = { |
1405 | .set_pio_mode = hpt3xx_set_pio_mode, | 1383 | .set_pio_mode = hpt3xx_set_pio_mode, |
1406 | .set_dma_mode = hpt3xx_set_mode, | 1384 | .set_dma_mode = hpt3xx_set_mode, |
1407 | .quirkproc = hpt3xx_quirkproc, | ||
1408 | .maskproc = hpt3xx_maskproc, | 1385 | .maskproc = hpt3xx_maskproc, |
1409 | .mdma_filter = hpt3xx_mdma_filter, | 1386 | .mdma_filter = hpt3xx_mdma_filter, |
1410 | .udma_filter = hpt3xx_udma_filter, | 1387 | .udma_filter = hpt3xx_udma_filter, |
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 36da913cc553..5af3d0ffaf0a 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c | |||
@@ -65,8 +65,6 @@ static struct cardinfo icside_cardinfo_v6_2 = { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct icside_state { | 67 | struct icside_state { |
68 | unsigned int channel; | ||
69 | unsigned int enabled; | ||
70 | void __iomem *irq_port; | 68 | void __iomem *irq_port; |
71 | void __iomem *ioc_base; | 69 | void __iomem *ioc_base; |
72 | unsigned int sel; | 70 | unsigned int sel; |
@@ -116,18 +114,11 @@ static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) | |||
116 | struct icside_state *state = ec->irq_data; | 114 | struct icside_state *state = ec->irq_data; |
117 | void __iomem *base = state->irq_port; | 115 | void __iomem *base = state->irq_port; |
118 | 116 | ||
119 | state->enabled = 1; | 117 | writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); |
118 | readb(base + ICS_ARCIN_V6_INTROFFSET_2); | ||
120 | 119 | ||
121 | switch (state->channel) { | 120 | writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); |
122 | case 0: | 121 | readb(base + ICS_ARCIN_V6_INTROFFSET_1); |
123 | writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1); | ||
124 | readb(base + ICS_ARCIN_V6_INTROFFSET_2); | ||
125 | break; | ||
126 | case 1: | ||
127 | writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2); | ||
128 | readb(base + ICS_ARCIN_V6_INTROFFSET_1); | ||
129 | break; | ||
130 | } | ||
131 | } | 122 | } |
132 | 123 | ||
133 | /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) | 124 | /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) |
@@ -137,8 +128,6 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) | |||
137 | { | 128 | { |
138 | struct icside_state *state = ec->irq_data; | 129 | struct icside_state *state = ec->irq_data; |
139 | 130 | ||
140 | state->enabled = 0; | ||
141 | |||
142 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); | 131 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); |
143 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); | 132 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); |
144 | } | 133 | } |
@@ -160,44 +149,6 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = { | |||
160 | .irqpending = icside_irqpending_arcin_v6, | 149 | .irqpending = icside_irqpending_arcin_v6, |
161 | }; | 150 | }; |
162 | 151 | ||
163 | /* | ||
164 | * Handle routing of interrupts. This is called before | ||
165 | * we write the command to the drive. | ||
166 | */ | ||
167 | static void icside_maskproc(ide_drive_t *drive, int mask) | ||
168 | { | ||
169 | ide_hwif_t *hwif = drive->hwif; | ||
170 | struct expansion_card *ec = ECARD_DEV(hwif->dev); | ||
171 | struct icside_state *state = ecard_get_drvdata(ec); | ||
172 | unsigned long flags; | ||
173 | |||
174 | local_irq_save(flags); | ||
175 | |||
176 | state->channel = hwif->channel; | ||
177 | |||
178 | if (state->enabled && !mask) { | ||
179 | switch (hwif->channel) { | ||
180 | case 0: | ||
181 | writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); | ||
182 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); | ||
183 | break; | ||
184 | case 1: | ||
185 | writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); | ||
186 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); | ||
187 | break; | ||
188 | } | ||
189 | } else { | ||
190 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2); | ||
191 | readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1); | ||
192 | } | ||
193 | |||
194 | local_irq_restore(flags); | ||
195 | } | ||
196 | |||
197 | static const struct ide_port_ops icside_v6_no_dma_port_ops = { | ||
198 | .maskproc = icside_maskproc, | ||
199 | }; | ||
200 | |||
201 | #ifdef CONFIG_BLK_DEV_IDEDMA_ICS | 152 | #ifdef CONFIG_BLK_DEV_IDEDMA_ICS |
202 | /* | 153 | /* |
203 | * SG-DMA support. | 154 | * SG-DMA support. |
@@ -275,7 +226,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode) | |||
275 | 226 | ||
276 | static const struct ide_port_ops icside_v6_port_ops = { | 227 | static const struct ide_port_ops icside_v6_port_ops = { |
277 | .set_dma_mode = icside_set_dma_mode, | 228 | .set_dma_mode = icside_set_dma_mode, |
278 | .maskproc = icside_maskproc, | ||
279 | }; | 229 | }; |
280 | 230 | ||
281 | static void icside_dma_host_set(ide_drive_t *drive, int on) | 231 | static void icside_dma_host_set(ide_drive_t *drive, int on) |
@@ -320,11 +270,6 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
320 | BUG_ON(dma_channel_active(ec->dma)); | 270 | BUG_ON(dma_channel_active(ec->dma)); |
321 | 271 | ||
322 | /* | 272 | /* |
323 | * Ensure that we have the right interrupt routed. | ||
324 | */ | ||
325 | icside_maskproc(drive, 0); | ||
326 | |||
327 | /* | ||
328 | * Route the DMA signals to the correct interface. | 273 | * Route the DMA signals to the correct interface. |
329 | */ | 274 | */ |
330 | writeb(state->sel | hwif->channel, state->ioc_base); | 275 | writeb(state->sel | hwif->channel, state->ioc_base); |
@@ -381,7 +326,7 @@ static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
381 | return -EOPNOTSUPP; | 326 | return -EOPNOTSUPP; |
382 | } | 327 | } |
383 | 328 | ||
384 | static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, | 329 | static void icside_setup_ports(struct ide_hw *hw, void __iomem *base, |
385 | struct cardinfo *info, struct expansion_card *ec) | 330 | struct cardinfo *info, struct expansion_card *ec) |
386 | { | 331 | { |
387 | unsigned long port = (unsigned long)base + info->dataoffset; | 332 | unsigned long port = (unsigned long)base + info->dataoffset; |
@@ -398,11 +343,11 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, | |||
398 | 343 | ||
399 | hw->irq = ec->irq; | 344 | hw->irq = ec->irq; |
400 | hw->dev = &ec->dev; | 345 | hw->dev = &ec->dev; |
401 | hw->chipset = ide_acorn; | ||
402 | } | 346 | } |
403 | 347 | ||
404 | static const struct ide_port_info icside_v5_port_info = { | 348 | static const struct ide_port_info icside_v5_port_info = { |
405 | .host_flags = IDE_HFLAG_NO_DMA, | 349 | .host_flags = IDE_HFLAG_NO_DMA, |
350 | .chipset = ide_acorn, | ||
406 | }; | 351 | }; |
407 | 352 | ||
408 | static int __devinit | 353 | static int __devinit |
@@ -410,7 +355,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) | |||
410 | { | 355 | { |
411 | void __iomem *base; | 356 | void __iomem *base; |
412 | struct ide_host *host; | 357 | struct ide_host *host; |
413 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 358 | struct ide_hw hw, *hws[] = { &hw }; |
414 | int ret; | 359 | int ret; |
415 | 360 | ||
416 | base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); | 361 | base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); |
@@ -431,7 +376,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) | |||
431 | 376 | ||
432 | icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); | 377 | icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec); |
433 | 378 | ||
434 | host = ide_host_alloc(&icside_v5_port_info, hws); | 379 | host = ide_host_alloc(&icside_v5_port_info, hws, 1); |
435 | if (host == NULL) | 380 | if (host == NULL) |
436 | return -ENODEV; | 381 | return -ENODEV; |
437 | 382 | ||
@@ -452,11 +397,11 @@ err_free: | |||
452 | 397 | ||
453 | static const struct ide_port_info icside_v6_port_info __initdata = { | 398 | static const struct ide_port_info icside_v6_port_info __initdata = { |
454 | .init_dma = icside_dma_off_init, | 399 | .init_dma = icside_dma_off_init, |
455 | .port_ops = &icside_v6_no_dma_port_ops, | ||
456 | .dma_ops = &icside_v6_dma_ops, | 400 | .dma_ops = &icside_v6_dma_ops, |
457 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, | 401 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, |
458 | .mwdma_mask = ATA_MWDMA2, | 402 | .mwdma_mask = ATA_MWDMA2, |
459 | .swdma_mask = ATA_SWDMA2, | 403 | .swdma_mask = ATA_SWDMA2, |
404 | .chipset = ide_acorn, | ||
460 | }; | 405 | }; |
461 | 406 | ||
462 | static int __devinit | 407 | static int __devinit |
@@ -466,7 +411,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) | |||
466 | struct ide_host *host; | 411 | struct ide_host *host; |
467 | unsigned int sel = 0; | 412 | unsigned int sel = 0; |
468 | int ret; | 413 | int ret; |
469 | hw_regs_t hw[2], *hws[] = { &hw[0], &hw[1], NULL, NULL }; | 414 | struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] }; |
470 | struct ide_port_info d = icside_v6_port_info; | 415 | struct ide_port_info d = icside_v6_port_info; |
471 | 416 | ||
472 | ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); | 417 | ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); |
@@ -506,7 +451,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) | |||
506 | icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); | 451 | icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec); |
507 | icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); | 452 | icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec); |
508 | 453 | ||
509 | host = ide_host_alloc(&d, hws); | 454 | host = ide_host_alloc(&d, hws, 2); |
510 | if (host == NULL) | 455 | if (host == NULL) |
511 | return -ENODEV; | 456 | return -ENODEV; |
512 | 457 | ||
diff --git a/drivers/ide/ide-4drives.c b/drivers/ide/ide-4drives.c index 78aca75a2c48..979d342c338a 100644 --- a/drivers/ide/ide-4drives.c +++ b/drivers/ide/ide-4drives.c | |||
@@ -25,12 +25,13 @@ static const struct ide_port_info ide_4drives_port_info = { | |||
25 | .port_ops = &ide_4drives_port_ops, | 25 | .port_ops = &ide_4drives_port_ops, |
26 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA | | 26 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA | |
27 | IDE_HFLAG_4DRIVES, | 27 | IDE_HFLAG_4DRIVES, |
28 | .chipset = ide_4drives, | ||
28 | }; | 29 | }; |
29 | 30 | ||
30 | static int __init ide_4drives_init(void) | 31 | static int __init ide_4drives_init(void) |
31 | { | 32 | { |
32 | unsigned long base = 0x1f0, ctl = 0x3f6; | 33 | unsigned long base = 0x1f0, ctl = 0x3f6; |
33 | hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL }; | 34 | struct ide_hw hw, *hws[] = { &hw, &hw }; |
34 | 35 | ||
35 | if (probe_4drives == 0) | 36 | if (probe_4drives == 0) |
36 | return -ENODEV; | 37 | return -ENODEV; |
@@ -52,9 +53,8 @@ static int __init ide_4drives_init(void) | |||
52 | 53 | ||
53 | ide_std_init_ports(&hw, base, ctl); | 54 | ide_std_init_ports(&hw, base, ctl); |
54 | hw.irq = 14; | 55 | hw.irq = 14; |
55 | hw.chipset = ide_4drives; | ||
56 | 56 | ||
57 | return ide_host_add(&ide_4drives_port_info, hws, NULL); | 57 | return ide_host_add(&ide_4drives_port_info, hws, 2, NULL); |
58 | } | 58 | } |
59 | 59 | ||
60 | module_init(ide_4drives_init); | 60 | module_init(ide_4drives_init); |
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 757e5956b132..bbdd2547f12a 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -259,7 +259,7 @@ void ide_retry_pc(ide_drive_t *drive) | |||
259 | pc->req_xfer = blk_rq_bytes(sense_rq); | 259 | pc->req_xfer = blk_rq_bytes(sense_rq); |
260 | 260 | ||
261 | if (drive->media == ide_tape) | 261 | if (drive->media == ide_tape) |
262 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); | 262 | drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; |
263 | 263 | ||
264 | /* | 264 | /* |
265 | * Push back the failed request and put request sense on top | 265 | * Push back the failed request and put request sense on top |
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 9e47f3529d55..527908ff298c 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
@@ -155,6 +155,7 @@ static const struct ide_port_info idecs_port_info = { | |||
155 | .port_ops = &idecs_port_ops, | 155 | .port_ops = &idecs_port_ops, |
156 | .host_flags = IDE_HFLAG_NO_DMA, | 156 | .host_flags = IDE_HFLAG_NO_DMA, |
157 | .irq_flags = IRQF_SHARED, | 157 | .irq_flags = IRQF_SHARED, |
158 | .chipset = ide_pci, | ||
158 | }; | 159 | }; |
159 | 160 | ||
160 | static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, | 161 | static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, |
@@ -163,7 +164,7 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, | |||
163 | struct ide_host *host; | 164 | struct ide_host *host; |
164 | ide_hwif_t *hwif; | 165 | ide_hwif_t *hwif; |
165 | int i, rc; | 166 | int i, rc; |
166 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 167 | struct ide_hw hw, *hws[] = { &hw }; |
167 | 168 | ||
168 | if (!request_region(io, 8, DRV_NAME)) { | 169 | if (!request_region(io, 8, DRV_NAME)) { |
169 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", | 170 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", |
@@ -181,10 +182,9 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl, | |||
181 | memset(&hw, 0, sizeof(hw)); | 182 | memset(&hw, 0, sizeof(hw)); |
182 | ide_std_init_ports(&hw, io, ctl); | 183 | ide_std_init_ports(&hw, io, ctl); |
183 | hw.irq = irq; | 184 | hw.irq = irq; |
184 | hw.chipset = ide_pci; | ||
185 | hw.dev = &handle->dev; | 185 | hw.dev = &handle->dev; |
186 | 186 | ||
187 | rc = ide_host_add(&idecs_port_info, hws, &host); | 187 | rc = ide_host_add(&idecs_port_info, hws, 1, &host); |
188 | if (rc) | 188 | if (rc) |
189 | goto out_release; | 189 | goto out_release; |
190 | 190 | ||
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index c6f7fcfb9d67..6a1de2169709 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -302,14 +302,12 @@ static const struct drive_list_entry hpa_list[] = { | |||
302 | { NULL, NULL } | 302 | { NULL, NULL } |
303 | }; | 303 | }; |
304 | 304 | ||
305 | static void idedisk_check_hpa(ide_drive_t *drive) | 305 | static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48) |
306 | { | 306 | { |
307 | unsigned long long capacity, set_max; | 307 | u64 capacity, set_max; |
308 | int lba48 = ata_id_lba48_enabled(drive->id); | ||
309 | 308 | ||
310 | capacity = drive->capacity64; | 309 | capacity = drive->capacity64; |
311 | 310 | set_max = idedisk_read_native_max_address(drive, lba48); | |
312 | set_max = idedisk_read_native_max_address(drive, lba48); | ||
313 | 311 | ||
314 | if (ide_in_drive_list(drive->id, hpa_list)) { | 312 | if (ide_in_drive_list(drive->id, hpa_list)) { |
315 | /* | 313 | /* |
@@ -320,9 +318,31 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
320 | set_max--; | 318 | set_max--; |
321 | } | 319 | } |
322 | 320 | ||
321 | return set_max; | ||
322 | } | ||
323 | |||
324 | static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48) | ||
325 | { | ||
326 | set_max = idedisk_set_max_address(drive, set_max, lba48); | ||
327 | if (set_max) | ||
328 | drive->capacity64 = set_max; | ||
329 | |||
330 | return set_max; | ||
331 | } | ||
332 | |||
333 | static void idedisk_check_hpa(ide_drive_t *drive) | ||
334 | { | ||
335 | u64 capacity, set_max; | ||
336 | int lba48 = ata_id_lba48_enabled(drive->id); | ||
337 | |||
338 | capacity = drive->capacity64; | ||
339 | set_max = ide_disk_hpa_get_native_capacity(drive, lba48); | ||
340 | |||
323 | if (set_max <= capacity) | 341 | if (set_max <= capacity) |
324 | return; | 342 | return; |
325 | 343 | ||
344 | drive->probed_capacity = set_max; | ||
345 | |||
326 | printk(KERN_INFO "%s: Host Protected Area detected.\n" | 346 | printk(KERN_INFO "%s: Host Protected Area detected.\n" |
327 | "\tcurrent capacity is %llu sectors (%llu MB)\n" | 347 | "\tcurrent capacity is %llu sectors (%llu MB)\n" |
328 | "\tnative capacity is %llu sectors (%llu MB)\n", | 348 | "\tnative capacity is %llu sectors (%llu MB)\n", |
@@ -330,13 +350,13 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
330 | capacity, sectors_to_MB(capacity), | 350 | capacity, sectors_to_MB(capacity), |
331 | set_max, sectors_to_MB(set_max)); | 351 | set_max, sectors_to_MB(set_max)); |
332 | 352 | ||
333 | set_max = idedisk_set_max_address(drive, set_max, lba48); | 353 | if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0) |
354 | return; | ||
334 | 355 | ||
335 | if (set_max) { | 356 | set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48); |
336 | drive->capacity64 = set_max; | 357 | if (set_max) |
337 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", | 358 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", |
338 | drive->name); | 359 | drive->name); |
339 | } | ||
340 | } | 360 | } |
341 | 361 | ||
342 | static int ide_disk_get_capacity(ide_drive_t *drive) | 362 | static int ide_disk_get_capacity(ide_drive_t *drive) |
@@ -358,6 +378,8 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
358 | drive->capacity64 = drive->cyl * drive->head * drive->sect; | 378 | drive->capacity64 = drive->cyl * drive->head * drive->sect; |
359 | } | 379 | } |
360 | 380 | ||
381 | drive->probed_capacity = drive->capacity64; | ||
382 | |||
361 | if (lba) { | 383 | if (lba) { |
362 | drive->dev_flags |= IDE_DFLAG_LBA; | 384 | drive->dev_flags |= IDE_DFLAG_LBA; |
363 | 385 | ||
@@ -376,7 +398,7 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
376 | "%llu sectors (%llu MB)\n", | 398 | "%llu sectors (%llu MB)\n", |
377 | drive->name, (unsigned long long)drive->capacity64, | 399 | drive->name, (unsigned long long)drive->capacity64, |
378 | sectors_to_MB(drive->capacity64)); | 400 | sectors_to_MB(drive->capacity64)); |
379 | drive->capacity64 = 1ULL << 28; | 401 | drive->probed_capacity = drive->capacity64 = 1ULL << 28; |
380 | } | 402 | } |
381 | 403 | ||
382 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && | 404 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && |
@@ -392,6 +414,34 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
392 | return 0; | 414 | return 0; |
393 | } | 415 | } |
394 | 416 | ||
417 | static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity) | ||
418 | { | ||
419 | u64 set = min(capacity, drive->probed_capacity); | ||
420 | u16 *id = drive->id; | ||
421 | int lba48 = ata_id_lba48_enabled(id); | ||
422 | |||
423 | if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 || | ||
424 | ata_id_hpa_enabled(id) == 0) | ||
425 | goto out; | ||
426 | |||
427 | /* | ||
428 | * according to the spec the SET MAX ADDRESS command shall be | ||
429 | * immediately preceded by a READ NATIVE MAX ADDRESS command | ||
430 | */ | ||
431 | capacity = ide_disk_hpa_get_native_capacity(drive, lba48); | ||
432 | if (capacity == 0) | ||
433 | goto out; | ||
434 | |||
435 | set = ide_disk_hpa_set_capacity(drive, set, lba48); | ||
436 | if (set) { | ||
437 | /* needed for ->resume to disable HPA */ | ||
438 | drive->dev_flags |= IDE_DFLAG_NOHPA; | ||
439 | return set; | ||
440 | } | ||
441 | out: | ||
442 | return drive->capacity64; | ||
443 | } | ||
444 | |||
395 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 445 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) |
396 | { | 446 | { |
397 | ide_drive_t *drive = q->queuedata; | 447 | ide_drive_t *drive = q->queuedata; |
@@ -428,14 +478,14 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
428 | if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) | 478 | if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) |
429 | return -EINVAL; | 479 | return -EINVAL; |
430 | 480 | ||
431 | if (drive->special.b.set_multmode) | 481 | if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) |
432 | return -EBUSY; | 482 | return -EBUSY; |
433 | 483 | ||
434 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 484 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
435 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 485 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
436 | 486 | ||
437 | drive->mult_req = arg; | 487 | drive->mult_req = arg; |
438 | drive->special.b.set_multmode = 1; | 488 | drive->special_flags |= IDE_SFLAG_SET_MULTMODE; |
439 | error = blk_execute_rq(drive->queue, NULL, rq, 0); | 489 | error = blk_execute_rq(drive->queue, NULL, rq, 0); |
440 | blk_put_request(rq); | 490 | blk_put_request(rq); |
441 | 491 | ||
@@ -740,6 +790,7 @@ static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | |||
740 | 790 | ||
741 | const struct ide_disk_ops ide_ata_disk_ops = { | 791 | const struct ide_disk_ops ide_ata_disk_ops = { |
742 | .check = ide_disk_check, | 792 | .check = ide_disk_check, |
793 | .set_capacity = ide_disk_set_capacity, | ||
743 | .get_capacity = ide_disk_get_capacity, | 794 | .get_capacity = ide_disk_get_capacity, |
744 | .setup = ide_disk_setup, | 795 | .setup = ide_disk_setup, |
745 | .flush = ide_disk_flush, | 796 | .flush = ide_disk_flush, |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 001f68f0bb28..219e6fb78dc6 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -347,7 +347,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode) | |||
347 | 347 | ||
348 | return mode; | 348 | return mode; |
349 | } | 349 | } |
350 | EXPORT_SYMBOL_GPL(ide_find_dma_mode); | ||
351 | 350 | ||
352 | static int ide_tune_dma(ide_drive_t *drive) | 351 | static int ide_tune_dma(ide_drive_t *drive) |
353 | { | 352 | { |
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 5d5fb961b5ce..2b9141979613 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c | |||
@@ -52,7 +52,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, | |||
52 | } | 52 | } |
53 | 53 | ||
54 | if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) | 54 | if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) |
55 | drive->special.b.recalibrate = 1; | 55 | drive->special_flags |= IDE_SFLAG_RECALIBRATE; |
56 | 56 | ||
57 | ++rq->errors; | 57 | ++rq->errors; |
58 | 58 | ||
@@ -268,9 +268,8 @@ static void ide_disk_pre_reset(ide_drive_t *drive) | |||
268 | { | 268 | { |
269 | int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; | 269 | int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; |
270 | 270 | ||
271 | drive->special.all = 0; | 271 | drive->special_flags = |
272 | drive->special.b.set_geometry = legacy; | 272 | legacy ? (IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE) : 0; |
273 | drive->special.b.recalibrate = legacy; | ||
274 | 273 | ||
275 | drive->mult_count = 0; | 274 | drive->mult_count = 0; |
276 | drive->dev_flags &= ~IDE_DFLAG_PARKED; | 275 | drive->dev_flags &= ~IDE_DFLAG_PARKED; |
@@ -280,7 +279,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive) | |||
280 | drive->mult_req = 0; | 279 | drive->mult_req = 0; |
281 | 280 | ||
282 | if (drive->mult_req != drive->mult_count) | 281 | if (drive->mult_req != drive->mult_count) |
283 | drive->special.b.set_multmode = 1; | 282 | drive->special_flags |= IDE_SFLAG_SET_MULTMODE; |
284 | } | 283 | } |
285 | 284 | ||
286 | static void pre_reset(ide_drive_t *drive) | 285 | static void pre_reset(ide_drive_t *drive) |
@@ -408,8 +407,9 @@ static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) | |||
408 | /* more than enough time */ | 407 | /* more than enough time */ |
409 | udelay(10); | 408 | udelay(10); |
410 | /* clear SRST, leave nIEN (unless device is on the quirk list) */ | 409 | /* clear SRST, leave nIEN (unless device is on the quirk list) */ |
411 | tp_ops->write_devctl(hwif, (drive->quirk_list == 2 ? 0 : ATA_NIEN) | | 410 | tp_ops->write_devctl(hwif, |
412 | ATA_DEVCTL_OBS); | 411 | ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) ? 0 : ATA_NIEN) | |
412 | ATA_DEVCTL_OBS); | ||
413 | /* more than enough time */ | 413 | /* more than enough time */ |
414 | udelay(10); | 414 | udelay(10); |
415 | hwif->poll_timeout = jiffies + WAIT_WORSTCASE; | 415 | hwif->poll_timeout = jiffies + WAIT_WORSTCASE; |
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 4b6b71e2cdf5..214119026b3f 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c | |||
@@ -287,6 +287,19 @@ static int ide_gd_media_changed(struct gendisk *disk) | |||
287 | return ret; | 287 | return ret; |
288 | } | 288 | } |
289 | 289 | ||
290 | static unsigned long long ide_gd_set_capacity(struct gendisk *disk, | ||
291 | unsigned long long capacity) | ||
292 | { | ||
293 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); | ||
294 | ide_drive_t *drive = idkp->drive; | ||
295 | const struct ide_disk_ops *disk_ops = drive->disk_ops; | ||
296 | |||
297 | if (disk_ops->set_capacity) | ||
298 | return disk_ops->set_capacity(drive, capacity); | ||
299 | |||
300 | return drive->capacity64; | ||
301 | } | ||
302 | |||
290 | static int ide_gd_revalidate_disk(struct gendisk *disk) | 303 | static int ide_gd_revalidate_disk(struct gendisk *disk) |
291 | { | 304 | { |
292 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); | 305 | struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); |
@@ -315,6 +328,7 @@ static struct block_device_operations ide_gd_ops = { | |||
315 | .locked_ioctl = ide_gd_ioctl, | 328 | .locked_ioctl = ide_gd_ioctl, |
316 | .getgeo = ide_gd_getgeo, | 329 | .getgeo = ide_gd_getgeo, |
317 | .media_changed = ide_gd_media_changed, | 330 | .media_changed = ide_gd_media_changed, |
331 | .set_capacity = ide_gd_set_capacity, | ||
318 | .revalidate_disk = ide_gd_revalidate_disk | 332 | .revalidate_disk = ide_gd_revalidate_disk |
319 | }; | 333 | }; |
320 | 334 | ||
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 7812ca0be13b..54d7c4685d23 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c | |||
@@ -29,6 +29,7 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); | |||
29 | 29 | ||
30 | static const struct ide_port_info ide_generic_port_info = { | 30 | static const struct ide_port_info ide_generic_port_info = { |
31 | .host_flags = IDE_HFLAG_NO_DMA, | 31 | .host_flags = IDE_HFLAG_NO_DMA, |
32 | .chipset = ide_generic, | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | #ifdef CONFIG_ARM | 35 | #ifdef CONFIG_ARM |
@@ -85,7 +86,7 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) | |||
85 | 86 | ||
86 | static int __init ide_generic_init(void) | 87 | static int __init ide_generic_init(void) |
87 | { | 88 | { |
88 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 89 | struct ide_hw hw, *hws[] = { &hw }; |
89 | unsigned long io_addr; | 90 | unsigned long io_addr; |
90 | int i, rc = 0, primary = 0, secondary = 0; | 91 | int i, rc = 0, primary = 0, secondary = 0; |
91 | 92 | ||
@@ -132,9 +133,7 @@ static int __init ide_generic_init(void) | |||
132 | #else | 133 | #else |
133 | hw.irq = legacy_irqs[i]; | 134 | hw.irq = legacy_irqs[i]; |
134 | #endif | 135 | #endif |
135 | hw.chipset = ide_generic; | 136 | rc = ide_host_add(&ide_generic_port_info, hws, 1, NULL); |
136 | |||
137 | rc = ide_host_add(&ide_generic_port_info, hws, NULL); | ||
138 | if (rc) { | 137 | if (rc) { |
139 | release_region(io_addr + 0x206, 1); | 138 | release_region(io_addr + 0x206, 1); |
140 | release_region(io_addr, 8); | 139 | release_region(io_addr, 8); |
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c index c06ebdc4a130..520f42c5445a 100644 --- a/drivers/ide/ide-h8300.c +++ b/drivers/ide/ide-h8300.c | |||
@@ -64,26 +64,26 @@ static const struct ide_tp_ops h8300_tp_ops = { | |||
64 | 64 | ||
65 | #define H8300_IDE_GAP (2) | 65 | #define H8300_IDE_GAP (2) |
66 | 66 | ||
67 | static inline void hw_setup(hw_regs_t *hw) | 67 | static inline void hw_setup(struct ide_hw *hw) |
68 | { | 68 | { |
69 | int i; | 69 | int i; |
70 | 70 | ||
71 | memset(hw, 0, sizeof(hw_regs_t)); | 71 | memset(hw, 0, sizeof(*hw)); |
72 | for (i = 0; i <= 7; i++) | 72 | for (i = 0; i <= 7; i++) |
73 | hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; | 73 | hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; |
74 | hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; | 74 | hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; |
75 | hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; | 75 | hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; |
76 | hw->chipset = ide_generic; | ||
77 | } | 76 | } |
78 | 77 | ||
79 | static const struct ide_port_info h8300_port_info = { | 78 | static const struct ide_port_info h8300_port_info = { |
80 | .tp_ops = &h8300_tp_ops, | 79 | .tp_ops = &h8300_tp_ops, |
81 | .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, | 80 | .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA, |
81 | .chipset = ide_generic, | ||
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int __init h8300_ide_init(void) | 84 | static int __init h8300_ide_init(void) |
85 | { | 85 | { |
86 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 86 | struct ide_hw hw, *hws[] = { &hw }; |
87 | 87 | ||
88 | printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); | 88 | printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n"); |
89 | 89 | ||
@@ -96,7 +96,7 @@ static int __init h8300_ide_init(void) | |||
96 | 96 | ||
97 | hw_setup(&hw); | 97 | hw_setup(&hw); |
98 | 98 | ||
99 | return ide_host_add(&h8300_port_info, hws, NULL); | 99 | return ide_host_add(&h8300_port_info, hws, 1, NULL); |
100 | 100 | ||
101 | out_busy: | 101 | out_busy: |
102 | printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); | 102 | printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index bba4297f2f03..272cc38f6dbe 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -184,29 +184,42 @@ static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | |||
184 | tf->command = ATA_CMD_SET_MULTI; | 184 | tf->command = ATA_CMD_SET_MULTI; |
185 | } | 185 | } |
186 | 186 | ||
187 | static ide_startstop_t ide_disk_special(ide_drive_t *drive) | 187 | /** |
188 | * do_special - issue some special commands | ||
189 | * @drive: drive the command is for | ||
190 | * | ||
191 | * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, | ||
192 | * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. | ||
193 | */ | ||
194 | |||
195 | static ide_startstop_t do_special(ide_drive_t *drive) | ||
188 | { | 196 | { |
189 | special_t *s = &drive->special; | ||
190 | struct ide_cmd cmd; | 197 | struct ide_cmd cmd; |
191 | 198 | ||
199 | #ifdef DEBUG | ||
200 | printk(KERN_DEBUG "%s: %s: 0x%02x\n", drive->name, __func__, | ||
201 | drive->special_flags); | ||
202 | #endif | ||
203 | if (drive->media != ide_disk) { | ||
204 | drive->special_flags = 0; | ||
205 | drive->mult_req = 0; | ||
206 | return ide_stopped; | ||
207 | } | ||
208 | |||
192 | memset(&cmd, 0, sizeof(cmd)); | 209 | memset(&cmd, 0, sizeof(cmd)); |
193 | cmd.protocol = ATA_PROT_NODATA; | 210 | cmd.protocol = ATA_PROT_NODATA; |
194 | 211 | ||
195 | if (s->b.set_geometry) { | 212 | if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) { |
196 | s->b.set_geometry = 0; | 213 | drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY; |
197 | ide_tf_set_specify_cmd(drive, &cmd.tf); | 214 | ide_tf_set_specify_cmd(drive, &cmd.tf); |
198 | } else if (s->b.recalibrate) { | 215 | } else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) { |
199 | s->b.recalibrate = 0; | 216 | drive->special_flags &= ~IDE_SFLAG_RECALIBRATE; |
200 | ide_tf_set_restore_cmd(drive, &cmd.tf); | 217 | ide_tf_set_restore_cmd(drive, &cmd.tf); |
201 | } else if (s->b.set_multmode) { | 218 | } else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) { |
202 | s->b.set_multmode = 0; | 219 | drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE; |
203 | ide_tf_set_setmult_cmd(drive, &cmd.tf); | 220 | ide_tf_set_setmult_cmd(drive, &cmd.tf); |
204 | } else if (s->all) { | 221 | } else |
205 | int special = s->all; | 222 | BUG(); |
206 | s->all = 0; | ||
207 | printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special); | ||
208 | return ide_stopped; | ||
209 | } | ||
210 | 223 | ||
211 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; | 224 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
212 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | 225 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
@@ -217,31 +230,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive) | |||
217 | return ide_started; | 230 | return ide_started; |
218 | } | 231 | } |
219 | 232 | ||
220 | /** | ||
221 | * do_special - issue some special commands | ||
222 | * @drive: drive the command is for | ||
223 | * | ||
224 | * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, | ||
225 | * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. | ||
226 | * | ||
227 | * It used to do much more, but has been scaled back. | ||
228 | */ | ||
229 | |||
230 | static ide_startstop_t do_special (ide_drive_t *drive) | ||
231 | { | ||
232 | special_t *s = &drive->special; | ||
233 | |||
234 | #ifdef DEBUG | ||
235 | printk("%s: do_special: 0x%02x\n", drive->name, s->all); | ||
236 | #endif | ||
237 | if (drive->media == ide_disk) | ||
238 | return ide_disk_special(drive); | ||
239 | |||
240 | s->all = 0; | ||
241 | drive->mult_req = 0; | ||
242 | return ide_stopped; | ||
243 | } | ||
244 | |||
245 | void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) | 233 | void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) |
246 | { | 234 | { |
247 | ide_hwif_t *hwif = drive->hwif; | 235 | ide_hwif_t *hwif = drive->hwif; |
@@ -351,7 +339,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
351 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); | 339 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); |
352 | return startstop; | 340 | return startstop; |
353 | } | 341 | } |
354 | if (!drive->special.all) { | 342 | |
343 | if (drive->special_flags == 0) { | ||
355 | struct ide_driver *drv; | 344 | struct ide_driver *drv; |
356 | 345 | ||
357 | /* | 346 | /* |
@@ -499,11 +488,15 @@ repeat: | |||
499 | 488 | ||
500 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && | 489 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && |
501 | hwif != prev_port) { | 490 | hwif != prev_port) { |
491 | ide_drive_t *cur_dev = | ||
492 | prev_port ? prev_port->cur_dev : NULL; | ||
493 | |||
502 | /* | 494 | /* |
503 | * set nIEN for previous port, drives in the | 495 | * set nIEN for previous port, drives in the |
504 | * quirk_list may not like intr setups/cleanups | 496 | * quirk list may not like intr setups/cleanups |
505 | */ | 497 | */ |
506 | if (prev_port && prev_port->cur_dev->quirk_list == 0) | 498 | if (cur_dev && |
499 | (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) | ||
507 | prev_port->tp_ops->write_devctl(prev_port, | 500 | prev_port->tp_ops->write_devctl(prev_port, |
508 | ATA_NIEN | | 501 | ATA_NIEN | |
509 | ATA_DEVCTL_OBS); | 502 | ATA_DEVCTL_OBS); |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 06fe002116ec..fa047150a1c6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -282,6 +282,29 @@ no_80w: | |||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | static const char *nien_quirk_list[] = { | ||
286 | "QUANTUM FIREBALLlct08 08", | ||
287 | "QUANTUM FIREBALLP KA6.4", | ||
288 | "QUANTUM FIREBALLP KA9.1", | ||
289 | "QUANTUM FIREBALLP KX13.6", | ||
290 | "QUANTUM FIREBALLP KX20.5", | ||
291 | "QUANTUM FIREBALLP KX27.3", | ||
292 | "QUANTUM FIREBALLP LM20.4", | ||
293 | "QUANTUM FIREBALLP LM20.5", | ||
294 | NULL | ||
295 | }; | ||
296 | |||
297 | void ide_check_nien_quirk_list(ide_drive_t *drive) | ||
298 | { | ||
299 | const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; | ||
300 | |||
301 | for (list = nien_quirk_list; *list != NULL; list++) | ||
302 | if (strstr(m, *list) != NULL) { | ||
303 | drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK; | ||
304 | return; | ||
305 | } | ||
306 | } | ||
307 | |||
285 | int ide_driveid_update(ide_drive_t *drive) | 308 | int ide_driveid_update(ide_drive_t *drive) |
286 | { | 309 | { |
287 | u16 *id; | 310 | u16 *id; |
@@ -311,7 +334,6 @@ int ide_driveid_update(ide_drive_t *drive) | |||
311 | 334 | ||
312 | return 1; | 335 | return 1; |
313 | out_err: | 336 | out_err: |
314 | SELECT_MASK(drive, 0); | ||
315 | if (rc == 2) | 337 | if (rc == 2) |
316 | printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); | 338 | printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); |
317 | kfree(id); | 339 | kfree(id); |
@@ -365,7 +387,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
365 | 387 | ||
366 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); | 388 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); |
367 | 389 | ||
368 | if (drive->quirk_list == 2) | 390 | if (drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) |
369 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | 391 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
370 | 392 | ||
371 | error = __ide_wait_stat(drive, drive->ready_stat, | 393 | error = __ide_wait_stat(drive, drive->ready_stat, |
diff --git a/drivers/ide/ide-legacy.c b/drivers/ide/ide-legacy.c index 8c5dcbf22547..b9654a7bb7be 100644 --- a/drivers/ide/ide-legacy.c +++ b/drivers/ide/ide-legacy.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/ide.h> | 2 | #include <linux/ide.h> |
3 | 3 | ||
4 | static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, | 4 | static void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw, |
5 | u8 port_no, const struct ide_port_info *d, | 5 | u8 port_no, const struct ide_port_info *d, |
6 | unsigned long config) | 6 | unsigned long config) |
7 | { | 7 | { |
@@ -33,7 +33,6 @@ static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, | |||
33 | 33 | ||
34 | ide_std_init_ports(hw, base, ctl); | 34 | ide_std_init_ports(hw, base, ctl); |
35 | hw->irq = irq; | 35 | hw->irq = irq; |
36 | hw->chipset = d->chipset; | ||
37 | hw->config = config; | 36 | hw->config = config; |
38 | 37 | ||
39 | hws[port_no] = hw; | 38 | hws[port_no] = hw; |
@@ -41,7 +40,7 @@ static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, | |||
41 | 40 | ||
42 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | 41 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) |
43 | { | 42 | { |
44 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; | 43 | struct ide_hw hw[2], *hws[] = { NULL, NULL }; |
45 | 44 | ||
46 | memset(&hw, 0, sizeof(hw)); | 45 | memset(&hw, 0, sizeof(hw)); |
47 | 46 | ||
@@ -53,6 +52,6 @@ int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | |||
53 | (d->host_flags & IDE_HFLAG_SINGLE)) | 52 | (d->host_flags & IDE_HFLAG_SINGLE)) |
54 | return -ENOENT; | 53 | return -ENOENT; |
55 | 54 | ||
56 | return ide_host_add(d, hws, NULL); | 55 | return ide_host_add(d, hws, 2, NULL); |
57 | } | 56 | } |
58 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); | 57 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); |
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index 6e80b774e88a..017b1df3b805 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c | |||
@@ -29,6 +29,7 @@ static struct pnp_device_id idepnp_devices[] = { | |||
29 | 29 | ||
30 | static const struct ide_port_info ide_pnp_port_info = { | 30 | static const struct ide_port_info ide_pnp_port_info = { |
31 | .host_flags = IDE_HFLAG_NO_DMA, | 31 | .host_flags = IDE_HFLAG_NO_DMA, |
32 | .chipset = ide_generic, | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | 35 | static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) |
@@ -36,7 +37,7 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | |||
36 | struct ide_host *host; | 37 | struct ide_host *host; |
37 | unsigned long base, ctl; | 38 | unsigned long base, ctl; |
38 | int rc; | 39 | int rc; |
39 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 40 | struct ide_hw hw, *hws[] = { &hw }; |
40 | 41 | ||
41 | printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n"); | 42 | printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n"); |
42 | 43 | ||
@@ -62,9 +63,8 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | |||
62 | memset(&hw, 0, sizeof(hw)); | 63 | memset(&hw, 0, sizeof(hw)); |
63 | ide_std_init_ports(&hw, base, ctl); | 64 | ide_std_init_ports(&hw, base, ctl); |
64 | hw.irq = pnp_irq(dev, 0); | 65 | hw.irq = pnp_irq(dev, 0); |
65 | hw.chipset = ide_generic; | ||
66 | 66 | ||
67 | rc = ide_host_add(&ide_pnp_port_info, hws, &host); | 67 | rc = ide_host_add(&ide_pnp_port_info, hws, 1, &host); |
68 | if (rc) | 68 | if (rc) |
69 | goto out; | 69 | goto out; |
70 | 70 | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c895ed52b2e8..f371b0de314f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -97,7 +97,7 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) | |||
97 | drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; | 97 | drive->mult_req = id[ATA_ID_MULTSECT] & 0xff; |
98 | 98 | ||
99 | if (drive->mult_req) | 99 | if (drive->mult_req) |
100 | drive->special.b.set_multmode = 1; | 100 | drive->special_flags |= IDE_SFLAG_SET_MULTMODE; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
@@ -465,23 +465,8 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
465 | int rc; | 465 | int rc; |
466 | u8 cmd; | 466 | u8 cmd; |
467 | 467 | ||
468 | /* | ||
469 | * In order to keep things simple we have an id | ||
470 | * block for all drives at all times. If the device | ||
471 | * is pre ATA or refuses ATA/ATAPI identify we | ||
472 | * will add faked data to this. | ||
473 | * | ||
474 | * Also note that 0 everywhere means "can't do X" | ||
475 | */ | ||
476 | |||
477 | drive->dev_flags &= ~IDE_DFLAG_ID_READ; | 468 | drive->dev_flags &= ~IDE_DFLAG_ID_READ; |
478 | 469 | ||
479 | drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); | ||
480 | if (drive->id == NULL) { | ||
481 | printk(KERN_ERR "ide: out of memory for id data.\n"); | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | m = (char *)&drive->id[ATA_ID_PROD]; | 470 | m = (char *)&drive->id[ATA_ID_PROD]; |
486 | strcpy(m, "UNKNOWN"); | 471 | strcpy(m, "UNKNOWN"); |
487 | 472 | ||
@@ -497,7 +482,7 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
497 | } | 482 | } |
498 | 483 | ||
499 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 484 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) |
500 | goto out_free; | 485 | return 0; |
501 | 486 | ||
502 | /* identification failed? */ | 487 | /* identification failed? */ |
503 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { | 488 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { |
@@ -521,7 +506,7 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
521 | } | 506 | } |
522 | 507 | ||
523 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 508 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) |
524 | goto out_free; | 509 | return 0; |
525 | 510 | ||
526 | /* The drive wasn't being helpful. Add generic info only */ | 511 | /* The drive wasn't being helpful. Add generic info only */ |
527 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { | 512 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { |
@@ -535,9 +520,6 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
535 | } | 520 | } |
536 | 521 | ||
537 | return 1; | 522 | return 1; |
538 | out_free: | ||
539 | kfree(drive->id); | ||
540 | return 0; | ||
541 | } | 523 | } |
542 | 524 | ||
543 | static void hwif_release_dev(struct device *dev) | 525 | static void hwif_release_dev(struct device *dev) |
@@ -702,8 +684,14 @@ static int ide_probe_port(ide_hwif_t *hwif) | |||
702 | if (irqd) | 684 | if (irqd) |
703 | disable_irq(hwif->irq); | 685 | disable_irq(hwif->irq); |
704 | 686 | ||
705 | if (ide_port_wait_ready(hwif) == -EBUSY) | 687 | rc = ide_port_wait_ready(hwif); |
706 | printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); | 688 | if (rc == -ENODEV) { |
689 | printk(KERN_INFO "%s: no devices on the port\n", hwif->name); | ||
690 | goto out; | ||
691 | } else if (rc == -EBUSY) | ||
692 | printk(KERN_ERR "%s: not ready before the probe\n", hwif->name); | ||
693 | else | ||
694 | rc = -ENODEV; | ||
707 | 695 | ||
708 | /* | 696 | /* |
709 | * Second drive should only exist if first drive was found, | 697 | * Second drive should only exist if first drive was found, |
@@ -714,7 +702,7 @@ static int ide_probe_port(ide_hwif_t *hwif) | |||
714 | if (drive->dev_flags & IDE_DFLAG_PRESENT) | 702 | if (drive->dev_flags & IDE_DFLAG_PRESENT) |
715 | rc = 0; | 703 | rc = 0; |
716 | } | 704 | } |
717 | 705 | out: | |
718 | /* | 706 | /* |
719 | * Use cached IRQ number. It might be (and is...) changed by probe | 707 | * Use cached IRQ number. It might be (and is...) changed by probe |
720 | * code above | 708 | * code above |
@@ -732,6 +720,8 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) | |||
732 | int i; | 720 | int i; |
733 | 721 | ||
734 | ide_port_for_each_present_dev(i, drive, hwif) { | 722 | ide_port_for_each_present_dev(i, drive, hwif) { |
723 | ide_check_nien_quirk_list(drive); | ||
724 | |||
735 | if (port_ops && port_ops->quirkproc) | 725 | if (port_ops && port_ops->quirkproc) |
736 | port_ops->quirkproc(drive); | 726 | port_ops->quirkproc(drive); |
737 | } | 727 | } |
@@ -817,8 +807,6 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
817 | if (ide_init_queue(drive)) { | 807 | if (ide_init_queue(drive)) { |
818 | printk(KERN_ERR "ide: failed to init %s\n", | 808 | printk(KERN_ERR "ide: failed to init %s\n", |
819 | drive->name); | 809 | drive->name); |
820 | kfree(drive->id); | ||
821 | drive->id = NULL; | ||
822 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 810 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
823 | continue; | 811 | continue; |
824 | } | 812 | } |
@@ -947,9 +935,6 @@ static void drive_release_dev (struct device *dev) | |||
947 | blk_cleanup_queue(drive->queue); | 935 | blk_cleanup_queue(drive->queue); |
948 | drive->queue = NULL; | 936 | drive->queue = NULL; |
949 | 937 | ||
950 | kfree(drive->id); | ||
951 | drive->id = NULL; | ||
952 | |||
953 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 938 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
954 | 939 | ||
955 | complete(&drive->gendev_rel_comp); | 940 | complete(&drive->gendev_rel_comp); |
@@ -1035,6 +1020,15 @@ static void ide_port_init_devices(ide_hwif_t *hwif) | |||
1035 | if (port_ops && port_ops->init_dev) | 1020 | if (port_ops && port_ops->init_dev) |
1036 | port_ops->init_dev(drive); | 1021 | port_ops->init_dev(drive); |
1037 | } | 1022 | } |
1023 | |||
1024 | ide_port_for_each_dev(i, drive, hwif) { | ||
1025 | /* | ||
1026 | * default to PIO Mode 0 before we figure out | ||
1027 | * the most suited mode for the attached device | ||
1028 | */ | ||
1029 | if (port_ops && port_ops->set_pio_mode) | ||
1030 | port_ops->set_pio_mode(drive, 0); | ||
1031 | } | ||
1038 | } | 1032 | } |
1039 | 1033 | ||
1040 | static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | 1034 | static void ide_init_port(ide_hwif_t *hwif, unsigned int port, |
@@ -1042,8 +1036,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
1042 | { | 1036 | { |
1043 | hwif->channel = port; | 1037 | hwif->channel = port; |
1044 | 1038 | ||
1045 | if (d->chipset) | 1039 | hwif->chipset = d->chipset ? d->chipset : ide_pci; |
1046 | hwif->chipset = d->chipset; | ||
1047 | 1040 | ||
1048 | if (d->init_iops) | 1041 | if (d->init_iops) |
1049 | d->init_iops(hwif); | 1042 | d->init_iops(hwif); |
@@ -1124,16 +1117,19 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | |||
1124 | 1117 | ||
1125 | ide_port_for_each_dev(i, drive, hwif) { | 1118 | ide_port_for_each_dev(i, drive, hwif) { |
1126 | u8 j = (hwif->index * MAX_DRIVES) + i; | 1119 | u8 j = (hwif->index * MAX_DRIVES) + i; |
1120 | u16 *saved_id = drive->id; | ||
1127 | 1121 | ||
1128 | memset(drive, 0, sizeof(*drive)); | 1122 | memset(drive, 0, sizeof(*drive)); |
1123 | memset(saved_id, 0, SECTOR_SIZE); | ||
1124 | drive->id = saved_id; | ||
1129 | 1125 | ||
1130 | drive->media = ide_disk; | 1126 | drive->media = ide_disk; |
1131 | drive->select = (i << 4) | ATA_DEVICE_OBS; | 1127 | drive->select = (i << 4) | ATA_DEVICE_OBS; |
1132 | drive->hwif = hwif; | 1128 | drive->hwif = hwif; |
1133 | drive->ready_stat = ATA_DRDY; | 1129 | drive->ready_stat = ATA_DRDY; |
1134 | drive->bad_wstat = BAD_W_STAT; | 1130 | drive->bad_wstat = BAD_W_STAT; |
1135 | drive->special.b.recalibrate = 1; | 1131 | drive->special_flags = IDE_SFLAG_RECALIBRATE | |
1136 | drive->special.b.set_geometry = 1; | 1132 | IDE_SFLAG_SET_GEOMETRY; |
1137 | drive->name[0] = 'h'; | 1133 | drive->name[0] = 'h'; |
1138 | drive->name[1] = 'd'; | 1134 | drive->name[1] = 'd'; |
1139 | drive->name[2] = 'a' + j; | 1135 | drive->name[2] = 'a' + j; |
@@ -1168,11 +1164,10 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) | |||
1168 | ide_port_init_devices_data(hwif); | 1164 | ide_port_init_devices_data(hwif); |
1169 | } | 1165 | } |
1170 | 1166 | ||
1171 | static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) | 1167 | static void ide_init_port_hw(ide_hwif_t *hwif, struct ide_hw *hw) |
1172 | { | 1168 | { |
1173 | memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); | 1169 | memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports)); |
1174 | hwif->irq = hw->irq; | 1170 | hwif->irq = hw->irq; |
1175 | hwif->chipset = hw->chipset; | ||
1176 | hwif->dev = hw->dev; | 1171 | hwif->dev = hw->dev; |
1177 | hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; | 1172 | hwif->gendev.parent = hw->parent ? hw->parent : hw->dev; |
1178 | hwif->ack_intr = hw->ack_intr; | 1173 | hwif->ack_intr = hw->ack_intr; |
@@ -1233,8 +1228,10 @@ static void ide_port_free_devices(ide_hwif_t *hwif) | |||
1233 | ide_drive_t *drive; | 1228 | ide_drive_t *drive; |
1234 | int i; | 1229 | int i; |
1235 | 1230 | ||
1236 | ide_port_for_each_dev(i, drive, hwif) | 1231 | ide_port_for_each_dev(i, drive, hwif) { |
1232 | kfree(drive->id); | ||
1237 | kfree(drive); | 1233 | kfree(drive); |
1234 | } | ||
1238 | } | 1235 | } |
1239 | 1236 | ||
1240 | static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) | 1237 | static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) |
@@ -1248,6 +1245,18 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) | |||
1248 | if (drive == NULL) | 1245 | if (drive == NULL) |
1249 | goto out_nomem; | 1246 | goto out_nomem; |
1250 | 1247 | ||
1248 | /* | ||
1249 | * In order to keep things simple we have an id | ||
1250 | * block for all drives at all times. If the device | ||
1251 | * is pre ATA or refuses ATA/ATAPI identify we | ||
1252 | * will add faked data to this. | ||
1253 | * | ||
1254 | * Also note that 0 everywhere means "can't do X" | ||
1255 | */ | ||
1256 | drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node); | ||
1257 | if (drive->id == NULL) | ||
1258 | goto out_nomem; | ||
1259 | |||
1251 | hwif->devices[i] = drive; | 1260 | hwif->devices[i] = drive; |
1252 | } | 1261 | } |
1253 | return 0; | 1262 | return 0; |
@@ -1257,7 +1266,8 @@ out_nomem: | |||
1257 | return -ENOMEM; | 1266 | return -ENOMEM; |
1258 | } | 1267 | } |
1259 | 1268 | ||
1260 | struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | 1269 | struct ide_host *ide_host_alloc(const struct ide_port_info *d, |
1270 | struct ide_hw **hws, unsigned int n_ports) | ||
1261 | { | 1271 | { |
1262 | struct ide_host *host; | 1272 | struct ide_host *host; |
1263 | struct device *dev = hws[0] ? hws[0]->dev : NULL; | 1273 | struct device *dev = hws[0] ? hws[0]->dev : NULL; |
@@ -1268,7 +1278,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | |||
1268 | if (host == NULL) | 1278 | if (host == NULL) |
1269 | return NULL; | 1279 | return NULL; |
1270 | 1280 | ||
1271 | for (i = 0; i < MAX_HOST_PORTS; i++) { | 1281 | for (i = 0; i < n_ports; i++) { |
1272 | ide_hwif_t *hwif; | 1282 | ide_hwif_t *hwif; |
1273 | int idx; | 1283 | int idx; |
1274 | 1284 | ||
@@ -1288,6 +1298,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) | |||
1288 | if (idx < 0) { | 1298 | if (idx < 0) { |
1289 | printk(KERN_ERR "%s: no free slot for interface\n", | 1299 | printk(KERN_ERR "%s: no free slot for interface\n", |
1290 | d ? d->name : "ide"); | 1300 | d ? d->name : "ide"); |
1301 | ide_port_free_devices(hwif); | ||
1291 | kfree(hwif); | 1302 | kfree(hwif); |
1292 | continue; | 1303 | continue; |
1293 | } | 1304 | } |
@@ -1344,7 +1355,7 @@ static void ide_disable_port(ide_hwif_t *hwif) | |||
1344 | } | 1355 | } |
1345 | 1356 | ||
1346 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | 1357 | int ide_host_register(struct ide_host *host, const struct ide_port_info *d, |
1347 | hw_regs_t **hws) | 1358 | struct ide_hw **hws) |
1348 | { | 1359 | { |
1349 | ide_hwif_t *hwif, *mate = NULL; | 1360 | ide_hwif_t *hwif, *mate = NULL; |
1350 | int i, j = 0; | 1361 | int i, j = 0; |
@@ -1438,13 +1449,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
1438 | } | 1449 | } |
1439 | EXPORT_SYMBOL_GPL(ide_host_register); | 1450 | EXPORT_SYMBOL_GPL(ide_host_register); |
1440 | 1451 | ||
1441 | int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws, | 1452 | int ide_host_add(const struct ide_port_info *d, struct ide_hw **hws, |
1442 | struct ide_host **hostp) | 1453 | unsigned int n_ports, struct ide_host **hostp) |
1443 | { | 1454 | { |
1444 | struct ide_host *host; | 1455 | struct ide_host *host; |
1445 | int rc; | 1456 | int rc; |
1446 | 1457 | ||
1447 | host = ide_host_alloc(d, hws); | 1458 | host = ide_host_alloc(d, hws, n_ports); |
1448 | if (host == NULL) | 1459 | if (host == NULL) |
1449 | return -ENOMEM; | 1460 | return -ENOMEM; |
1450 | 1461 | ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d9764f0bc82f..4b447a8a49d4 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -240,18 +240,27 @@ static struct class *idetape_sysfs_class; | |||
240 | 240 | ||
241 | static void ide_tape_release(struct device *); | 241 | static void ide_tape_release(struct device *); |
242 | 242 | ||
243 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk) | 243 | static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES]; |
244 | |||
245 | static struct ide_tape_obj *ide_tape_get(struct gendisk *disk, bool cdev, | ||
246 | unsigned int i) | ||
244 | { | 247 | { |
245 | struct ide_tape_obj *tape = NULL; | 248 | struct ide_tape_obj *tape = NULL; |
246 | 249 | ||
247 | mutex_lock(&idetape_ref_mutex); | 250 | mutex_lock(&idetape_ref_mutex); |
248 | tape = ide_drv_g(disk, ide_tape_obj); | 251 | |
252 | if (cdev) | ||
253 | tape = idetape_devs[i]; | ||
254 | else | ||
255 | tape = ide_drv_g(disk, ide_tape_obj); | ||
256 | |||
249 | if (tape) { | 257 | if (tape) { |
250 | if (ide_device_get(tape->drive)) | 258 | if (ide_device_get(tape->drive)) |
251 | tape = NULL; | 259 | tape = NULL; |
252 | else | 260 | else |
253 | get_device(&tape->dev); | 261 | get_device(&tape->dev); |
254 | } | 262 | } |
263 | |||
255 | mutex_unlock(&idetape_ref_mutex); | 264 | mutex_unlock(&idetape_ref_mutex); |
256 | return tape; | 265 | return tape; |
257 | } | 266 | } |
@@ -267,24 +276,6 @@ static void ide_tape_put(struct ide_tape_obj *tape) | |||
267 | } | 276 | } |
268 | 277 | ||
269 | /* | 278 | /* |
270 | * The variables below are used for the character device interface. Additional | ||
271 | * state variables are defined in our ide_drive_t structure. | ||
272 | */ | ||
273 | static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES]; | ||
274 | |||
275 | static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) | ||
276 | { | ||
277 | struct ide_tape_obj *tape = NULL; | ||
278 | |||
279 | mutex_lock(&idetape_ref_mutex); | ||
280 | tape = idetape_devs[i]; | ||
281 | if (tape) | ||
282 | get_device(&tape->dev); | ||
283 | mutex_unlock(&idetape_ref_mutex); | ||
284 | return tape; | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * called on each failed packet command retry to analyze the request sense. We | 279 | * called on each failed packet command retry to analyze the request sense. We |
289 | * currently do not utilize this information. | 280 | * currently do not utilize this information. |
290 | */ | 281 | */ |
@@ -397,7 +388,8 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) | |||
397 | if (readpos[0] & 0x4) { | 388 | if (readpos[0] & 0x4) { |
398 | printk(KERN_INFO "ide-tape: Block location is unknown" | 389 | printk(KERN_INFO "ide-tape: Block location is unknown" |
399 | "to the tape\n"); | 390 | "to the tape\n"); |
400 | clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); | 391 | clear_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), |
392 | &drive->atapi_flags); | ||
401 | uptodate = 0; | 393 | uptodate = 0; |
402 | err = IDE_DRV_ERROR_GENERAL; | 394 | err = IDE_DRV_ERROR_GENERAL; |
403 | } else { | 395 | } else { |
@@ -406,7 +398,8 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) | |||
406 | 398 | ||
407 | tape->partition = readpos[1]; | 399 | tape->partition = readpos[1]; |
408 | tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]); | 400 | tape->first_frame = be32_to_cpup((__be32 *)&readpos[4]); |
409 | set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); | 401 | set_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), |
402 | &drive->atapi_flags); | ||
410 | } | 403 | } |
411 | } | 404 | } |
412 | 405 | ||
@@ -656,15 +649,15 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
656 | 649 | ||
657 | if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 && | 650 | if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 && |
658 | (rq->cmd[13] & REQ_IDETAPE_PC2) == 0) | 651 | (rq->cmd[13] & REQ_IDETAPE_PC2) == 0) |
659 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); | 652 | drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; |
660 | 653 | ||
661 | if (drive->dev_flags & IDE_DFLAG_POST_RESET) { | 654 | if (drive->dev_flags & IDE_DFLAG_POST_RESET) { |
662 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); | 655 | drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; |
663 | drive->dev_flags &= ~IDE_DFLAG_POST_RESET; | 656 | drive->dev_flags &= ~IDE_DFLAG_POST_RESET; |
664 | } | 657 | } |
665 | 658 | ||
666 | if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) && | 659 | if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) && |
667 | (stat & ATA_DSC) == 0) { | 660 | !(stat & ATA_DSC)) { |
668 | if (postponed_rq == NULL) { | 661 | if (postponed_rq == NULL) { |
669 | tape->dsc_polling_start = jiffies; | 662 | tape->dsc_polling_start = jiffies; |
670 | tape->dsc_poll_freq = tape->best_dsc_rw_freq; | 663 | tape->dsc_poll_freq = tape->best_dsc_rw_freq; |
@@ -684,7 +677,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
684 | tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW; | 677 | tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW; |
685 | idetape_postpone_request(drive); | 678 | idetape_postpone_request(drive); |
686 | return ide_stopped; | 679 | return ide_stopped; |
687 | } | 680 | } else |
681 | drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC; | ||
682 | |||
688 | if (rq->cmd[13] & REQ_IDETAPE_READ) { | 683 | if (rq->cmd[13] & REQ_IDETAPE_READ) { |
689 | pc = &tape->queued_pc; | 684 | pc = &tape->queued_pc; |
690 | ide_tape_create_rw_cmd(tape, pc, rq, READ_6); | 685 | ide_tape_create_rw_cmd(tape, pc, rq, READ_6); |
@@ -744,7 +739,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout) | |||
744 | int load_attempted = 0; | 739 | int load_attempted = 0; |
745 | 740 | ||
746 | /* Wait for the tape to become ready */ | 741 | /* Wait for the tape to become ready */ |
747 | set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); | 742 | set_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), &drive->atapi_flags); |
748 | timeout += jiffies; | 743 | timeout += jiffies; |
749 | while (time_before(jiffies, timeout)) { | 744 | while (time_before(jiffies, timeout)) { |
750 | if (ide_do_test_unit_ready(drive, disk) == 0) | 745 | if (ide_do_test_unit_ready(drive, disk) == 0) |
@@ -820,7 +815,7 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) | |||
820 | if (tape->chrdev_dir != IDETAPE_DIR_READ) | 815 | if (tape->chrdev_dir != IDETAPE_DIR_READ) |
821 | return; | 816 | return; |
822 | 817 | ||
823 | clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); | 818 | clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags); |
824 | tape->valid = 0; | 819 | tape->valid = 0; |
825 | if (tape->buf != NULL) { | 820 | if (tape->buf != NULL) { |
826 | kfree(tape->buf); | 821 | kfree(tape->buf); |
@@ -1113,7 +1108,8 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, | |||
1113 | 1108 | ||
1114 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { | 1109 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { |
1115 | tape->valid = 0; | 1110 | tape->valid = 0; |
1116 | if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1111 | if (test_and_clear_bit(ilog2(IDE_AFLAG_FILEMARK), |
1112 | &drive->atapi_flags)) | ||
1117 | ++count; | 1113 | ++count; |
1118 | ide_tape_discard_merge_buffer(drive, 0); | 1114 | ide_tape_discard_merge_buffer(drive, 0); |
1119 | } | 1115 | } |
@@ -1168,7 +1164,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1168 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); | 1164 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); |
1169 | 1165 | ||
1170 | if (tape->chrdev_dir != IDETAPE_DIR_READ) { | 1166 | if (tape->chrdev_dir != IDETAPE_DIR_READ) { |
1171 | if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags)) | 1167 | if (test_bit(ilog2(IDE_AFLAG_DETECT_BS), &drive->atapi_flags)) |
1172 | if (count > tape->blk_size && | 1168 | if (count > tape->blk_size && |
1173 | (count % tape->blk_size) == 0) | 1169 | (count % tape->blk_size) == 0) |
1174 | tape->user_bs_factor = count / tape->blk_size; | 1170 | tape->user_bs_factor = count / tape->blk_size; |
@@ -1184,7 +1180,8 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1184 | /* refill if staging buffer is empty */ | 1180 | /* refill if staging buffer is empty */ |
1185 | if (!tape->valid) { | 1181 | if (!tape->valid) { |
1186 | /* If we are at a filemark, nothing more to read */ | 1182 | /* If we are at a filemark, nothing more to read */ |
1187 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1183 | if (test_bit(ilog2(IDE_AFLAG_FILEMARK), |
1184 | &drive->atapi_flags)) | ||
1188 | break; | 1185 | break; |
1189 | /* read */ | 1186 | /* read */ |
1190 | if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, | 1187 | if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, |
@@ -1202,7 +1199,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1202 | done += todo; | 1199 | done += todo; |
1203 | } | 1200 | } |
1204 | 1201 | ||
1205 | if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { | 1202 | if (!done && test_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags)) { |
1206 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); | 1203 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); |
1207 | 1204 | ||
1208 | idetape_space_over_filemarks(drive, MTFSF, 1); | 1205 | idetape_space_over_filemarks(drive, MTFSF, 1); |
@@ -1336,7 +1333,8 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) | |||
1336 | ide_tape_discard_merge_buffer(drive, 0); | 1333 | ide_tape_discard_merge_buffer(drive, 0); |
1337 | retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK); | 1334 | retval = ide_do_start_stop(drive, disk, !IDETAPE_LU_LOAD_MASK); |
1338 | if (!retval) | 1335 | if (!retval) |
1339 | clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags); | 1336 | clear_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), |
1337 | &drive->atapi_flags); | ||
1340 | return retval; | 1338 | return retval; |
1341 | case MTNOP: | 1339 | case MTNOP: |
1342 | ide_tape_discard_merge_buffer(drive, 0); | 1340 | ide_tape_discard_merge_buffer(drive, 0); |
@@ -1358,9 +1356,11 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) | |||
1358 | mt_count % tape->blk_size) | 1356 | mt_count % tape->blk_size) |
1359 | return -EIO; | 1357 | return -EIO; |
1360 | tape->user_bs_factor = mt_count / tape->blk_size; | 1358 | tape->user_bs_factor = mt_count / tape->blk_size; |
1361 | clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags); | 1359 | clear_bit(ilog2(IDE_AFLAG_DETECT_BS), |
1360 | &drive->atapi_flags); | ||
1362 | } else | 1361 | } else |
1363 | set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags); | 1362 | set_bit(ilog2(IDE_AFLAG_DETECT_BS), |
1363 | &drive->atapi_flags); | ||
1364 | return 0; | 1364 | return 0; |
1365 | case MTSEEK: | 1365 | case MTSEEK: |
1366 | ide_tape_discard_merge_buffer(drive, 0); | 1366 | ide_tape_discard_merge_buffer(drive, 0); |
@@ -1486,7 +1486,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) | |||
1486 | return -ENXIO; | 1486 | return -ENXIO; |
1487 | 1487 | ||
1488 | lock_kernel(); | 1488 | lock_kernel(); |
1489 | tape = ide_tape_chrdev_get(i); | 1489 | tape = ide_tape_get(NULL, true, i); |
1490 | if (!tape) { | 1490 | if (!tape) { |
1491 | unlock_kernel(); | 1491 | unlock_kernel(); |
1492 | return -ENXIO; | 1492 | return -ENXIO; |
@@ -1505,20 +1505,20 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) | |||
1505 | 1505 | ||
1506 | filp->private_data = tape; | 1506 | filp->private_data = tape; |
1507 | 1507 | ||
1508 | if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) { | 1508 | if (test_and_set_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags)) { |
1509 | retval = -EBUSY; | 1509 | retval = -EBUSY; |
1510 | goto out_put_tape; | 1510 | goto out_put_tape; |
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | retval = idetape_wait_ready(drive, 60 * HZ); | 1513 | retval = idetape_wait_ready(drive, 60 * HZ); |
1514 | if (retval) { | 1514 | if (retval) { |
1515 | clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); | 1515 | clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); |
1516 | printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); | 1516 | printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); |
1517 | goto out_put_tape; | 1517 | goto out_put_tape; |
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | idetape_read_position(drive); | 1520 | idetape_read_position(drive); |
1521 | if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags)) | 1521 | if (!test_bit(ilog2(IDE_AFLAG_ADDRESS_VALID), &drive->atapi_flags)) |
1522 | (void)idetape_rewind_tape(drive); | 1522 | (void)idetape_rewind_tape(drive); |
1523 | 1523 | ||
1524 | /* Read block size and write protect status from drive. */ | 1524 | /* Read block size and write protect status from drive. */ |
@@ -1534,7 +1534,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp) | |||
1534 | if (tape->write_prot) { | 1534 | if (tape->write_prot) { |
1535 | if ((filp->f_flags & O_ACCMODE) == O_WRONLY || | 1535 | if ((filp->f_flags & O_ACCMODE) == O_WRONLY || |
1536 | (filp->f_flags & O_ACCMODE) == O_RDWR) { | 1536 | (filp->f_flags & O_ACCMODE) == O_RDWR) { |
1537 | clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); | 1537 | clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); |
1538 | retval = -EROFS; | 1538 | retval = -EROFS; |
1539 | goto out_put_tape; | 1539 | goto out_put_tape; |
1540 | } | 1540 | } |
@@ -1591,15 +1591,17 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp) | |||
1591 | ide_tape_discard_merge_buffer(drive, 1); | 1591 | ide_tape_discard_merge_buffer(drive, 1); |
1592 | } | 1592 | } |
1593 | 1593 | ||
1594 | if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags)) | 1594 | if (minor < 128 && test_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), |
1595 | &drive->atapi_flags)) | ||
1595 | (void) idetape_rewind_tape(drive); | 1596 | (void) idetape_rewind_tape(drive); |
1597 | |||
1596 | if (tape->chrdev_dir == IDETAPE_DIR_NONE) { | 1598 | if (tape->chrdev_dir == IDETAPE_DIR_NONE) { |
1597 | if (tape->door_locked == DOOR_LOCKED) { | 1599 | if (tape->door_locked == DOOR_LOCKED) { |
1598 | if (!ide_set_media_lock(drive, tape->disk, 0)) | 1600 | if (!ide_set_media_lock(drive, tape->disk, 0)) |
1599 | tape->door_locked = DOOR_UNLOCKED; | 1601 | tape->door_locked = DOOR_UNLOCKED; |
1600 | } | 1602 | } |
1601 | } | 1603 | } |
1602 | clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags); | 1604 | clear_bit(ilog2(IDE_AFLAG_BUSY), &drive->atapi_flags); |
1603 | ide_tape_put(tape); | 1605 | ide_tape_put(tape); |
1604 | unlock_kernel(); | 1606 | unlock_kernel(); |
1605 | return 0; | 1607 | return 0; |
@@ -1905,7 +1907,7 @@ static const struct file_operations idetape_fops = { | |||
1905 | 1907 | ||
1906 | static int idetape_open(struct block_device *bdev, fmode_t mode) | 1908 | static int idetape_open(struct block_device *bdev, fmode_t mode) |
1907 | { | 1909 | { |
1908 | struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk); | 1910 | struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk, false, 0); |
1909 | 1911 | ||
1910 | if (!tape) | 1912 | if (!tape) |
1911 | return -ENXIO; | 1913 | return -ENXIO; |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index a0c3e1b2f73c..75b85a8cd2d4 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -98,7 +98,6 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) | |||
98 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { | 98 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { |
99 | ide_tf_dump(drive->name, cmd); | 99 | ide_tf_dump(drive->name, cmd); |
100 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | 100 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
101 | SELECT_MASK(drive, 0); | ||
102 | 101 | ||
103 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | 102 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { |
104 | u8 data[2] = { cmd->tf.data, cmd->hob.data }; | 103 | u8 data[2] = { cmd->tf.data, cmd->hob.data }; |
@@ -166,7 +165,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) | |||
166 | if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { | 165 | if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { |
167 | if (custom && tf->command == ATA_CMD_SET_MULTI) { | 166 | if (custom && tf->command == ATA_CMD_SET_MULTI) { |
168 | drive->mult_req = drive->mult_count = 0; | 167 | drive->mult_req = drive->mult_count = 0; |
169 | drive->special.b.recalibrate = 1; | 168 | drive->special_flags |= IDE_SFLAG_RECALIBRATE; |
170 | (void)ide_dump_status(drive, __func__, stat); | 169 | (void)ide_dump_status(drive, __func__, stat); |
171 | return ide_stopped; | 170 | return ide_stopped; |
172 | } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { | 171 | } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) { |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 92c9b90931e7..16d056939f9f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -211,6 +211,11 @@ static unsigned int ide_noflush; | |||
211 | module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); | 211 | module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); |
212 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); | 212 | MODULE_PARM_DESC(noflush, "disable flush requests for a device"); |
213 | 213 | ||
214 | static unsigned int ide_nohpa; | ||
215 | |||
216 | module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0); | ||
217 | MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device"); | ||
218 | |||
214 | static unsigned int ide_noprobe; | 219 | static unsigned int ide_noprobe; |
215 | 220 | ||
216 | module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); | 221 | module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); |
@@ -281,6 +286,11 @@ static void ide_dev_apply_params(ide_drive_t *drive, u8 unit) | |||
281 | drive->name); | 286 | drive->name); |
282 | drive->dev_flags |= IDE_DFLAG_NOFLUSH; | 287 | drive->dev_flags |= IDE_DFLAG_NOFLUSH; |
283 | } | 288 | } |
289 | if (ide_nohpa & (1 << i)) { | ||
290 | printk(KERN_INFO "ide: disabling Host Protected Area for %s\n", | ||
291 | drive->name); | ||
292 | drive->dev_flags |= IDE_DFLAG_NOHPA; | ||
293 | } | ||
284 | if (ide_noprobe & (1 << i)) { | 294 | if (ide_noprobe & (1 << i)) { |
285 | printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); | 295 | printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); |
286 | drive->dev_flags |= IDE_DFLAG_NOPROBE; | 296 | drive->dev_flags |= IDE_DFLAG_NOPROBE; |
diff --git a/drivers/ide/ide_platform.c b/drivers/ide/ide_platform.c index 051b4ab0f359..ee9b55ecc62b 100644 --- a/drivers/ide/ide_platform.c +++ b/drivers/ide/ide_platform.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | static void __devinit plat_ide_setup_ports(hw_regs_t *hw, | 24 | static void __devinit plat_ide_setup_ports(struct ide_hw *hw, |
25 | void __iomem *base, | 25 | void __iomem *base, |
26 | void __iomem *ctrl, | 26 | void __iomem *ctrl, |
27 | struct pata_platform_info *pdata, | 27 | struct pata_platform_info *pdata, |
@@ -40,12 +40,11 @@ static void __devinit plat_ide_setup_ports(hw_regs_t *hw, | |||
40 | hw->io_ports.ctl_addr = (unsigned long)ctrl; | 40 | hw->io_ports.ctl_addr = (unsigned long)ctrl; |
41 | 41 | ||
42 | hw->irq = irq; | 42 | hw->irq = irq; |
43 | |||
44 | hw->chipset = ide_generic; | ||
45 | } | 43 | } |
46 | 44 | ||
47 | static const struct ide_port_info platform_ide_port_info = { | 45 | static const struct ide_port_info platform_ide_port_info = { |
48 | .host_flags = IDE_HFLAG_NO_DMA, | 46 | .host_flags = IDE_HFLAG_NO_DMA, |
47 | .chipset = ide_generic, | ||
49 | }; | 48 | }; |
50 | 49 | ||
51 | static int __devinit plat_ide_probe(struct platform_device *pdev) | 50 | static int __devinit plat_ide_probe(struct platform_device *pdev) |
@@ -55,7 +54,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) | |||
55 | struct pata_platform_info *pdata; | 54 | struct pata_platform_info *pdata; |
56 | struct ide_host *host; | 55 | struct ide_host *host; |
57 | int ret = 0, mmio = 0; | 56 | int ret = 0, mmio = 0; |
58 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 57 | struct ide_hw hw, *hws[] = { &hw }; |
59 | struct ide_port_info d = platform_ide_port_info; | 58 | struct ide_port_info d = platform_ide_port_info; |
60 | 59 | ||
61 | pdata = pdev->dev.platform_data; | 60 | pdata = pdev->dev.platform_data; |
@@ -99,7 +98,7 @@ static int __devinit plat_ide_probe(struct platform_device *pdev) | |||
99 | if (mmio) | 98 | if (mmio) |
100 | d.host_flags |= IDE_HFLAG_MMIO; | 99 | d.host_flags |= IDE_HFLAG_MMIO; |
101 | 100 | ||
102 | ret = ide_host_add(&d, hws, &host); | 101 | ret = ide_host_add(&d, hws, 1, &host); |
103 | if (ret) | 102 | if (ret) |
104 | goto out; | 103 | goto out; |
105 | 104 | ||
diff --git a/drivers/ide/macide.c b/drivers/ide/macide.c index 4b1718e83283..1447c8c90565 100644 --- a/drivers/ide/macide.c +++ b/drivers/ide/macide.c | |||
@@ -62,7 +62,7 @@ int macide_ack_intr(ide_hwif_t* hwif) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, | 65 | static void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, |
66 | int irq, ide_ack_intr_t *ack_intr) | 66 | int irq, ide_ack_intr_t *ack_intr) |
67 | { | 67 | { |
68 | int i; | 68 | int i; |
@@ -76,13 +76,12 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, | |||
76 | 76 | ||
77 | hw->irq = irq; | 77 | hw->irq = irq; |
78 | hw->ack_intr = ack_intr; | 78 | hw->ack_intr = ack_intr; |
79 | |||
80 | hw->chipset = ide_generic; | ||
81 | } | 79 | } |
82 | 80 | ||
83 | static const struct ide_port_info macide_port_info = { | 81 | static const struct ide_port_info macide_port_info = { |
84 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | 82 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, |
85 | .irq_flags = IRQF_SHARED, | 83 | .irq_flags = IRQF_SHARED, |
84 | .chipset = ide_generic, | ||
86 | }; | 85 | }; |
87 | 86 | ||
88 | static const char *mac_ide_name[] = | 87 | static const char *mac_ide_name[] = |
@@ -97,7 +96,7 @@ static int __init macide_init(void) | |||
97 | ide_ack_intr_t *ack_intr; | 96 | ide_ack_intr_t *ack_intr; |
98 | unsigned long base; | 97 | unsigned long base; |
99 | int irq; | 98 | int irq; |
100 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 99 | struct ide_hw hw, *hws[] = { &hw }; |
101 | 100 | ||
102 | if (!MACH_IS_MAC) | 101 | if (!MACH_IS_MAC) |
103 | return -ENODEV; | 102 | return -ENODEV; |
@@ -127,7 +126,7 @@ static int __init macide_init(void) | |||
127 | 126 | ||
128 | macide_setup_ports(&hw, base, irq, ack_intr); | 127 | macide_setup_ports(&hw, base, irq, ack_intr); |
129 | 128 | ||
130 | return ide_host_add(&macide_port_info, hws, NULL); | 129 | return ide_host_add(&macide_port_info, hws, 1, NULL); |
131 | } | 130 | } |
132 | 131 | ||
133 | module_init(macide_init); | 132 | module_init(macide_init); |
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c index 09d813d313f4..3c1dc0152153 100644 --- a/drivers/ide/palm_bk3710.c +++ b/drivers/ide/palm_bk3710.c | |||
@@ -306,6 +306,7 @@ static struct ide_port_info __devinitdata palm_bk3710_port_info = { | |||
306 | .host_flags = IDE_HFLAG_MMIO, | 306 | .host_flags = IDE_HFLAG_MMIO, |
307 | .pio_mask = ATA_PIO4, | 307 | .pio_mask = ATA_PIO4, |
308 | .mwdma_mask = ATA_MWDMA2, | 308 | .mwdma_mask = ATA_MWDMA2, |
309 | .chipset = ide_palm3710, | ||
309 | }; | 310 | }; |
310 | 311 | ||
311 | static int __init palm_bk3710_probe(struct platform_device *pdev) | 312 | static int __init palm_bk3710_probe(struct platform_device *pdev) |
@@ -315,7 +316,7 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) | |||
315 | void __iomem *base; | 316 | void __iomem *base; |
316 | unsigned long rate, mem_size; | 317 | unsigned long rate, mem_size; |
317 | int i, rc; | 318 | int i, rc; |
318 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 319 | struct ide_hw hw, *hws[] = { &hw }; |
319 | 320 | ||
320 | clk = clk_get(&pdev->dev, "IDECLK"); | 321 | clk = clk_get(&pdev->dev, "IDECLK"); |
321 | if (IS_ERR(clk)) | 322 | if (IS_ERR(clk)) |
@@ -363,13 +364,12 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) | |||
363 | (base + IDE_PALM_ATA_PRI_CTL_OFFSET); | 364 | (base + IDE_PALM_ATA_PRI_CTL_OFFSET); |
364 | hw.irq = irq->start; | 365 | hw.irq = irq->start; |
365 | hw.dev = &pdev->dev; | 366 | hw.dev = &pdev->dev; |
366 | hw.chipset = ide_palm3710; | ||
367 | 367 | ||
368 | palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : | 368 | palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : |
369 | ATA_UDMA5; | 369 | ATA_UDMA5; |
370 | 370 | ||
371 | /* Register the IDE interface with Linux */ | 371 | /* Register the IDE interface with Linux */ |
372 | rc = ide_host_add(&palm_bk3710_port_info, hws, NULL); | 372 | rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL); |
373 | if (rc) | 373 | if (rc) |
374 | goto out; | 374 | goto out; |
375 | 375 | ||
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index b68906c3c17e..65ba8239e7b5 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c | |||
@@ -40,18 +40,6 @@ | |||
40 | #define DBG(fmt, args...) | 40 | #define DBG(fmt, args...) |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | static const char *pdc_quirk_drives[] = { | ||
44 | "QUANTUM FIREBALLlct08 08", | ||
45 | "QUANTUM FIREBALLP KA6.4", | ||
46 | "QUANTUM FIREBALLP KA9.1", | ||
47 | "QUANTUM FIREBALLP LM20.4", | ||
48 | "QUANTUM FIREBALLP KX13.6", | ||
49 | "QUANTUM FIREBALLP KX20.5", | ||
50 | "QUANTUM FIREBALLP KX27.3", | ||
51 | "QUANTUM FIREBALLP LM20.5", | ||
52 | NULL | ||
53 | }; | ||
54 | |||
55 | static u8 max_dma_rate(struct pci_dev *pdev) | 43 | static u8 max_dma_rate(struct pci_dev *pdev) |
56 | { | 44 | { |
57 | u8 mode; | 45 | u8 mode; |
@@ -200,19 +188,6 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) | |||
200 | return ATA_CBL_PATA80; | 188 | return ATA_CBL_PATA80; |
201 | } | 189 | } |
202 | 190 | ||
203 | static void pdcnew_quirkproc(ide_drive_t *drive) | ||
204 | { | ||
205 | const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; | ||
206 | |||
207 | for (list = pdc_quirk_drives; *list != NULL; list++) | ||
208 | if (strstr(m, *list) != NULL) { | ||
209 | drive->quirk_list = 2; | ||
210 | return; | ||
211 | } | ||
212 | |||
213 | drive->quirk_list = 0; | ||
214 | } | ||
215 | |||
216 | static void pdcnew_reset(ide_drive_t *drive) | 191 | static void pdcnew_reset(ide_drive_t *drive) |
217 | { | 192 | { |
218 | /* | 193 | /* |
@@ -473,7 +448,6 @@ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) | |||
473 | static const struct ide_port_ops pdcnew_port_ops = { | 448 | static const struct ide_port_ops pdcnew_port_ops = { |
474 | .set_pio_mode = pdcnew_set_pio_mode, | 449 | .set_pio_mode = pdcnew_set_pio_mode, |
475 | .set_dma_mode = pdcnew_set_dma_mode, | 450 | .set_dma_mode = pdcnew_set_dma_mode, |
476 | .quirkproc = pdcnew_quirkproc, | ||
477 | .resetproc = pdcnew_reset, | 451 | .resetproc = pdcnew_reset, |
478 | .cable_detect = pdcnew_cable_detect, | 452 | .cable_detect = pdcnew_cable_detect, |
479 | }; | 453 | }; |
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index e24ecc87a9b1..b6abf7e52cac 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c | |||
@@ -23,18 +23,6 @@ | |||
23 | 23 | ||
24 | #define PDC202XX_DEBUG_DRIVE_INFO 0 | 24 | #define PDC202XX_DEBUG_DRIVE_INFO 0 |
25 | 25 | ||
26 | static const char *pdc_quirk_drives[] = { | ||
27 | "QUANTUM FIREBALLlct08 08", | ||
28 | "QUANTUM FIREBALLP KA6.4", | ||
29 | "QUANTUM FIREBALLP KA9.1", | ||
30 | "QUANTUM FIREBALLP LM20.4", | ||
31 | "QUANTUM FIREBALLP KX13.6", | ||
32 | "QUANTUM FIREBALLP KX20.5", | ||
33 | "QUANTUM FIREBALLP KX27.3", | ||
34 | "QUANTUM FIREBALLP LM20.5", | ||
35 | NULL | ||
36 | }; | ||
37 | |||
38 | static void pdc_old_disable_66MHz_clock(ide_hwif_t *); | 26 | static void pdc_old_disable_66MHz_clock(ide_hwif_t *); |
39 | 27 | ||
40 | static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) | 28 | static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed) |
@@ -151,19 +139,6 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) | |||
151 | outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); | 139 | outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); |
152 | } | 140 | } |
153 | 141 | ||
154 | static void pdc202xx_quirkproc(ide_drive_t *drive) | ||
155 | { | ||
156 | const char **list, *m = (char *)&drive->id[ATA_ID_PROD]; | ||
157 | |||
158 | for (list = pdc_quirk_drives; *list != NULL; list++) | ||
159 | if (strstr(m, *list) != NULL) { | ||
160 | drive->quirk_list = 2; | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | drive->quirk_list = 0; | ||
165 | } | ||
166 | |||
167 | static void pdc202xx_dma_start(ide_drive_t *drive) | 142 | static void pdc202xx_dma_start(ide_drive_t *drive) |
168 | { | 143 | { |
169 | if (drive->current_speed > XFER_UDMA_2) | 144 | if (drive->current_speed > XFER_UDMA_2) |
@@ -203,52 +178,6 @@ static int pdc202xx_dma_end(ide_drive_t *drive) | |||
203 | return ide_dma_end(drive); | 178 | return ide_dma_end(drive); |
204 | } | 179 | } |
205 | 180 | ||
206 | static int pdc202xx_dma_test_irq(ide_drive_t *drive) | ||
207 | { | ||
208 | ide_hwif_t *hwif = drive->hwif; | ||
209 | unsigned long high_16 = hwif->extra_base - 16; | ||
210 | u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); | ||
211 | u8 sc1d = inb(high_16 + 0x001d); | ||
212 | |||
213 | if (hwif->channel) { | ||
214 | /* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */ | ||
215 | if ((sc1d & 0x50) == 0x50) | ||
216 | goto somebody_else; | ||
217 | else if ((sc1d & 0x40) == 0x40) | ||
218 | return (dma_stat & 4) == 4; | ||
219 | } else { | ||
220 | /* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */ | ||
221 | if ((sc1d & 0x05) == 0x05) | ||
222 | goto somebody_else; | ||
223 | else if ((sc1d & 0x04) == 0x04) | ||
224 | return (dma_stat & 4) == 4; | ||
225 | } | ||
226 | somebody_else: | ||
227 | return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ | ||
228 | } | ||
229 | |||
230 | static void pdc202xx_reset(ide_drive_t *drive) | ||
231 | { | ||
232 | ide_hwif_t *hwif = drive->hwif; | ||
233 | unsigned long high_16 = hwif->extra_base - 16; | ||
234 | u8 udma_speed_flag = inb(high_16 | 0x001f); | ||
235 | |||
236 | printk(KERN_WARNING "PDC202xx: software reset...\n"); | ||
237 | |||
238 | outb(udma_speed_flag | 0x10, high_16 | 0x001f); | ||
239 | mdelay(100); | ||
240 | outb(udma_speed_flag & ~0x10, high_16 | 0x001f); | ||
241 | mdelay(2000); /* 2 seconds ?! */ | ||
242 | |||
243 | ide_set_max_pio(drive); | ||
244 | } | ||
245 | |||
246 | static void pdc202xx_dma_lost_irq(ide_drive_t *drive) | ||
247 | { | ||
248 | pdc202xx_reset(drive); | ||
249 | ide_dma_lost_irq(drive); | ||
250 | } | ||
251 | |||
252 | static int init_chipset_pdc202xx(struct pci_dev *dev) | 181 | static int init_chipset_pdc202xx(struct pci_dev *dev) |
253 | { | 182 | { |
254 | unsigned long dmabase = pci_resource_start(dev, 4); | 183 | unsigned long dmabase = pci_resource_start(dev, 4); |
@@ -302,37 +231,22 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, | |||
302 | static const struct ide_port_ops pdc20246_port_ops = { | 231 | static const struct ide_port_ops pdc20246_port_ops = { |
303 | .set_pio_mode = pdc202xx_set_pio_mode, | 232 | .set_pio_mode = pdc202xx_set_pio_mode, |
304 | .set_dma_mode = pdc202xx_set_mode, | 233 | .set_dma_mode = pdc202xx_set_mode, |
305 | .quirkproc = pdc202xx_quirkproc, | ||
306 | }; | 234 | }; |
307 | 235 | ||
308 | static const struct ide_port_ops pdc2026x_port_ops = { | 236 | static const struct ide_port_ops pdc2026x_port_ops = { |
309 | .set_pio_mode = pdc202xx_set_pio_mode, | 237 | .set_pio_mode = pdc202xx_set_pio_mode, |
310 | .set_dma_mode = pdc202xx_set_mode, | 238 | .set_dma_mode = pdc202xx_set_mode, |
311 | .quirkproc = pdc202xx_quirkproc, | ||
312 | .resetproc = pdc202xx_reset, | ||
313 | .cable_detect = pdc2026x_cable_detect, | 239 | .cable_detect = pdc2026x_cable_detect, |
314 | }; | 240 | }; |
315 | 241 | ||
316 | static const struct ide_dma_ops pdc20246_dma_ops = { | ||
317 | .dma_host_set = ide_dma_host_set, | ||
318 | .dma_setup = ide_dma_setup, | ||
319 | .dma_start = ide_dma_start, | ||
320 | .dma_end = ide_dma_end, | ||
321 | .dma_test_irq = pdc202xx_dma_test_irq, | ||
322 | .dma_lost_irq = ide_dma_lost_irq, | ||
323 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | ||
324 | .dma_sff_read_status = ide_dma_sff_read_status, | ||
325 | }; | ||
326 | |||
327 | static const struct ide_dma_ops pdc2026x_dma_ops = { | 242 | static const struct ide_dma_ops pdc2026x_dma_ops = { |
328 | .dma_host_set = ide_dma_host_set, | 243 | .dma_host_set = ide_dma_host_set, |
329 | .dma_setup = ide_dma_setup, | 244 | .dma_setup = ide_dma_setup, |
330 | .dma_start = pdc202xx_dma_start, | 245 | .dma_start = pdc202xx_dma_start, |
331 | .dma_end = pdc202xx_dma_end, | 246 | .dma_end = pdc202xx_dma_end, |
332 | .dma_test_irq = pdc202xx_dma_test_irq, | 247 | .dma_test_irq = ide_dma_test_irq, |
333 | .dma_lost_irq = pdc202xx_dma_lost_irq, | 248 | .dma_lost_irq = ide_dma_lost_irq, |
334 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 249 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
335 | .dma_clear = pdc202xx_reset, | ||
336 | .dma_sff_read_status = ide_dma_sff_read_status, | 250 | .dma_sff_read_status = ide_dma_sff_read_status, |
337 | }; | 251 | }; |
338 | 252 | ||
@@ -354,7 +268,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { | |||
354 | .name = DRV_NAME, | 268 | .name = DRV_NAME, |
355 | .init_chipset = init_chipset_pdc202xx, | 269 | .init_chipset = init_chipset_pdc202xx, |
356 | .port_ops = &pdc20246_port_ops, | 270 | .port_ops = &pdc20246_port_ops, |
357 | .dma_ops = &pdc20246_dma_ops, | 271 | .dma_ops = &sff_dma_ops, |
358 | .host_flags = IDE_HFLAGS_PDC202XX, | 272 | .host_flags = IDE_HFLAGS_PDC202XX, |
359 | .pio_mask = ATA_PIO4, | 273 | .pio_mask = ATA_PIO4, |
360 | .mwdma_mask = ATA_MWDMA2, | 274 | .mwdma_mask = ATA_MWDMA2, |
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index f76e4e6b408f..97642a7a79c4 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c | |||
@@ -1023,13 +1023,14 @@ static const struct ide_port_info pmac_port_info = { | |||
1023 | * Setup, register & probe an IDE channel driven by this driver, this is | 1023 | * Setup, register & probe an IDE channel driven by this driver, this is |
1024 | * called by one of the 2 probe functions (macio or PCI). | 1024 | * called by one of the 2 probe functions (macio or PCI). |
1025 | */ | 1025 | */ |
1026 | static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) | 1026 | static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, |
1027 | struct ide_hw *hw) | ||
1027 | { | 1028 | { |
1028 | struct device_node *np = pmif->node; | 1029 | struct device_node *np = pmif->node; |
1029 | const int *bidp; | 1030 | const int *bidp; |
1030 | struct ide_host *host; | 1031 | struct ide_host *host; |
1031 | ide_hwif_t *hwif; | 1032 | ide_hwif_t *hwif; |
1032 | hw_regs_t *hws[] = { hw, NULL, NULL, NULL }; | 1033 | struct ide_hw *hws[] = { hw }; |
1033 | struct ide_port_info d = pmac_port_info; | 1034 | struct ide_port_info d = pmac_port_info; |
1034 | int rc; | 1035 | int rc; |
1035 | 1036 | ||
@@ -1077,7 +1078,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) | |||
1077 | /* Make sure we have sane timings */ | 1078 | /* Make sure we have sane timings */ |
1078 | sanitize_timings(pmif); | 1079 | sanitize_timings(pmif); |
1079 | 1080 | ||
1080 | host = ide_host_alloc(&d, hws); | 1081 | host = ide_host_alloc(&d, hws, 1); |
1081 | if (host == NULL) | 1082 | if (host == NULL) |
1082 | return -ENOMEM; | 1083 | return -ENOMEM; |
1083 | hwif = host->ports[0]; | 1084 | hwif = host->ports[0]; |
@@ -1124,7 +1125,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) | |||
1124 | return 0; | 1125 | return 0; |
1125 | } | 1126 | } |
1126 | 1127 | ||
1127 | static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base) | 1128 | static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) |
1128 | { | 1129 | { |
1129 | int i; | 1130 | int i; |
1130 | 1131 | ||
@@ -1144,7 +1145,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) | |||
1144 | unsigned long regbase; | 1145 | unsigned long regbase; |
1145 | pmac_ide_hwif_t *pmif; | 1146 | pmac_ide_hwif_t *pmif; |
1146 | int irq, rc; | 1147 | int irq, rc; |
1147 | hw_regs_t hw; | 1148 | struct ide_hw hw; |
1148 | 1149 | ||
1149 | pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); | 1150 | pmif = kzalloc(sizeof(*pmif), GFP_KERNEL); |
1150 | if (pmif == NULL) | 1151 | if (pmif == NULL) |
@@ -1268,7 +1269,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1268 | void __iomem *base; | 1269 | void __iomem *base; |
1269 | unsigned long rbase, rlen; | 1270 | unsigned long rbase, rlen; |
1270 | int rc; | 1271 | int rc; |
1271 | hw_regs_t hw; | 1272 | struct ide_hw hw; |
1272 | 1273 | ||
1273 | np = pci_device_to_OF_node(pdev); | 1274 | np = pci_device_to_OF_node(pdev); |
1274 | if (np == NULL) { | 1275 | if (np == NULL) { |
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c index c79346679244..ab49a97023d9 100644 --- a/drivers/ide/q40ide.c +++ b/drivers/ide/q40ide.c | |||
@@ -51,11 +51,11 @@ static int q40ide_default_irq(unsigned long base) | |||
51 | /* | 51 | /* |
52 | * Addresses are pretranslated for Q40 ISA access. | 52 | * Addresses are pretranslated for Q40 ISA access. |
53 | */ | 53 | */ |
54 | static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, | 54 | static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, |
55 | ide_ack_intr_t *ack_intr, | 55 | ide_ack_intr_t *ack_intr, |
56 | int irq) | 56 | int irq) |
57 | { | 57 | { |
58 | memset(hw, 0, sizeof(hw_regs_t)); | 58 | memset(hw, 0, sizeof(*hw)); |
59 | /* BIG FAT WARNING: | 59 | /* BIG FAT WARNING: |
60 | assumption: only DATA port is ever used in 16 bit mode */ | 60 | assumption: only DATA port is ever used in 16 bit mode */ |
61 | hw->io_ports.data_addr = Q40_ISA_IO_W(base); | 61 | hw->io_ports.data_addr = Q40_ISA_IO_W(base); |
@@ -70,8 +70,6 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, | |||
70 | 70 | ||
71 | hw->irq = irq; | 71 | hw->irq = irq; |
72 | hw->ack_intr = ack_intr; | 72 | hw->ack_intr = ack_intr; |
73 | |||
74 | hw->chipset = ide_generic; | ||
75 | } | 73 | } |
76 | 74 | ||
77 | static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, | 75 | static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, |
@@ -119,6 +117,7 @@ static const struct ide_port_info q40ide_port_info = { | |||
119 | .tp_ops = &q40ide_tp_ops, | 117 | .tp_ops = &q40ide_tp_ops, |
120 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | 118 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, |
121 | .irq_flags = IRQF_SHARED, | 119 | .irq_flags = IRQF_SHARED, |
120 | .chipset = ide_generic, | ||
122 | }; | 121 | }; |
123 | 122 | ||
124 | /* | 123 | /* |
@@ -136,7 +135,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ | |||
136 | static int __init q40ide_init(void) | 135 | static int __init q40ide_init(void) |
137 | { | 136 | { |
138 | int i; | 137 | int i; |
139 | hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL }; | 138 | struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL }; |
140 | 139 | ||
141 | if (!MACH_IS_Q40) | 140 | if (!MACH_IS_Q40) |
142 | return -ENODEV; | 141 | return -ENODEV; |
@@ -163,7 +162,7 @@ static int __init q40ide_init(void) | |||
163 | hws[i] = &hw[i]; | 162 | hws[i] = &hw[i]; |
164 | } | 163 | } |
165 | 164 | ||
166 | return ide_host_add(&q40ide_port_info, hws, NULL); | 165 | return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL); |
167 | } | 166 | } |
168 | 167 | ||
169 | module_init(q40ide_init); | 168 | module_init(q40ide_init); |
diff --git a/drivers/ide/rapide.c b/drivers/ide/rapide.c index d5003ca69801..00f54248f41f 100644 --- a/drivers/ide/rapide.c +++ b/drivers/ide/rapide.c | |||
@@ -13,9 +13,10 @@ | |||
13 | 13 | ||
14 | static const struct ide_port_info rapide_port_info = { | 14 | static const struct ide_port_info rapide_port_info = { |
15 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | 15 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, |
16 | .chipset = ide_generic, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base, | 19 | static void rapide_setup_ports(struct ide_hw *hw, void __iomem *base, |
19 | void __iomem *ctrl, unsigned int sz, int irq) | 20 | void __iomem *ctrl, unsigned int sz, int irq) |
20 | { | 21 | { |
21 | unsigned long port = (unsigned long)base; | 22 | unsigned long port = (unsigned long)base; |
@@ -35,7 +36,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
35 | void __iomem *base; | 36 | void __iomem *base; |
36 | struct ide_host *host; | 37 | struct ide_host *host; |
37 | int ret; | 38 | int ret; |
38 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 39 | struct ide_hw hw, *hws[] = { &hw }; |
39 | 40 | ||
40 | ret = ecard_request_resources(ec); | 41 | ret = ecard_request_resources(ec); |
41 | if (ret) | 42 | if (ret) |
@@ -49,10 +50,9 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) | |||
49 | 50 | ||
50 | memset(&hw, 0, sizeof(hw)); | 51 | memset(&hw, 0, sizeof(hw)); |
51 | rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); | 52 | rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq); |
52 | hw.chipset = ide_generic; | ||
53 | hw.dev = &ec->dev; | 53 | hw.dev = &ec->dev; |
54 | 54 | ||
55 | ret = ide_host_add(&rapide_port_info, hws, &host); | 55 | ret = ide_host_add(&rapide_port_info, hws, 1, &host); |
56 | if (ret) | 56 | if (ret) |
57 | goto release; | 57 | goto release; |
58 | 58 | ||
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index 5be41f25204f..1104bb301eb9 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c | |||
@@ -559,7 +559,7 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, | |||
559 | { | 559 | { |
560 | struct scc_ports *ports = pci_get_drvdata(dev); | 560 | struct scc_ports *ports = pci_get_drvdata(dev); |
561 | struct ide_host *host; | 561 | struct ide_host *host; |
562 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 562 | struct ide_hw hw, *hws[] = { &hw }; |
563 | int i, rc; | 563 | int i, rc; |
564 | 564 | ||
565 | memset(&hw, 0, sizeof(hw)); | 565 | memset(&hw, 0, sizeof(hw)); |
@@ -567,9 +567,8 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev, | |||
567 | hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; | 567 | hw.io_ports_array[i] = ports->dma + 0x20 + i * 4; |
568 | hw.irq = dev->irq; | 568 | hw.irq = dev->irq; |
569 | hw.dev = &dev->dev; | 569 | hw.dev = &dev->dev; |
570 | hw.chipset = ide_pci; | ||
571 | 570 | ||
572 | rc = ide_host_add(d, hws, &host); | 571 | rc = ide_host_add(d, hws, 1, &host); |
573 | if (rc) | 572 | if (rc) |
574 | return rc; | 573 | return rc; |
575 | 574 | ||
@@ -823,6 +822,7 @@ static const struct ide_port_info scc_chipset __devinitdata = { | |||
823 | .host_flags = IDE_HFLAG_SINGLE, | 822 | .host_flags = IDE_HFLAG_SINGLE, |
824 | .irq_flags = IRQF_SHARED, | 823 | .irq_flags = IRQF_SHARED, |
825 | .pio_mask = ATA_PIO4, | 824 | .pio_mask = ATA_PIO4, |
825 | .chipset = ide_pci, | ||
826 | }; | 826 | }; |
827 | 827 | ||
828 | /** | 828 | /** |
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 7a3a12d6e638..ab3db61d2ba0 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> | 2 | * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> |
3 | * Copyright (C) 1995-1998 Mark Lord | 3 | * Copyright (C) 1995-1998 Mark Lord |
4 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | 4 | * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz |
5 | * | 5 | * |
6 | * May be copied or modified under the terms of the GNU General Public License | 6 | * May be copied or modified under the terms of the GNU General Public License |
7 | */ | 7 | */ |
@@ -301,11 +301,11 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * | |||
301 | } | 301 | } |
302 | 302 | ||
303 | /** | 303 | /** |
304 | * ide_hw_configure - configure a hw_regs_t instance | 304 | * ide_hw_configure - configure a struct ide_hw instance |
305 | * @dev: PCI device holding interface | 305 | * @dev: PCI device holding interface |
306 | * @d: IDE port info | 306 | * @d: IDE port info |
307 | * @port: port number | 307 | * @port: port number |
308 | * @hw: hw_regs_t instance corresponding to this port | 308 | * @hw: struct ide_hw instance corresponding to this port |
309 | * | 309 | * |
310 | * Perform the initial set up for the hardware interface structure. This | 310 | * Perform the initial set up for the hardware interface structure. This |
311 | * is done per interface port rather than per PCI device. There may be | 311 | * 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 * | |||
315 | */ | 315 | */ |
316 | 316 | ||
317 | static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, | 317 | static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, |
318 | unsigned int port, hw_regs_t *hw) | 318 | unsigned int port, struct ide_hw *hw) |
319 | { | 319 | { |
320 | unsigned long ctl = 0, base = 0; | 320 | unsigned long ctl = 0, base = 0; |
321 | 321 | ||
@@ -344,7 +344,6 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, | |||
344 | 344 | ||
345 | memset(hw, 0, sizeof(*hw)); | 345 | memset(hw, 0, sizeof(*hw)); |
346 | hw->dev = &dev->dev; | 346 | hw->dev = &dev->dev; |
347 | hw->chipset = d->chipset ? d->chipset : ide_pci; | ||
348 | ide_std_init_ports(hw, base, ctl | 2); | 347 | ide_std_init_ports(hw, base, ctl | 2); |
349 | 348 | ||
350 | return 0; | 349 | return 0; |
@@ -446,8 +445,8 @@ out: | |||
446 | * ide_pci_setup_ports - configure ports/devices on PCI IDE | 445 | * ide_pci_setup_ports - configure ports/devices on PCI IDE |
447 | * @dev: PCI device | 446 | * @dev: PCI device |
448 | * @d: IDE port info | 447 | * @d: IDE port info |
449 | * @hw: hw_regs_t instances corresponding to this PCI IDE device | 448 | * @hw: struct ide_hw instances corresponding to this PCI IDE device |
450 | * @hws: hw_regs_t pointers table to update | 449 | * @hws: struct ide_hw pointers table to update |
451 | * | 450 | * |
452 | * Scan the interfaces attached to this device and do any | 451 | * Scan the interfaces attached to this device and do any |
453 | * necessary per port setup. Attach the devices and ask the | 452 | * necessary per port setup. Attach the devices and ask the |
@@ -459,7 +458,7 @@ out: | |||
459 | */ | 458 | */ |
460 | 459 | ||
461 | void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, | 460 | void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, |
462 | hw_regs_t *hw, hw_regs_t **hws) | 461 | struct ide_hw *hw, struct ide_hw **hws) |
463 | { | 462 | { |
464 | int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; | 463 | int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; |
465 | u8 tmp; | 464 | u8 tmp; |
@@ -535,61 +534,15 @@ out: | |||
535 | return ret; | 534 | return ret; |
536 | } | 535 | } |
537 | 536 | ||
538 | int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, | ||
539 | void *priv) | ||
540 | { | ||
541 | struct ide_host *host; | ||
542 | hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; | ||
543 | int ret; | ||
544 | |||
545 | ret = ide_setup_pci_controller(dev, d, 1); | ||
546 | if (ret < 0) | ||
547 | goto out; | ||
548 | |||
549 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); | ||
550 | |||
551 | host = ide_host_alloc(d, hws); | ||
552 | if (host == NULL) { | ||
553 | ret = -ENOMEM; | ||
554 | goto out; | ||
555 | } | ||
556 | |||
557 | host->dev[0] = &dev->dev; | ||
558 | |||
559 | host->host_priv = priv; | ||
560 | |||
561 | host->irq_flags = IRQF_SHARED; | ||
562 | |||
563 | pci_set_drvdata(dev, host); | ||
564 | |||
565 | ret = do_ide_setup_pci_device(dev, d, 1); | ||
566 | if (ret < 0) | ||
567 | goto out; | ||
568 | |||
569 | /* fixup IRQ */ | ||
570 | if (ide_pci_is_in_compatibility_mode(dev)) { | ||
571 | hw[0].irq = pci_get_legacy_ide_irq(dev, 0); | ||
572 | hw[1].irq = pci_get_legacy_ide_irq(dev, 1); | ||
573 | } else | ||
574 | hw[1].irq = hw[0].irq = ret; | ||
575 | |||
576 | ret = ide_host_register(host, d, hws); | ||
577 | if (ret) | ||
578 | ide_host_free(host); | ||
579 | out: | ||
580 | return ret; | ||
581 | } | ||
582 | EXPORT_SYMBOL_GPL(ide_pci_init_one); | ||
583 | |||
584 | int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, | 537 | int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, |
585 | const struct ide_port_info *d, void *priv) | 538 | const struct ide_port_info *d, void *priv) |
586 | { | 539 | { |
587 | struct pci_dev *pdev[] = { dev1, dev2 }; | 540 | struct pci_dev *pdev[] = { dev1, dev2 }; |
588 | struct ide_host *host; | 541 | struct ide_host *host; |
589 | int ret, i; | 542 | int ret, i, n_ports = dev2 ? 4 : 2; |
590 | hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL }; | 543 | struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; |
591 | 544 | ||
592 | for (i = 0; i < 2; i++) { | 545 | for (i = 0; i < n_ports / 2; i++) { |
593 | ret = ide_setup_pci_controller(pdev[i], d, !i); | 546 | ret = ide_setup_pci_controller(pdev[i], d, !i); |
594 | if (ret < 0) | 547 | if (ret < 0) |
595 | goto out; | 548 | goto out; |
@@ -597,23 +550,24 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, | |||
597 | ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); | 550 | ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); |
598 | } | 551 | } |
599 | 552 | ||
600 | host = ide_host_alloc(d, hws); | 553 | host = ide_host_alloc(d, hws, n_ports); |
601 | if (host == NULL) { | 554 | if (host == NULL) { |
602 | ret = -ENOMEM; | 555 | ret = -ENOMEM; |
603 | goto out; | 556 | goto out; |
604 | } | 557 | } |
605 | 558 | ||
606 | host->dev[0] = &dev1->dev; | 559 | host->dev[0] = &dev1->dev; |
607 | host->dev[1] = &dev2->dev; | 560 | if (dev2) |
561 | host->dev[1] = &dev2->dev; | ||
608 | 562 | ||
609 | host->host_priv = priv; | 563 | host->host_priv = priv; |
610 | |||
611 | host->irq_flags = IRQF_SHARED; | 564 | host->irq_flags = IRQF_SHARED; |
612 | 565 | ||
613 | pci_set_drvdata(pdev[0], host); | 566 | pci_set_drvdata(pdev[0], host); |
614 | pci_set_drvdata(pdev[1], host); | 567 | if (dev2) |
568 | pci_set_drvdata(pdev[1], host); | ||
615 | 569 | ||
616 | for (i = 0; i < 2; i++) { | 570 | for (i = 0; i < n_ports / 2; i++) { |
617 | ret = do_ide_setup_pci_device(pdev[i], d, !i); | 571 | ret = do_ide_setup_pci_device(pdev[i], d, !i); |
618 | 572 | ||
619 | /* | 573 | /* |
@@ -639,6 +593,13 @@ out: | |||
639 | } | 593 | } |
640 | EXPORT_SYMBOL_GPL(ide_pci_init_two); | 594 | EXPORT_SYMBOL_GPL(ide_pci_init_two); |
641 | 595 | ||
596 | int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, | ||
597 | void *priv) | ||
598 | { | ||
599 | return ide_pci_init_two(dev, NULL, d, priv); | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(ide_pci_init_one); | ||
602 | |||
642 | void ide_pci_remove(struct pci_dev *dev) | 603 | void ide_pci_remove(struct pci_dev *dev) |
643 | { | 604 | { |
644 | struct ide_host *host = pci_get_drvdata(dev); | 605 | struct ide_host *host = pci_get_drvdata(dev); |
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c index e5d2a48a84de..5f37f168f944 100644 --- a/drivers/ide/sgiioc4.c +++ b/drivers/ide/sgiioc4.c | |||
@@ -91,7 +91,7 @@ typedef struct { | |||
91 | 91 | ||
92 | 92 | ||
93 | static void | 93 | static void |
94 | sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, | 94 | sgiioc4_init_hwif_ports(struct ide_hw *hw, unsigned long data_port, |
95 | unsigned long ctrl_port, unsigned long irq_port) | 95 | unsigned long ctrl_port, unsigned long irq_port) |
96 | { | 96 | { |
97 | unsigned long reg = data_port; | 97 | unsigned long reg = data_port; |
@@ -546,7 +546,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
546 | unsigned long cmd_base, irqport; | 546 | unsigned long cmd_base, irqport; |
547 | unsigned long bar0, cmd_phys_base, ctl; | 547 | unsigned long bar0, cmd_phys_base, ctl; |
548 | void __iomem *virt_base; | 548 | void __iomem *virt_base; |
549 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 549 | struct ide_hw hw, *hws[] = { &hw }; |
550 | int rc; | 550 | int rc; |
551 | 551 | ||
552 | /* Get the CmdBlk and CtrlBlk Base Registers */ | 552 | /* Get the CmdBlk and CtrlBlk Base Registers */ |
@@ -575,13 +575,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
575 | memset(&hw, 0, sizeof(hw)); | 575 | memset(&hw, 0, sizeof(hw)); |
576 | sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); | 576 | sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport); |
577 | hw.irq = dev->irq; | 577 | hw.irq = dev->irq; |
578 | hw.chipset = ide_pci; | ||
579 | hw.dev = &dev->dev; | 578 | hw.dev = &dev->dev; |
580 | 579 | ||
581 | /* Initializing chipset IRQ Registers */ | 580 | /* Initializing chipset IRQ Registers */ |
582 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); | 581 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); |
583 | 582 | ||
584 | rc = ide_host_add(&sgiioc4_port_info, hws, NULL); | 583 | rc = ide_host_add(&sgiioc4_port_info, hws, 1, NULL); |
585 | if (!rc) | 584 | if (!rc) |
586 | return 0; | 585 | return 0; |
587 | 586 | ||
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index e4973cd1fba9..bd82d228608c 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c | |||
@@ -451,8 +451,8 @@ static int sil_sata_reset_poll(ide_drive_t *drive) | |||
451 | static void sil_sata_pre_reset(ide_drive_t *drive) | 451 | static void sil_sata_pre_reset(ide_drive_t *drive) |
452 | { | 452 | { |
453 | if (drive->media == ide_disk) { | 453 | if (drive->media == ide_disk) { |
454 | drive->special.b.set_geometry = 0; | 454 | drive->special_flags &= |
455 | drive->special.b.recalibrate = 0; | 455 | ~(IDE_SFLAG_SET_GEOMETRY | IDE_SFLAG_RECALIBRATE); |
456 | } | 456 | } |
457 | } | 457 | } |
458 | 458 | ||
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index b0a460625335..0924abff52ff 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * with the timing registers setup. | 10 | * with the timing registers setup. |
11 | * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org | 11 | * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org |
12 | * | 12 | * |
13 | * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> | 13 | * Copyright (C) 2006-2007,2009 MontaVista Software, Inc. <source@mvista.com> |
14 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | 14 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz |
15 | */ | 15 | */ |
16 | 16 | ||
@@ -146,14 +146,15 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive) | |||
146 | u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; | 146 | u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; |
147 | u8 dma_cmd; | 147 | u8 dma_cmd; |
148 | 148 | ||
149 | printk("sl82c105: lost IRQ, resetting host\n"); | 149 | printk(KERN_WARNING "sl82c105: lost IRQ, resetting host\n"); |
150 | 150 | ||
151 | /* | 151 | /* |
152 | * Check the raw interrupt from the drive. | 152 | * Check the raw interrupt from the drive. |
153 | */ | 153 | */ |
154 | pci_read_config_dword(dev, 0x40, &val); | 154 | pci_read_config_dword(dev, 0x40, &val); |
155 | if (val & mask) | 155 | if (val & mask) |
156 | printk("sl82c105: drive was requesting IRQ, but host lost it\n"); | 156 | printk(KERN_INFO "sl82c105: drive was requesting IRQ, " |
157 | "but host lost it\n"); | ||
157 | 158 | ||
158 | /* | 159 | /* |
159 | * Was DMA enabled? If so, disable it - we're resetting the | 160 | * Was DMA enabled? If so, disable it - we're resetting the |
@@ -162,7 +163,7 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive) | |||
162 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 163 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
163 | if (dma_cmd & 1) { | 164 | if (dma_cmd & 1) { |
164 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); | 165 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); |
165 | printk("sl82c105: DMA was enabled\n"); | 166 | printk(KERN_INFO "sl82c105: DMA was enabled\n"); |
166 | } | 167 | } |
167 | 168 | ||
168 | sl82c105_reset_host(dev); | 169 | sl82c105_reset_host(dev); |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index e33d764e2945..ea89fddeed91 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -130,8 +130,7 @@ static const struct ide_port_info tx4938ide_port_info __initdata = { | |||
130 | 130 | ||
131 | static int __init tx4938ide_probe(struct platform_device *pdev) | 131 | static int __init tx4938ide_probe(struct platform_device *pdev) |
132 | { | 132 | { |
133 | hw_regs_t hw; | 133 | struct ide_hw hw, *hws[] = { &hw }; |
134 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
135 | struct ide_host *host; | 134 | struct ide_host *host; |
136 | struct resource *res; | 135 | struct resource *res; |
137 | struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; | 136 | struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; |
@@ -183,7 +182,7 @@ static int __init tx4938ide_probe(struct platform_device *pdev) | |||
183 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); | 182 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); |
184 | else | 183 | else |
185 | d.port_ops = NULL; | 184 | d.port_ops = NULL; |
186 | ret = ide_host_add(&d, hws, &host); | 185 | ret = ide_host_add(&d, hws, 1, &host); |
187 | if (!ret) | 186 | if (!ret) |
188 | platform_set_drvdata(pdev, host); | 187 | platform_set_drvdata(pdev, host); |
189 | return ret; | 188 | return ret; |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 5ca76224f6d1..64b58ecc3f0e 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -537,8 +537,7 @@ static const struct ide_port_info tx4939ide_port_info __initdata = { | |||
537 | 537 | ||
538 | static int __init tx4939ide_probe(struct platform_device *pdev) | 538 | static int __init tx4939ide_probe(struct platform_device *pdev) |
539 | { | 539 | { |
540 | hw_regs_t hw; | 540 | struct ide_hw hw, *hws[] = { &hw }; |
541 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
542 | struct ide_host *host; | 541 | struct ide_host *host; |
543 | struct resource *res; | 542 | struct resource *res; |
544 | int irq, ret; | 543 | int irq, ret; |
@@ -581,7 +580,7 @@ static int __init tx4939ide_probe(struct platform_device *pdev) | |||
581 | hw.dev = &pdev->dev; | 580 | hw.dev = &pdev->dev; |
582 | 581 | ||
583 | pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq); | 582 | pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq); |
584 | host = ide_host_alloc(&tx4939ide_port_info, hws); | 583 | host = ide_host_alloc(&tx4939ide_port_info, hws, 1); |
585 | if (!host) | 584 | if (!host) |
586 | return -ENOMEM; | 585 | return -ENOMEM; |
587 | /* use extra_base for base address of the all registers */ | 586 | /* use extra_base for base address of the all registers */ |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 35e8eb02b9e9..e4e4d433b007 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -354,7 +354,7 @@ static int default_crt_on __devinitdata = 0; | |||
354 | static int default_lcd_on __devinitdata = 1; | 354 | static int default_lcd_on __devinitdata = 1; |
355 | 355 | ||
356 | #ifdef CONFIG_MTRR | 356 | #ifdef CONFIG_MTRR |
357 | static int mtrr = 1; | 357 | static bool mtrr = true; |
358 | #endif | 358 | #endif |
359 | 359 | ||
360 | #ifdef CONFIG_PMAC_BACKLIGHT | 360 | #ifdef CONFIG_PMAC_BACKLIGHT |
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 83c5cefc266c..da7c01b39be2 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c | |||
@@ -1736,10 +1736,8 @@ static int __init cyber2000fb_init(void) | |||
1736 | 1736 | ||
1737 | #ifdef CONFIG_ARCH_SHARK | 1737 | #ifdef CONFIG_ARCH_SHARK |
1738 | err = cyberpro_vl_probe(); | 1738 | err = cyberpro_vl_probe(); |
1739 | if (!err) { | 1739 | if (!err) |
1740 | ret = 0; | 1740 | ret = 0; |
1741 | __module_get(THIS_MODULE); | ||
1742 | } | ||
1743 | #endif | 1741 | #endif |
1744 | #ifdef CONFIG_PCI | 1742 | #ifdef CONFIG_PCI |
1745 | err = pci_register_driver(&cyberpro_driver); | 1743 | err = pci_register_driver(&cyberpro_driver); |
@@ -1749,14 +1747,15 @@ static int __init cyber2000fb_init(void) | |||
1749 | 1747 | ||
1750 | return ret ? err : 0; | 1748 | return ret ? err : 0; |
1751 | } | 1749 | } |
1750 | module_init(cyber2000fb_init); | ||
1752 | 1751 | ||
1752 | #ifndef CONFIG_ARCH_SHARK | ||
1753 | static void __exit cyberpro_exit(void) | 1753 | static void __exit cyberpro_exit(void) |
1754 | { | 1754 | { |
1755 | pci_unregister_driver(&cyberpro_driver); | 1755 | pci_unregister_driver(&cyberpro_driver); |
1756 | } | 1756 | } |
1757 | |||
1758 | module_init(cyber2000fb_init); | ||
1759 | module_exit(cyberpro_exit); | 1757 | module_exit(cyberpro_exit); |
1758 | #endif | ||
1760 | 1759 | ||
1761 | MODULE_AUTHOR("Russell King"); | 1760 | MODULE_AUTHOR("Russell King"); |
1762 | MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); | 1761 | MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 421770b5e6ab..ca5b4643a401 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -45,7 +45,7 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = { | |||
45 | static int mtrr __devinitdata = 3; /* enable mtrr by default */ | 45 | static int mtrr __devinitdata = 3; /* enable mtrr by default */ |
46 | static int blank = 1; /* enable blanking by default */ | 46 | static int blank = 1; /* enable blanking by default */ |
47 | static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ | 47 | static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ |
48 | static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */ | 48 | static bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */ |
49 | static int nocrtc __devinitdata; /* ignore CRTC settings */ | 49 | static int nocrtc __devinitdata; /* ignore CRTC settings */ |
50 | static int noedid __devinitdata; /* don't try DDC transfers */ | 50 | static int noedid __devinitdata; /* don't try DDC transfers */ |
51 | static int vram_remap __devinitdata; /* set amt. of memory to be used */ | 51 | static int vram_remap __devinitdata; /* set amt. of memory to be used */ |
@@ -2002,11 +2002,7 @@ static void __devexit uvesafb_exit(void) | |||
2002 | 2002 | ||
2003 | module_exit(uvesafb_exit); | 2003 | module_exit(uvesafb_exit); |
2004 | 2004 | ||
2005 | static int param_get_scroll(char *buffer, struct kernel_param *kp) | 2005 | #define param_get_scroll NULL |
2006 | { | ||
2007 | return 0; | ||
2008 | } | ||
2009 | |||
2010 | static int param_set_scroll(const char *val, struct kernel_param *kp) | 2006 | static int param_set_scroll(const char *val, struct kernel_param *kp) |
2011 | { | 2007 | { |
2012 | ypan = 0; | 2008 | ypan = 0; |
@@ -2017,6 +2013,8 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) | |||
2017 | ypan = 1; | 2013 | ypan = 1; |
2018 | else if (!strcmp(val, "ywrap")) | 2014 | else if (!strcmp(val, "ywrap")) |
2019 | ypan = 2; | 2015 | ypan = 2; |
2016 | else | ||
2017 | return -EINVAL; | ||
2020 | 2018 | ||
2021 | return 0; | 2019 | return 0; |
2022 | } | 2020 | } |
diff --git a/fs/Kconfig b/fs/Kconfig index 9f7270f36b2a..525da2e8f73b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -62,6 +62,16 @@ source "fs/autofs/Kconfig" | |||
62 | source "fs/autofs4/Kconfig" | 62 | source "fs/autofs4/Kconfig" |
63 | source "fs/fuse/Kconfig" | 63 | source "fs/fuse/Kconfig" |
64 | 64 | ||
65 | config CUSE | ||
66 | tristate "Character device in Userpace support" | ||
67 | depends on FUSE_FS | ||
68 | help | ||
69 | This FUSE extension allows character devices to be | ||
70 | implemented in userspace. | ||
71 | |||
72 | If you want to develop or use userspace character device | ||
73 | based on CUSE, answer Y or M. | ||
74 | |||
65 | config GENERIC_ACL | 75 | config GENERIC_ACL |
66 | bool | 76 | bool |
67 | select FS_POSIX_ACL | 77 | select FS_POSIX_ACL |
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile index 72437065f6ad..e95eeb445e58 100644 --- a/fs/fuse/Makefile +++ b/fs/fuse/Makefile | |||
@@ -3,5 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_FUSE_FS) += fuse.o | 5 | obj-$(CONFIG_FUSE_FS) += fuse.o |
6 | obj-$(CONFIG_CUSE) += cuse.o | ||
6 | 7 | ||
7 | fuse-objs := dev.o dir.o file.o inode.o control.o | 8 | fuse-objs := dev.o dir.o file.o inode.o control.o |
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c new file mode 100644 index 000000000000..de792dcf3274 --- /dev/null +++ b/fs/fuse/cuse.c | |||
@@ -0,0 +1,610 @@ | |||
1 | /* | ||
2 | * CUSE: Character device in Userspace | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 SUSE Linux Products GmbH | ||
5 | * Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org> | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | * | ||
9 | * CUSE enables character devices to be implemented from userland much | ||
10 | * like FUSE allows filesystems. On initialization /dev/cuse is | ||
11 | * created. By opening the file and replying to the CUSE_INIT request | ||
12 | * userland CUSE server can create a character device. After that the | ||
13 | * operation is very similar to FUSE. | ||
14 | * | ||
15 | * A CUSE instance involves the following objects. | ||
16 | * | ||
17 | * cuse_conn : contains fuse_conn and serves as bonding structure | ||
18 | * channel : file handle connected to the userland CUSE server | ||
19 | * cdev : the implemented character device | ||
20 | * dev : generic device for cdev | ||
21 | * | ||
22 | * Note that 'channel' is what 'dev' is in FUSE. As CUSE deals with | ||
23 | * devices, it's called 'channel' to reduce confusion. | ||
24 | * | ||
25 | * channel determines when the character device dies. When channel is | ||
26 | * closed, everything begins to destruct. The cuse_conn is taken off | ||
27 | * the lookup table preventing further access from cdev, cdev and | ||
28 | * generic device are removed and the base reference of cuse_conn is | ||
29 | * put. | ||
30 | * | ||
31 | * On each open, the matching cuse_conn is looked up and if found an | ||
32 | * additional reference is taken which is released when the file is | ||
33 | * closed. | ||
34 | */ | ||
35 | |||
36 | #include <linux/fuse.h> | ||
37 | #include <linux/cdev.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/file.h> | ||
40 | #include <linux/fs.h> | ||
41 | #include <linux/kdev_t.h> | ||
42 | #include <linux/kthread.h> | ||
43 | #include <linux/list.h> | ||
44 | #include <linux/magic.h> | ||
45 | #include <linux/miscdevice.h> | ||
46 | #include <linux/mutex.h> | ||
47 | #include <linux/spinlock.h> | ||
48 | #include <linux/stat.h> | ||
49 | |||
50 | #include "fuse_i.h" | ||
51 | |||
52 | #define CUSE_CONNTBL_LEN 64 | ||
53 | |||
54 | struct cuse_conn { | ||
55 | struct list_head list; /* linked on cuse_conntbl */ | ||
56 | struct fuse_conn fc; /* fuse connection */ | ||
57 | struct cdev *cdev; /* associated character device */ | ||
58 | struct device *dev; /* device representing @cdev */ | ||
59 | |||
60 | /* init parameters, set once during initialization */ | ||
61 | bool unrestricted_ioctl; | ||
62 | }; | ||
63 | |||
64 | static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ | ||
65 | static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; | ||
66 | static struct class *cuse_class; | ||
67 | |||
68 | static struct cuse_conn *fc_to_cc(struct fuse_conn *fc) | ||
69 | { | ||
70 | return container_of(fc, struct cuse_conn, fc); | ||
71 | } | ||
72 | |||
73 | static struct list_head *cuse_conntbl_head(dev_t devt) | ||
74 | { | ||
75 | return &cuse_conntbl[(MAJOR(devt) + MINOR(devt)) % CUSE_CONNTBL_LEN]; | ||
76 | } | ||
77 | |||
78 | |||
79 | /************************************************************************** | ||
80 | * CUSE frontend operations | ||
81 | * | ||
82 | * These are file operations for the character device. | ||
83 | * | ||
84 | * On open, CUSE opens a file from the FUSE mnt and stores it to | ||
85 | * private_data of the open file. All other ops call FUSE ops on the | ||
86 | * FUSE file. | ||
87 | */ | ||
88 | |||
89 | static ssize_t cuse_read(struct file *file, char __user *buf, size_t count, | ||
90 | loff_t *ppos) | ||
91 | { | ||
92 | loff_t pos = 0; | ||
93 | |||
94 | return fuse_direct_io(file, buf, count, &pos, 0); | ||
95 | } | ||
96 | |||
97 | static ssize_t cuse_write(struct file *file, const char __user *buf, | ||
98 | size_t count, loff_t *ppos) | ||
99 | { | ||
100 | loff_t pos = 0; | ||
101 | /* | ||
102 | * No locking or generic_write_checks(), the server is | ||
103 | * responsible for locking and sanity checks. | ||
104 | */ | ||
105 | return fuse_direct_io(file, buf, count, &pos, 1); | ||
106 | } | ||
107 | |||
108 | static int cuse_open(struct inode *inode, struct file *file) | ||
109 | { | ||
110 | dev_t devt = inode->i_cdev->dev; | ||
111 | struct cuse_conn *cc = NULL, *pos; | ||
112 | int rc; | ||
113 | |||
114 | /* look up and get the connection */ | ||
115 | spin_lock(&cuse_lock); | ||
116 | list_for_each_entry(pos, cuse_conntbl_head(devt), list) | ||
117 | if (pos->dev->devt == devt) { | ||
118 | fuse_conn_get(&pos->fc); | ||
119 | cc = pos; | ||
120 | break; | ||
121 | } | ||
122 | spin_unlock(&cuse_lock); | ||
123 | |||
124 | /* dead? */ | ||
125 | if (!cc) | ||
126 | return -ENODEV; | ||
127 | |||
128 | /* | ||
129 | * Generic permission check is already done against the chrdev | ||
130 | * file, proceed to open. | ||
131 | */ | ||
132 | rc = fuse_do_open(&cc->fc, 0, file, 0); | ||
133 | if (rc) | ||
134 | fuse_conn_put(&cc->fc); | ||
135 | return rc; | ||
136 | } | ||
137 | |||
138 | static int cuse_release(struct inode *inode, struct file *file) | ||
139 | { | ||
140 | struct fuse_file *ff = file->private_data; | ||
141 | struct fuse_conn *fc = ff->fc; | ||
142 | |||
143 | fuse_sync_release(ff, file->f_flags); | ||
144 | fuse_conn_put(fc); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static long cuse_file_ioctl(struct file *file, unsigned int cmd, | ||
150 | unsigned long arg) | ||
151 | { | ||
152 | struct fuse_file *ff = file->private_data; | ||
153 | struct cuse_conn *cc = fc_to_cc(ff->fc); | ||
154 | unsigned int flags = 0; | ||
155 | |||
156 | if (cc->unrestricted_ioctl) | ||
157 | flags |= FUSE_IOCTL_UNRESTRICTED; | ||
158 | |||
159 | return fuse_do_ioctl(file, cmd, arg, flags); | ||
160 | } | ||
161 | |||
162 | static long cuse_file_compat_ioctl(struct file *file, unsigned int cmd, | ||
163 | unsigned long arg) | ||
164 | { | ||
165 | struct fuse_file *ff = file->private_data; | ||
166 | struct cuse_conn *cc = fc_to_cc(ff->fc); | ||
167 | unsigned int flags = FUSE_IOCTL_COMPAT; | ||
168 | |||
169 | if (cc->unrestricted_ioctl) | ||
170 | flags |= FUSE_IOCTL_UNRESTRICTED; | ||
171 | |||
172 | return fuse_do_ioctl(file, cmd, arg, flags); | ||
173 | } | ||
174 | |||
175 | static const struct file_operations cuse_frontend_fops = { | ||
176 | .owner = THIS_MODULE, | ||
177 | .read = cuse_read, | ||
178 | .write = cuse_write, | ||
179 | .open = cuse_open, | ||
180 | .release = cuse_release, | ||
181 | .unlocked_ioctl = cuse_file_ioctl, | ||
182 | .compat_ioctl = cuse_file_compat_ioctl, | ||
183 | .poll = fuse_file_poll, | ||
184 | }; | ||
185 | |||
186 | |||
187 | /************************************************************************** | ||
188 | * CUSE channel initialization and destruction | ||
189 | */ | ||
190 | |||
191 | struct cuse_devinfo { | ||
192 | const char *name; | ||
193 | }; | ||
194 | |||
195 | /** | ||
196 | * cuse_parse_one - parse one key=value pair | ||
197 | * @pp: i/o parameter for the current position | ||
198 | * @end: points to one past the end of the packed string | ||
199 | * @keyp: out parameter for key | ||
200 | * @valp: out parameter for value | ||
201 | * | ||
202 | * *@pp points to packed strings - "key0=val0\0key1=val1\0" which ends | ||
203 | * at @end - 1. This function parses one pair and set *@keyp to the | ||
204 | * start of the key and *@valp to the start of the value. Note that | ||
205 | * the original string is modified such that the key string is | ||
206 | * terminated with '\0'. *@pp is updated to point to the next string. | ||
207 | * | ||
208 | * RETURNS: | ||
209 | * 1 on successful parse, 0 on EOF, -errno on failure. | ||
210 | */ | ||
211 | static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) | ||
212 | { | ||
213 | char *p = *pp; | ||
214 | char *key, *val; | ||
215 | |||
216 | while (p < end && *p == '\0') | ||
217 | p++; | ||
218 | if (p == end) | ||
219 | return 0; | ||
220 | |||
221 | if (end[-1] != '\0') { | ||
222 | printk(KERN_ERR "CUSE: info not properly terminated\n"); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | |||
226 | key = val = p; | ||
227 | p += strlen(p); | ||
228 | |||
229 | if (valp) { | ||
230 | strsep(&val, "="); | ||
231 | if (!val) | ||
232 | val = key + strlen(key); | ||
233 | key = strstrip(key); | ||
234 | val = strstrip(val); | ||
235 | } else | ||
236 | key = strstrip(key); | ||
237 | |||
238 | if (!strlen(key)) { | ||
239 | printk(KERN_ERR "CUSE: zero length info key specified\n"); | ||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | *pp = p; | ||
244 | *keyp = key; | ||
245 | if (valp) | ||
246 | *valp = val; | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * cuse_parse_dev_info - parse device info | ||
253 | * @p: device info string | ||
254 | * @len: length of device info string | ||
255 | * @devinfo: out parameter for parsed device info | ||
256 | * | ||
257 | * Parse @p to extract device info and store it into @devinfo. String | ||
258 | * pointed to by @p is modified by parsing and @devinfo points into | ||
259 | * them, so @p shouldn't be freed while @devinfo is in use. | ||
260 | * | ||
261 | * RETURNS: | ||
262 | * 0 on success, -errno on failure. | ||
263 | */ | ||
264 | static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) | ||
265 | { | ||
266 | char *end = p + len; | ||
267 | char *key, *val; | ||
268 | int rc; | ||
269 | |||
270 | while (true) { | ||
271 | rc = cuse_parse_one(&p, end, &key, &val); | ||
272 | if (rc < 0) | ||
273 | return rc; | ||
274 | if (!rc) | ||
275 | break; | ||
276 | if (strcmp(key, "DEVNAME") == 0) | ||
277 | devinfo->name = val; | ||
278 | else | ||
279 | printk(KERN_WARNING "CUSE: unknown device info \"%s\"\n", | ||
280 | key); | ||
281 | } | ||
282 | |||
283 | if (!devinfo->name || !strlen(devinfo->name)) { | ||
284 | printk(KERN_ERR "CUSE: DEVNAME unspecified\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static void cuse_gendev_release(struct device *dev) | ||
292 | { | ||
293 | kfree(dev); | ||
294 | } | ||
295 | |||
296 | /** | ||
297 | * cuse_process_init_reply - finish initializing CUSE channel | ||
298 | * | ||
299 | * This function creates the character device and sets up all the | ||
300 | * required data structures for it. Please read the comment at the | ||
301 | * top of this file for high level overview. | ||
302 | */ | ||
303 | static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | ||
304 | { | ||
305 | struct cuse_conn *cc = fc_to_cc(fc); | ||
306 | struct cuse_init_out *arg = &req->misc.cuse_init_out; | ||
307 | struct page *page = req->pages[0]; | ||
308 | struct cuse_devinfo devinfo = { }; | ||
309 | struct device *dev; | ||
310 | struct cdev *cdev; | ||
311 | dev_t devt; | ||
312 | int rc; | ||
313 | |||
314 | if (req->out.h.error || | ||
315 | arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { | ||
316 | goto err; | ||
317 | } | ||
318 | |||
319 | fc->minor = arg->minor; | ||
320 | fc->max_read = max_t(unsigned, arg->max_read, 4096); | ||
321 | fc->max_write = max_t(unsigned, arg->max_write, 4096); | ||
322 | |||
323 | /* parse init reply */ | ||
324 | cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL; | ||
325 | |||
326 | rc = cuse_parse_devinfo(page_address(page), req->out.args[1].size, | ||
327 | &devinfo); | ||
328 | if (rc) | ||
329 | goto err; | ||
330 | |||
331 | /* determine and reserve devt */ | ||
332 | devt = MKDEV(arg->dev_major, arg->dev_minor); | ||
333 | if (!MAJOR(devt)) | ||
334 | rc = alloc_chrdev_region(&devt, MINOR(devt), 1, devinfo.name); | ||
335 | else | ||
336 | rc = register_chrdev_region(devt, 1, devinfo.name); | ||
337 | if (rc) { | ||
338 | printk(KERN_ERR "CUSE: failed to register chrdev region\n"); | ||
339 | goto err; | ||
340 | } | ||
341 | |||
342 | /* devt determined, create device */ | ||
343 | rc = -ENOMEM; | ||
344 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
345 | if (!dev) | ||
346 | goto err_region; | ||
347 | |||
348 | device_initialize(dev); | ||
349 | dev_set_uevent_suppress(dev, 1); | ||
350 | dev->class = cuse_class; | ||
351 | dev->devt = devt; | ||
352 | dev->release = cuse_gendev_release; | ||
353 | dev_set_drvdata(dev, cc); | ||
354 | dev_set_name(dev, "%s", devinfo.name); | ||
355 | |||
356 | rc = device_add(dev); | ||
357 | if (rc) | ||
358 | goto err_device; | ||
359 | |||
360 | /* register cdev */ | ||
361 | rc = -ENOMEM; | ||
362 | cdev = cdev_alloc(); | ||
363 | if (!cdev) | ||
364 | goto err_device; | ||
365 | |||
366 | cdev->owner = THIS_MODULE; | ||
367 | cdev->ops = &cuse_frontend_fops; | ||
368 | |||
369 | rc = cdev_add(cdev, devt, 1); | ||
370 | if (rc) | ||
371 | goto err_cdev; | ||
372 | |||
373 | cc->dev = dev; | ||
374 | cc->cdev = cdev; | ||
375 | |||
376 | /* make the device available */ | ||
377 | spin_lock(&cuse_lock); | ||
378 | list_add(&cc->list, cuse_conntbl_head(devt)); | ||
379 | spin_unlock(&cuse_lock); | ||
380 | |||
381 | /* announce device availability */ | ||
382 | dev_set_uevent_suppress(dev, 0); | ||
383 | kobject_uevent(&dev->kobj, KOBJ_ADD); | ||
384 | out: | ||
385 | __free_page(page); | ||
386 | return; | ||
387 | |||
388 | err_cdev: | ||
389 | cdev_del(cdev); | ||
390 | err_device: | ||
391 | put_device(dev); | ||
392 | err_region: | ||
393 | unregister_chrdev_region(devt, 1); | ||
394 | err: | ||
395 | fc->conn_error = 1; | ||
396 | goto out; | ||
397 | } | ||
398 | |||
399 | static int cuse_send_init(struct cuse_conn *cc) | ||
400 | { | ||
401 | int rc; | ||
402 | struct fuse_req *req; | ||
403 | struct page *page; | ||
404 | struct fuse_conn *fc = &cc->fc; | ||
405 | struct cuse_init_in *arg; | ||
406 | |||
407 | BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); | ||
408 | |||
409 | req = fuse_get_req(fc); | ||
410 | if (IS_ERR(req)) { | ||
411 | rc = PTR_ERR(req); | ||
412 | goto err; | ||
413 | } | ||
414 | |||
415 | rc = -ENOMEM; | ||
416 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
417 | if (!page) | ||
418 | goto err_put_req; | ||
419 | |||
420 | arg = &req->misc.cuse_init_in; | ||
421 | arg->major = FUSE_KERNEL_VERSION; | ||
422 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | ||
423 | arg->flags |= CUSE_UNRESTRICTED_IOCTL; | ||
424 | req->in.h.opcode = CUSE_INIT; | ||
425 | req->in.numargs = 1; | ||
426 | req->in.args[0].size = sizeof(struct cuse_init_in); | ||
427 | req->in.args[0].value = arg; | ||
428 | req->out.numargs = 2; | ||
429 | req->out.args[0].size = sizeof(struct cuse_init_out); | ||
430 | req->out.args[0].value = &req->misc.cuse_init_out; | ||
431 | req->out.args[1].size = CUSE_INIT_INFO_MAX; | ||
432 | req->out.argvar = 1; | ||
433 | req->out.argpages = 1; | ||
434 | req->pages[0] = page; | ||
435 | req->num_pages = 1; | ||
436 | req->end = cuse_process_init_reply; | ||
437 | fuse_request_send_background(fc, req); | ||
438 | |||
439 | return 0; | ||
440 | |||
441 | err_put_req: | ||
442 | fuse_put_request(fc, req); | ||
443 | err: | ||
444 | return rc; | ||
445 | } | ||
446 | |||
447 | static void cuse_fc_release(struct fuse_conn *fc) | ||
448 | { | ||
449 | struct cuse_conn *cc = fc_to_cc(fc); | ||
450 | kfree(cc); | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * cuse_channel_open - open method for /dev/cuse | ||
455 | * @inode: inode for /dev/cuse | ||
456 | * @file: file struct being opened | ||
457 | * | ||
458 | * Userland CUSE server can create a CUSE device by opening /dev/cuse | ||
459 | * and replying to the initilaization request kernel sends. This | ||
460 | * function is responsible for handling CUSE device initialization. | ||
461 | * Because the fd opened by this function is used during | ||
462 | * initialization, this function only creates cuse_conn and sends | ||
463 | * init. The rest is delegated to a kthread. | ||
464 | * | ||
465 | * RETURNS: | ||
466 | * 0 on success, -errno on failure. | ||
467 | */ | ||
468 | static int cuse_channel_open(struct inode *inode, struct file *file) | ||
469 | { | ||
470 | struct cuse_conn *cc; | ||
471 | int rc; | ||
472 | |||
473 | /* set up cuse_conn */ | ||
474 | cc = kzalloc(sizeof(*cc), GFP_KERNEL); | ||
475 | if (!cc) | ||
476 | return -ENOMEM; | ||
477 | |||
478 | fuse_conn_init(&cc->fc); | ||
479 | |||
480 | INIT_LIST_HEAD(&cc->list); | ||
481 | cc->fc.release = cuse_fc_release; | ||
482 | |||
483 | cc->fc.connected = 1; | ||
484 | cc->fc.blocked = 0; | ||
485 | rc = cuse_send_init(cc); | ||
486 | if (rc) { | ||
487 | fuse_conn_put(&cc->fc); | ||
488 | return rc; | ||
489 | } | ||
490 | file->private_data = &cc->fc; /* channel owns base reference to cc */ | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * cuse_channel_release - release method for /dev/cuse | ||
497 | * @inode: inode for /dev/cuse | ||
498 | * @file: file struct being closed | ||
499 | * | ||
500 | * Disconnect the channel, deregister CUSE device and initiate | ||
501 | * destruction by putting the default reference. | ||
502 | * | ||
503 | * RETURNS: | ||
504 | * 0 on success, -errno on failure. | ||
505 | */ | ||
506 | static int cuse_channel_release(struct inode *inode, struct file *file) | ||
507 | { | ||
508 | struct cuse_conn *cc = fc_to_cc(file->private_data); | ||
509 | int rc; | ||
510 | |||
511 | /* remove from the conntbl, no more access from this point on */ | ||
512 | spin_lock(&cuse_lock); | ||
513 | list_del_init(&cc->list); | ||
514 | spin_unlock(&cuse_lock); | ||
515 | |||
516 | /* remove device */ | ||
517 | if (cc->dev) | ||
518 | device_unregister(cc->dev); | ||
519 | if (cc->cdev) { | ||
520 | unregister_chrdev_region(cc->cdev->dev, 1); | ||
521 | cdev_del(cc->cdev); | ||
522 | } | ||
523 | |||
524 | /* kill connection and shutdown channel */ | ||
525 | fuse_conn_kill(&cc->fc); | ||
526 | rc = fuse_dev_release(inode, file); /* puts the base reference */ | ||
527 | |||
528 | return rc; | ||
529 | } | ||
530 | |||
531 | static struct file_operations cuse_channel_fops; /* initialized during init */ | ||
532 | |||
533 | |||
534 | /************************************************************************** | ||
535 | * Misc stuff and module initializatiion | ||
536 | * | ||
537 | * CUSE exports the same set of attributes to sysfs as fusectl. | ||
538 | */ | ||
539 | |||
540 | static ssize_t cuse_class_waiting_show(struct device *dev, | ||
541 | struct device_attribute *attr, char *buf) | ||
542 | { | ||
543 | struct cuse_conn *cc = dev_get_drvdata(dev); | ||
544 | |||
545 | return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting)); | ||
546 | } | ||
547 | |||
548 | static ssize_t cuse_class_abort_store(struct device *dev, | ||
549 | struct device_attribute *attr, | ||
550 | const char *buf, size_t count) | ||
551 | { | ||
552 | struct cuse_conn *cc = dev_get_drvdata(dev); | ||
553 | |||
554 | fuse_abort_conn(&cc->fc); | ||
555 | return count; | ||
556 | } | ||
557 | |||
558 | static struct device_attribute cuse_class_dev_attrs[] = { | ||
559 | __ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL), | ||
560 | __ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store), | ||
561 | { } | ||
562 | }; | ||
563 | |||
564 | static struct miscdevice cuse_miscdev = { | ||
565 | .minor = MISC_DYNAMIC_MINOR, | ||
566 | .name = "cuse", | ||
567 | .fops = &cuse_channel_fops, | ||
568 | }; | ||
569 | |||
570 | static int __init cuse_init(void) | ||
571 | { | ||
572 | int i, rc; | ||
573 | |||
574 | /* init conntbl */ | ||
575 | for (i = 0; i < CUSE_CONNTBL_LEN; i++) | ||
576 | INIT_LIST_HEAD(&cuse_conntbl[i]); | ||
577 | |||
578 | /* inherit and extend fuse_dev_operations */ | ||
579 | cuse_channel_fops = fuse_dev_operations; | ||
580 | cuse_channel_fops.owner = THIS_MODULE; | ||
581 | cuse_channel_fops.open = cuse_channel_open; | ||
582 | cuse_channel_fops.release = cuse_channel_release; | ||
583 | |||
584 | cuse_class = class_create(THIS_MODULE, "cuse"); | ||
585 | if (IS_ERR(cuse_class)) | ||
586 | return PTR_ERR(cuse_class); | ||
587 | |||
588 | cuse_class->dev_attrs = cuse_class_dev_attrs; | ||
589 | |||
590 | rc = misc_register(&cuse_miscdev); | ||
591 | if (rc) { | ||
592 | class_destroy(cuse_class); | ||
593 | return rc; | ||
594 | } | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static void __exit cuse_exit(void) | ||
600 | { | ||
601 | misc_deregister(&cuse_miscdev); | ||
602 | class_destroy(cuse_class); | ||
603 | } | ||
604 | |||
605 | module_init(cuse_init); | ||
606 | module_exit(cuse_exit); | ||
607 | |||
608 | MODULE_AUTHOR("Tejun Heo <tj@kernel.org>"); | ||
609 | MODULE_DESCRIPTION("Character device in Userspace"); | ||
610 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ba76b68c52ff..8fed2ed12f38 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -46,6 +46,7 @@ struct fuse_req *fuse_request_alloc(void) | |||
46 | fuse_request_init(req); | 46 | fuse_request_init(req); |
47 | return req; | 47 | return req; |
48 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(fuse_request_alloc); | ||
49 | 50 | ||
50 | struct fuse_req *fuse_request_alloc_nofs(void) | 51 | struct fuse_req *fuse_request_alloc_nofs(void) |
51 | { | 52 | { |
@@ -124,6 +125,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc) | |||
124 | atomic_dec(&fc->num_waiting); | 125 | atomic_dec(&fc->num_waiting); |
125 | return ERR_PTR(err); | 126 | return ERR_PTR(err); |
126 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(fuse_get_req); | ||
127 | 129 | ||
128 | /* | 130 | /* |
129 | * Return request in fuse_file->reserved_req. However that may | 131 | * Return request in fuse_file->reserved_req. However that may |
@@ -208,6 +210,7 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) | |||
208 | fuse_request_free(req); | 210 | fuse_request_free(req); |
209 | } | 211 | } |
210 | } | 212 | } |
213 | EXPORT_SYMBOL_GPL(fuse_put_request); | ||
211 | 214 | ||
212 | static unsigned len_args(unsigned numargs, struct fuse_arg *args) | 215 | static unsigned len_args(unsigned numargs, struct fuse_arg *args) |
213 | { | 216 | { |
@@ -282,7 +285,7 @@ __releases(&fc->lock) | |||
282 | wake_up_all(&fc->blocked_waitq); | 285 | wake_up_all(&fc->blocked_waitq); |
283 | } | 286 | } |
284 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 287 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
285 | fc->connected) { | 288 | fc->connected && fc->bdi_initialized) { |
286 | clear_bdi_congested(&fc->bdi, READ); | 289 | clear_bdi_congested(&fc->bdi, READ); |
287 | clear_bdi_congested(&fc->bdi, WRITE); | 290 | clear_bdi_congested(&fc->bdi, WRITE); |
288 | } | 291 | } |
@@ -400,6 +403,7 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
400 | } | 403 | } |
401 | spin_unlock(&fc->lock); | 404 | spin_unlock(&fc->lock); |
402 | } | 405 | } |
406 | EXPORT_SYMBOL_GPL(fuse_request_send); | ||
403 | 407 | ||
404 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | 408 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, |
405 | struct fuse_req *req) | 409 | struct fuse_req *req) |
@@ -408,7 +412,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | |||
408 | fc->num_background++; | 412 | fc->num_background++; |
409 | if (fc->num_background == FUSE_MAX_BACKGROUND) | 413 | if (fc->num_background == FUSE_MAX_BACKGROUND) |
410 | fc->blocked = 1; | 414 | fc->blocked = 1; |
411 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { | 415 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
416 | fc->bdi_initialized) { | ||
412 | set_bdi_congested(&fc->bdi, READ); | 417 | set_bdi_congested(&fc->bdi, READ); |
413 | set_bdi_congested(&fc->bdi, WRITE); | 418 | set_bdi_congested(&fc->bdi, WRITE); |
414 | } | 419 | } |
@@ -439,6 +444,7 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) | |||
439 | req->isreply = 1; | 444 | req->isreply = 1; |
440 | fuse_request_send_nowait(fc, req); | 445 | fuse_request_send_nowait(fc, req); |
441 | } | 446 | } |
447 | EXPORT_SYMBOL_GPL(fuse_request_send_background); | ||
442 | 448 | ||
443 | /* | 449 | /* |
444 | * Called under fc->lock | 450 | * Called under fc->lock |
@@ -1105,8 +1111,9 @@ void fuse_abort_conn(struct fuse_conn *fc) | |||
1105 | } | 1111 | } |
1106 | spin_unlock(&fc->lock); | 1112 | spin_unlock(&fc->lock); |
1107 | } | 1113 | } |
1114 | EXPORT_SYMBOL_GPL(fuse_abort_conn); | ||
1108 | 1115 | ||
1109 | static int fuse_dev_release(struct inode *inode, struct file *file) | 1116 | int fuse_dev_release(struct inode *inode, struct file *file) |
1110 | { | 1117 | { |
1111 | struct fuse_conn *fc = fuse_get_conn(file); | 1118 | struct fuse_conn *fc = fuse_get_conn(file); |
1112 | if (fc) { | 1119 | if (fc) { |
@@ -1120,6 +1127,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file) | |||
1120 | 1127 | ||
1121 | return 0; | 1128 | return 0; |
1122 | } | 1129 | } |
1130 | EXPORT_SYMBOL_GPL(fuse_dev_release); | ||
1123 | 1131 | ||
1124 | static int fuse_dev_fasync(int fd, struct file *file, int on) | 1132 | static int fuse_dev_fasync(int fd, struct file *file, int on) |
1125 | { | 1133 | { |
@@ -1142,6 +1150,7 @@ const struct file_operations fuse_dev_operations = { | |||
1142 | .release = fuse_dev_release, | 1150 | .release = fuse_dev_release, |
1143 | .fasync = fuse_dev_fasync, | 1151 | .fasync = fuse_dev_fasync, |
1144 | }; | 1152 | }; |
1153 | EXPORT_SYMBOL_GPL(fuse_dev_operations); | ||
1145 | 1154 | ||
1146 | static struct miscdevice fuse_miscdevice = { | 1155 | static struct miscdevice fuse_miscdevice = { |
1147 | .minor = FUSE_MINOR, | 1156 | .minor = FUSE_MINOR, |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8b8eebc5614b..b3089a083d30 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -362,19 +362,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
362 | } | 362 | } |
363 | 363 | ||
364 | /* | 364 | /* |
365 | * Synchronous release for the case when something goes wrong in CREATE_OPEN | ||
366 | */ | ||
367 | static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff, | ||
368 | u64 nodeid, int flags) | ||
369 | { | ||
370 | fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE); | ||
371 | ff->reserved_req->force = 1; | ||
372 | fuse_request_send(fc, ff->reserved_req); | ||
373 | fuse_put_request(fc, ff->reserved_req); | ||
374 | kfree(ff); | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * Atomic create+open operation | 365 | * Atomic create+open operation |
379 | * | 366 | * |
380 | * If the filesystem doesn't support this, then fall back to separate | 367 | * If the filesystem doesn't support this, then fall back to separate |
@@ -445,12 +432,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
445 | goto out_free_ff; | 432 | goto out_free_ff; |
446 | 433 | ||
447 | fuse_put_request(fc, req); | 434 | fuse_put_request(fc, req); |
435 | ff->fh = outopen.fh; | ||
436 | ff->nodeid = outentry.nodeid; | ||
437 | ff->open_flags = outopen.open_flags; | ||
448 | inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, | 438 | inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, |
449 | &outentry.attr, entry_attr_timeout(&outentry), 0); | 439 | &outentry.attr, entry_attr_timeout(&outentry), 0); |
450 | if (!inode) { | 440 | if (!inode) { |
451 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); | 441 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); |
452 | ff->fh = outopen.fh; | 442 | fuse_sync_release(ff, flags); |
453 | fuse_sync_release(fc, ff, outentry.nodeid, flags); | ||
454 | fuse_send_forget(fc, forget_req, outentry.nodeid, 1); | 443 | fuse_send_forget(fc, forget_req, outentry.nodeid, 1); |
455 | return -ENOMEM; | 444 | return -ENOMEM; |
456 | } | 445 | } |
@@ -460,11 +449,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
460 | fuse_invalidate_attr(dir); | 449 | fuse_invalidate_attr(dir); |
461 | file = lookup_instantiate_filp(nd, entry, generic_file_open); | 450 | file = lookup_instantiate_filp(nd, entry, generic_file_open); |
462 | if (IS_ERR(file)) { | 451 | if (IS_ERR(file)) { |
463 | ff->fh = outopen.fh; | 452 | fuse_sync_release(ff, flags); |
464 | fuse_sync_release(fc, ff, outentry.nodeid, flags); | ||
465 | return PTR_ERR(file); | 453 | return PTR_ERR(file); |
466 | } | 454 | } |
467 | fuse_finish_open(inode, file, ff, &outopen); | 455 | file->private_data = fuse_file_get(ff); |
456 | fuse_finish_open(inode, file); | ||
468 | return 0; | 457 | return 0; |
469 | 458 | ||
470 | out_free_ff: | 459 | out_free_ff: |
@@ -1035,7 +1024,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
1035 | req->out.argpages = 1; | 1024 | req->out.argpages = 1; |
1036 | req->num_pages = 1; | 1025 | req->num_pages = 1; |
1037 | req->pages[0] = page; | 1026 | req->pages[0] = page; |
1038 | fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); | 1027 | fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); |
1039 | fuse_request_send(fc, req); | 1028 | fuse_request_send(fc, req); |
1040 | nbytes = req->out.args[0].size; | 1029 | nbytes = req->out.args[0].size; |
1041 | err = req->out.h.error; | 1030 | err = req->out.h.error; |
@@ -1101,12 +1090,14 @@ static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) | |||
1101 | 1090 | ||
1102 | static int fuse_dir_open(struct inode *inode, struct file *file) | 1091 | static int fuse_dir_open(struct inode *inode, struct file *file) |
1103 | { | 1092 | { |
1104 | return fuse_open_common(inode, file, 1); | 1093 | return fuse_open_common(inode, file, true); |
1105 | } | 1094 | } |
1106 | 1095 | ||
1107 | static int fuse_dir_release(struct inode *inode, struct file *file) | 1096 | static int fuse_dir_release(struct inode *inode, struct file *file) |
1108 | { | 1097 | { |
1109 | return fuse_release_common(inode, file, 1); | 1098 | fuse_release_common(file, FUSE_RELEASEDIR); |
1099 | |||
1100 | return 0; | ||
1110 | } | 1101 | } |
1111 | 1102 | ||
1112 | static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) | 1103 | static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 06f30e965676..fce6ce694fde 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -12,13 +12,13 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/module.h> | ||
15 | 16 | ||
16 | static const struct file_operations fuse_direct_io_file_operations; | 17 | static const struct file_operations fuse_direct_io_file_operations; |
17 | 18 | ||
18 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | 19 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
19 | struct fuse_open_out *outargp) | 20 | int opcode, struct fuse_open_out *outargp) |
20 | { | 21 | { |
21 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
22 | struct fuse_open_in inarg; | 22 | struct fuse_open_in inarg; |
23 | struct fuse_req *req; | 23 | struct fuse_req *req; |
24 | int err; | 24 | int err; |
@@ -31,8 +31,8 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); | 31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
32 | if (!fc->atomic_o_trunc) | 32 | if (!fc->atomic_o_trunc) |
33 | inarg.flags &= ~O_TRUNC; | 33 | inarg.flags &= ~O_TRUNC; |
34 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | 34 | req->in.h.opcode = opcode; |
35 | req->in.h.nodeid = get_node_id(inode); | 35 | req->in.h.nodeid = nodeid; |
36 | req->in.numargs = 1; | 36 | req->in.numargs = 1; |
37 | req->in.args[0].size = sizeof(inarg); | 37 | req->in.args[0].size = sizeof(inarg); |
38 | req->in.args[0].value = &inarg; | 38 | req->in.args[0].value = &inarg; |
@@ -49,22 +49,27 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
49 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | 49 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) |
50 | { | 50 | { |
51 | struct fuse_file *ff; | 51 | struct fuse_file *ff; |
52 | |||
52 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); | 53 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); |
53 | if (ff) { | 54 | if (unlikely(!ff)) |
54 | ff->reserved_req = fuse_request_alloc(); | 55 | return NULL; |
55 | if (!ff->reserved_req) { | 56 | |
56 | kfree(ff); | 57 | ff->fc = fc; |
57 | return NULL; | 58 | ff->reserved_req = fuse_request_alloc(); |
58 | } else { | 59 | if (unlikely(!ff->reserved_req)) { |
59 | INIT_LIST_HEAD(&ff->write_entry); | 60 | kfree(ff); |
60 | atomic_set(&ff->count, 0); | 61 | return NULL; |
61 | spin_lock(&fc->lock); | ||
62 | ff->kh = ++fc->khctr; | ||
63 | spin_unlock(&fc->lock); | ||
64 | } | ||
65 | RB_CLEAR_NODE(&ff->polled_node); | ||
66 | init_waitqueue_head(&ff->poll_wait); | ||
67 | } | 62 | } |
63 | |||
64 | INIT_LIST_HEAD(&ff->write_entry); | ||
65 | atomic_set(&ff->count, 0); | ||
66 | RB_CLEAR_NODE(&ff->polled_node); | ||
67 | init_waitqueue_head(&ff->poll_wait); | ||
68 | |||
69 | spin_lock(&fc->lock); | ||
70 | ff->kh = ++fc->khctr; | ||
71 | spin_unlock(&fc->lock); | ||
72 | |||
68 | return ff; | 73 | return ff; |
69 | } | 74 | } |
70 | 75 | ||
@@ -74,7 +79,7 @@ void fuse_file_free(struct fuse_file *ff) | |||
74 | kfree(ff); | 79 | kfree(ff); |
75 | } | 80 | } |
76 | 81 | ||
77 | static struct fuse_file *fuse_file_get(struct fuse_file *ff) | 82 | struct fuse_file *fuse_file_get(struct fuse_file *ff) |
78 | { | 83 | { |
79 | atomic_inc(&ff->count); | 84 | atomic_inc(&ff->count); |
80 | return ff; | 85 | return ff; |
@@ -82,40 +87,65 @@ static struct fuse_file *fuse_file_get(struct fuse_file *ff) | |||
82 | 87 | ||
83 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 88 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) |
84 | { | 89 | { |
85 | dput(req->misc.release.dentry); | 90 | path_put(&req->misc.release.path); |
86 | mntput(req->misc.release.vfsmount); | ||
87 | } | 91 | } |
88 | 92 | ||
89 | static void fuse_file_put(struct fuse_file *ff) | 93 | static void fuse_file_put(struct fuse_file *ff) |
90 | { | 94 | { |
91 | if (atomic_dec_and_test(&ff->count)) { | 95 | if (atomic_dec_and_test(&ff->count)) { |
92 | struct fuse_req *req = ff->reserved_req; | 96 | struct fuse_req *req = ff->reserved_req; |
93 | struct inode *inode = req->misc.release.dentry->d_inode; | 97 | |
94 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
95 | req->end = fuse_release_end; | 98 | req->end = fuse_release_end; |
96 | fuse_request_send_background(fc, req); | 99 | fuse_request_send_background(ff->fc, req); |
97 | kfree(ff); | 100 | kfree(ff); |
98 | } | 101 | } |
99 | } | 102 | } |
100 | 103 | ||
101 | void fuse_finish_open(struct inode *inode, struct file *file, | 104 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
102 | struct fuse_file *ff, struct fuse_open_out *outarg) | 105 | bool isdir) |
103 | { | 106 | { |
104 | if (outarg->open_flags & FOPEN_DIRECT_IO) | 107 | struct fuse_open_out outarg; |
108 | struct fuse_file *ff; | ||
109 | int err; | ||
110 | int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | ||
111 | |||
112 | ff = fuse_file_alloc(fc); | ||
113 | if (!ff) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | err = fuse_send_open(fc, nodeid, file, opcode, &outarg); | ||
117 | if (err) { | ||
118 | fuse_file_free(ff); | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | if (isdir) | ||
123 | outarg.open_flags &= ~FOPEN_DIRECT_IO; | ||
124 | |||
125 | ff->fh = outarg.fh; | ||
126 | ff->nodeid = nodeid; | ||
127 | ff->open_flags = outarg.open_flags; | ||
128 | file->private_data = fuse_file_get(ff); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(fuse_do_open); | ||
133 | |||
134 | void fuse_finish_open(struct inode *inode, struct file *file) | ||
135 | { | ||
136 | struct fuse_file *ff = file->private_data; | ||
137 | |||
138 | if (ff->open_flags & FOPEN_DIRECT_IO) | ||
105 | file->f_op = &fuse_direct_io_file_operations; | 139 | file->f_op = &fuse_direct_io_file_operations; |
106 | if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) | 140 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) |
107 | invalidate_inode_pages2(inode->i_mapping); | 141 | invalidate_inode_pages2(inode->i_mapping); |
108 | if (outarg->open_flags & FOPEN_NONSEEKABLE) | 142 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
109 | nonseekable_open(inode, file); | 143 | nonseekable_open(inode, file); |
110 | ff->fh = outarg->fh; | ||
111 | file->private_data = fuse_file_get(ff); | ||
112 | } | 144 | } |
113 | 145 | ||
114 | int fuse_open_common(struct inode *inode, struct file *file, int isdir) | 146 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) |
115 | { | 147 | { |
116 | struct fuse_conn *fc = get_fuse_conn(inode); | 148 | struct fuse_conn *fc = get_fuse_conn(inode); |
117 | struct fuse_open_out outarg; | ||
118 | struct fuse_file *ff; | ||
119 | int err; | 149 | int err; |
120 | 150 | ||
121 | /* VFS checks this, but only _after_ ->open() */ | 151 | /* VFS checks this, but only _after_ ->open() */ |
@@ -126,78 +156,85 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
126 | if (err) | 156 | if (err) |
127 | return err; | 157 | return err; |
128 | 158 | ||
129 | ff = fuse_file_alloc(fc); | 159 | err = fuse_do_open(fc, get_node_id(inode), file, isdir); |
130 | if (!ff) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | err = fuse_send_open(inode, file, isdir, &outarg); | ||
134 | if (err) | 160 | if (err) |
135 | fuse_file_free(ff); | 161 | return err; |
136 | else { | ||
137 | if (isdir) | ||
138 | outarg.open_flags &= ~FOPEN_DIRECT_IO; | ||
139 | fuse_finish_open(inode, file, ff, &outarg); | ||
140 | } | ||
141 | 162 | ||
142 | return err; | 163 | fuse_finish_open(inode, file); |
164 | |||
165 | return 0; | ||
143 | } | 166 | } |
144 | 167 | ||
145 | void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode) | 168 | static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) |
146 | { | 169 | { |
170 | struct fuse_conn *fc = ff->fc; | ||
147 | struct fuse_req *req = ff->reserved_req; | 171 | struct fuse_req *req = ff->reserved_req; |
148 | struct fuse_release_in *inarg = &req->misc.release.in; | 172 | struct fuse_release_in *inarg = &req->misc.release.in; |
149 | 173 | ||
174 | spin_lock(&fc->lock); | ||
175 | list_del(&ff->write_entry); | ||
176 | if (!RB_EMPTY_NODE(&ff->polled_node)) | ||
177 | rb_erase(&ff->polled_node, &fc->polled_files); | ||
178 | spin_unlock(&fc->lock); | ||
179 | |||
180 | wake_up_interruptible_sync(&ff->poll_wait); | ||
181 | |||
150 | inarg->fh = ff->fh; | 182 | inarg->fh = ff->fh; |
151 | inarg->flags = flags; | 183 | inarg->flags = flags; |
152 | req->in.h.opcode = opcode; | 184 | req->in.h.opcode = opcode; |
153 | req->in.h.nodeid = nodeid; | 185 | req->in.h.nodeid = ff->nodeid; |
154 | req->in.numargs = 1; | 186 | req->in.numargs = 1; |
155 | req->in.args[0].size = sizeof(struct fuse_release_in); | 187 | req->in.args[0].size = sizeof(struct fuse_release_in); |
156 | req->in.args[0].value = inarg; | 188 | req->in.args[0].value = inarg; |
157 | } | 189 | } |
158 | 190 | ||
159 | int fuse_release_common(struct inode *inode, struct file *file, int isdir) | 191 | void fuse_release_common(struct file *file, int opcode) |
160 | { | 192 | { |
161 | struct fuse_file *ff = file->private_data; | 193 | struct fuse_file *ff; |
162 | if (ff) { | 194 | struct fuse_req *req; |
163 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
164 | struct fuse_req *req = ff->reserved_req; | ||
165 | |||
166 | fuse_release_fill(ff, get_node_id(inode), file->f_flags, | ||
167 | isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); | ||
168 | 195 | ||
169 | /* Hold vfsmount and dentry until release is finished */ | 196 | ff = file->private_data; |
170 | req->misc.release.vfsmount = mntget(file->f_path.mnt); | 197 | if (unlikely(!ff)) |
171 | req->misc.release.dentry = dget(file->f_path.dentry); | 198 | return; |
172 | 199 | ||
173 | spin_lock(&fc->lock); | 200 | req = ff->reserved_req; |
174 | list_del(&ff->write_entry); | 201 | fuse_prepare_release(ff, file->f_flags, opcode); |
175 | if (!RB_EMPTY_NODE(&ff->polled_node)) | ||
176 | rb_erase(&ff->polled_node, &fc->polled_files); | ||
177 | spin_unlock(&fc->lock); | ||
178 | 202 | ||
179 | wake_up_interruptible_sync(&ff->poll_wait); | 203 | /* Hold vfsmount and dentry until release is finished */ |
180 | /* | 204 | path_get(&file->f_path); |
181 | * Normally this will send the RELEASE request, | 205 | req->misc.release.path = file->f_path; |
182 | * however if some asynchronous READ or WRITE requests | ||
183 | * are outstanding, the sending will be delayed | ||
184 | */ | ||
185 | fuse_file_put(ff); | ||
186 | } | ||
187 | 206 | ||
188 | /* Return value is ignored by VFS */ | 207 | /* |
189 | return 0; | 208 | * Normally this will send the RELEASE request, however if |
209 | * some asynchronous READ or WRITE requests are outstanding, | ||
210 | * the sending will be delayed. | ||
211 | */ | ||
212 | fuse_file_put(ff); | ||
190 | } | 213 | } |
191 | 214 | ||
192 | static int fuse_open(struct inode *inode, struct file *file) | 215 | static int fuse_open(struct inode *inode, struct file *file) |
193 | { | 216 | { |
194 | return fuse_open_common(inode, file, 0); | 217 | return fuse_open_common(inode, file, false); |
195 | } | 218 | } |
196 | 219 | ||
197 | static int fuse_release(struct inode *inode, struct file *file) | 220 | static int fuse_release(struct inode *inode, struct file *file) |
198 | { | 221 | { |
199 | return fuse_release_common(inode, file, 0); | 222 | fuse_release_common(file, FUSE_RELEASE); |
223 | |||
224 | /* return value is ignored by VFS */ | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | void fuse_sync_release(struct fuse_file *ff, int flags) | ||
229 | { | ||
230 | WARN_ON(atomic_read(&ff->count) > 1); | ||
231 | fuse_prepare_release(ff, flags, FUSE_RELEASE); | ||
232 | ff->reserved_req->force = 1; | ||
233 | fuse_request_send(ff->fc, ff->reserved_req); | ||
234 | fuse_put_request(ff->fc, ff->reserved_req); | ||
235 | kfree(ff); | ||
200 | } | 236 | } |
237 | EXPORT_SYMBOL_GPL(fuse_sync_release); | ||
201 | 238 | ||
202 | /* | 239 | /* |
203 | * Scramble the ID space with XTEA, so that the value of the files_struct | 240 | * Scramble the ID space with XTEA, so that the value of the files_struct |
@@ -371,8 +408,8 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) | |||
371 | return fuse_fsync_common(file, de, datasync, 0); | 408 | return fuse_fsync_common(file, de, datasync, 0); |
372 | } | 409 | } |
373 | 410 | ||
374 | void fuse_read_fill(struct fuse_req *req, struct file *file, | 411 | void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, |
375 | struct inode *inode, loff_t pos, size_t count, int opcode) | 412 | size_t count, int opcode) |
376 | { | 413 | { |
377 | struct fuse_read_in *inarg = &req->misc.read.in; | 414 | struct fuse_read_in *inarg = &req->misc.read.in; |
378 | struct fuse_file *ff = file->private_data; | 415 | struct fuse_file *ff = file->private_data; |
@@ -382,7 +419,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
382 | inarg->size = count; | 419 | inarg->size = count; |
383 | inarg->flags = file->f_flags; | 420 | inarg->flags = file->f_flags; |
384 | req->in.h.opcode = opcode; | 421 | req->in.h.opcode = opcode; |
385 | req->in.h.nodeid = get_node_id(inode); | 422 | req->in.h.nodeid = ff->nodeid; |
386 | req->in.numargs = 1; | 423 | req->in.numargs = 1; |
387 | req->in.args[0].size = sizeof(struct fuse_read_in); | 424 | req->in.args[0].size = sizeof(struct fuse_read_in); |
388 | req->in.args[0].value = inarg; | 425 | req->in.args[0].value = inarg; |
@@ -392,12 +429,12 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
392 | } | 429 | } |
393 | 430 | ||
394 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, | 431 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, |
395 | struct inode *inode, loff_t pos, size_t count, | 432 | loff_t pos, size_t count, fl_owner_t owner) |
396 | fl_owner_t owner) | ||
397 | { | 433 | { |
398 | struct fuse_conn *fc = get_fuse_conn(inode); | 434 | struct fuse_file *ff = file->private_data; |
435 | struct fuse_conn *fc = ff->fc; | ||
399 | 436 | ||
400 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 437 | fuse_read_fill(req, file, pos, count, FUSE_READ); |
401 | if (owner != NULL) { | 438 | if (owner != NULL) { |
402 | struct fuse_read_in *inarg = &req->misc.read.in; | 439 | struct fuse_read_in *inarg = &req->misc.read.in; |
403 | 440 | ||
@@ -455,7 +492,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
455 | req->out.argpages = 1; | 492 | req->out.argpages = 1; |
456 | req->num_pages = 1; | 493 | req->num_pages = 1; |
457 | req->pages[0] = page; | 494 | req->pages[0] = page; |
458 | num_read = fuse_send_read(req, file, inode, pos, count, NULL); | 495 | num_read = fuse_send_read(req, file, pos, count, NULL); |
459 | err = req->out.h.error; | 496 | err = req->out.h.error; |
460 | fuse_put_request(fc, req); | 497 | fuse_put_request(fc, req); |
461 | 498 | ||
@@ -504,19 +541,18 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
504 | fuse_file_put(req->ff); | 541 | fuse_file_put(req->ff); |
505 | } | 542 | } |
506 | 543 | ||
507 | static void fuse_send_readpages(struct fuse_req *req, struct file *file, | 544 | static void fuse_send_readpages(struct fuse_req *req, struct file *file) |
508 | struct inode *inode) | ||
509 | { | 545 | { |
510 | struct fuse_conn *fc = get_fuse_conn(inode); | 546 | struct fuse_file *ff = file->private_data; |
547 | struct fuse_conn *fc = ff->fc; | ||
511 | loff_t pos = page_offset(req->pages[0]); | 548 | loff_t pos = page_offset(req->pages[0]); |
512 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 549 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
513 | 550 | ||
514 | req->out.argpages = 1; | 551 | req->out.argpages = 1; |
515 | req->out.page_zeroing = 1; | 552 | req->out.page_zeroing = 1; |
516 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 553 | fuse_read_fill(req, file, pos, count, FUSE_READ); |
517 | req->misc.read.attr_ver = fuse_get_attr_version(fc); | 554 | req->misc.read.attr_ver = fuse_get_attr_version(fc); |
518 | if (fc->async_read) { | 555 | if (fc->async_read) { |
519 | struct fuse_file *ff = file->private_data; | ||
520 | req->ff = fuse_file_get(ff); | 556 | req->ff = fuse_file_get(ff); |
521 | req->end = fuse_readpages_end; | 557 | req->end = fuse_readpages_end; |
522 | fuse_request_send_background(fc, req); | 558 | fuse_request_send_background(fc, req); |
@@ -546,7 +582,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
546 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 582 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
547 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 583 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
548 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 584 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
549 | fuse_send_readpages(req, data->file, inode); | 585 | fuse_send_readpages(req, data->file); |
550 | data->req = req = fuse_get_req(fc); | 586 | data->req = req = fuse_get_req(fc); |
551 | if (IS_ERR(req)) { | 587 | if (IS_ERR(req)) { |
552 | unlock_page(page); | 588 | unlock_page(page); |
@@ -580,7 +616,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
580 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 616 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
581 | if (!err) { | 617 | if (!err) { |
582 | if (data.req->num_pages) | 618 | if (data.req->num_pages) |
583 | fuse_send_readpages(data.req, file, inode); | 619 | fuse_send_readpages(data.req, file); |
584 | else | 620 | else |
585 | fuse_put_request(fc, data.req); | 621 | fuse_put_request(fc, data.req); |
586 | } | 622 | } |
@@ -607,24 +643,19 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
607 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | 643 | return generic_file_aio_read(iocb, iov, nr_segs, pos); |
608 | } | 644 | } |
609 | 645 | ||
610 | static void fuse_write_fill(struct fuse_req *req, struct file *file, | 646 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, |
611 | struct fuse_file *ff, struct inode *inode, | 647 | loff_t pos, size_t count) |
612 | loff_t pos, size_t count, int writepage) | ||
613 | { | 648 | { |
614 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
615 | struct fuse_write_in *inarg = &req->misc.write.in; | 649 | struct fuse_write_in *inarg = &req->misc.write.in; |
616 | struct fuse_write_out *outarg = &req->misc.write.out; | 650 | struct fuse_write_out *outarg = &req->misc.write.out; |
617 | 651 | ||
618 | memset(inarg, 0, sizeof(struct fuse_write_in)); | ||
619 | inarg->fh = ff->fh; | 652 | inarg->fh = ff->fh; |
620 | inarg->offset = pos; | 653 | inarg->offset = pos; |
621 | inarg->size = count; | 654 | inarg->size = count; |
622 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | ||
623 | inarg->flags = file ? file->f_flags : 0; | ||
624 | req->in.h.opcode = FUSE_WRITE; | 655 | req->in.h.opcode = FUSE_WRITE; |
625 | req->in.h.nodeid = get_node_id(inode); | 656 | req->in.h.nodeid = ff->nodeid; |
626 | req->in.numargs = 2; | 657 | req->in.numargs = 2; |
627 | if (fc->minor < 9) | 658 | if (ff->fc->minor < 9) |
628 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; | 659 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; |
629 | else | 660 | else |
630 | req->in.args[0].size = sizeof(struct fuse_write_in); | 661 | req->in.args[0].size = sizeof(struct fuse_write_in); |
@@ -636,13 +667,15 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file, | |||
636 | } | 667 | } |
637 | 668 | ||
638 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 669 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, |
639 | struct inode *inode, loff_t pos, size_t count, | 670 | loff_t pos, size_t count, fl_owner_t owner) |
640 | fl_owner_t owner) | ||
641 | { | 671 | { |
642 | struct fuse_conn *fc = get_fuse_conn(inode); | 672 | struct fuse_file *ff = file->private_data; |
643 | fuse_write_fill(req, file, file->private_data, inode, pos, count, 0); | 673 | struct fuse_conn *fc = ff->fc; |
674 | struct fuse_write_in *inarg = &req->misc.write.in; | ||
675 | |||
676 | fuse_write_fill(req, ff, pos, count); | ||
677 | inarg->flags = file->f_flags; | ||
644 | if (owner != NULL) { | 678 | if (owner != NULL) { |
645 | struct fuse_write_in *inarg = &req->misc.write.in; | ||
646 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 679 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
647 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | 680 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); |
648 | } | 681 | } |
@@ -700,7 +733,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
700 | req->num_pages = 1; | 733 | req->num_pages = 1; |
701 | req->pages[0] = page; | 734 | req->pages[0] = page; |
702 | req->page_offset = offset; | 735 | req->page_offset = offset; |
703 | nres = fuse_send_write(req, file, inode, pos, count, NULL); | 736 | nres = fuse_send_write(req, file, pos, count, NULL); |
704 | err = req->out.h.error; | 737 | err = req->out.h.error; |
705 | fuse_put_request(fc, req); | 738 | fuse_put_request(fc, req); |
706 | if (!err && !nres) | 739 | if (!err && !nres) |
@@ -741,7 +774,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | |||
741 | for (i = 0; i < req->num_pages; i++) | 774 | for (i = 0; i < req->num_pages; i++) |
742 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); | 775 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); |
743 | 776 | ||
744 | res = fuse_send_write(req, file, inode, pos, count, NULL); | 777 | res = fuse_send_write(req, file, pos, count, NULL); |
745 | 778 | ||
746 | offset = req->page_offset; | 779 | offset = req->page_offset; |
747 | count = res; | 780 | count = res; |
@@ -979,25 +1012,23 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | |||
979 | return 0; | 1012 | return 0; |
980 | } | 1013 | } |
981 | 1014 | ||
982 | static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | 1015 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, |
983 | size_t count, loff_t *ppos, int write) | 1016 | size_t count, loff_t *ppos, int write) |
984 | { | 1017 | { |
985 | struct inode *inode = file->f_path.dentry->d_inode; | 1018 | struct fuse_file *ff = file->private_data; |
986 | struct fuse_conn *fc = get_fuse_conn(inode); | 1019 | struct fuse_conn *fc = ff->fc; |
987 | size_t nmax = write ? fc->max_write : fc->max_read; | 1020 | size_t nmax = write ? fc->max_write : fc->max_read; |
988 | loff_t pos = *ppos; | 1021 | loff_t pos = *ppos; |
989 | ssize_t res = 0; | 1022 | ssize_t res = 0; |
990 | struct fuse_req *req; | 1023 | struct fuse_req *req; |
991 | 1024 | ||
992 | if (is_bad_inode(inode)) | ||
993 | return -EIO; | ||
994 | |||
995 | req = fuse_get_req(fc); | 1025 | req = fuse_get_req(fc); |
996 | if (IS_ERR(req)) | 1026 | if (IS_ERR(req)) |
997 | return PTR_ERR(req); | 1027 | return PTR_ERR(req); |
998 | 1028 | ||
999 | while (count) { | 1029 | while (count) { |
1000 | size_t nres; | 1030 | size_t nres; |
1031 | fl_owner_t owner = current->files; | ||
1001 | size_t nbytes = min(count, nmax); | 1032 | size_t nbytes = min(count, nmax); |
1002 | int err = fuse_get_user_pages(req, buf, &nbytes, write); | 1033 | int err = fuse_get_user_pages(req, buf, &nbytes, write); |
1003 | if (err) { | 1034 | if (err) { |
@@ -1006,11 +1037,10 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1006 | } | 1037 | } |
1007 | 1038 | ||
1008 | if (write) | 1039 | if (write) |
1009 | nres = fuse_send_write(req, file, inode, pos, nbytes, | 1040 | nres = fuse_send_write(req, file, pos, nbytes, owner); |
1010 | current->files); | ||
1011 | else | 1041 | else |
1012 | nres = fuse_send_read(req, file, inode, pos, nbytes, | 1042 | nres = fuse_send_read(req, file, pos, nbytes, owner); |
1013 | current->files); | 1043 | |
1014 | fuse_release_user_pages(req, !write); | 1044 | fuse_release_user_pages(req, !write); |
1015 | if (req->out.h.error) { | 1045 | if (req->out.h.error) { |
1016 | if (!res) | 1046 | if (!res) |
@@ -1034,20 +1064,27 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1034 | } | 1064 | } |
1035 | } | 1065 | } |
1036 | fuse_put_request(fc, req); | 1066 | fuse_put_request(fc, req); |
1037 | if (res > 0) { | 1067 | if (res > 0) |
1038 | if (write) | ||
1039 | fuse_write_update_size(inode, pos); | ||
1040 | *ppos = pos; | 1068 | *ppos = pos; |
1041 | } | ||
1042 | fuse_invalidate_attr(inode); | ||
1043 | 1069 | ||
1044 | return res; | 1070 | return res; |
1045 | } | 1071 | } |
1072 | EXPORT_SYMBOL_GPL(fuse_direct_io); | ||
1046 | 1073 | ||
1047 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, | 1074 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, |
1048 | size_t count, loff_t *ppos) | 1075 | size_t count, loff_t *ppos) |
1049 | { | 1076 | { |
1050 | return fuse_direct_io(file, buf, count, ppos, 0); | 1077 | ssize_t res; |
1078 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1079 | |||
1080 | if (is_bad_inode(inode)) | ||
1081 | return -EIO; | ||
1082 | |||
1083 | res = fuse_direct_io(file, buf, count, ppos, 0); | ||
1084 | |||
1085 | fuse_invalidate_attr(inode); | ||
1086 | |||
1087 | return res; | ||
1051 | } | 1088 | } |
1052 | 1089 | ||
1053 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | 1090 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, |
@@ -1055,12 +1092,22 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
1055 | { | 1092 | { |
1056 | struct inode *inode = file->f_path.dentry->d_inode; | 1093 | struct inode *inode = file->f_path.dentry->d_inode; |
1057 | ssize_t res; | 1094 | ssize_t res; |
1095 | |||
1096 | if (is_bad_inode(inode)) | ||
1097 | return -EIO; | ||
1098 | |||
1058 | /* Don't allow parallel writes to the same file */ | 1099 | /* Don't allow parallel writes to the same file */ |
1059 | mutex_lock(&inode->i_mutex); | 1100 | mutex_lock(&inode->i_mutex); |
1060 | res = generic_write_checks(file, ppos, &count, 0); | 1101 | res = generic_write_checks(file, ppos, &count, 0); |
1061 | if (!res) | 1102 | if (!res) { |
1062 | res = fuse_direct_io(file, buf, count, ppos, 1); | 1103 | res = fuse_direct_io(file, buf, count, ppos, 1); |
1104 | if (res > 0) | ||
1105 | fuse_write_update_size(inode, *ppos); | ||
1106 | } | ||
1063 | mutex_unlock(&inode->i_mutex); | 1107 | mutex_unlock(&inode->i_mutex); |
1108 | |||
1109 | fuse_invalidate_attr(inode); | ||
1110 | |||
1064 | return res; | 1111 | return res; |
1065 | } | 1112 | } |
1066 | 1113 | ||
@@ -1177,9 +1224,10 @@ static int fuse_writepage_locked(struct page *page) | |||
1177 | req->ff = fuse_file_get(ff); | 1224 | req->ff = fuse_file_get(ff); |
1178 | spin_unlock(&fc->lock); | 1225 | spin_unlock(&fc->lock); |
1179 | 1226 | ||
1180 | fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); | 1227 | fuse_write_fill(req, ff, page_offset(page), 0); |
1181 | 1228 | ||
1182 | copy_highpage(tmp_page, page); | 1229 | copy_highpage(tmp_page, page); |
1230 | req->misc.write.in.write_flags |= FUSE_WRITE_CACHE; | ||
1183 | req->in.argpages = 1; | 1231 | req->in.argpages = 1; |
1184 | req->num_pages = 1; | 1232 | req->num_pages = 1; |
1185 | req->pages[0] = tmp_page; | 1233 | req->pages[0] = tmp_page; |
@@ -1603,12 +1651,11 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, | |||
1603 | * limits ioctl data transfers to well-formed ioctls and is the forced | 1651 | * limits ioctl data transfers to well-formed ioctls and is the forced |
1604 | * behavior for all FUSE servers. | 1652 | * behavior for all FUSE servers. |
1605 | */ | 1653 | */ |
1606 | static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | 1654 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, |
1607 | unsigned long arg, unsigned int flags) | 1655 | unsigned int flags) |
1608 | { | 1656 | { |
1609 | struct inode *inode = file->f_dentry->d_inode; | ||
1610 | struct fuse_file *ff = file->private_data; | 1657 | struct fuse_file *ff = file->private_data; |
1611 | struct fuse_conn *fc = get_fuse_conn(inode); | 1658 | struct fuse_conn *fc = ff->fc; |
1612 | struct fuse_ioctl_in inarg = { | 1659 | struct fuse_ioctl_in inarg = { |
1613 | .fh = ff->fh, | 1660 | .fh = ff->fh, |
1614 | .cmd = cmd, | 1661 | .cmd = cmd, |
@@ -1627,13 +1674,6 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1627 | /* assume all the iovs returned by client always fits in a page */ | 1674 | /* assume all the iovs returned by client always fits in a page */ |
1628 | BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); | 1675 | BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); |
1629 | 1676 | ||
1630 | if (!fuse_allow_task(fc, current)) | ||
1631 | return -EACCES; | ||
1632 | |||
1633 | err = -EIO; | ||
1634 | if (is_bad_inode(inode)) | ||
1635 | goto out; | ||
1636 | |||
1637 | err = -ENOMEM; | 1677 | err = -ENOMEM; |
1638 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); | 1678 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); |
1639 | iov_page = alloc_page(GFP_KERNEL); | 1679 | iov_page = alloc_page(GFP_KERNEL); |
@@ -1694,7 +1734,7 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1694 | 1734 | ||
1695 | /* okay, let's send it to the client */ | 1735 | /* okay, let's send it to the client */ |
1696 | req->in.h.opcode = FUSE_IOCTL; | 1736 | req->in.h.opcode = FUSE_IOCTL; |
1697 | req->in.h.nodeid = get_node_id(inode); | 1737 | req->in.h.nodeid = ff->nodeid; |
1698 | req->in.numargs = 1; | 1738 | req->in.numargs = 1; |
1699 | req->in.args[0].size = sizeof(inarg); | 1739 | req->in.args[0].size = sizeof(inarg); |
1700 | req->in.args[0].value = &inarg; | 1740 | req->in.args[0].value = &inarg; |
@@ -1777,17 +1817,33 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1777 | 1817 | ||
1778 | return err ? err : outarg.result; | 1818 | return err ? err : outarg.result; |
1779 | } | 1819 | } |
1820 | EXPORT_SYMBOL_GPL(fuse_do_ioctl); | ||
1821 | |||
1822 | static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, | ||
1823 | unsigned long arg, unsigned int flags) | ||
1824 | { | ||
1825 | struct inode *inode = file->f_dentry->d_inode; | ||
1826 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
1827 | |||
1828 | if (!fuse_allow_task(fc, current)) | ||
1829 | return -EACCES; | ||
1830 | |||
1831 | if (is_bad_inode(inode)) | ||
1832 | return -EIO; | ||
1833 | |||
1834 | return fuse_do_ioctl(file, cmd, arg, flags); | ||
1835 | } | ||
1780 | 1836 | ||
1781 | static long fuse_file_ioctl(struct file *file, unsigned int cmd, | 1837 | static long fuse_file_ioctl(struct file *file, unsigned int cmd, |
1782 | unsigned long arg) | 1838 | unsigned long arg) |
1783 | { | 1839 | { |
1784 | return fuse_file_do_ioctl(file, cmd, arg, 0); | 1840 | return fuse_file_ioctl_common(file, cmd, arg, 0); |
1785 | } | 1841 | } |
1786 | 1842 | ||
1787 | static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, | 1843 | static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, |
1788 | unsigned long arg) | 1844 | unsigned long arg) |
1789 | { | 1845 | { |
1790 | return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT); | 1846 | return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); |
1791 | } | 1847 | } |
1792 | 1848 | ||
1793 | /* | 1849 | /* |
@@ -1841,11 +1897,10 @@ static void fuse_register_polled_file(struct fuse_conn *fc, | |||
1841 | spin_unlock(&fc->lock); | 1897 | spin_unlock(&fc->lock); |
1842 | } | 1898 | } |
1843 | 1899 | ||
1844 | static unsigned fuse_file_poll(struct file *file, poll_table *wait) | 1900 | unsigned fuse_file_poll(struct file *file, poll_table *wait) |
1845 | { | 1901 | { |
1846 | struct inode *inode = file->f_dentry->d_inode; | ||
1847 | struct fuse_file *ff = file->private_data; | 1902 | struct fuse_file *ff = file->private_data; |
1848 | struct fuse_conn *fc = get_fuse_conn(inode); | 1903 | struct fuse_conn *fc = ff->fc; |
1849 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; | 1904 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; |
1850 | struct fuse_poll_out outarg; | 1905 | struct fuse_poll_out outarg; |
1851 | struct fuse_req *req; | 1906 | struct fuse_req *req; |
@@ -1870,7 +1925,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
1870 | return PTR_ERR(req); | 1925 | return PTR_ERR(req); |
1871 | 1926 | ||
1872 | req->in.h.opcode = FUSE_POLL; | 1927 | req->in.h.opcode = FUSE_POLL; |
1873 | req->in.h.nodeid = get_node_id(inode); | 1928 | req->in.h.nodeid = ff->nodeid; |
1874 | req->in.numargs = 1; | 1929 | req->in.numargs = 1; |
1875 | req->in.args[0].size = sizeof(inarg); | 1930 | req->in.args[0].size = sizeof(inarg); |
1876 | req->in.args[0].value = &inarg; | 1931 | req->in.args[0].value = &inarg; |
@@ -1889,6 +1944,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
1889 | } | 1944 | } |
1890 | return POLLERR; | 1945 | return POLLERR; |
1891 | } | 1946 | } |
1947 | EXPORT_SYMBOL_GPL(fuse_file_poll); | ||
1892 | 1948 | ||
1893 | /* | 1949 | /* |
1894 | * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and | 1950 | * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6fc5aedaa0d5..aaf2f9ff970e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -97,8 +97,13 @@ struct fuse_inode { | |||
97 | struct list_head writepages; | 97 | struct list_head writepages; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | struct fuse_conn; | ||
101 | |||
100 | /** FUSE specific file data */ | 102 | /** FUSE specific file data */ |
101 | struct fuse_file { | 103 | struct fuse_file { |
104 | /** Fuse connection for this file */ | ||
105 | struct fuse_conn *fc; | ||
106 | |||
102 | /** Request reserved for flush and release */ | 107 | /** Request reserved for flush and release */ |
103 | struct fuse_req *reserved_req; | 108 | struct fuse_req *reserved_req; |
104 | 109 | ||
@@ -108,9 +113,15 @@ struct fuse_file { | |||
108 | /** File handle used by userspace */ | 113 | /** File handle used by userspace */ |
109 | u64 fh; | 114 | u64 fh; |
110 | 115 | ||
116 | /** Node id of this file */ | ||
117 | u64 nodeid; | ||
118 | |||
111 | /** Refcount */ | 119 | /** Refcount */ |
112 | atomic_t count; | 120 | atomic_t count; |
113 | 121 | ||
122 | /** FOPEN_* flags returned by open */ | ||
123 | u32 open_flags; | ||
124 | |||
114 | /** Entry on inode's write_files list */ | 125 | /** Entry on inode's write_files list */ |
115 | struct list_head write_entry; | 126 | struct list_head write_entry; |
116 | 127 | ||
@@ -185,8 +196,6 @@ enum fuse_req_state { | |||
185 | FUSE_REQ_FINISHED | 196 | FUSE_REQ_FINISHED |
186 | }; | 197 | }; |
187 | 198 | ||
188 | struct fuse_conn; | ||
189 | |||
190 | /** | 199 | /** |
191 | * A request to the client | 200 | * A request to the client |
192 | */ | 201 | */ |
@@ -248,11 +257,12 @@ struct fuse_req { | |||
248 | struct fuse_forget_in forget_in; | 257 | struct fuse_forget_in forget_in; |
249 | struct { | 258 | struct { |
250 | struct fuse_release_in in; | 259 | struct fuse_release_in in; |
251 | struct vfsmount *vfsmount; | 260 | struct path path; |
252 | struct dentry *dentry; | ||
253 | } release; | 261 | } release; |
254 | struct fuse_init_in init_in; | 262 | struct fuse_init_in init_in; |
255 | struct fuse_init_out init_out; | 263 | struct fuse_init_out init_out; |
264 | struct cuse_init_in cuse_init_in; | ||
265 | struct cuse_init_out cuse_init_out; | ||
256 | struct { | 266 | struct { |
257 | struct fuse_read_in in; | 267 | struct fuse_read_in in; |
258 | u64 attr_ver; | 268 | u64 attr_ver; |
@@ -386,6 +396,9 @@ struct fuse_conn { | |||
386 | /** Filesystem supports NFS exporting. Only set in INIT */ | 396 | /** Filesystem supports NFS exporting. Only set in INIT */ |
387 | unsigned export_support:1; | 397 | unsigned export_support:1; |
388 | 398 | ||
399 | /** Set if bdi is valid */ | ||
400 | unsigned bdi_initialized:1; | ||
401 | |||
389 | /* | 402 | /* |
390 | * The following bitfields are only for optimization purposes | 403 | * The following bitfields are only for optimization purposes |
391 | * and hence races in setting them will not cause malfunction | 404 | * and hence races in setting them will not cause malfunction |
@@ -515,25 +528,24 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | |||
515 | * Initialize READ or READDIR request | 528 | * Initialize READ or READDIR request |
516 | */ | 529 | */ |
517 | void fuse_read_fill(struct fuse_req *req, struct file *file, | 530 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
518 | struct inode *inode, loff_t pos, size_t count, int opcode); | 531 | loff_t pos, size_t count, int opcode); |
519 | 532 | ||
520 | /** | 533 | /** |
521 | * Send OPEN or OPENDIR request | 534 | * Send OPEN or OPENDIR request |
522 | */ | 535 | */ |
523 | int fuse_open_common(struct inode *inode, struct file *file, int isdir); | 536 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir); |
524 | 537 | ||
525 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc); | 538 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc); |
539 | struct fuse_file *fuse_file_get(struct fuse_file *ff); | ||
526 | void fuse_file_free(struct fuse_file *ff); | 540 | void fuse_file_free(struct fuse_file *ff); |
527 | void fuse_finish_open(struct inode *inode, struct file *file, | 541 | void fuse_finish_open(struct inode *inode, struct file *file); |
528 | struct fuse_file *ff, struct fuse_open_out *outarg); | ||
529 | 542 | ||
530 | /** Fill in ff->reserved_req with a RELEASE request */ | 543 | void fuse_sync_release(struct fuse_file *ff, int flags); |
531 | void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode); | ||
532 | 544 | ||
533 | /** | 545 | /** |
534 | * Send RELEASE or RELEASEDIR request | 546 | * Send RELEASE or RELEASEDIR request |
535 | */ | 547 | */ |
536 | int fuse_release_common(struct inode *inode, struct file *file, int isdir); | 548 | void fuse_release_common(struct file *file, int opcode); |
537 | 549 | ||
538 | /** | 550 | /** |
539 | * Send FSYNC or FSYNCDIR request | 551 | * Send FSYNC or FSYNCDIR request |
@@ -652,10 +664,12 @@ void fuse_invalidate_entry_cache(struct dentry *entry); | |||
652 | */ | 664 | */ |
653 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); | 665 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); |
654 | 666 | ||
667 | void fuse_conn_kill(struct fuse_conn *fc); | ||
668 | |||
655 | /** | 669 | /** |
656 | * Initialize fuse_conn | 670 | * Initialize fuse_conn |
657 | */ | 671 | */ |
658 | int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb); | 672 | void fuse_conn_init(struct fuse_conn *fc); |
659 | 673 | ||
660 | /** | 674 | /** |
661 | * Release reference to fuse_conn | 675 | * Release reference to fuse_conn |
@@ -694,4 +708,13 @@ void fuse_release_nowrite(struct inode *inode); | |||
694 | 708 | ||
695 | u64 fuse_get_attr_version(struct fuse_conn *fc); | 709 | u64 fuse_get_attr_version(struct fuse_conn *fc); |
696 | 710 | ||
711 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | ||
712 | bool isdir); | ||
713 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, | ||
714 | size_t count, loff_t *ppos, int write); | ||
715 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | ||
716 | unsigned int flags); | ||
717 | unsigned fuse_file_poll(struct file *file, poll_table *wait); | ||
718 | int fuse_dev_release(struct inode *inode, struct file *file); | ||
719 | |||
697 | #endif /* _FS_FUSE_I_H */ | 720 | #endif /* _FS_FUSE_I_H */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 91f7c85f1ffd..f0df55a52929 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -277,11 +277,14 @@ static void fuse_send_destroy(struct fuse_conn *fc) | |||
277 | } | 277 | } |
278 | } | 278 | } |
279 | 279 | ||
280 | static void fuse_put_super(struct super_block *sb) | 280 | static void fuse_bdi_destroy(struct fuse_conn *fc) |
281 | { | 281 | { |
282 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 282 | if (fc->bdi_initialized) |
283 | bdi_destroy(&fc->bdi); | ||
284 | } | ||
283 | 285 | ||
284 | fuse_send_destroy(fc); | 286 | void fuse_conn_kill(struct fuse_conn *fc) |
287 | { | ||
285 | spin_lock(&fc->lock); | 288 | spin_lock(&fc->lock); |
286 | fc->connected = 0; | 289 | fc->connected = 0; |
287 | fc->blocked = 0; | 290 | fc->blocked = 0; |
@@ -295,7 +298,16 @@ static void fuse_put_super(struct super_block *sb) | |||
295 | list_del(&fc->entry); | 298 | list_del(&fc->entry); |
296 | fuse_ctl_remove_conn(fc); | 299 | fuse_ctl_remove_conn(fc); |
297 | mutex_unlock(&fuse_mutex); | 300 | mutex_unlock(&fuse_mutex); |
298 | bdi_destroy(&fc->bdi); | 301 | fuse_bdi_destroy(fc); |
302 | } | ||
303 | EXPORT_SYMBOL_GPL(fuse_conn_kill); | ||
304 | |||
305 | static void fuse_put_super(struct super_block *sb) | ||
306 | { | ||
307 | struct fuse_conn *fc = get_fuse_conn_super(sb); | ||
308 | |||
309 | fuse_send_destroy(fc); | ||
310 | fuse_conn_kill(fc); | ||
299 | fuse_conn_put(fc); | 311 | fuse_conn_put(fc); |
300 | } | 312 | } |
301 | 313 | ||
@@ -466,10 +478,8 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
466 | return 0; | 478 | return 0; |
467 | } | 479 | } |
468 | 480 | ||
469 | int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) | 481 | void fuse_conn_init(struct fuse_conn *fc) |
470 | { | 482 | { |
471 | int err; | ||
472 | |||
473 | memset(fc, 0, sizeof(*fc)); | 483 | memset(fc, 0, sizeof(*fc)); |
474 | spin_lock_init(&fc->lock); | 484 | spin_lock_init(&fc->lock); |
475 | mutex_init(&fc->inst_mutex); | 485 | mutex_init(&fc->inst_mutex); |
@@ -484,49 +494,12 @@ int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) | |||
484 | INIT_LIST_HEAD(&fc->bg_queue); | 494 | INIT_LIST_HEAD(&fc->bg_queue); |
485 | INIT_LIST_HEAD(&fc->entry); | 495 | INIT_LIST_HEAD(&fc->entry); |
486 | atomic_set(&fc->num_waiting, 0); | 496 | atomic_set(&fc->num_waiting, 0); |
487 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | ||
488 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | ||
489 | /* fuse does it's own writeback accounting */ | ||
490 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | ||
491 | fc->khctr = 0; | 497 | fc->khctr = 0; |
492 | fc->polled_files = RB_ROOT; | 498 | fc->polled_files = RB_ROOT; |
493 | fc->dev = sb->s_dev; | ||
494 | err = bdi_init(&fc->bdi); | ||
495 | if (err) | ||
496 | goto error_mutex_destroy; | ||
497 | if (sb->s_bdev) { | ||
498 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", | ||
499 | MAJOR(fc->dev), MINOR(fc->dev)); | ||
500 | } else { | ||
501 | err = bdi_register_dev(&fc->bdi, fc->dev); | ||
502 | } | ||
503 | if (err) | ||
504 | goto error_bdi_destroy; | ||
505 | /* | ||
506 | * For a single fuse filesystem use max 1% of dirty + | ||
507 | * writeback threshold. | ||
508 | * | ||
509 | * This gives about 1M of write buffer for memory maps on a | ||
510 | * machine with 1G and 10% dirty_ratio, which should be more | ||
511 | * than enough. | ||
512 | * | ||
513 | * Privileged users can raise it by writing to | ||
514 | * | ||
515 | * /sys/class/bdi/<bdi>/max_ratio | ||
516 | */ | ||
517 | bdi_set_max_ratio(&fc->bdi, 1); | ||
518 | fc->reqctr = 0; | 499 | fc->reqctr = 0; |
519 | fc->blocked = 1; | 500 | fc->blocked = 1; |
520 | fc->attr_version = 1; | 501 | fc->attr_version = 1; |
521 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | 502 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); |
522 | |||
523 | return 0; | ||
524 | |||
525 | error_bdi_destroy: | ||
526 | bdi_destroy(&fc->bdi); | ||
527 | error_mutex_destroy: | ||
528 | mutex_destroy(&fc->inst_mutex); | ||
529 | return err; | ||
530 | } | 503 | } |
531 | EXPORT_SYMBOL_GPL(fuse_conn_init); | 504 | EXPORT_SYMBOL_GPL(fuse_conn_init); |
532 | 505 | ||
@@ -539,12 +512,14 @@ void fuse_conn_put(struct fuse_conn *fc) | |||
539 | fc->release(fc); | 512 | fc->release(fc); |
540 | } | 513 | } |
541 | } | 514 | } |
515 | EXPORT_SYMBOL_GPL(fuse_conn_put); | ||
542 | 516 | ||
543 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) | 517 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) |
544 | { | 518 | { |
545 | atomic_inc(&fc->count); | 519 | atomic_inc(&fc->count); |
546 | return fc; | 520 | return fc; |
547 | } | 521 | } |
522 | EXPORT_SYMBOL_GPL(fuse_conn_get); | ||
548 | 523 | ||
549 | static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) | 524 | static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) |
550 | { | 525 | { |
@@ -797,6 +772,48 @@ static void fuse_free_conn(struct fuse_conn *fc) | |||
797 | kfree(fc); | 772 | kfree(fc); |
798 | } | 773 | } |
799 | 774 | ||
775 | static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) | ||
776 | { | ||
777 | int err; | ||
778 | |||
779 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | ||
780 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | ||
781 | /* fuse does it's own writeback accounting */ | ||
782 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | ||
783 | |||
784 | err = bdi_init(&fc->bdi); | ||
785 | if (err) | ||
786 | return err; | ||
787 | |||
788 | fc->bdi_initialized = 1; | ||
789 | |||
790 | if (sb->s_bdev) { | ||
791 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", | ||
792 | MAJOR(fc->dev), MINOR(fc->dev)); | ||
793 | } else { | ||
794 | err = bdi_register_dev(&fc->bdi, fc->dev); | ||
795 | } | ||
796 | |||
797 | if (err) | ||
798 | return err; | ||
799 | |||
800 | /* | ||
801 | * For a single fuse filesystem use max 1% of dirty + | ||
802 | * writeback threshold. | ||
803 | * | ||
804 | * This gives about 1M of write buffer for memory maps on a | ||
805 | * machine with 1G and 10% dirty_ratio, which should be more | ||
806 | * than enough. | ||
807 | * | ||
808 | * Privileged users can raise it by writing to | ||
809 | * | ||
810 | * /sys/class/bdi/<bdi>/max_ratio | ||
811 | */ | ||
812 | bdi_set_max_ratio(&fc->bdi, 1); | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
800 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) | 817 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) |
801 | { | 818 | { |
802 | struct fuse_conn *fc; | 819 | struct fuse_conn *fc; |
@@ -843,11 +860,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
843 | if (!fc) | 860 | if (!fc) |
844 | goto err_fput; | 861 | goto err_fput; |
845 | 862 | ||
846 | err = fuse_conn_init(fc, sb); | 863 | fuse_conn_init(fc); |
847 | if (err) { | 864 | |
848 | kfree(fc); | 865 | fc->dev = sb->s_dev; |
849 | goto err_fput; | 866 | err = fuse_bdi_init(fc, sb); |
850 | } | 867 | if (err) |
868 | goto err_put_conn; | ||
851 | 869 | ||
852 | fc->release = fuse_free_conn; | 870 | fc->release = fuse_free_conn; |
853 | fc->flags = d.flags; | 871 | fc->flags = d.flags; |
@@ -911,7 +929,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
911 | err_put_root: | 929 | err_put_root: |
912 | dput(root_dentry); | 930 | dput(root_dentry); |
913 | err_put_conn: | 931 | err_put_conn: |
914 | bdi_destroy(&fc->bdi); | 932 | fuse_bdi_destroy(fc); |
915 | fuse_conn_put(fc); | 933 | fuse_conn_put(fc); |
916 | err_fput: | 934 | err_fput: |
917 | fput(file); | 935 | fput(file); |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 0af36085eb28..1a9c7878f864 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -556,27 +556,49 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
556 | 556 | ||
557 | /* add partitions */ | 557 | /* add partitions */ |
558 | for (p = 1; p < state->limit; p++) { | 558 | for (p = 1; p < state->limit; p++) { |
559 | sector_t size = state->parts[p].size; | 559 | sector_t size, from; |
560 | sector_t from = state->parts[p].from; | 560 | try_scan: |
561 | size = state->parts[p].size; | ||
561 | if (!size) | 562 | if (!size) |
562 | continue; | 563 | continue; |
564 | |||
565 | from = state->parts[p].from; | ||
563 | if (from >= get_capacity(disk)) { | 566 | if (from >= get_capacity(disk)) { |
564 | printk(KERN_WARNING | 567 | printk(KERN_WARNING |
565 | "%s: p%d ignored, start %llu is behind the end of the disk\n", | 568 | "%s: p%d ignored, start %llu is behind the end of the disk\n", |
566 | disk->disk_name, p, (unsigned long long) from); | 569 | disk->disk_name, p, (unsigned long long) from); |
567 | continue; | 570 | continue; |
568 | } | 571 | } |
572 | |||
569 | if (from + size > get_capacity(disk)) { | 573 | if (from + size > get_capacity(disk)) { |
570 | /* | 574 | struct block_device_operations *bdops = disk->fops; |
571 | * we can not ignore partitions of broken tables | 575 | unsigned long long capacity; |
572 | * created by for example camera firmware, but we | 576 | |
573 | * limit them to the end of the disk to avoid | ||
574 | * creating invalid block devices | ||
575 | */ | ||
576 | printk(KERN_WARNING | 577 | printk(KERN_WARNING |
577 | "%s: p%d size %llu limited to end of disk\n", | 578 | "%s: p%d size %llu exceeds device capacity, ", |
578 | disk->disk_name, p, (unsigned long long) size); | 579 | disk->disk_name, p, (unsigned long long) size); |
579 | size = get_capacity(disk) - from; | 580 | |
581 | if (bdops->set_capacity && | ||
582 | (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) { | ||
583 | printk(KERN_CONT "enabling native capacity\n"); | ||
584 | capacity = bdops->set_capacity(disk, ~0ULL); | ||
585 | disk->flags |= GENHD_FL_NATIVE_CAPACITY; | ||
586 | if (capacity > get_capacity(disk)) { | ||
587 | set_capacity(disk, capacity); | ||
588 | check_disk_size_change(disk, bdev); | ||
589 | bdev->bd_invalidated = 0; | ||
590 | } | ||
591 | goto try_scan; | ||
592 | } else { | ||
593 | /* | ||
594 | * we can not ignore partitions of broken tables | ||
595 | * created by for example camera firmware, but | ||
596 | * we limit them to the end of the disk to avoid | ||
597 | * creating invalid block devices | ||
598 | */ | ||
599 | printk(KERN_CONT "limited to end of disk\n"); | ||
600 | size = get_capacity(disk) - from; | ||
601 | } | ||
580 | } | 602 | } |
581 | part = add_partition(disk, p, from, size, | 603 | part = add_partition(disk, p, from, size, |
582 | state->parts[p].flags); | 604 | state->parts[p].flags); |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ebdfde8fe556..0b1a6cae9de1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -1226,6 +1226,8 @@ struct block_device_operations { | |||
1226 | int (*direct_access) (struct block_device *, sector_t, | 1226 | int (*direct_access) (struct block_device *, sector_t, |
1227 | void **, unsigned long *); | 1227 | void **, unsigned long *); |
1228 | int (*media_changed) (struct gendisk *); | 1228 | int (*media_changed) (struct gendisk *); |
1229 | unsigned long long (*set_capacity) (struct gendisk *, | ||
1230 | unsigned long long); | ||
1229 | int (*revalidate_disk) (struct gendisk *); | 1231 | int (*revalidate_disk) (struct gendisk *); |
1230 | int (*getgeo)(struct block_device *, struct hd_geometry *); | 1232 | int (*getgeo)(struct block_device *, struct hd_geometry *); |
1231 | struct module *owner; | 1233 | struct module *owner; |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 37bcb50a4d7c..04fb5135b4e1 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -261,6 +261,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
261 | # define __section(S) __attribute__ ((__section__(#S))) | 261 | # define __section(S) __attribute__ ((__section__(#S))) |
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | /* Are two types/vars the same type (ignoring qualifiers)? */ | ||
265 | #ifndef __same_type | ||
266 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | ||
267 | #endif | ||
268 | |||
264 | /* | 269 | /* |
265 | * Prevent the compiler from merging or refetching accesses. The compiler | 270 | * Prevent the compiler from merging or refetching accesses. The compiler |
266 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | 271 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), |
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 162e5defe683..d41ed593f79f 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
@@ -121,6 +121,13 @@ struct fuse_file_lock { | |||
121 | #define FUSE_BIG_WRITES (1 << 5) | 121 | #define FUSE_BIG_WRITES (1 << 5) |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * CUSE INIT request/reply flags | ||
125 | * | ||
126 | * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl | ||
127 | */ | ||
128 | #define CUSE_UNRESTRICTED_IOCTL (1 << 0) | ||
129 | |||
130 | /** | ||
124 | * Release flags | 131 | * Release flags |
125 | */ | 132 | */ |
126 | #define FUSE_RELEASE_FLUSH (1 << 0) | 133 | #define FUSE_RELEASE_FLUSH (1 << 0) |
@@ -210,6 +217,9 @@ enum fuse_opcode { | |||
210 | FUSE_DESTROY = 38, | 217 | FUSE_DESTROY = 38, |
211 | FUSE_IOCTL = 39, | 218 | FUSE_IOCTL = 39, |
212 | FUSE_POLL = 40, | 219 | FUSE_POLL = 40, |
220 | |||
221 | /* CUSE specific operations */ | ||
222 | CUSE_INIT = 4096, | ||
213 | }; | 223 | }; |
214 | 224 | ||
215 | enum fuse_notify_code { | 225 | enum fuse_notify_code { |
@@ -401,6 +411,27 @@ struct fuse_init_out { | |||
401 | __u32 max_write; | 411 | __u32 max_write; |
402 | }; | 412 | }; |
403 | 413 | ||
414 | #define CUSE_INIT_INFO_MAX 4096 | ||
415 | |||
416 | struct cuse_init_in { | ||
417 | __u32 major; | ||
418 | __u32 minor; | ||
419 | __u32 unused; | ||
420 | __u32 flags; | ||
421 | }; | ||
422 | |||
423 | struct cuse_init_out { | ||
424 | __u32 major; | ||
425 | __u32 minor; | ||
426 | __u32 unused; | ||
427 | __u32 flags; | ||
428 | __u32 max_read; | ||
429 | __u32 max_write; | ||
430 | __u32 dev_major; /* chardev major */ | ||
431 | __u32 dev_minor; /* chardev minor */ | ||
432 | __u32 spare[10]; | ||
433 | }; | ||
434 | |||
404 | struct fuse_interrupt_in { | 435 | struct fuse_interrupt_in { |
405 | __u64 unique; | 436 | __u64 unique; |
406 | }; | 437 | }; |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 149fda264c86..7cbd38d363a2 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -114,6 +114,7 @@ struct hd_struct { | |||
114 | #define GENHD_FL_UP 16 | 114 | #define GENHD_FL_UP 16 |
115 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 | 115 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 |
116 | #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ | 116 | #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */ |
117 | #define GENHD_FL_NATIVE_CAPACITY 128 | ||
117 | 118 | ||
118 | #define BLK_SCSI_MAX_CMDS (256) | 119 | #define BLK_SCSI_MAX_CMDS (256) |
119 | #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) | 120 | #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8)) |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 867cb68d8461..a6c6a2fad7c8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -178,7 +178,7 @@ typedef u8 hwif_chipset_t; | |||
178 | /* | 178 | /* |
179 | * Structure to hold all information about the location of this port | 179 | * Structure to hold all information about the location of this port |
180 | */ | 180 | */ |
181 | typedef struct hw_regs_s { | 181 | struct ide_hw { |
182 | union { | 182 | union { |
183 | struct ide_io_ports io_ports; | 183 | struct ide_io_ports io_ports; |
184 | unsigned long io_ports_array[IDE_NR_PORTS]; | 184 | unsigned long io_ports_array[IDE_NR_PORTS]; |
@@ -186,12 +186,11 @@ typedef struct hw_regs_s { | |||
186 | 186 | ||
187 | int irq; /* our irq number */ | 187 | int irq; /* our irq number */ |
188 | ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ | 188 | ide_ack_intr_t *ack_intr; /* acknowledge interrupt */ |
189 | hwif_chipset_t chipset; | ||
190 | struct device *dev, *parent; | 189 | struct device *dev, *parent; |
191 | unsigned long config; | 190 | unsigned long config; |
192 | } hw_regs_t; | 191 | }; |
193 | 192 | ||
194 | static inline void ide_std_init_ports(hw_regs_t *hw, | 193 | static inline void ide_std_init_ports(struct ide_hw *hw, |
195 | unsigned long io_addr, | 194 | unsigned long io_addr, |
196 | unsigned long ctl_addr) | 195 | unsigned long ctl_addr) |
197 | { | 196 | { |
@@ -218,21 +217,12 @@ static inline void ide_std_init_ports(hw_regs_t *hw, | |||
218 | 217 | ||
219 | /* | 218 | /* |
220 | * Special Driver Flags | 219 | * Special Driver Flags |
221 | * | ||
222 | * set_geometry : respecify drive geometry | ||
223 | * recalibrate : seek to cyl 0 | ||
224 | * set_multmode : set multmode count | ||
225 | * reserved : unused | ||
226 | */ | 220 | */ |
227 | typedef union { | 221 | enum { |
228 | unsigned all : 8; | 222 | IDE_SFLAG_SET_GEOMETRY = (1 << 0), |
229 | struct { | 223 | IDE_SFLAG_RECALIBRATE = (1 << 1), |
230 | unsigned set_geometry : 1; | 224 | IDE_SFLAG_SET_MULTMODE = (1 << 2), |
231 | unsigned recalibrate : 1; | 225 | }; |
232 | unsigned set_multmode : 1; | ||
233 | unsigned reserved : 5; | ||
234 | } b; | ||
235 | } special_t; | ||
236 | 226 | ||
237 | /* | 227 | /* |
238 | * Status returned from various ide_ functions | 228 | * Status returned from various ide_ functions |
@@ -391,6 +381,7 @@ struct ide_drive_s; | |||
391 | struct ide_disk_ops { | 381 | struct ide_disk_ops { |
392 | int (*check)(struct ide_drive_s *, const char *); | 382 | int (*check)(struct ide_drive_s *, const char *); |
393 | int (*get_capacity)(struct ide_drive_s *); | 383 | int (*get_capacity)(struct ide_drive_s *); |
384 | u64 (*set_capacity)(struct ide_drive_s *, u64); | ||
394 | void (*setup)(struct ide_drive_s *); | 385 | void (*setup)(struct ide_drive_s *); |
395 | void (*flush)(struct ide_drive_s *); | 386 | void (*flush)(struct ide_drive_s *); |
396 | int (*init_media)(struct ide_drive_s *, struct gendisk *); | 387 | int (*init_media)(struct ide_drive_s *, struct gendisk *); |
@@ -468,6 +459,8 @@ enum { | |||
468 | IDE_DFLAG_NICE1 = (1 << 5), | 459 | IDE_DFLAG_NICE1 = (1 << 5), |
469 | /* device is physically present */ | 460 | /* device is physically present */ |
470 | IDE_DFLAG_PRESENT = (1 << 6), | 461 | IDE_DFLAG_PRESENT = (1 << 6), |
462 | /* disable Host Protected Area */ | ||
463 | IDE_DFLAG_NOHPA = (1 << 7), | ||
471 | /* id read from device (synthetic if not set) */ | 464 | /* id read from device (synthetic if not set) */ |
472 | IDE_DFLAG_ID_READ = (1 << 8), | 465 | IDE_DFLAG_ID_READ = (1 << 8), |
473 | IDE_DFLAG_NOPROBE = (1 << 9), | 466 | IDE_DFLAG_NOPROBE = (1 << 9), |
@@ -506,6 +499,7 @@ enum { | |||
506 | /* write protect */ | 499 | /* write protect */ |
507 | IDE_DFLAG_WP = (1 << 29), | 500 | IDE_DFLAG_WP = (1 << 29), |
508 | IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), | 501 | IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), |
502 | IDE_DFLAG_NIEN_QUIRK = (1 << 31), | ||
509 | }; | 503 | }; |
510 | 504 | ||
511 | struct ide_drive_s { | 505 | struct ide_drive_s { |
@@ -530,14 +524,13 @@ struct ide_drive_s { | |||
530 | unsigned long sleep; /* sleep until this time */ | 524 | unsigned long sleep; /* sleep until this time */ |
531 | unsigned long timeout; /* max time to wait for irq */ | 525 | unsigned long timeout; /* max time to wait for irq */ |
532 | 526 | ||
533 | special_t special; /* special action flags */ | 527 | u8 special_flags; /* special action flags */ |
534 | 528 | ||
535 | u8 select; /* basic drive/head select reg value */ | 529 | u8 select; /* basic drive/head select reg value */ |
536 | u8 retry_pio; /* retrying dma capable host in pio */ | 530 | u8 retry_pio; /* retrying dma capable host in pio */ |
537 | u8 waiting_for_dma; /* dma currently in progress */ | 531 | u8 waiting_for_dma; /* dma currently in progress */ |
538 | u8 dma; /* atapi dma flag */ | 532 | u8 dma; /* atapi dma flag */ |
539 | 533 | ||
540 | u8 quirk_list; /* considered quirky, set for a specific host */ | ||
541 | u8 init_speed; /* transfer rate set at boot */ | 534 | u8 init_speed; /* transfer rate set at boot */ |
542 | u8 current_speed; /* current transfer rate set */ | 535 | u8 current_speed; /* current transfer rate set */ |
543 | u8 desired_speed; /* desired transfer rate set */ | 536 | u8 desired_speed; /* desired transfer rate set */ |
@@ -562,8 +555,7 @@ struct ide_drive_s { | |||
562 | unsigned int drive_data; /* used by set_pio_mode/dev_select() */ | 555 | unsigned int drive_data; /* used by set_pio_mode/dev_select() */ |
563 | unsigned int failures; /* current failure count */ | 556 | unsigned int failures; /* current failure count */ |
564 | unsigned int max_failures; /* maximum allowed failure count */ | 557 | unsigned int max_failures; /* maximum allowed failure count */ |
565 | u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */ | 558 | u64 probed_capacity;/* initial/native media capacity */ |
566 | |||
567 | u64 capacity64; /* total number of sectors */ | 559 | u64 capacity64; /* total number of sectors */ |
568 | 560 | ||
569 | int lun; /* logical unit */ | 561 | int lun; /* logical unit */ |
@@ -1222,7 +1214,7 @@ static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev) | |||
1222 | } | 1214 | } |
1223 | 1215 | ||
1224 | void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, | 1216 | void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, |
1225 | hw_regs_t *, hw_regs_t **); | 1217 | struct ide_hw *, struct ide_hw **); |
1226 | void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); | 1218 | void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); |
1227 | 1219 | ||
1228 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI | 1220 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI |
@@ -1461,16 +1453,18 @@ static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {} | |||
1461 | void ide_register_region(struct gendisk *); | 1453 | void ide_register_region(struct gendisk *); |
1462 | void ide_unregister_region(struct gendisk *); | 1454 | void ide_unregister_region(struct gendisk *); |
1463 | 1455 | ||
1456 | void ide_check_nien_quirk_list(ide_drive_t *); | ||
1464 | void ide_undecoded_slave(ide_drive_t *); | 1457 | void ide_undecoded_slave(ide_drive_t *); |
1465 | 1458 | ||
1466 | void ide_port_apply_params(ide_hwif_t *); | 1459 | void ide_port_apply_params(ide_hwif_t *); |
1467 | int ide_sysfs_register_port(ide_hwif_t *); | 1460 | int ide_sysfs_register_port(ide_hwif_t *); |
1468 | 1461 | ||
1469 | struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); | 1462 | struct ide_host *ide_host_alloc(const struct ide_port_info *, struct ide_hw **, |
1463 | unsigned int); | ||
1470 | void ide_host_free(struct ide_host *); | 1464 | void ide_host_free(struct ide_host *); |
1471 | int ide_host_register(struct ide_host *, const struct ide_port_info *, | 1465 | int ide_host_register(struct ide_host *, const struct ide_port_info *, |
1472 | hw_regs_t **); | 1466 | struct ide_hw **); |
1473 | int ide_host_add(const struct ide_port_info *, hw_regs_t **, | 1467 | int ide_host_add(const struct ide_port_info *, struct ide_hw **, unsigned int, |
1474 | struct ide_host **); | 1468 | struct ide_host **); |
1475 | void ide_host_remove(struct ide_host *); | 1469 | void ide_host_remove(struct ide_host *); |
1476 | int ide_legacy_device_add(const struct ide_port_info *, unsigned long); | 1470 | int ide_legacy_device_add(const struct ide_port_info *, unsigned long); |
diff --git a/include/linux/module.h b/include/linux/module.h index a8f2c0aa4c32..a7bc6e7b43a7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -77,6 +77,7 @@ search_extable(const struct exception_table_entry *first, | |||
77 | void sort_extable(struct exception_table_entry *start, | 77 | void sort_extable(struct exception_table_entry *start, |
78 | struct exception_table_entry *finish); | 78 | struct exception_table_entry *finish); |
79 | void sort_main_extable(void); | 79 | void sort_main_extable(void); |
80 | void trim_init_extable(struct module *m); | ||
80 | 81 | ||
81 | #ifdef MODULE | 82 | #ifdef MODULE |
82 | #define MODULE_GENERIC_TABLE(gtype,name) \ | 83 | #define MODULE_GENERIC_TABLE(gtype,name) \ |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index a4f0b931846c..6547c3cdbc4c 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -36,9 +36,14 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp); | |||
36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ | 36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ |
37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); | 37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); |
38 | 38 | ||
39 | /* Flag bits for kernel_param.flags */ | ||
40 | #define KPARAM_KMALLOCED 1 | ||
41 | #define KPARAM_ISBOOL 2 | ||
42 | |||
39 | struct kernel_param { | 43 | struct kernel_param { |
40 | const char *name; | 44 | const char *name; |
41 | unsigned int perm; | 45 | u16 perm; |
46 | u16 flags; | ||
42 | param_set_fn set; | 47 | param_set_fn set; |
43 | param_get_fn get; | 48 | param_get_fn get; |
44 | union { | 49 | union { |
@@ -79,7 +84,7 @@ struct kparam_array | |||
79 | parameters. perm sets the visibility in sysfs: 000 means it's | 84 | parameters. perm sets the visibility in sysfs: 000 means it's |
80 | not there, read bits mean it's readable, write bits mean it's | 85 | not there, read bits mean it's readable, write bits mean it's |
81 | writable. */ | 86 | writable. */ |
82 | #define __module_param_call(prefix, name, set, get, arg, perm) \ | 87 | #define __module_param_call(prefix, name, set, get, arg, isbool, perm) \ |
83 | /* Default value instead of permissions? */ \ | 88 | /* Default value instead of permissions? */ \ |
84 | static int __param_perm_check_##name __attribute__((unused)) = \ | 89 | static int __param_perm_check_##name __attribute__((unused)) = \ |
85 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 90 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -88,10 +93,13 @@ struct kparam_array | |||
88 | static struct kernel_param __moduleparam_const __param_##name \ | 93 | static struct kernel_param __moduleparam_const __param_##name \ |
89 | __used \ | 94 | __used \ |
90 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 95 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
91 | = { __param_str_##name, perm, set, get, { arg } } | 96 | = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \ |
97 | set, get, { arg } } | ||
92 | 98 | ||
93 | #define module_param_call(name, set, get, arg, perm) \ | 99 | #define module_param_call(name, set, get, arg, perm) \ |
94 | __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm) | 100 | __module_param_call(MODULE_PARAM_PREFIX, \ |
101 | name, set, get, arg, \ | ||
102 | __same_type(*(arg), bool), perm) | ||
95 | 103 | ||
96 | /* Helper functions: type is byte, short, ushort, int, uint, long, | 104 | /* Helper functions: type is byte, short, ushort, int, uint, long, |
97 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, | 105 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, |
@@ -120,15 +128,16 @@ struct kparam_array | |||
120 | #define core_param(name, var, type, perm) \ | 128 | #define core_param(name, var, type, perm) \ |
121 | param_check_##type(name, &(var)); \ | 129 | param_check_##type(name, &(var)); \ |
122 | __module_param_call("", name, param_set_##type, param_get_##type, \ | 130 | __module_param_call("", name, param_set_##type, param_get_##type, \ |
123 | &var, perm) | 131 | &var, __same_type(var, bool), perm) |
124 | #endif /* !MODULE */ | 132 | #endif /* !MODULE */ |
125 | 133 | ||
126 | /* Actually copy string: maxlen param is usually sizeof(string). */ | 134 | /* Actually copy string: maxlen param is usually sizeof(string). */ |
127 | #define module_param_string(name, string, len, perm) \ | 135 | #define module_param_string(name, string, len, perm) \ |
128 | static const struct kparam_string __param_string_##name \ | 136 | static const struct kparam_string __param_string_##name \ |
129 | = { len, string }; \ | 137 | = { len, string }; \ |
130 | module_param_call(name, param_set_copystring, param_get_string, \ | 138 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
131 | .str = &__param_string_##name, perm); \ | 139 | param_set_copystring, param_get_string, \ |
140 | .str = &__param_string_##name, 0, perm); \ | ||
132 | __MODULE_PARM_TYPE(name, "string") | 141 | __MODULE_PARM_TYPE(name, "string") |
133 | 142 | ||
134 | /* Called on module insert or kernel boot */ | 143 | /* Called on module insert or kernel boot */ |
@@ -186,21 +195,30 @@ extern int param_set_charp(const char *val, struct kernel_param *kp); | |||
186 | extern int param_get_charp(char *buffer, struct kernel_param *kp); | 195 | extern int param_get_charp(char *buffer, struct kernel_param *kp); |
187 | #define param_check_charp(name, p) __param_check(name, p, char *) | 196 | #define param_check_charp(name, p) __param_check(name, p, char *) |
188 | 197 | ||
198 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ | ||
189 | extern int param_set_bool(const char *val, struct kernel_param *kp); | 199 | extern int param_set_bool(const char *val, struct kernel_param *kp); |
190 | extern int param_get_bool(char *buffer, struct kernel_param *kp); | 200 | extern int param_get_bool(char *buffer, struct kernel_param *kp); |
191 | #define param_check_bool(name, p) __param_check(name, p, int) | 201 | #define param_check_bool(name, p) \ |
202 | static inline void __check_##name(void) \ | ||
203 | { \ | ||
204 | BUILD_BUG_ON(!__same_type(*(p), bool) && \ | ||
205 | !__same_type(*(p), unsigned int) && \ | ||
206 | !__same_type(*(p), int)); \ | ||
207 | } | ||
192 | 208 | ||
193 | extern int param_set_invbool(const char *val, struct kernel_param *kp); | 209 | extern int param_set_invbool(const char *val, struct kernel_param *kp); |
194 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); | 210 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); |
195 | #define param_check_invbool(name, p) __param_check(name, p, int) | 211 | #define param_check_invbool(name, p) __param_check(name, p, bool) |
196 | 212 | ||
197 | /* Comma-separated array: *nump is set to number they actually specified. */ | 213 | /* Comma-separated array: *nump is set to number they actually specified. */ |
198 | #define module_param_array_named(name, array, type, nump, perm) \ | 214 | #define module_param_array_named(name, array, type, nump, perm) \ |
199 | static const struct kparam_array __param_arr_##name \ | 215 | static const struct kparam_array __param_arr_##name \ |
200 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ | 216 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ |
201 | sizeof(array[0]), array }; \ | 217 | sizeof(array[0]), array }; \ |
202 | module_param_call(name, param_array_set, param_array_get, \ | 218 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
203 | .arr = &__param_arr_##name, perm); \ | 219 | param_array_set, param_array_get, \ |
220 | .arr = &__param_arr_##name, \ | ||
221 | __same_type(array[0], bool), perm); \ | ||
204 | __MODULE_PARM_TYPE(name, "array of " #type) | 222 | __MODULE_PARM_TYPE(name, "array of " #type) |
205 | 223 | ||
206 | #define module_param_array(name, type, nump, perm) \ | 224 | #define module_param_array(name, type, nump, perm) \ |
diff --git a/kernel/module.c b/kernel/module.c index 35f7de00bf0d..e4ab36ce7672 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2455,6 +2455,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
2455 | mutex_lock(&module_mutex); | 2455 | mutex_lock(&module_mutex); |
2456 | /* Drop initial reference. */ | 2456 | /* Drop initial reference. */ |
2457 | module_put(mod); | 2457 | module_put(mod); |
2458 | trim_init_extable(mod); | ||
2458 | module_free(mod, mod->module_init); | 2459 | module_free(mod, mod->module_init); |
2459 | mod->module_init = NULL; | 2460 | mod->module_init = NULL; |
2460 | mod->init_size = 0; | 2461 | mod->init_size = 0; |
diff --git a/kernel/params.c b/kernel/params.c index de273ec85bd2..7f6912ced2ba 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -24,9 +24,6 @@ | |||
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | 26 | ||
27 | /* We abuse the high bits of "perm" to record whether we kmalloc'ed. */ | ||
28 | #define KPARAM_KMALLOCED 0x80000000 | ||
29 | |||
30 | #if 0 | 27 | #if 0 |
31 | #define DEBUGP printk | 28 | #define DEBUGP printk |
32 | #else | 29 | #else |
@@ -220,13 +217,13 @@ int param_set_charp(const char *val, struct kernel_param *kp) | |||
220 | return -ENOSPC; | 217 | return -ENOSPC; |
221 | } | 218 | } |
222 | 219 | ||
223 | if (kp->perm & KPARAM_KMALLOCED) | 220 | if (kp->flags & KPARAM_KMALLOCED) |
224 | kfree(*(char **)kp->arg); | 221 | kfree(*(char **)kp->arg); |
225 | 222 | ||
226 | /* This is a hack. We can't need to strdup in early boot, and we | 223 | /* This is a hack. We can't need to strdup in early boot, and we |
227 | * don't need to; this mangled commandline is preserved. */ | 224 | * don't need to; this mangled commandline is preserved. */ |
228 | if (slab_is_available()) { | 225 | if (slab_is_available()) { |
229 | kp->perm |= KPARAM_KMALLOCED; | 226 | kp->flags |= KPARAM_KMALLOCED; |
230 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 227 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); |
231 | if (!kp->arg) | 228 | if (!kp->arg) |
232 | return -ENOMEM; | 229 | return -ENOMEM; |
@@ -241,44 +238,63 @@ int param_get_charp(char *buffer, struct kernel_param *kp) | |||
241 | return sprintf(buffer, "%s", *((char **)kp->arg)); | 238 | return sprintf(buffer, "%s", *((char **)kp->arg)); |
242 | } | 239 | } |
243 | 240 | ||
241 | /* Actually could be a bool or an int, for historical reasons. */ | ||
244 | int param_set_bool(const char *val, struct kernel_param *kp) | 242 | int param_set_bool(const char *val, struct kernel_param *kp) |
245 | { | 243 | { |
244 | bool v; | ||
245 | |||
246 | /* No equals means "set"... */ | 246 | /* No equals means "set"... */ |
247 | if (!val) val = "1"; | 247 | if (!val) val = "1"; |
248 | 248 | ||
249 | /* One of =[yYnN01] */ | 249 | /* One of =[yYnN01] */ |
250 | switch (val[0]) { | 250 | switch (val[0]) { |
251 | case 'y': case 'Y': case '1': | 251 | case 'y': case 'Y': case '1': |
252 | *(int *)kp->arg = 1; | 252 | v = true; |
253 | return 0; | 253 | break; |
254 | case 'n': case 'N': case '0': | 254 | case 'n': case 'N': case '0': |
255 | *(int *)kp->arg = 0; | 255 | v = false; |
256 | return 0; | 256 | break; |
257 | default: | ||
258 | return -EINVAL; | ||
257 | } | 259 | } |
258 | return -EINVAL; | 260 | |
261 | if (kp->flags & KPARAM_ISBOOL) | ||
262 | *(bool *)kp->arg = v; | ||
263 | else | ||
264 | *(int *)kp->arg = v; | ||
265 | return 0; | ||
259 | } | 266 | } |
260 | 267 | ||
261 | int param_get_bool(char *buffer, struct kernel_param *kp) | 268 | int param_get_bool(char *buffer, struct kernel_param *kp) |
262 | { | 269 | { |
270 | bool val; | ||
271 | if (kp->flags & KPARAM_ISBOOL) | ||
272 | val = *(bool *)kp->arg; | ||
273 | else | ||
274 | val = *(int *)kp->arg; | ||
275 | |||
263 | /* Y and N chosen as being relatively non-coder friendly */ | 276 | /* Y and N chosen as being relatively non-coder friendly */ |
264 | return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N'); | 277 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); |
265 | } | 278 | } |
266 | 279 | ||
280 | /* This one must be bool. */ | ||
267 | int param_set_invbool(const char *val, struct kernel_param *kp) | 281 | int param_set_invbool(const char *val, struct kernel_param *kp) |
268 | { | 282 | { |
269 | int boolval, ret; | 283 | int ret; |
284 | bool boolval; | ||
270 | struct kernel_param dummy; | 285 | struct kernel_param dummy; |
271 | 286 | ||
272 | dummy.arg = &boolval; | 287 | dummy.arg = &boolval; |
288 | dummy.flags = KPARAM_ISBOOL; | ||
273 | ret = param_set_bool(val, &dummy); | 289 | ret = param_set_bool(val, &dummy); |
274 | if (ret == 0) | 290 | if (ret == 0) |
275 | *(int *)kp->arg = !boolval; | 291 | *(bool *)kp->arg = !boolval; |
276 | return ret; | 292 | return ret; |
277 | } | 293 | } |
278 | 294 | ||
279 | int param_get_invbool(char *buffer, struct kernel_param *kp) | 295 | int param_get_invbool(char *buffer, struct kernel_param *kp) |
280 | { | 296 | { |
281 | return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'N' : 'Y'); | 297 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); |
282 | } | 298 | } |
283 | 299 | ||
284 | /* We break the rule and mangle the string. */ | 300 | /* We break the rule and mangle the string. */ |
@@ -591,7 +607,7 @@ void destroy_params(const struct kernel_param *params, unsigned num) | |||
591 | unsigned int i; | 607 | unsigned int i; |
592 | 608 | ||
593 | for (i = 0; i < num; i++) | 609 | for (i = 0; i < num; i++) |
594 | if (params[i].perm & KPARAM_KMALLOCED) | 610 | if (params[i].flags & KPARAM_KMALLOCED) |
595 | kfree(*(char **)params[i].arg); | 611 | kfree(*(char **)params[i].arg); |
596 | } | 612 | } |
597 | 613 | ||
diff --git a/lib/extable.c b/lib/extable.c index 179c08745595..4cac81ec225e 100644 --- a/lib/extable.c +++ b/lib/extable.c | |||
@@ -39,7 +39,26 @@ void sort_extable(struct exception_table_entry *start, | |||
39 | sort(start, finish - start, sizeof(struct exception_table_entry), | 39 | sort(start, finish - start, sizeof(struct exception_table_entry), |
40 | cmp_ex, NULL); | 40 | cmp_ex, NULL); |
41 | } | 41 | } |
42 | #endif | 42 | |
43 | #ifdef CONFIG_MODULES | ||
44 | /* | ||
45 | * If the exception table is sorted, any referring to the module init | ||
46 | * will be at the beginning or the end. | ||
47 | */ | ||
48 | void trim_init_extable(struct module *m) | ||
49 | { | ||
50 | /*trim the beginning*/ | ||
51 | while (m->num_exentries && within_module_init(m->extable[0].insn, m)) { | ||
52 | m->extable++; | ||
53 | m->num_exentries--; | ||
54 | } | ||
55 | /*trim the end*/ | ||
56 | while (m->num_exentries && | ||
57 | within_module_init(m->extable[m->num_exentries-1].insn, m)) | ||
58 | m->num_exentries--; | ||
59 | } | ||
60 | #endif /* CONFIG_MODULES */ | ||
61 | #endif /* !ARCH_HAS_SORT_EXTABLE */ | ||
43 | 62 | ||
44 | #ifndef ARCH_HAS_SEARCH_EXTABLE | 63 | #ifndef ARCH_HAS_SEARCH_EXTABLE |
45 | /* | 64 | /* |