diff options
29 files changed, 744 insertions, 627 deletions
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index 95d7f62e4dbc..941343a7a265 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt | |||
@@ -35,6 +35,7 @@ The driver load creates the following directories under the /sys file system. | |||
35 | /sys/class/firmware/dell_rbu/data | 35 | /sys/class/firmware/dell_rbu/data |
36 | /sys/devices/platform/dell_rbu/image_type | 36 | /sys/devices/platform/dell_rbu/image_type |
37 | /sys/devices/platform/dell_rbu/data | 37 | /sys/devices/platform/dell_rbu/data |
38 | /sys/devices/platform/dell_rbu/packet_size | ||
38 | 39 | ||
39 | The driver supports two types of update mechanism; monolithic and packetized. | 40 | The driver supports two types of update mechanism; monolithic and packetized. |
40 | These update mechanism depends upon the BIOS currently running on the system. | 41 | These update mechanism depends upon the BIOS currently running on the system. |
@@ -47,8 +48,26 @@ By default the driver uses monolithic memory for the update type. This can be | |||
47 | changed to packets during the driver load time by specifying the load | 48 | changed to packets during the driver load time by specifying the load |
48 | parameter image_type=packet. This can also be changed later as below | 49 | parameter image_type=packet. This can also be changed later as below |
49 | echo packet > /sys/devices/platform/dell_rbu/image_type | 50 | echo packet > /sys/devices/platform/dell_rbu/image_type |
50 | Also echoing either mono ,packet or init in to image_type will free up the | 51 | |
51 | memory allocated by the driver. | 52 | In packet update mode the packet size has to be given before any packets can |
53 | be downloaded. It is done as below | ||
54 | echo XXXX > /sys/devices/platform/dell_rbu/packet_size | ||
55 | In the packet update mechanism, the user neesd to create a new file having | ||
56 | packets of data arranged back to back. It can be done as follows | ||
57 | The user creates packets header, gets the chunk of the BIOS image and | ||
58 | placs it next to the packetheader; now, the packetheader + BIOS image chunk | ||
59 | added to geather should match the specified packet_size. This makes one | ||
60 | packet, the user needs to create more such packets out of the entire BIOS | ||
61 | image file and then arrange all these packets back to back in to one single | ||
62 | file. | ||
63 | This file is then copied to /sys/class/firmware/dell_rbu/data. | ||
64 | Once this file gets to the driver, the driver extracts packet_size data from | ||
65 | the file and spreads it accross the physical memory in contiguous packet_sized | ||
66 | space. | ||
67 | This method makes sure that all the packets get to the driver in a single operation. | ||
68 | |||
69 | In monolithic update the user simply get the BIOS image (.hdr file) and copies | ||
70 | to the data file as is without any change to the BIOS image itself. | ||
52 | 71 | ||
53 | Do the steps below to download the BIOS image. | 72 | Do the steps below to download the BIOS image. |
54 | 1) echo 1 > /sys/class/firmware/dell_rbu/loading | 73 | 1) echo 1 > /sys/class/firmware/dell_rbu/loading |
@@ -58,7 +77,10 @@ Do the steps below to download the BIOS image. | |||
58 | The /sys/class/firmware/dell_rbu/ entries will remain till the following is | 77 | The /sys/class/firmware/dell_rbu/ entries will remain till the following is |
59 | done. | 78 | done. |
60 | echo -1 > /sys/class/firmware/dell_rbu/loading. | 79 | echo -1 > /sys/class/firmware/dell_rbu/loading. |
61 | Until this step is completed the drivr cannot be unloaded. | 80 | Until this step is completed the driver cannot be unloaded. |
81 | Also echoing either mono ,packet or init in to image_type will free up the | ||
82 | memory allocated by the driver. | ||
83 | |||
62 | If an user by accident executes steps 1 and 3 above without executing step 2; | 84 | If an user by accident executes steps 1 and 3 above without executing step 2; |
63 | it will make the /sys/class/firmware/dell_rbu/ entries to disappear. | 85 | it will make the /sys/class/firmware/dell_rbu/ entries to disappear. |
64 | The entries can be recreated by doing the following | 86 | The entries can be recreated by doing the following |
@@ -66,15 +88,11 @@ echo init > /sys/devices/platform/dell_rbu/image_type | |||
66 | NOTE: echoing init in image_type does not change it original value. | 88 | NOTE: echoing init in image_type does not change it original value. |
67 | 89 | ||
68 | Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to | 90 | Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to |
69 | read back the image downloaded. This is useful in case of packet update | 91 | read back the image downloaded. |
70 | mechanism where the above steps 1,2,3 will repeated for every packet. | ||
71 | By reading the /sys/devices/platform/dell_rbu/data file all packet data | ||
72 | downloaded can be verified in a single file. | ||
73 | The packets are arranged in this file one after the other in a FIFO order. | ||
74 | 92 | ||
75 | NOTE: | 93 | NOTE: |
76 | This driver requires a patch for firmware_class.c which has the addition | 94 | This driver requires a patch for firmware_class.c which has the modified |
77 | of request_firmware_nowait_nohotplug function to wortk | 95 | request_firmware_nowait function. |
78 | Also after updating the BIOS image an user mdoe application neeeds to execute | 96 | Also after updating the BIOS image an user mdoe application neeeds to execute |
79 | code which message the BIOS update request to the BIOS. So on the next reboot | 97 | code which message the BIOS update request to the BIOS. So on the next reboot |
80 | the BIOS knows about the new image downloaded and it updates it self. | 98 | the BIOS knows about the new image downloaded and it updates it self. |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 14 | 3 | SUBLEVEL = 14 |
4 | EXTRAVERSION =-rc3 | 4 | EXTRAVERSION =-rc4 |
5 | NAME=Affluent Albatross | 5 | NAME=Affluent Albatross |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index dddbf6b5ed2c..85920fb8d08c 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S | |||
@@ -681,6 +681,15 @@ ENTRY(debug_trap) | |||
681 | bl do_debug_trap | 681 | bl do_debug_trap |
682 | bra error_code | 682 | bra error_code |
683 | 683 | ||
684 | ENTRY(ill_trap) | ||
685 | /* void ill_trap(void) */ | ||
686 | SWITCH_TO_KERNEL_STACK | ||
687 | SAVE_ALL | ||
688 | ldi r1, #0 ; error_code ; FIXME | ||
689 | mv r0, sp ; pt_regs | ||
690 | bl do_ill_trap | ||
691 | bra error_code | ||
692 | |||
684 | 693 | ||
685 | /* Cache flushing handler */ | 694 | /* Cache flushing handler */ |
686 | ENTRY(cache_flushing_handler) | 695 | ENTRY(cache_flushing_handler) |
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c index 01922271d17e..5fe8ed6d62dc 100644 --- a/arch/m32r/kernel/traps.c +++ b/arch/m32r/kernel/traps.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Hitoshi Yamamoto | 5 | * Hitoshi Yamamoto |
6 | */ | 6 | */ |
7 | 7 | ||
8 | /* $Id$ */ | ||
9 | |||
10 | /* | 8 | /* |
11 | * 'traps.c' handles hardware traps and faults after we have saved some | 9 | * 'traps.c' handles hardware traps and faults after we have saved some |
12 | * state in 'entry.S'. | 10 | * state in 'entry.S'. |
@@ -35,6 +33,7 @@ asmlinkage void ei_handler(void); | |||
35 | asmlinkage void rie_handler(void); | 33 | asmlinkage void rie_handler(void); |
36 | asmlinkage void debug_trap(void); | 34 | asmlinkage void debug_trap(void); |
37 | asmlinkage void cache_flushing_handler(void); | 35 | asmlinkage void cache_flushing_handler(void); |
36 | asmlinkage void ill_trap(void); | ||
38 | 37 | ||
39 | #ifdef CONFIG_SMP | 38 | #ifdef CONFIG_SMP |
40 | extern void smp_reschedule_interrupt(void); | 39 | extern void smp_reschedule_interrupt(void); |
@@ -77,22 +76,22 @@ void set_eit_vector_entries(void) | |||
77 | eit_vector[5] = BRA_INSN(default_eit_handler, 5); | 76 | eit_vector[5] = BRA_INSN(default_eit_handler, 5); |
78 | eit_vector[8] = BRA_INSN(rie_handler, 8); | 77 | eit_vector[8] = BRA_INSN(rie_handler, 8); |
79 | eit_vector[12] = BRA_INSN(alignment_check, 12); | 78 | eit_vector[12] = BRA_INSN(alignment_check, 12); |
80 | eit_vector[16] = 0xff000000UL; | 79 | eit_vector[16] = BRA_INSN(ill_trap, 16); |
81 | eit_vector[17] = BRA_INSN(debug_trap, 17); | 80 | eit_vector[17] = BRA_INSN(debug_trap, 17); |
82 | eit_vector[18] = BRA_INSN(system_call, 18); | 81 | eit_vector[18] = BRA_INSN(system_call, 18); |
83 | eit_vector[19] = 0xff000000UL; | 82 | eit_vector[19] = BRA_INSN(ill_trap, 19); |
84 | eit_vector[20] = 0xff000000UL; | 83 | eit_vector[20] = BRA_INSN(ill_trap, 20); |
85 | eit_vector[21] = 0xff000000UL; | 84 | eit_vector[21] = BRA_INSN(ill_trap, 21); |
86 | eit_vector[22] = 0xff000000UL; | 85 | eit_vector[22] = BRA_INSN(ill_trap, 22); |
87 | eit_vector[23] = 0xff000000UL; | 86 | eit_vector[23] = BRA_INSN(ill_trap, 23); |
88 | eit_vector[24] = 0xff000000UL; | 87 | eit_vector[24] = BRA_INSN(ill_trap, 24); |
89 | eit_vector[25] = 0xff000000UL; | 88 | eit_vector[25] = BRA_INSN(ill_trap, 25); |
90 | eit_vector[26] = 0xff000000UL; | 89 | eit_vector[26] = BRA_INSN(ill_trap, 26); |
91 | eit_vector[27] = 0xff000000UL; | 90 | eit_vector[27] = BRA_INSN(ill_trap, 27); |
92 | eit_vector[28] = BRA_INSN(cache_flushing_handler, 28); | 91 | eit_vector[28] = BRA_INSN(cache_flushing_handler, 28); |
93 | eit_vector[29] = 0xff000000UL; | 92 | eit_vector[29] = BRA_INSN(ill_trap, 29); |
94 | eit_vector[30] = 0xff000000UL; | 93 | eit_vector[30] = BRA_INSN(ill_trap, 30); |
95 | eit_vector[31] = 0xff000000UL; | 94 | eit_vector[31] = BRA_INSN(ill_trap, 31); |
96 | eit_vector[32] = BRA_INSN(ei_handler, 32); | 95 | eit_vector[32] = BRA_INSN(ei_handler, 32); |
97 | eit_vector[64] = BRA_INSN(pie_handler, 64); | 96 | eit_vector[64] = BRA_INSN(pie_handler, 64); |
98 | #ifdef CONFIG_MMU | 97 | #ifdef CONFIG_MMU |
@@ -286,7 +285,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ | |||
286 | 285 | ||
287 | DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap) | 286 | DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap) |
288 | DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc) | 287 | DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc) |
289 | DO_ERROR_INFO(0x100, SIGILL, "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc) | 288 | DO_ERROR_INFO(0x100, SIGILL, "privileged instruction", pie_handler, ILL_PRVOPC, regs->bpc) |
289 | DO_ERROR_INFO(-1, SIGILL, "illegal trap", ill_trap, ILL_ILLTRP, regs->bpc) | ||
290 | 290 | ||
291 | extern int handle_unaligned_access(unsigned long, struct pt_regs *); | 291 | extern int handle_unaligned_access(unsigned long, struct pt_regs *); |
292 | 292 | ||
@@ -329,4 +329,3 @@ asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code) | |||
329 | set_fs(oldfs); | 329 | set_fs(oldfs); |
330 | } | 330 | } |
331 | } | 331 | } |
332 | |||
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 546e1ea4cafa..6b76cf58d9e0 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c | |||
@@ -91,7 +91,7 @@ struct cpu_spec cpu_specs[] = { | |||
91 | .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | | 91 | .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | |
92 | CPU_FTR_HPTE_TABLE, | 92 | CPU_FTR_HPTE_TABLE, |
93 | .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | | 93 | .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | |
94 | PPC_FEATURE_UNIFIED_CACHE, | 94 | PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, |
95 | .icache_bsize = 32, | 95 | .icache_bsize = 32, |
96 | .dcache_bsize = 32, | 96 | .dcache_bsize = 32, |
97 | .cpu_setup = __setup_cpu_601 | 97 | .cpu_setup = __setup_cpu_601 |
@@ -745,7 +745,8 @@ struct cpu_spec cpu_specs[] = { | |||
745 | .cpu_name = "403GCX", | 745 | .cpu_name = "403GCX", |
746 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | | 746 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | |
747 | CPU_FTR_USE_TB, | 747 | CPU_FTR_USE_TB, |
748 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 748 | .cpu_user_features = PPC_FEATURE_32 | |
749 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, | ||
749 | .icache_bsize = 16, | 750 | .icache_bsize = 16, |
750 | .dcache_bsize = 16, | 751 | .dcache_bsize = 16, |
751 | }, | 752 | }, |
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index b566d982806c..8edee806dae7 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c | |||
@@ -401,10 +401,10 @@ EXPORT_SYMBOL(__dma_sync); | |||
401 | static inline void __dma_sync_page_highmem(struct page *page, | 401 | static inline void __dma_sync_page_highmem(struct page *page, |
402 | unsigned long offset, size_t size, int direction) | 402 | unsigned long offset, size_t size, int direction) |
403 | { | 403 | { |
404 | size_t seg_size = min((size_t)PAGE_SIZE, size) - offset; | 404 | size_t seg_size = min((size_t)(PAGE_SIZE - offset), size); |
405 | size_t cur_size = seg_size; | 405 | size_t cur_size = seg_size; |
406 | unsigned long flags, start, seg_offset = offset; | 406 | unsigned long flags, start, seg_offset = offset; |
407 | int nr_segs = PAGE_ALIGN(size + (PAGE_SIZE - offset))/PAGE_SIZE; | 407 | int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE; |
408 | int seg_nr = 0; | 408 | int seg_nr = 0; |
409 | 409 | ||
410 | local_irq_save(flags); | 410 | local_irq_save(flags); |
diff --git a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c index c683bf88e690..928b8581fcb0 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/ppc64/kernel/module.c | |||
@@ -341,6 +341,19 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
341 | *(unsigned long *)location = my_r2(sechdrs, me); | 341 | *(unsigned long *)location = my_r2(sechdrs, me); |
342 | break; | 342 | break; |
343 | 343 | ||
344 | case R_PPC64_TOC16: | ||
345 | /* Subtact TOC pointer */ | ||
346 | value -= my_r2(sechdrs, me); | ||
347 | if (value + 0x8000 > 0xffff) { | ||
348 | printk("%s: bad TOC16 relocation (%lu)\n", | ||
349 | me->name, value); | ||
350 | return -ENOEXEC; | ||
351 | } | ||
352 | *((uint16_t *) location) | ||
353 | = (*((uint16_t *) location) & ~0xffff) | ||
354 | | (value & 0xffff); | ||
355 | break; | ||
356 | |||
344 | case R_PPC64_TOC16_DS: | 357 | case R_PPC64_TOC16_DS: |
345 | /* Subtact TOC pointer */ | 358 | /* Subtact TOC pointer */ |
346 | value -= my_r2(sechdrs, me); | 359 | value -= my_r2(sechdrs, me); |
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index 1f5f141fb7a1..928f8febdb3b 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include "pci.h" | 33 | #include "pci.h" |
34 | 34 | ||
35 | static int __initdata s7a_workaround = -1; | 35 | static int __devinitdata s7a_workaround = -1; |
36 | 36 | ||
37 | #if 0 | 37 | #if 0 |
38 | void pcibios_name_device(struct pci_dev *dev) | 38 | void pcibios_name_device(struct pci_dev *dev) |
@@ -60,7 +60,7 @@ void pcibios_name_device(struct pci_dev *dev) | |||
60 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); | 60 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | static void __init check_s7a(void) | 63 | static void __devinit check_s7a(void) |
64 | { | 64 | { |
65 | struct device_node *root; | 65 | struct device_node *root; |
66 | char *model; | 66 | char *model; |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index f7c51b869049..6537445dac0e 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -21,10 +21,6 @@ config GENERIC_ISA_DMA | |||
21 | bool | 21 | bool |
22 | default y | 22 | default y |
23 | 23 | ||
24 | config GENERIC_IOMAP | ||
25 | bool | ||
26 | default y | ||
27 | |||
28 | source "init/Kconfig" | 24 | source "init/Kconfig" |
29 | 25 | ||
30 | menu "General machine setup" | 26 | menu "General machine setup" |
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index 8a3aef1e22f5..a69856263009 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig | |||
@@ -5,7 +5,6 @@ CONFIG_MMU=y | |||
5 | CONFIG_UID16=y | 5 | CONFIG_UID16=y |
6 | CONFIG_HIGHMEM=y | 6 | CONFIG_HIGHMEM=y |
7 | CONFIG_GENERIC_ISA_DMA=y | 7 | CONFIG_GENERIC_ISA_DMA=y |
8 | CONFIG_GENERIC_IOMAP=y | ||
9 | 8 | ||
10 | # | 9 | # |
11 | # Code maturity level options | 10 | # Code maturity level options |
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index f1dcdf8f7433..4c942f71184d 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
@@ -191,8 +191,9 @@ prom_boot_mapping_phys_low: | |||
191 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 | 191 | stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 |
192 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" | 192 | stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" |
193 | stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache | 193 | stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache |
194 | srlx %l0, 22, %l3 | 194 | /* PAGE align */ |
195 | sllx %l3, 22, %l3 | 195 | srlx %l0, 13, %l3 |
196 | sllx %l3, 13, %l3 | ||
196 | stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC | 197 | stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC |
197 | stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 | 198 | stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 |
198 | stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 | 199 | stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 |
@@ -211,6 +212,9 @@ prom_boot_mapping_phys_low: | |||
211 | ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high | 212 | ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high |
212 | stx %l2, [%l4 + 0x0] | 213 | stx %l2, [%l4 + 0x0] |
213 | ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low | 214 | ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low |
215 | /* 4MB align */ | ||
216 | srlx %l3, 22, %l3 | ||
217 | sllx %l3, 22, %l3 | ||
214 | stx %l3, [%l4 + 0x8] | 218 | stx %l3, [%l4 + 0x8] |
215 | 219 | ||
216 | /* Leave service as-is, "call-method" */ | 220 | /* Leave service as-is, "call-method" */ |
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 783e18cae090..de17d4c6e02d 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile | |||
@@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o | |||
13 | net-objs := net_kern.o net_user.o | 13 | net-objs := net_kern.o net_user.o |
14 | mconsole-objs := mconsole_kern.o mconsole_user.o | 14 | mconsole-objs := mconsole_kern.o mconsole_user.o |
15 | hostaudio-objs := hostaudio_kern.o | 15 | hostaudio-objs := hostaudio_kern.o |
16 | ubd-objs := ubd_kern.o | 16 | ubd-objs := ubd_kern.o ubd_user.o |
17 | port-objs := port_kern.o port_user.o | 17 | port-objs := port_kern.o port_user.o |
18 | harddog-objs := harddog_kern.o harddog_user.o | 18 | harddog-objs := harddog_kern.o harddog_user.o |
19 | 19 | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index e77a38da4350..f73134333f64 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include "linux/blkpg.h" | 35 | #include "linux/blkpg.h" |
36 | #include "linux/genhd.h" | 36 | #include "linux/genhd.h" |
37 | #include "linux/spinlock.h" | 37 | #include "linux/spinlock.h" |
38 | #include "asm/atomic.h" | ||
39 | #include "asm/segment.h" | 38 | #include "asm/segment.h" |
40 | #include "asm/uaccess.h" | 39 | #include "asm/uaccess.h" |
41 | #include "asm/irq.h" | 40 | #include "asm/irq.h" |
@@ -54,21 +53,20 @@ | |||
54 | #include "mem.h" | 53 | #include "mem.h" |
55 | #include "mem_kern.h" | 54 | #include "mem_kern.h" |
56 | #include "cow.h" | 55 | #include "cow.h" |
57 | #include "aio.h" | ||
58 | 56 | ||
59 | enum ubd_req { UBD_READ, UBD_WRITE }; | 57 | enum ubd_req { UBD_READ, UBD_WRITE }; |
60 | 58 | ||
61 | struct io_thread_req { | 59 | struct io_thread_req { |
62 | enum aio_type op; | 60 | enum ubd_req op; |
63 | int fds[2]; | 61 | int fds[2]; |
64 | unsigned long offsets[2]; | 62 | unsigned long offsets[2]; |
65 | unsigned long long offset; | 63 | unsigned long long offset; |
66 | unsigned long length; | 64 | unsigned long length; |
67 | char *buffer; | 65 | char *buffer; |
68 | int sectorsize; | 66 | int sectorsize; |
69 | int bitmap_offset; | 67 | unsigned long sector_mask; |
70 | long bitmap_start; | 68 | unsigned long long cow_offset; |
71 | long bitmap_end; | 69 | unsigned long bitmap_words[2]; |
72 | int error; | 70 | int error; |
73 | }; | 71 | }; |
74 | 72 | ||
@@ -82,31 +80,28 @@ extern int create_cow_file(char *cow_file, char *backing_file, | |||
82 | unsigned long *bitmap_len_out, | 80 | unsigned long *bitmap_len_out, |
83 | int *data_offset_out); | 81 | int *data_offset_out); |
84 | extern int read_cow_bitmap(int fd, void *buf, int offset, int len); | 82 | extern int read_cow_bitmap(int fd, void *buf, int offset, int len); |
85 | extern void do_io(struct io_thread_req *req, struct request *r, | 83 | extern void do_io(struct io_thread_req *req); |
86 | unsigned long *bitmap); | ||
87 | 84 | ||
88 | static inline int ubd_test_bit(__u64 bit, void *data) | 85 | static inline int ubd_test_bit(__u64 bit, unsigned char *data) |
89 | { | 86 | { |
90 | unsigned char *buffer = data; | ||
91 | __u64 n; | 87 | __u64 n; |
92 | int bits, off; | 88 | int bits, off; |
93 | 89 | ||
94 | bits = sizeof(buffer[0]) * 8; | 90 | bits = sizeof(data[0]) * 8; |
95 | n = bit / bits; | 91 | n = bit / bits; |
96 | off = bit % bits; | 92 | off = bit % bits; |
97 | return((buffer[n] & (1 << off)) != 0); | 93 | return((data[n] & (1 << off)) != 0); |
98 | } | 94 | } |
99 | 95 | ||
100 | static inline void ubd_set_bit(__u64 bit, void *data) | 96 | static inline void ubd_set_bit(__u64 bit, unsigned char *data) |
101 | { | 97 | { |
102 | unsigned char *buffer = data; | ||
103 | __u64 n; | 98 | __u64 n; |
104 | int bits, off; | 99 | int bits, off; |
105 | 100 | ||
106 | bits = sizeof(buffer[0]) * 8; | 101 | bits = sizeof(data[0]) * 8; |
107 | n = bit / bits; | 102 | n = bit / bits; |
108 | off = bit % bits; | 103 | off = bit % bits; |
109 | buffer[n] |= (1 << off); | 104 | data[n] |= (1 << off); |
110 | } | 105 | } |
111 | /*End stuff from ubd_user.h*/ | 106 | /*End stuff from ubd_user.h*/ |
112 | 107 | ||
@@ -115,6 +110,8 @@ static inline void ubd_set_bit(__u64 bit, void *data) | |||
115 | static DEFINE_SPINLOCK(ubd_io_lock); | 110 | static DEFINE_SPINLOCK(ubd_io_lock); |
116 | static DEFINE_SPINLOCK(ubd_lock); | 111 | static DEFINE_SPINLOCK(ubd_lock); |
117 | 112 | ||
113 | static void (*do_ubd)(void); | ||
114 | |||
118 | static int ubd_open(struct inode * inode, struct file * filp); | 115 | static int ubd_open(struct inode * inode, struct file * filp); |
119 | static int ubd_release(struct inode * inode, struct file * file); | 116 | static int ubd_release(struct inode * inode, struct file * file); |
120 | static int ubd_ioctl(struct inode * inode, struct file * file, | 117 | static int ubd_ioctl(struct inode * inode, struct file * file, |
@@ -161,8 +158,6 @@ struct cow { | |||
161 | int data_offset; | 158 | int data_offset; |
162 | }; | 159 | }; |
163 | 160 | ||
164 | #define MAX_SG 64 | ||
165 | |||
166 | struct ubd { | 161 | struct ubd { |
167 | char *file; | 162 | char *file; |
168 | int count; | 163 | int count; |
@@ -173,7 +168,6 @@ struct ubd { | |||
173 | int no_cow; | 168 | int no_cow; |
174 | struct cow cow; | 169 | struct cow cow; |
175 | struct platform_device pdev; | 170 | struct platform_device pdev; |
176 | struct scatterlist sg[MAX_SG]; | ||
177 | }; | 171 | }; |
178 | 172 | ||
179 | #define DEFAULT_COW { \ | 173 | #define DEFAULT_COW { \ |
@@ -466,114 +460,81 @@ __uml_help(fakehd, | |||
466 | ); | 460 | ); |
467 | 461 | ||
468 | static void do_ubd_request(request_queue_t * q); | 462 | static void do_ubd_request(request_queue_t * q); |
469 | static int in_ubd; | 463 | |
464 | /* Only changed by ubd_init, which is an initcall. */ | ||
465 | int thread_fd = -1; | ||
470 | 466 | ||
471 | /* Changed by ubd_handler, which is serialized because interrupts only | 467 | /* Changed by ubd_handler, which is serialized because interrupts only |
472 | * happen on CPU 0. | 468 | * happen on CPU 0. |
473 | */ | 469 | */ |
474 | int intr_count = 0; | 470 | int intr_count = 0; |
475 | 471 | ||
476 | static void ubd_end_request(struct request *req, int bytes, int uptodate) | 472 | /* call ubd_finish if you need to serialize */ |
473 | static void __ubd_finish(struct request *req, int error) | ||
477 | { | 474 | { |
478 | if (!end_that_request_first(req, uptodate, bytes >> 9)) { | 475 | int nsect; |
479 | add_disk_randomness(req->rq_disk); | 476 | |
480 | end_that_request_last(req); | 477 | if(error){ |
478 | end_request(req, 0); | ||
479 | return; | ||
481 | } | 480 | } |
481 | nsect = req->current_nr_sectors; | ||
482 | req->sector += nsect; | ||
483 | req->buffer += nsect << 9; | ||
484 | req->errors = 0; | ||
485 | req->nr_sectors -= nsect; | ||
486 | req->current_nr_sectors = 0; | ||
487 | end_request(req, 1); | ||
482 | } | 488 | } |
483 | 489 | ||
484 | /* call ubd_finish if you need to serialize */ | 490 | static inline void ubd_finish(struct request *req, int error) |
485 | static void __ubd_finish(struct request *req, int bytes) | ||
486 | { | 491 | { |
487 | if(bytes < 0){ | 492 | spin_lock(&ubd_io_lock); |
488 | ubd_end_request(req, 0, 0); | 493 | __ubd_finish(req, error); |
489 | return; | 494 | spin_unlock(&ubd_io_lock); |
490 | } | ||
491 | |||
492 | ubd_end_request(req, bytes, 1); | ||
493 | } | 495 | } |
494 | 496 | ||
495 | static inline void ubd_finish(struct request *req, int bytes) | 497 | /* Called without ubd_io_lock held */ |
498 | static void ubd_handler(void) | ||
496 | { | 499 | { |
497 | spin_lock(&ubd_io_lock); | 500 | struct io_thread_req req; |
498 | __ubd_finish(req, bytes); | 501 | struct request *rq = elv_next_request(ubd_queue); |
499 | spin_unlock(&ubd_io_lock); | 502 | int n; |
503 | |||
504 | do_ubd = NULL; | ||
505 | intr_count++; | ||
506 | n = os_read_file(thread_fd, &req, sizeof(req)); | ||
507 | if(n != sizeof(req)){ | ||
508 | printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " | ||
509 | "err = %d\n", os_getpid(), -n); | ||
510 | spin_lock(&ubd_io_lock); | ||
511 | end_request(rq, 0); | ||
512 | spin_unlock(&ubd_io_lock); | ||
513 | return; | ||
514 | } | ||
515 | |||
516 | ubd_finish(rq, req.error); | ||
517 | reactivate_fd(thread_fd, UBD_IRQ); | ||
518 | do_ubd_request(ubd_queue); | ||
500 | } | 519 | } |
501 | 520 | ||
502 | struct bitmap_io { | ||
503 | atomic_t count; | ||
504 | struct aio_context aio; | ||
505 | }; | ||
506 | |||
507 | struct ubd_aio { | ||
508 | struct aio_context aio; | ||
509 | struct request *req; | ||
510 | int len; | ||
511 | struct bitmap_io *bitmap; | ||
512 | void *bitmap_buf; | ||
513 | }; | ||
514 | |||
515 | static int ubd_reply_fd = -1; | ||
516 | |||
517 | static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) | 521 | static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) |
518 | { | 522 | { |
519 | struct aio_thread_reply reply; | 523 | ubd_handler(); |
520 | struct ubd_aio *aio; | 524 | return(IRQ_HANDLED); |
521 | struct request *req; | 525 | } |
522 | int err, n, fd = (int) (long) dev; | ||
523 | |||
524 | while(1){ | ||
525 | err = os_read_file(fd, &reply, sizeof(reply)); | ||
526 | if(err == -EAGAIN) | ||
527 | break; | ||
528 | if(err < 0){ | ||
529 | printk("ubd_aio_handler - read returned err %d\n", | ||
530 | -err); | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | aio = container_of(reply.data, struct ubd_aio, aio); | ||
535 | n = reply.err; | ||
536 | |||
537 | if(n == 0){ | ||
538 | req = aio->req; | ||
539 | req->nr_sectors -= aio->len >> 9; | ||
540 | |||
541 | if((aio->bitmap != NULL) && | ||
542 | (atomic_dec_and_test(&aio->bitmap->count))){ | ||
543 | aio->aio = aio->bitmap->aio; | ||
544 | aio->len = 0; | ||
545 | kfree(aio->bitmap); | ||
546 | aio->bitmap = NULL; | ||
547 | submit_aio(&aio->aio); | ||
548 | } | ||
549 | else { | ||
550 | if((req->nr_sectors == 0) && | ||
551 | (aio->bitmap == NULL)){ | ||
552 | int len = req->hard_nr_sectors << 9; | ||
553 | ubd_finish(req, len); | ||
554 | } | ||
555 | |||
556 | if(aio->bitmap_buf != NULL) | ||
557 | kfree(aio->bitmap_buf); | ||
558 | kfree(aio); | ||
559 | } | ||
560 | } | ||
561 | else if(n < 0){ | ||
562 | ubd_finish(aio->req, n); | ||
563 | if(aio->bitmap != NULL) | ||
564 | kfree(aio->bitmap); | ||
565 | if(aio->bitmap_buf != NULL) | ||
566 | kfree(aio->bitmap_buf); | ||
567 | kfree(aio); | ||
568 | } | ||
569 | } | ||
570 | reactivate_fd(fd, UBD_IRQ); | ||
571 | 526 | ||
572 | do_ubd_request(ubd_queue); | 527 | /* Only changed by ubd_init, which is an initcall. */ |
528 | static int io_pid = -1; | ||
573 | 529 | ||
574 | return(IRQ_HANDLED); | 530 | void kill_io_thread(void) |
531 | { | ||
532 | if(io_pid != -1) | ||
533 | os_kill_process(io_pid, 1); | ||
575 | } | 534 | } |
576 | 535 | ||
536 | __uml_exitcall(kill_io_thread); | ||
537 | |||
577 | static int ubd_file_size(struct ubd *dev, __u64 *size_out) | 538 | static int ubd_file_size(struct ubd *dev, __u64 *size_out) |
578 | { | 539 | { |
579 | char *file; | 540 | char *file; |
@@ -608,7 +569,7 @@ static int ubd_open_dev(struct ubd *dev) | |||
608 | &dev->cow.data_offset, create_ptr); | 569 | &dev->cow.data_offset, create_ptr); |
609 | 570 | ||
610 | if((dev->fd == -ENOENT) && create_cow){ | 571 | if((dev->fd == -ENOENT) && create_cow){ |
611 | dev->fd = create_cow_file(dev->file, dev->cow.file, | 572 | dev->fd = create_cow_file(dev->file, dev->cow.file, |
612 | dev->openflags, 1 << 9, PAGE_SIZE, | 573 | dev->openflags, 1 << 9, PAGE_SIZE, |
613 | &dev->cow.bitmap_offset, | 574 | &dev->cow.bitmap_offset, |
614 | &dev->cow.bitmap_len, | 575 | &dev->cow.bitmap_len, |
@@ -870,10 +831,6 @@ int ubd_init(void) | |||
870 | { | 831 | { |
871 | int i; | 832 | int i; |
872 | 833 | ||
873 | ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr); | ||
874 | if(ubd_reply_fd < 0) | ||
875 | printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd); | ||
876 | |||
877 | devfs_mk_dir("ubd"); | 834 | devfs_mk_dir("ubd"); |
878 | if (register_blkdev(MAJOR_NR, "ubd")) | 835 | if (register_blkdev(MAJOR_NR, "ubd")) |
879 | return -1; | 836 | return -1; |
@@ -884,7 +841,6 @@ int ubd_init(void) | |||
884 | return -1; | 841 | return -1; |
885 | } | 842 | } |
886 | 843 | ||
887 | blk_queue_max_hw_segments(ubd_queue, MAX_SG); | ||
888 | if (fake_major != MAJOR_NR) { | 844 | if (fake_major != MAJOR_NR) { |
889 | char name[sizeof("ubd_nnn\0")]; | 845 | char name[sizeof("ubd_nnn\0")]; |
890 | 846 | ||
@@ -896,12 +852,40 @@ int ubd_init(void) | |||
896 | driver_register(&ubd_driver); | 852 | driver_register(&ubd_driver); |
897 | for (i = 0; i < MAX_DEV; i++) | 853 | for (i = 0; i < MAX_DEV; i++) |
898 | ubd_add(i); | 854 | ubd_add(i); |
899 | |||
900 | return 0; | 855 | return 0; |
901 | } | 856 | } |
902 | 857 | ||
903 | late_initcall(ubd_init); | 858 | late_initcall(ubd_init); |
904 | 859 | ||
860 | int ubd_driver_init(void){ | ||
861 | unsigned long stack; | ||
862 | int err; | ||
863 | |||
864 | /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/ | ||
865 | if(global_openflags.s){ | ||
866 | printk(KERN_INFO "ubd: Synchronous mode\n"); | ||
867 | /* Letting ubd=sync be like using ubd#s= instead of ubd#= is | ||
868 | * enough. So use anyway the io thread. */ | ||
869 | } | ||
870 | stack = alloc_stack(0, 0); | ||
871 | io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), | ||
872 | &thread_fd); | ||
873 | if(io_pid < 0){ | ||
874 | printk(KERN_ERR | ||
875 | "ubd : Failed to start I/O thread (errno = %d) - " | ||
876 | "falling back to synchronous I/O\n", -io_pid); | ||
877 | io_pid = -1; | ||
878 | return(0); | ||
879 | } | ||
880 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | ||
881 | SA_INTERRUPT, "ubd", ubd_dev); | ||
882 | if(err != 0) | ||
883 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | ||
884 | return(err); | ||
885 | } | ||
886 | |||
887 | device_initcall(ubd_driver_init); | ||
888 | |||
905 | static int ubd_open(struct inode *inode, struct file *filp) | 889 | static int ubd_open(struct inode *inode, struct file *filp) |
906 | { | 890 | { |
907 | struct gendisk *disk = inode->i_bdev->bd_disk; | 891 | struct gendisk *disk = inode->i_bdev->bd_disk; |
@@ -939,55 +923,105 @@ static int ubd_release(struct inode * inode, struct file * file) | |||
939 | return(0); | 923 | return(0); |
940 | } | 924 | } |
941 | 925 | ||
942 | static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap) | 926 | static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, |
927 | __u64 *cow_offset, unsigned long *bitmap, | ||
928 | __u64 bitmap_offset, unsigned long *bitmap_words, | ||
929 | __u64 bitmap_len) | ||
943 | { | 930 | { |
944 | __u64 sector = req->offset / req->sectorsize; | 931 | __u64 sector = io_offset >> 9; |
945 | int i; | 932 | int i, update_bitmap = 0; |
933 | |||
934 | for(i = 0; i < length >> 9; i++){ | ||
935 | if(cow_mask != NULL) | ||
936 | ubd_set_bit(i, (unsigned char *) cow_mask); | ||
937 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) | ||
938 | continue; | ||
946 | 939 | ||
947 | for(i = 0; i < req->length / req->sectorsize; i++){ | 940 | update_bitmap = 1; |
948 | if(ubd_test_bit(sector + i, bitmap)) | 941 | ubd_set_bit(sector + i, (unsigned char *) bitmap); |
949 | continue; | 942 | } |
943 | |||
944 | if(!update_bitmap) | ||
945 | return; | ||
950 | 946 | ||
951 | if(req->bitmap_start == -1) | 947 | *cow_offset = sector / (sizeof(unsigned long) * 8); |
952 | req->bitmap_start = sector + i; | ||
953 | req->bitmap_end = sector + i + 1; | ||
954 | 948 | ||
955 | ubd_set_bit(sector + i, bitmap); | 949 | /* This takes care of the case where we're exactly at the end of the |
956 | } | 950 | * device, and *cow_offset + 1 is off the end. So, just back it up |
951 | * by one word. Thanks to Lynn Kerby for the fix and James McMechan | ||
952 | * for the original diagnosis. | ||
953 | */ | ||
954 | if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / | ||
955 | sizeof(unsigned long) - 1)) | ||
956 | (*cow_offset)--; | ||
957 | |||
958 | bitmap_words[0] = bitmap[*cow_offset]; | ||
959 | bitmap_words[1] = bitmap[*cow_offset + 1]; | ||
960 | |||
961 | *cow_offset *= sizeof(unsigned long); | ||
962 | *cow_offset += bitmap_offset; | ||
963 | } | ||
964 | |||
965 | static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | ||
966 | __u64 bitmap_offset, __u64 bitmap_len) | ||
967 | { | ||
968 | __u64 sector = req->offset >> 9; | ||
969 | int i; | ||
970 | |||
971 | if(req->length > (sizeof(req->sector_mask) * 8) << 9) | ||
972 | panic("Operation too long"); | ||
973 | |||
974 | if(req->op == UBD_READ) { | ||
975 | for(i = 0; i < req->length >> 9; i++){ | ||
976 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) | ||
977 | ubd_set_bit(i, (unsigned char *) | ||
978 | &req->sector_mask); | ||
979 | } | ||
980 | } | ||
981 | else cowify_bitmap(req->offset, req->length, &req->sector_mask, | ||
982 | &req->cow_offset, bitmap, bitmap_offset, | ||
983 | req->bitmap_words, bitmap_len); | ||
957 | } | 984 | } |
958 | 985 | ||
959 | /* Called with ubd_io_lock held */ | 986 | /* Called with ubd_io_lock held */ |
960 | static int prepare_request(struct request *req, struct io_thread_req *io_req, | 987 | static int prepare_request(struct request *req, struct io_thread_req *io_req) |
961 | unsigned long long offset, int page_offset, | ||
962 | int len, struct page *page) | ||
963 | { | 988 | { |
964 | struct gendisk *disk = req->rq_disk; | 989 | struct gendisk *disk = req->rq_disk; |
965 | struct ubd *dev = disk->private_data; | 990 | struct ubd *dev = disk->private_data; |
991 | __u64 offset; | ||
992 | int len; | ||
993 | |||
994 | if(req->rq_status == RQ_INACTIVE) return(1); | ||
966 | 995 | ||
967 | /* This should be impossible now */ | 996 | /* This should be impossible now */ |
968 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 997 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ |
969 | printk("Write attempted on readonly ubd device %s\n", | 998 | printk("Write attempted on readonly ubd device %s\n", |
970 | disk->disk_name); | 999 | disk->disk_name); |
971 | ubd_end_request(req, 0, 0); | 1000 | end_request(req, 0); |
972 | return(1); | 1001 | return(1); |
973 | } | 1002 | } |
974 | 1003 | ||
1004 | offset = ((__u64) req->sector) << 9; | ||
1005 | len = req->current_nr_sectors << 9; | ||
1006 | |||
975 | io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; | 1007 | io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; |
976 | io_req->fds[1] = dev->fd; | 1008 | io_req->fds[1] = dev->fd; |
1009 | io_req->cow_offset = -1; | ||
977 | io_req->offset = offset; | 1010 | io_req->offset = offset; |
978 | io_req->length = len; | 1011 | io_req->length = len; |
979 | io_req->error = 0; | 1012 | io_req->error = 0; |
980 | io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE; | 1013 | io_req->sector_mask = 0; |
1014 | |||
1015 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; | ||
981 | io_req->offsets[0] = 0; | 1016 | io_req->offsets[0] = 0; |
982 | io_req->offsets[1] = dev->cow.data_offset; | 1017 | io_req->offsets[1] = dev->cow.data_offset; |
983 | io_req->buffer = page_address(page) + page_offset; | 1018 | io_req->buffer = req->buffer; |
984 | io_req->sectorsize = 1 << 9; | 1019 | io_req->sectorsize = 1 << 9; |
985 | io_req->bitmap_offset = dev->cow.bitmap_offset; | ||
986 | io_req->bitmap_start = -1; | ||
987 | io_req->bitmap_end = -1; | ||
988 | 1020 | ||
989 | if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE)) | 1021 | if(dev->cow.file != NULL) |
990 | cowify_bitmap(io_req, dev->cow.bitmap); | 1022 | cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, |
1023 | dev->cow.bitmap_len); | ||
1024 | |||
991 | return(0); | 1025 | return(0); |
992 | } | 1026 | } |
993 | 1027 | ||
@@ -996,36 +1030,30 @@ static void do_ubd_request(request_queue_t *q) | |||
996 | { | 1030 | { |
997 | struct io_thread_req io_req; | 1031 | struct io_thread_req io_req; |
998 | struct request *req; | 1032 | struct request *req; |
999 | __u64 sector; | 1033 | int err, n; |
1000 | int err; | 1034 | |
1001 | 1035 | if(thread_fd == -1){ | |
1002 | if(in_ubd) | 1036 | while((req = elv_next_request(q)) != NULL){ |
1003 | return; | 1037 | err = prepare_request(req, &io_req); |
1004 | in_ubd = 1; | 1038 | if(!err){ |
1005 | while((req = elv_next_request(q)) != NULL){ | 1039 | do_io(&io_req); |
1006 | struct gendisk *disk = req->rq_disk; | 1040 | __ubd_finish(req, io_req.error); |
1007 | struct ubd *dev = disk->private_data; | 1041 | } |
1008 | int n, i; | 1042 | } |
1009 | 1043 | } | |
1010 | blkdev_dequeue_request(req); | 1044 | else { |
1011 | 1045 | if(do_ubd || (req = elv_next_request(q)) == NULL) | |
1012 | sector = req->sector; | 1046 | return; |
1013 | n = blk_rq_map_sg(q, req, dev->sg); | 1047 | err = prepare_request(req, &io_req); |
1014 | 1048 | if(!err){ | |
1015 | for(i = 0; i < n; i++){ | 1049 | do_ubd = ubd_handler; |
1016 | struct scatterlist *sg = &dev->sg[i]; | 1050 | n = os_write_file(thread_fd, (char *) &io_req, |
1017 | 1051 | sizeof(io_req)); | |
1018 | err = prepare_request(req, &io_req, sector << 9, | 1052 | if(n != sizeof(io_req)) |
1019 | sg->offset, sg->length, | 1053 | printk("write to io thread failed, " |
1020 | sg->page); | 1054 | "errno = %d\n", -n); |
1021 | if(err) | ||
1022 | continue; | ||
1023 | |||
1024 | sector += sg->length >> 9; | ||
1025 | do_io(&io_req, req, dev->cow.bitmap); | ||
1026 | } | 1055 | } |
1027 | } | 1056 | } |
1028 | in_ubd = 0; | ||
1029 | } | 1057 | } |
1030 | 1058 | ||
1031 | static int ubd_ioctl(struct inode * inode, struct file * file, | 1059 | static int ubd_ioctl(struct inode * inode, struct file * file, |
@@ -1241,95 +1269,131 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, | |||
1241 | return(err); | 1269 | return(err); |
1242 | } | 1270 | } |
1243 | 1271 | ||
1244 | void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap) | 1272 | static int update_bitmap(struct io_thread_req *req) |
1245 | { | 1273 | { |
1246 | struct ubd_aio *aio; | 1274 | int n; |
1247 | struct bitmap_io *bitmap_io = NULL; | ||
1248 | char *buf; | ||
1249 | void *bitmap_buf = NULL; | ||
1250 | unsigned long len, sector; | ||
1251 | int nsectors, start, end, bit, err; | ||
1252 | __u64 off; | ||
1253 | |||
1254 | if(req->bitmap_start != -1){ | ||
1255 | /* Round up to the nearest word */ | ||
1256 | int round = sizeof(unsigned long); | ||
1257 | len = (req->bitmap_end - req->bitmap_start + | ||
1258 | round * 8 - 1) / (round * 8); | ||
1259 | len *= round; | ||
1260 | |||
1261 | off = req->bitmap_start / (8 * round); | ||
1262 | off *= round; | ||
1263 | |||
1264 | bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL); | ||
1265 | if(bitmap_io == NULL){ | ||
1266 | printk("Failed to kmalloc bitmap IO\n"); | ||
1267 | req->error = 1; | ||
1268 | return; | ||
1269 | } | ||
1270 | 1275 | ||
1271 | bitmap_buf = kmalloc(len, GFP_KERNEL); | 1276 | if(req->cow_offset == -1) |
1272 | if(bitmap_buf == NULL){ | 1277 | return(0); |
1273 | printk("do_io : kmalloc of bitmap chunk " | ||
1274 | "failed\n"); | ||
1275 | kfree(bitmap_io); | ||
1276 | req->error = 1; | ||
1277 | return; | ||
1278 | } | ||
1279 | memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len); | ||
1280 | |||
1281 | *bitmap_io = ((struct bitmap_io) | ||
1282 | { .count = ATOMIC_INIT(0), | ||
1283 | .aio = INIT_AIO(AIO_WRITE, req->fds[1], | ||
1284 | bitmap_buf, len, | ||
1285 | req->bitmap_offset + off, | ||
1286 | ubd_reply_fd) } ); | ||
1287 | } | ||
1288 | 1278 | ||
1289 | nsectors = req->length / req->sectorsize; | 1279 | n = os_seek_file(req->fds[1], req->cow_offset); |
1290 | start = 0; | 1280 | if(n < 0){ |
1291 | end = nsectors; | 1281 | printk("do_io - bitmap lseek failed : err = %d\n", -n); |
1292 | bit = 0; | 1282 | return(1); |
1293 | do { | 1283 | } |
1294 | if(bitmap != NULL){ | ||
1295 | sector = req->offset / req->sectorsize; | ||
1296 | bit = ubd_test_bit(sector + start, bitmap); | ||
1297 | end = start; | ||
1298 | while((end < nsectors) && | ||
1299 | (ubd_test_bit(sector + end, bitmap) == bit)) | ||
1300 | end++; | ||
1301 | } | ||
1302 | 1284 | ||
1303 | off = req->offsets[bit] + req->offset + | 1285 | n = os_write_file(req->fds[1], &req->bitmap_words, |
1304 | start * req->sectorsize; | 1286 | sizeof(req->bitmap_words)); |
1305 | len = (end - start) * req->sectorsize; | 1287 | if(n != sizeof(req->bitmap_words)){ |
1306 | buf = &req->buffer[start * req->sectorsize]; | 1288 | printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, |
1289 | req->fds[1]); | ||
1290 | return(1); | ||
1291 | } | ||
1307 | 1292 | ||
1308 | aio = kmalloc(sizeof(*aio), GFP_KERNEL); | 1293 | return(0); |
1309 | if(aio == NULL){ | 1294 | } |
1310 | req->error = 1; | ||
1311 | return; | ||
1312 | } | ||
1313 | 1295 | ||
1314 | *aio = ((struct ubd_aio) | 1296 | void do_io(struct io_thread_req *req) |
1315 | { .aio = INIT_AIO(req->op, req->fds[bit], buf, | 1297 | { |
1316 | len, off, ubd_reply_fd), | 1298 | char *buf; |
1317 | .len = len, | 1299 | unsigned long len; |
1318 | .req = r, | 1300 | int n, nsectors, start, end, bit; |
1319 | .bitmap = bitmap_io, | 1301 | int err; |
1320 | .bitmap_buf = bitmap_buf }); | 1302 | __u64 off; |
1321 | 1303 | ||
1322 | if(aio->bitmap != NULL) | 1304 | nsectors = req->length / req->sectorsize; |
1323 | atomic_inc(&aio->bitmap->count); | 1305 | start = 0; |
1324 | 1306 | do { | |
1325 | err = submit_aio(&aio->aio); | 1307 | bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask); |
1326 | if(err){ | 1308 | end = start; |
1327 | printk("do_io - submit_aio failed, " | 1309 | while((end < nsectors) && |
1328 | "err = %d\n", err); | 1310 | (ubd_test_bit(end, (unsigned char *) |
1329 | req->error = 1; | 1311 | &req->sector_mask) == bit)) |
1330 | return; | 1312 | end++; |
1331 | } | 1313 | |
1314 | off = req->offset + req->offsets[bit] + | ||
1315 | start * req->sectorsize; | ||
1316 | len = (end - start) * req->sectorsize; | ||
1317 | buf = &req->buffer[start * req->sectorsize]; | ||
1318 | |||
1319 | err = os_seek_file(req->fds[bit], off); | ||
1320 | if(err < 0){ | ||
1321 | printk("do_io - lseek failed : err = %d\n", -err); | ||
1322 | req->error = 1; | ||
1323 | return; | ||
1324 | } | ||
1325 | if(req->op == UBD_READ){ | ||
1326 | n = 0; | ||
1327 | do { | ||
1328 | buf = &buf[n]; | ||
1329 | len -= n; | ||
1330 | n = os_read_file(req->fds[bit], buf, len); | ||
1331 | if (n < 0) { | ||
1332 | printk("do_io - read failed, err = %d " | ||
1333 | "fd = %d\n", -n, req->fds[bit]); | ||
1334 | req->error = 1; | ||
1335 | return; | ||
1336 | } | ||
1337 | } while((n < len) && (n != 0)); | ||
1338 | if (n < len) memset(&buf[n], 0, len - n); | ||
1339 | } else { | ||
1340 | n = os_write_file(req->fds[bit], buf, len); | ||
1341 | if(n != len){ | ||
1342 | printk("do_io - write failed err = %d " | ||
1343 | "fd = %d\n", -n, req->fds[bit]); | ||
1344 | req->error = 1; | ||
1345 | return; | ||
1346 | } | ||
1347 | } | ||
1348 | |||
1349 | start = end; | ||
1350 | } while(start < nsectors); | ||
1332 | 1351 | ||
1333 | start = end; | 1352 | req->error = update_bitmap(req); |
1334 | } while(start < nsectors); | ||
1335 | } | 1353 | } |
1354 | |||
1355 | /* Changed in start_io_thread, which is serialized by being called only | ||
1356 | * from ubd_init, which is an initcall. | ||
1357 | */ | ||
1358 | int kernel_fd = -1; | ||
1359 | |||
1360 | /* Only changed by the io thread */ | ||
1361 | int io_count = 0; | ||
1362 | |||
1363 | int io_thread(void *arg) | ||
1364 | { | ||
1365 | struct io_thread_req req; | ||
1366 | int n; | ||
1367 | |||
1368 | ignore_sigwinch_sig(); | ||
1369 | while(1){ | ||
1370 | n = os_read_file(kernel_fd, &req, sizeof(req)); | ||
1371 | if(n != sizeof(req)){ | ||
1372 | if(n < 0) | ||
1373 | printk("io_thread - read failed, fd = %d, " | ||
1374 | "err = %d\n", kernel_fd, -n); | ||
1375 | else { | ||
1376 | printk("io_thread - short read, fd = %d, " | ||
1377 | "length = %d\n", kernel_fd, n); | ||
1378 | } | ||
1379 | continue; | ||
1380 | } | ||
1381 | io_count++; | ||
1382 | do_io(&req); | ||
1383 | n = os_write_file(kernel_fd, &req, sizeof(req)); | ||
1384 | if(n != sizeof(req)) | ||
1385 | printk("io_thread - write failed, fd = %d, err = %d\n", | ||
1386 | kernel_fd, -n); | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1392 | * Emacs will notice this stuff at the end of the file and automatically | ||
1393 | * adjust the settings for this buffer only. This must remain at the end | ||
1394 | * of the file. | ||
1395 | * --------------------------------------------------------------------------- | ||
1396 | * Local variables: | ||
1397 | * c-file-style: "linux" | ||
1398 | * End: | ||
1399 | */ | ||
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c new file mode 100644 index 000000000000..b94d2bc4fe06 --- /dev/null +++ b/arch/um/drivers/ubd_user.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <unistd.h> | ||
9 | #include <errno.h> | ||
10 | #include <sched.h> | ||
11 | #include <signal.h> | ||
12 | #include <string.h> | ||
13 | #include <netinet/in.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <sys/socket.h> | ||
16 | #include <sys/mman.h> | ||
17 | #include <sys/param.h> | ||
18 | #include "asm/types.h" | ||
19 | #include "user_util.h" | ||
20 | #include "kern_util.h" | ||
21 | #include "user.h" | ||
22 | #include "ubd_user.h" | ||
23 | #include "os.h" | ||
24 | #include "cow.h" | ||
25 | |||
26 | #include <endian.h> | ||
27 | #include <byteswap.h> | ||
28 | |||
29 | void ignore_sigwinch_sig(void) | ||
30 | { | ||
31 | signal(SIGWINCH, SIG_IGN); | ||
32 | } | ||
33 | |||
34 | int start_io_thread(unsigned long sp, int *fd_out) | ||
35 | { | ||
36 | int pid, fds[2], err; | ||
37 | |||
38 | err = os_pipe(fds, 1, 1); | ||
39 | if(err < 0){ | ||
40 | printk("start_io_thread - os_pipe failed, err = %d\n", -err); | ||
41 | goto out; | ||
42 | } | ||
43 | |||
44 | kernel_fd = fds[0]; | ||
45 | *fd_out = fds[1]; | ||
46 | |||
47 | pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, | ||
48 | NULL); | ||
49 | if(pid < 0){ | ||
50 | printk("start_io_thread - clone failed : errno = %d\n", errno); | ||
51 | err = -errno; | ||
52 | goto out_close; | ||
53 | } | ||
54 | |||
55 | return(pid); | ||
56 | |||
57 | out_close: | ||
58 | os_close_file(fds[0]); | ||
59 | os_close_file(fds[1]); | ||
60 | kernel_fd = -1; | ||
61 | *fd_out = -1; | ||
62 | out: | ||
63 | return(err); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
68 | * Emacs will notice this stuff at the end of the file and automatically | ||
69 | * adjust the settings for this buffer only. This must remain at the end | ||
70 | * of the file. | ||
71 | * --------------------------------------------------------------------------- | ||
72 | * Local variables: | ||
73 | * c-file-style: "linux" | ||
74 | * End: | ||
75 | */ | ||
diff --git a/arch/um/include/aio.h b/arch/um/include/aio.h index 83f16877ab08..423bae9153f8 100644 --- a/arch/um/include/aio.h +++ b/arch/um/include/aio.h | |||
@@ -14,27 +14,15 @@ struct aio_thread_reply { | |||
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct aio_context { | 16 | struct aio_context { |
17 | enum aio_type type; | ||
18 | int fd; | ||
19 | void *data; | ||
20 | int len; | ||
21 | unsigned long long offset; | ||
22 | int reply_fd; | 17 | int reply_fd; |
23 | struct aio_context *next; | 18 | struct aio_context *next; |
24 | }; | 19 | }; |
25 | 20 | ||
26 | #define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \ | ||
27 | aio_reply_fd) \ | ||
28 | { .type = aio_type, \ | ||
29 | .fd = aio_fd, \ | ||
30 | .data = aio_data, \ | ||
31 | .len = aio_len, \ | ||
32 | .offset = aio_offset, \ | ||
33 | .reply_fd = aio_reply_fd } | ||
34 | |||
35 | #define INIT_AIO_CONTEXT { .reply_fd = -1, \ | 21 | #define INIT_AIO_CONTEXT { .reply_fd = -1, \ |
36 | .next = NULL } | 22 | .next = NULL } |
37 | 23 | ||
38 | extern int submit_aio(struct aio_context *aio); | 24 | extern int submit_aio(enum aio_type type, int fd, char *buf, int len, |
25 | unsigned long long offset, int reply_fd, | ||
26 | struct aio_context *aio); | ||
39 | 27 | ||
40 | #endif | 28 | #endif |
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6f766e1faecc..2e58e304b8be 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #ifndef __OS_H__ | 6 | #ifndef __OS_H__ |
7 | #define __OS_H__ | 7 | #define __OS_H__ |
8 | 8 | ||
9 | #include "uml-config.h" | ||
9 | #include "asm/types.h" | 10 | #include "asm/types.h" |
10 | #include "../os/include/file.h" | 11 | #include "../os/include/file.h" |
11 | 12 | ||
@@ -159,7 +160,11 @@ extern int can_do_skas(void); | |||
159 | 160 | ||
160 | /* Make sure they are clear when running in TT mode. Required by | 161 | /* Make sure they are clear when running in TT mode. Required by |
161 | * SEGV_MAYBE_FIXABLE */ | 162 | * SEGV_MAYBE_FIXABLE */ |
163 | #ifdef UML_CONFIG_MODE_SKAS | ||
162 | #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) | 164 | #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) |
165 | #else | ||
166 | #define clear_can_do_skas() do {} while (0) | ||
167 | #endif | ||
163 | 168 | ||
164 | /* mem.c */ | 169 | /* mem.c */ |
165 | extern int create_mem_file(unsigned long len); | 170 | extern int create_mem_file(unsigned long len); |
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index f6e64026f995..41cfb0944201 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <unistd.h> | 7 | #include <unistd.h> |
8 | #include <signal.h> | 8 | #include <signal.h> |
9 | #include <string.h> | ||
10 | #include <errno.h> | 9 | #include <errno.h> |
11 | #include <sched.h> | 10 | #include <sched.h> |
12 | #include <sys/syscall.h> | 11 | #include <sys/syscall.h> |
@@ -17,31 +16,18 @@ | |||
17 | #include "user.h" | 16 | #include "user.h" |
18 | #include "mode.h" | 17 | #include "mode.h" |
19 | 18 | ||
19 | struct aio_thread_req { | ||
20 | enum aio_type type; | ||
21 | int io_fd; | ||
22 | unsigned long long offset; | ||
23 | char *buf; | ||
24 | int len; | ||
25 | struct aio_context *aio; | ||
26 | }; | ||
27 | |||
20 | static int aio_req_fd_r = -1; | 28 | static int aio_req_fd_r = -1; |
21 | static int aio_req_fd_w = -1; | 29 | static int aio_req_fd_w = -1; |
22 | 30 | ||
23 | static int update_aio(struct aio_context *aio, int res) | ||
24 | { | ||
25 | if(res < 0) | ||
26 | aio->len = res; | ||
27 | else if((res == 0) && (aio->type == AIO_READ)){ | ||
28 | /* This is the EOF case - we have hit the end of the file | ||
29 | * and it ends in a partial block, so we fill the end of | ||
30 | * the block with zeros and claim success. | ||
31 | */ | ||
32 | memset(aio->data, 0, aio->len); | ||
33 | aio->len = 0; | ||
34 | } | ||
35 | else if(res > 0){ | ||
36 | aio->len -= res; | ||
37 | aio->data += res; | ||
38 | aio->offset += res; | ||
39 | return aio->len; | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | #if defined(HAVE_AIO_ABI) | 31 | #if defined(HAVE_AIO_ABI) |
46 | #include <linux/aio_abi.h> | 32 | #include <linux/aio_abi.h> |
47 | 33 | ||
@@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, | |||
80 | * that it now backs the mmapped area. | 66 | * that it now backs the mmapped area. |
81 | */ | 67 | */ |
82 | 68 | ||
83 | static int do_aio(aio_context_t ctx, struct aio_context *aio) | 69 | static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, |
70 | int len, unsigned long long offset, struct aio_context *aio) | ||
84 | { | 71 | { |
85 | struct iocb iocb, *iocbp = &iocb; | 72 | struct iocb iocb, *iocbp = &iocb; |
86 | char c; | 73 | char c; |
@@ -88,39 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio) | |||
88 | 75 | ||
89 | iocb = ((struct iocb) { .aio_data = (unsigned long) aio, | 76 | iocb = ((struct iocb) { .aio_data = (unsigned long) aio, |
90 | .aio_reqprio = 0, | 77 | .aio_reqprio = 0, |
91 | .aio_fildes = aio->fd, | 78 | .aio_fildes = fd, |
92 | .aio_buf = (unsigned long) aio->data, | 79 | .aio_buf = (unsigned long) buf, |
93 | .aio_nbytes = aio->len, | 80 | .aio_nbytes = len, |
94 | .aio_offset = aio->offset, | 81 | .aio_offset = offset, |
95 | .aio_reserved1 = 0, | 82 | .aio_reserved1 = 0, |
96 | .aio_reserved2 = 0, | 83 | .aio_reserved2 = 0, |
97 | .aio_reserved3 = 0 }); | 84 | .aio_reserved3 = 0 }); |
98 | 85 | ||
99 | switch(aio->type){ | 86 | switch(type){ |
100 | case AIO_READ: | 87 | case AIO_READ: |
101 | iocb.aio_lio_opcode = IOCB_CMD_PREAD; | 88 | iocb.aio_lio_opcode = IOCB_CMD_PREAD; |
89 | err = io_submit(ctx, 1, &iocbp); | ||
102 | break; | 90 | break; |
103 | case AIO_WRITE: | 91 | case AIO_WRITE: |
104 | iocb.aio_lio_opcode = IOCB_CMD_PWRITE; | 92 | iocb.aio_lio_opcode = IOCB_CMD_PWRITE; |
93 | err = io_submit(ctx, 1, &iocbp); | ||
105 | break; | 94 | break; |
106 | case AIO_MMAP: | 95 | case AIO_MMAP: |
107 | iocb.aio_lio_opcode = IOCB_CMD_PREAD; | 96 | iocb.aio_lio_opcode = IOCB_CMD_PREAD; |
108 | iocb.aio_buf = (unsigned long) &c; | 97 | iocb.aio_buf = (unsigned long) &c; |
109 | iocb.aio_nbytes = sizeof(c); | 98 | iocb.aio_nbytes = sizeof(c); |
99 | err = io_submit(ctx, 1, &iocbp); | ||
110 | break; | 100 | break; |
111 | default: | 101 | default: |
112 | printk("Bogus op in do_aio - %d\n", aio->type); | 102 | printk("Bogus op in do_aio - %d\n", type); |
113 | err = -EINVAL; | 103 | err = -EINVAL; |
114 | goto out; | 104 | break; |
115 | } | 105 | } |
116 | 106 | ||
117 | err = io_submit(ctx, 1, &iocbp); | ||
118 | if(err > 0) | 107 | if(err > 0) |
119 | err = 0; | 108 | err = 0; |
120 | else | 109 | else |
121 | err = -errno; | 110 | err = -errno; |
122 | 111 | ||
123 | out: | ||
124 | return err; | 112 | return err; |
125 | } | 113 | } |
126 | 114 | ||
@@ -129,9 +117,8 @@ static aio_context_t ctx = 0; | |||
129 | static int aio_thread(void *arg) | 117 | static int aio_thread(void *arg) |
130 | { | 118 | { |
131 | struct aio_thread_reply reply; | 119 | struct aio_thread_reply reply; |
132 | struct aio_context *aio; | ||
133 | struct io_event event; | 120 | struct io_event event; |
134 | int err, n; | 121 | int err, n, reply_fd; |
135 | 122 | ||
136 | signal(SIGWINCH, SIG_IGN); | 123 | signal(SIGWINCH, SIG_IGN); |
137 | 124 | ||
@@ -144,22 +131,14 @@ static int aio_thread(void *arg) | |||
144 | "errno = %d\n", errno); | 131 | "errno = %d\n", errno); |
145 | } | 132 | } |
146 | else { | 133 | else { |
147 | /* This is safe as we've just a pointer here. */ | ||
148 | aio = (struct aio_context *) (long) event.data; | ||
149 | if(update_aio(aio, event.res)){ | ||
150 | do_aio(ctx, aio); | ||
151 | continue; | ||
152 | } | ||
153 | |||
154 | reply = ((struct aio_thread_reply) | 134 | reply = ((struct aio_thread_reply) |
155 | { .data = aio, | 135 | { .data = (void *) (long) event.data, |
156 | .err = aio->len }); | 136 | .err = event.res }); |
157 | err = os_write_file(aio->reply_fd, &reply, | 137 | reply_fd = ((struct aio_context *) reply.data)->reply_fd; |
158 | sizeof(reply)); | 138 | err = os_write_file(reply_fd, &reply, sizeof(reply)); |
159 | if(err != sizeof(reply)) | 139 | if(err != sizeof(reply)) |
160 | printk("aio_thread - write failed, " | 140 | printk("aio_thread - write failed, fd = %d, " |
161 | "fd = %d, err = %d\n", aio->reply_fd, | 141 | "err = %d\n", aio_req_fd_r, -err); |
162 | -err); | ||
163 | } | 142 | } |
164 | } | 143 | } |
165 | return 0; | 144 | return 0; |
@@ -167,35 +146,35 @@ static int aio_thread(void *arg) | |||
167 | 146 | ||
168 | #endif | 147 | #endif |
169 | 148 | ||
170 | static int do_not_aio(struct aio_context *aio) | 149 | static int do_not_aio(struct aio_thread_req *req) |
171 | { | 150 | { |
172 | char c; | 151 | char c; |
173 | int err; | 152 | int err; |
174 | 153 | ||
175 | switch(aio->type){ | 154 | switch(req->type){ |
176 | case AIO_READ: | 155 | case AIO_READ: |
177 | err = os_seek_file(aio->fd, aio->offset); | 156 | err = os_seek_file(req->io_fd, req->offset); |
178 | if(err) | 157 | if(err) |
179 | goto out; | 158 | goto out; |
180 | 159 | ||
181 | err = os_read_file(aio->fd, aio->data, aio->len); | 160 | err = os_read_file(req->io_fd, req->buf, req->len); |
182 | break; | 161 | break; |
183 | case AIO_WRITE: | 162 | case AIO_WRITE: |
184 | err = os_seek_file(aio->fd, aio->offset); | 163 | err = os_seek_file(req->io_fd, req->offset); |
185 | if(err) | 164 | if(err) |
186 | goto out; | 165 | goto out; |
187 | 166 | ||
188 | err = os_write_file(aio->fd, aio->data, aio->len); | 167 | err = os_write_file(req->io_fd, req->buf, req->len); |
189 | break; | 168 | break; |
190 | case AIO_MMAP: | 169 | case AIO_MMAP: |
191 | err = os_seek_file(aio->fd, aio->offset); | 170 | err = os_seek_file(req->io_fd, req->offset); |
192 | if(err) | 171 | if(err) |
193 | goto out; | 172 | goto out; |
194 | 173 | ||
195 | err = os_read_file(aio->fd, &c, sizeof(c)); | 174 | err = os_read_file(req->io_fd, &c, sizeof(c)); |
196 | break; | 175 | break; |
197 | default: | 176 | default: |
198 | printk("do_not_aio - bad request type : %d\n", aio->type); | 177 | printk("do_not_aio - bad request type : %d\n", req->type); |
199 | err = -EINVAL; | 178 | err = -EINVAL; |
200 | break; | 179 | break; |
201 | } | 180 | } |
@@ -206,14 +185,14 @@ static int do_not_aio(struct aio_context *aio) | |||
206 | 185 | ||
207 | static int not_aio_thread(void *arg) | 186 | static int not_aio_thread(void *arg) |
208 | { | 187 | { |
209 | struct aio_context *aio; | 188 | struct aio_thread_req req; |
210 | struct aio_thread_reply reply; | 189 | struct aio_thread_reply reply; |
211 | int err; | 190 | int err; |
212 | 191 | ||
213 | signal(SIGWINCH, SIG_IGN); | 192 | signal(SIGWINCH, SIG_IGN); |
214 | while(1){ | 193 | while(1){ |
215 | err = os_read_file(aio_req_fd_r, &aio, sizeof(aio)); | 194 | err = os_read_file(aio_req_fd_r, &req, sizeof(req)); |
216 | if(err != sizeof(aio)){ | 195 | if(err != sizeof(req)){ |
217 | if(err < 0) | 196 | if(err < 0) |
218 | printk("not_aio_thread - read failed, " | 197 | printk("not_aio_thread - read failed, " |
219 | "fd = %d, err = %d\n", aio_req_fd_r, | 198 | "fd = %d, err = %d\n", aio_req_fd_r, |
@@ -224,34 +203,17 @@ static int not_aio_thread(void *arg) | |||
224 | } | 203 | } |
225 | continue; | 204 | continue; |
226 | } | 205 | } |
227 | again: | 206 | err = do_not_aio(&req); |
228 | err = do_not_aio(aio); | 207 | reply = ((struct aio_thread_reply) { .data = req.aio, |
229 | 208 | .err = err }); | |
230 | if(update_aio(aio, err)) | 209 | err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); |
231 | goto again; | ||
232 | |||
233 | reply = ((struct aio_thread_reply) { .data = aio, | ||
234 | .err = aio->len }); | ||
235 | err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); | ||
236 | if(err != sizeof(reply)) | 210 | if(err != sizeof(reply)) |
237 | printk("not_aio_thread - write failed, fd = %d, " | 211 | printk("not_aio_thread - write failed, fd = %d, " |
238 | "err = %d\n", aio_req_fd_r, -err); | 212 | "err = %d\n", aio_req_fd_r, -err); |
239 | } | 213 | } |
240 | } | 214 | } |
241 | 215 | ||
242 | static int submit_aio_24(struct aio_context *aio) | ||
243 | { | ||
244 | int err; | ||
245 | |||
246 | err = os_write_file(aio_req_fd_w, &aio, sizeof(aio)); | ||
247 | if(err == sizeof(aio)) | ||
248 | err = 0; | ||
249 | |||
250 | return err; | ||
251 | } | ||
252 | |||
253 | static int aio_pid = -1; | 216 | static int aio_pid = -1; |
254 | static int (*submit_proc)(struct aio_context *aio); | ||
255 | 217 | ||
256 | static int init_aio_24(void) | 218 | static int init_aio_24(void) |
257 | { | 219 | { |
@@ -283,33 +245,11 @@ static int init_aio_24(void) | |||
283 | #endif | 245 | #endif |
284 | printk("2.6 host AIO support not used - falling back to I/O " | 246 | printk("2.6 host AIO support not used - falling back to I/O " |
285 | "thread\n"); | 247 | "thread\n"); |
286 | |||
287 | submit_proc = submit_aio_24; | ||
288 | |||
289 | return 0; | 248 | return 0; |
290 | } | 249 | } |
291 | 250 | ||
292 | #ifdef HAVE_AIO_ABI | 251 | #ifdef HAVE_AIO_ABI |
293 | #define DEFAULT_24_AIO 0 | 252 | #define DEFAULT_24_AIO 0 |
294 | static int submit_aio_26(struct aio_context *aio) | ||
295 | { | ||
296 | struct aio_thread_reply reply; | ||
297 | int err; | ||
298 | |||
299 | err = do_aio(ctx, aio); | ||
300 | if(err){ | ||
301 | reply = ((struct aio_thread_reply) { .data = aio, | ||
302 | .err = err }); | ||
303 | err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); | ||
304 | if(err != sizeof(reply)) | ||
305 | printk("submit_aio_26 - write failed, " | ||
306 | "fd = %d, err = %d\n", aio->reply_fd, -err); | ||
307 | else err = 0; | ||
308 | } | ||
309 | |||
310 | return err; | ||
311 | } | ||
312 | |||
313 | static int init_aio_26(void) | 253 | static int init_aio_26(void) |
314 | { | 254 | { |
315 | unsigned long stack; | 255 | unsigned long stack; |
@@ -330,22 +270,39 @@ static int init_aio_26(void) | |||
330 | aio_pid = err; | 270 | aio_pid = err; |
331 | 271 | ||
332 | printk("Using 2.6 host AIO\n"); | 272 | printk("Using 2.6 host AIO\n"); |
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, | ||
277 | unsigned long long offset, struct aio_context *aio) | ||
278 | { | ||
279 | struct aio_thread_reply reply; | ||
280 | int err; | ||
333 | 281 | ||
334 | submit_proc = submit_aio_26; | 282 | err = do_aio(ctx, type, io_fd, buf, len, offset, aio); |
283 | if(err){ | ||
284 | reply = ((struct aio_thread_reply) { .data = aio, | ||
285 | .err = err }); | ||
286 | err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); | ||
287 | if(err != sizeof(reply)) | ||
288 | printk("submit_aio_26 - write failed, " | ||
289 | "fd = %d, err = %d\n", aio->reply_fd, -err); | ||
290 | else err = 0; | ||
291 | } | ||
335 | 292 | ||
336 | return 0; | 293 | return err; |
337 | } | 294 | } |
338 | 295 | ||
339 | #else | 296 | #else |
340 | #define DEFAULT_24_AIO 1 | 297 | #define DEFAULT_24_AIO 1 |
341 | static int submit_aio_26(struct aio_context *aio) | 298 | static int init_aio_26(void) |
342 | { | 299 | { |
343 | return -ENOSYS; | 300 | return -ENOSYS; |
344 | } | 301 | } |
345 | 302 | ||
346 | static int init_aio_26(void) | 303 | static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, |
304 | unsigned long long offset, struct aio_context *aio) | ||
347 | { | 305 | { |
348 | submit_proc = submit_aio_26; | ||
349 | return -ENOSYS; | 306 | return -ENOSYS; |
350 | } | 307 | } |
351 | #endif | 308 | #endif |
@@ -412,7 +369,33 @@ static void exit_aio(void) | |||
412 | 369 | ||
413 | __uml_exitcall(exit_aio); | 370 | __uml_exitcall(exit_aio); |
414 | 371 | ||
415 | int submit_aio(struct aio_context *aio) | 372 | static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, |
373 | unsigned long long offset, struct aio_context *aio) | ||
416 | { | 374 | { |
417 | return (*submit_proc)(aio); | 375 | struct aio_thread_req req = { .type = type, |
376 | .io_fd = io_fd, | ||
377 | .offset = offset, | ||
378 | .buf = buf, | ||
379 | .len = len, | ||
380 | .aio = aio, | ||
381 | }; | ||
382 | int err; | ||
383 | |||
384 | err = os_write_file(aio_req_fd_w, &req, sizeof(req)); | ||
385 | if(err == sizeof(req)) | ||
386 | err = 0; | ||
387 | |||
388 | return err; | ||
389 | } | ||
390 | |||
391 | int submit_aio(enum aio_type type, int io_fd, char *buf, int len, | ||
392 | unsigned long long offset, int reply_fd, | ||
393 | struct aio_context *aio) | ||
394 | { | ||
395 | aio->reply_fd = reply_fd; | ||
396 | if(aio_24) | ||
397 | return submit_aio_24(type, io_fd, buf, len, offset, aio); | ||
398 | else { | ||
399 | return submit_aio_26(type, io_fd, buf, len, offset, aio); | ||
400 | } | ||
418 | } | 401 | } |
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index b66782398258..4f4ba9b6d182 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
@@ -50,7 +50,7 @@ | |||
50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
52 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
53 | MODULE_VERSION("2.0"); | 53 | MODULE_VERSION("3.0"); |
54 | 54 | ||
55 | #define BIOS_SCAN_LIMIT 0xffffffff | 55 | #define BIOS_SCAN_LIMIT 0xffffffff |
56 | #define MAX_IMAGE_LENGTH 16 | 56 | #define MAX_IMAGE_LENGTH 16 |
@@ -62,15 +62,16 @@ static struct _rbu_data { | |||
62 | int dma_alloc; | 62 | int dma_alloc; |
63 | spinlock_t lock; | 63 | spinlock_t lock; |
64 | unsigned long packet_read_count; | 64 | unsigned long packet_read_count; |
65 | unsigned long packet_write_count; | ||
66 | unsigned long num_packets; | 65 | unsigned long num_packets; |
67 | unsigned long packetsize; | 66 | unsigned long packetsize; |
67 | unsigned long imagesize; | ||
68 | int entry_created; | 68 | int entry_created; |
69 | } rbu_data; | 69 | } rbu_data; |
70 | 70 | ||
71 | static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; | 71 | static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; |
72 | module_param_string(image_type, image_type, sizeof (image_type), 0); | 72 | module_param_string(image_type, image_type, sizeof (image_type), 0); |
73 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); | 73 | MODULE_PARM_DESC(image_type, |
74 | "BIOS image type. choose- mono or packet or init"); | ||
74 | 75 | ||
75 | struct packet_data { | 76 | struct packet_data { |
76 | struct list_head list; | 77 | struct list_head list; |
@@ -88,55 +89,13 @@ static dma_addr_t dell_rbu_dmaaddr; | |||
88 | static void init_packet_head(void) | 89 | static void init_packet_head(void) |
89 | { | 90 | { |
90 | INIT_LIST_HEAD(&packet_data_head.list); | 91 | INIT_LIST_HEAD(&packet_data_head.list); |
91 | rbu_data.packet_write_count = 0; | ||
92 | rbu_data.packet_read_count = 0; | 92 | rbu_data.packet_read_count = 0; |
93 | rbu_data.num_packets = 0; | 93 | rbu_data.num_packets = 0; |
94 | rbu_data.packetsize = 0; | 94 | rbu_data.packetsize = 0; |
95 | rbu_data.imagesize = 0; | ||
95 | } | 96 | } |
96 | 97 | ||
97 | static int fill_last_packet(void *data, size_t length) | 98 | static int create_packet(void *data, size_t length) |
98 | { | ||
99 | struct list_head *ptemp_list; | ||
100 | struct packet_data *packet = NULL; | ||
101 | int packet_count = 0; | ||
102 | |||
103 | pr_debug("fill_last_packet: entry \n"); | ||
104 | |||
105 | if (!rbu_data.num_packets) { | ||
106 | pr_debug("fill_last_packet: num_packets=0\n"); | ||
107 | return -ENOMEM; | ||
108 | } | ||
109 | |||
110 | packet_count = rbu_data.num_packets; | ||
111 | |||
112 | ptemp_list = (&packet_data_head.list)->prev; | ||
113 | |||
114 | packet = list_entry(ptemp_list, struct packet_data, list); | ||
115 | |||
116 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { | ||
117 | pr_debug("dell_rbu:%s: packet size data " | ||
118 | "overrun\n", __FUNCTION__); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | |||
122 | pr_debug("fill_last_packet : buffer = %p\n", packet->data); | ||
123 | |||
124 | memcpy((packet->data + rbu_data.packet_write_count), data, length); | ||
125 | |||
126 | if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) { | ||
127 | /* | ||
128 | * this was the last data chunk in the packet | ||
129 | * so reinitialize the packet data counter to zero | ||
130 | */ | ||
131 | rbu_data.packet_write_count = 0; | ||
132 | } else | ||
133 | rbu_data.packet_write_count += length; | ||
134 | |||
135 | pr_debug("fill_last_packet: exit \n"); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int create_packet(size_t length) | ||
140 | { | 99 | { |
141 | struct packet_data *newpacket; | 100 | struct packet_data *newpacket; |
142 | int ordernum = 0; | 101 | int ordernum = 0; |
@@ -186,9 +145,11 @@ static int create_packet(size_t length) | |||
186 | INIT_LIST_HEAD(&newpacket->list); | 145 | INIT_LIST_HEAD(&newpacket->list); |
187 | list_add_tail(&newpacket->list, &packet_data_head.list); | 146 | list_add_tail(&newpacket->list, &packet_data_head.list); |
188 | /* | 147 | /* |
189 | * packets have fixed size | 148 | * packets may not have fixed size |
190 | */ | 149 | */ |
191 | newpacket->length = rbu_data.packetsize; | 150 | newpacket->length = length; |
151 | |||
152 | memcpy(newpacket->data, data, length); | ||
192 | 153 | ||
193 | pr_debug("create_packet: exit \n"); | 154 | pr_debug("create_packet: exit \n"); |
194 | 155 | ||
@@ -198,13 +159,37 @@ static int create_packet(size_t length) | |||
198 | static int packetize_data(void *data, size_t length) | 159 | static int packetize_data(void *data, size_t length) |
199 | { | 160 | { |
200 | int rc = 0; | 161 | int rc = 0; |
162 | int done = 0; | ||
163 | int packet_length; | ||
164 | u8 *temp; | ||
165 | u8 *end = (u8 *) data + length; | ||
166 | pr_debug("packetize_data: data length %d\n", length); | ||
167 | if (!rbu_data.packetsize) { | ||
168 | printk(KERN_WARNING | ||
169 | "dell_rbu: packetsize not specified\n"); | ||
170 | return -EIO; | ||
171 | } | ||
201 | 172 | ||
202 | if (!rbu_data.packet_write_count) { | 173 | temp = (u8 *) data; |
203 | if ((rc = create_packet(length))) | 174 | |
175 | /* packetize the hunk */ | ||
176 | while (!done) { | ||
177 | if ((temp + rbu_data.packetsize) < end) | ||
178 | packet_length = rbu_data.packetsize; | ||
179 | else { | ||
180 | /* this is the last packet */ | ||
181 | packet_length = end - temp; | ||
182 | done = 1; | ||
183 | } | ||
184 | |||
185 | if ((rc = create_packet(temp, packet_length))) | ||
204 | return rc; | 186 | return rc; |
187 | |||
188 | pr_debug("%lu:%lu\n", temp, (end - temp)); | ||
189 | temp += packet_length; | ||
205 | } | 190 | } |
206 | if ((rc = fill_last_packet(data, length))) | 191 | |
207 | return rc; | 192 | rbu_data.imagesize = length; |
208 | 193 | ||
209 | return rc; | 194 | return rc; |
210 | } | 195 | } |
@@ -243,7 +228,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list, | |||
243 | return bytes_copied; | 228 | return bytes_copied; |
244 | } | 229 | } |
245 | 230 | ||
246 | static int packet_read_list(char *data, size_t *pread_length) | 231 | static int packet_read_list(char *data, size_t * pread_length) |
247 | { | 232 | { |
248 | struct list_head *ptemp_list; | 233 | struct list_head *ptemp_list; |
249 | int temp_count = 0; | 234 | int temp_count = 0; |
@@ -303,10 +288,9 @@ static void packet_empty_list(void) | |||
303 | newpacket->ordernum); | 288 | newpacket->ordernum); |
304 | kfree(newpacket); | 289 | kfree(newpacket); |
305 | } | 290 | } |
306 | rbu_data.packet_write_count = 0; | ||
307 | rbu_data.packet_read_count = 0; | 291 | rbu_data.packet_read_count = 0; |
308 | rbu_data.num_packets = 0; | 292 | rbu_data.num_packets = 0; |
309 | rbu_data.packetsize = 0; | 293 | rbu_data.imagesize = 0; |
310 | } | 294 | } |
311 | 295 | ||
312 | /* | 296 | /* |
@@ -425,7 +409,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
425 | size_t bytes_left; | 409 | size_t bytes_left; |
426 | size_t data_length; | 410 | size_t data_length; |
427 | char *ptempBuf = buffer; | 411 | char *ptempBuf = buffer; |
428 | unsigned long imagesize; | ||
429 | 412 | ||
430 | /* check to see if we have something to return */ | 413 | /* check to see if we have something to return */ |
431 | if (rbu_data.num_packets == 0) { | 414 | if (rbu_data.num_packets == 0) { |
@@ -434,22 +417,20 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
434 | goto read_rbu_data_exit; | 417 | goto read_rbu_data_exit; |
435 | } | 418 | } |
436 | 419 | ||
437 | imagesize = rbu_data.num_packets * rbu_data.packetsize; | 420 | if (pos > rbu_data.imagesize) { |
438 | |||
439 | if (pos > imagesize) { | ||
440 | retval = 0; | 421 | retval = 0; |
441 | printk(KERN_WARNING "dell_rbu:read_packet_data: " | 422 | printk(KERN_WARNING "dell_rbu:read_packet_data: " |
442 | "data underrun\n"); | 423 | "data underrun\n"); |
443 | goto read_rbu_data_exit; | 424 | goto read_rbu_data_exit; |
444 | } | 425 | } |
445 | 426 | ||
446 | bytes_left = imagesize - pos; | 427 | bytes_left = rbu_data.imagesize - pos; |
447 | data_length = min(bytes_left, count); | 428 | data_length = min(bytes_left, count); |
448 | 429 | ||
449 | if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) | 430 | if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) |
450 | goto read_rbu_data_exit; | 431 | goto read_rbu_data_exit; |
451 | 432 | ||
452 | if ((pos + count) > imagesize) { | 433 | if ((pos + count) > rbu_data.imagesize) { |
453 | rbu_data.packet_read_count = 0; | 434 | rbu_data.packet_read_count = 0; |
454 | /* this was the last copy */ | 435 | /* this was the last copy */ |
455 | retval = bytes_left; | 436 | retval = bytes_left; |
@@ -499,7 +480,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
499 | } | 480 | } |
500 | 481 | ||
501 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, | 482 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, |
502 | loff_t pos, size_t count) | 483 | loff_t pos, size_t count) |
503 | { | 484 | { |
504 | ssize_t ret_count = 0; | 485 | ssize_t ret_count = 0; |
505 | 486 | ||
@@ -531,13 +512,18 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
531 | memcpy(rbu_data.image_update_buffer, | 512 | memcpy(rbu_data.image_update_buffer, |
532 | fw->data, fw->size); | 513 | fw->data, fw->size); |
533 | } else if (!strcmp(image_type, "packet")) { | 514 | } else if (!strcmp(image_type, "packet")) { |
534 | if (!rbu_data.packetsize) | 515 | /* |
535 | rbu_data.packetsize = fw->size; | 516 | * we need to free previous packets if a |
536 | else if (rbu_data.packetsize != fw->size) { | 517 | * new hunk of packets needs to be downloaded |
518 | */ | ||
519 | packet_empty_list(); | ||
520 | if (packetize_data(fw->data, fw->size)) | ||
521 | /* Incase something goes wrong when we are | ||
522 | * in middle of packetizing the data, we | ||
523 | * need to free up whatever packets might | ||
524 | * have been created before we quit. | ||
525 | */ | ||
537 | packet_empty_list(); | 526 | packet_empty_list(); |
538 | rbu_data.packetsize = fw->size; | ||
539 | } | ||
540 | packetize_data(fw->data, fw->size); | ||
541 | } else | 527 | } else |
542 | pr_debug("invalid image type specified.\n"); | 528 | pr_debug("invalid image type specified.\n"); |
543 | spin_unlock(&rbu_data.lock); | 529 | spin_unlock(&rbu_data.lock); |
@@ -553,7 +539,7 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
553 | } | 539 | } |
554 | 540 | ||
555 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | 541 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, |
556 | loff_t pos, size_t count) | 542 | loff_t pos, size_t count) |
557 | { | 543 | { |
558 | int size = 0; | 544 | int size = 0; |
559 | if (!pos) | 545 | if (!pos) |
@@ -562,7 +548,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | |||
562 | } | 548 | } |
563 | 549 | ||
564 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | 550 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, |
565 | loff_t pos, size_t count) | 551 | loff_t pos, size_t count) |
566 | { | 552 | { |
567 | int rc = count; | 553 | int rc = count; |
568 | int req_firm_rc = 0; | 554 | int req_firm_rc = 0; |
@@ -621,25 +607,49 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | |||
621 | return rc; | 607 | return rc; |
622 | } | 608 | } |
623 | 609 | ||
610 | static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, | ||
611 | loff_t pos, size_t count) | ||
612 | { | ||
613 | int size = 0; | ||
614 | if (!pos) { | ||
615 | spin_lock(&rbu_data.lock); | ||
616 | size = sprintf(buffer, "%lu\n", rbu_data.packetsize); | ||
617 | spin_unlock(&rbu_data.lock); | ||
618 | } | ||
619 | return size; | ||
620 | } | ||
621 | |||
622 | static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, | ||
623 | loff_t pos, size_t count) | ||
624 | { | ||
625 | unsigned long temp; | ||
626 | spin_lock(&rbu_data.lock); | ||
627 | packet_empty_list(); | ||
628 | sscanf(buffer, "%lu", &temp); | ||
629 | if (temp < 0xffffffff) | ||
630 | rbu_data.packetsize = temp; | ||
631 | |||
632 | spin_unlock(&rbu_data.lock); | ||
633 | return count; | ||
634 | } | ||
635 | |||
624 | static struct bin_attribute rbu_data_attr = { | 636 | static struct bin_attribute rbu_data_attr = { |
625 | .attr = { | 637 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, |
626 | .name = "data", | ||
627 | .owner = THIS_MODULE, | ||
628 | .mode = 0444, | ||
629 | }, | ||
630 | .read = read_rbu_data, | 638 | .read = read_rbu_data, |
631 | }; | 639 | }; |
632 | 640 | ||
633 | static struct bin_attribute rbu_image_type_attr = { | 641 | static struct bin_attribute rbu_image_type_attr = { |
634 | .attr = { | 642 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, |
635 | .name = "image_type", | ||
636 | .owner = THIS_MODULE, | ||
637 | .mode = 0644, | ||
638 | }, | ||
639 | .read = read_rbu_image_type, | 643 | .read = read_rbu_image_type, |
640 | .write = write_rbu_image_type, | 644 | .write = write_rbu_image_type, |
641 | }; | 645 | }; |
642 | 646 | ||
647 | static struct bin_attribute rbu_packet_size_attr = { | ||
648 | .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644}, | ||
649 | .read = read_rbu_packet_size, | ||
650 | .write = write_rbu_packet_size, | ||
651 | }; | ||
652 | |||
643 | static int __init dcdrbu_init(void) | 653 | static int __init dcdrbu_init(void) |
644 | { | 654 | { |
645 | int rc = 0; | 655 | int rc = 0; |
@@ -657,6 +667,8 @@ static int __init dcdrbu_init(void) | |||
657 | 667 | ||
658 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); | 668 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); |
659 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); | 669 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); |
670 | sysfs_create_bin_file(&rbu_device->dev.kobj, | ||
671 | &rbu_packet_size_attr); | ||
660 | 672 | ||
661 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 673 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
662 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); | 674 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 6c332800d6ab..0881a17d5226 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
@@ -2393,10 +2393,10 @@ struct tvcard bttv_tvcards[] = { | |||
2393 | .tuner = 0, | 2393 | .tuner = 0, |
2394 | .tuner_type = TUNER_LG_TDVS_H062F, | 2394 | .tuner_type = TUNER_LG_TDVS_H062F, |
2395 | .tuner_addr = ADDR_UNSET, | 2395 | .tuner_addr = ADDR_UNSET, |
2396 | .video_inputs = 2, | 2396 | .video_inputs = 3, |
2397 | .audio_inputs = 1, | 2397 | .audio_inputs = 1, |
2398 | .svhs = 2, | 2398 | .svhs = 2, |
2399 | .muxsel = { 2, 3 }, | 2399 | .muxsel = { 2, 3, 1 }, |
2400 | .gpiomask = 0x00e00007, | 2400 | .gpiomask = 0x00e00007, |
2401 | .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, | 2401 | .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, |
2402 | .no_msp34xx = 1, | 2402 | .no_msp34xx = 1, |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 14c76f5e4177..9adc11e8b8bc 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -544,7 +544,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) | |||
544 | .sibling = sibling, | 544 | .sibling = sibling, |
545 | }; | 545 | }; |
546 | 546 | ||
547 | dev = bus_find_device(&css_bus_type, NULL, &data, match_devno); | 547 | dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno); |
548 | 548 | ||
549 | return dev ? to_ccwdev(dev) : NULL; | 549 | return dev ? to_ccwdev(dev) : NULL; |
550 | } | 550 | } |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index e971156daa60..ba9381fd3f2d 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -274,7 +274,6 @@ static void transmit_chars(struct uart_sunsab_port *up, | |||
274 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 274 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
275 | up->interrupt_mask1 |= SAB82532_IMR1_XPR; | 275 | up->interrupt_mask1 |= SAB82532_IMR1_XPR; |
276 | writeb(up->interrupt_mask1, &up->regs->w.imr1); | 276 | writeb(up->interrupt_mask1, &up->regs->w.imr1); |
277 | uart_write_wakeup(&up->port); | ||
278 | return; | 277 | return; |
279 | } | 278 | } |
280 | 279 | ||
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d75445738c88..7653d6cf05af 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -517,10 +517,9 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, | |||
517 | if (up->port.info == NULL) | 517 | if (up->port.info == NULL) |
518 | goto ack_tx_int; | 518 | goto ack_tx_int; |
519 | xmit = &up->port.info->xmit; | 519 | xmit = &up->port.info->xmit; |
520 | if (uart_circ_empty(xmit)) { | 520 | if (uart_circ_empty(xmit)) |
521 | uart_write_wakeup(&up->port); | ||
522 | goto ack_tx_int; | 521 | goto ack_tx_int; |
523 | } | 522 | |
524 | if (uart_tx_stopped(&up->port)) | 523 | if (uart_tx_stopped(&up->port)) |
525 | goto ack_tx_int; | 524 | goto ack_tx_int; |
526 | 525 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a4799e971d1c..bbc3cc63854f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -175,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
175 | } | 175 | } |
176 | 176 | ||
177 | /** | 177 | /** |
178 | * v9fs_read - read from a file (internal) | 178 | * v9fs_file_read - read from a file |
179 | * @filep: file pointer to read | 179 | * @filep: file pointer to read |
180 | * @data: data buffer to read data into | 180 | * @data: data buffer to read data into |
181 | * @count: size of buffer | 181 | * @count: size of buffer |
182 | * @offset: offset at which to read data | 182 | * @offset: offset at which to read data |
183 | * | 183 | * |
184 | */ | 184 | */ |
185 | |||
186 | static ssize_t | 185 | static ssize_t |
187 | v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | 186 | v9fs_file_read(struct file *filp, char __user * data, size_t count, |
187 | loff_t * offset) | ||
188 | { | 188 | { |
189 | struct inode *inode = filp->f_dentry->d_inode; | 189 | struct inode *inode = filp->f_dentry->d_inode; |
190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
@@ -194,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
194 | int rsize = 0; | 194 | int rsize = 0; |
195 | int result = 0; | 195 | int result = 0; |
196 | int total = 0; | 196 | int total = 0; |
197 | int n; | ||
197 | 198 | ||
198 | dprintk(DEBUG_VFS, "\n"); | 199 | dprintk(DEBUG_VFS, "\n"); |
199 | 200 | ||
@@ -216,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
216 | } else | 217 | } else |
217 | *offset += result; | 218 | *offset += result; |
218 | 219 | ||
219 | /* XXX - extra copy */ | 220 | n = copy_to_user(data, fcall->params.rread.data, result); |
220 | memcpy(buffer, fcall->params.rread.data, result); | 221 | if (n) { |
222 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); | ||
223 | kfree(fcall); | ||
224 | return -EFAULT; | ||
225 | } | ||
226 | |||
221 | count -= result; | 227 | count -= result; |
222 | buffer += result; | 228 | data += result; |
223 | total += result; | 229 | total += result; |
224 | 230 | ||
225 | kfree(fcall); | 231 | kfree(fcall); |
@@ -232,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
232 | } | 238 | } |
233 | 239 | ||
234 | /** | 240 | /** |
235 | * v9fs_file_read - read from a file | 241 | * v9fs_file_write - write to a file |
236 | * @filep: file pointer to read | ||
237 | * @data: data buffer to read data into | ||
238 | * @count: size of buffer | ||
239 | * @offset: offset at which to read data | ||
240 | * | ||
241 | */ | ||
242 | |||
243 | static ssize_t | ||
244 | v9fs_file_read(struct file *filp, char __user * data, size_t count, | ||
245 | loff_t * offset) | ||
246 | { | ||
247 | int retval = -1; | ||
248 | int ret = 0; | ||
249 | char *buffer; | ||
250 | |||
251 | buffer = kmalloc(count, GFP_KERNEL); | ||
252 | if (!buffer) | ||
253 | return -ENOMEM; | ||
254 | |||
255 | retval = v9fs_read(filp, buffer, count, offset); | ||
256 | if (retval > 0) { | ||
257 | if ((ret = copy_to_user(data, buffer, retval)) != 0) { | ||
258 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", | ||
259 | ret); | ||
260 | retval = ret; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | kfree(buffer); | ||
265 | |||
266 | return retval; | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * v9fs_write - write to a file | ||
271 | * @filep: file pointer to write | 242 | * @filep: file pointer to write |
272 | * @data: data buffer to write data from | 243 | * @data: data buffer to write data from |
273 | * @count: size of buffer | 244 | * @count: size of buffer |
@@ -276,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, | |||
276 | */ | 247 | */ |
277 | 248 | ||
278 | static ssize_t | 249 | static ssize_t |
279 | v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | 250 | v9fs_file_write(struct file *filp, const char __user * data, |
251 | size_t count, loff_t * offset) | ||
280 | { | 252 | { |
281 | struct inode *inode = filp->f_dentry->d_inode; | 253 | struct inode *inode = filp->f_dentry->d_inode; |
282 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 254 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
@@ -286,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
286 | int result = -EIO; | 258 | int result = -EIO; |
287 | int rsize = 0; | 259 | int rsize = 0; |
288 | int total = 0; | 260 | int total = 0; |
261 | char *buf; | ||
289 | 262 | ||
290 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, | 263 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, |
291 | (int)*offset); | 264 | (int)*offset); |
292 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; | 265 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; |
293 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) | 266 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) |
294 | rsize = v9fid->iounit; | 267 | rsize = v9fid->iounit; |
295 | 268 | ||
296 | dump_data(buffer, count); | 269 | buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); |
270 | if (!buf) | ||
271 | return -ENOMEM; | ||
297 | 272 | ||
298 | do { | 273 | do { |
299 | if (count < rsize) | 274 | if (count < rsize) |
300 | rsize = count; | 275 | rsize = count; |
301 | 276 | ||
302 | result = | 277 | result = copy_from_user(buf, data, rsize); |
303 | v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); | 278 | if (result) { |
279 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
280 | kfree(buf); | ||
281 | return -EFAULT; | ||
282 | } | ||
283 | |||
284 | dump_data(buf, rsize); | ||
285 | result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); | ||
304 | if (result < 0) { | 286 | if (result < 0) { |
305 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", | 287 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", |
306 | FCALL_ERROR(fcall), result); | 288 | FCALL_ERROR(fcall), result); |
307 | kfree(fcall); | 289 | kfree(fcall); |
290 | kfree(buf); | ||
308 | return result; | 291 | return result; |
309 | } else | 292 | } else |
310 | *offset += result; | 293 | *offset += result; |
311 | 294 | ||
312 | kfree(fcall); | 295 | kfree(fcall); |
296 | fcall = NULL; | ||
313 | 297 | ||
314 | if (result != rsize) { | 298 | if (result != rsize) { |
315 | eprintk(KERN_ERR, | 299 | eprintk(KERN_ERR, |
@@ -319,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
319 | } | 303 | } |
320 | 304 | ||
321 | count -= result; | 305 | count -= result; |
322 | buffer += result; | 306 | data += result; |
323 | total += result; | 307 | total += result; |
324 | } while (count); | 308 | } while (count); |
325 | 309 | ||
310 | kfree(buf); | ||
326 | return total; | 311 | return total; |
327 | } | 312 | } |
328 | 313 | ||
329 | /** | ||
330 | * v9fs_file_write - write to a file | ||
331 | * @filep: file pointer to write | ||
332 | * @data: data buffer to write data from | ||
333 | * @count: size of buffer | ||
334 | * @offset: offset at which to write data | ||
335 | * | ||
336 | */ | ||
337 | |||
338 | static ssize_t | ||
339 | v9fs_file_write(struct file *filp, const char __user * data, | ||
340 | size_t count, loff_t * offset) | ||
341 | { | ||
342 | int ret = -1; | ||
343 | char *buffer; | ||
344 | |||
345 | buffer = kmalloc(count, GFP_KERNEL); | ||
346 | if (buffer == NULL) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | ret = copy_from_user(buffer, data, count); | ||
350 | if (ret) { | ||
351 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
352 | ret = -EFAULT; | ||
353 | } else { | ||
354 | ret = v9fs_write(filp, buffer, count, offset); | ||
355 | } | ||
356 | |||
357 | kfree(buffer); | ||
358 | |||
359 | return ret; | ||
360 | } | ||
361 | |||
362 | struct file_operations v9fs_file_operations = { | 314 | struct file_operations v9fs_file_operations = { |
363 | .llseek = generic_file_llseek, | 315 | .llseek = generic_file_llseek, |
364 | .read = v9fs_file_read, | 316 | .read = v9fs_file_read, |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7976a238f0a3..d4b15576e584 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -905,7 +905,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
905 | send_sig(SIGKILL, current, 0); | 905 | send_sig(SIGKILL, current, 0); |
906 | goto out_free_dentry; | 906 | goto out_free_dentry; |
907 | } | 907 | } |
908 | if (padzero(elf_bss)) { | 908 | if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { |
909 | send_sig(SIGSEGV, current, 0); | 909 | send_sig(SIGSEGV, current, 0); |
910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ | 910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ |
911 | goto out_free_dentry; | 911 | goto out_free_dentry; |
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 251e5a1bb1c4..0c2be8c0307d 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
@@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
48 | (struct nfsacl_encode_desc *) desc; | 48 | (struct nfsacl_encode_desc *) desc; |
49 | u32 *p = (u32 *) elem; | 49 | u32 *p = (u32 *) elem; |
50 | 50 | ||
51 | if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { | 51 | struct posix_acl_entry *entry = |
52 | struct posix_acl_entry *entry = | 52 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
53 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; | ||
54 | 53 | ||
55 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); | 54 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
56 | switch(entry->e_tag) { | 55 | switch(entry->e_tag) { |
57 | case ACL_USER_OBJ: | 56 | case ACL_USER_OBJ: |
58 | *p++ = htonl(nfsacl_desc->uid); | 57 | *p++ = htonl(nfsacl_desc->uid); |
59 | break; | 58 | break; |
60 | case ACL_GROUP_OBJ: | 59 | case ACL_GROUP_OBJ: |
61 | *p++ = htonl(nfsacl_desc->gid); | 60 | *p++ = htonl(nfsacl_desc->gid); |
62 | break; | 61 | break; |
63 | case ACL_USER: | 62 | case ACL_USER: |
64 | case ACL_GROUP: | 63 | case ACL_GROUP: |
65 | *p++ = htonl(entry->e_id); | 64 | *p++ = htonl(entry->e_id); |
66 | break; | 65 | break; |
67 | default: /* Solaris depends on that! */ | 66 | default: /* Solaris depends on that! */ |
68 | *p++ = 0; | 67 | *p++ = 0; |
69 | break; | 68 | break; |
70 | } | ||
71 | *p++ = htonl(entry->e_perm & S_IRWXO); | ||
72 | } else { | ||
73 | const struct posix_acl_entry *pa, *pe; | ||
74 | int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; | ||
75 | |||
76 | FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { | ||
77 | if (pa->e_tag == ACL_GROUP_OBJ) { | ||
78 | group_obj_perm = pa->e_perm & S_IRWXO; | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | /* fake up ACL_MASK entry */ | ||
83 | *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); | ||
84 | *p++ = htonl(0); | ||
85 | *p++ = htonl(group_obj_perm); | ||
86 | } | 69 | } |
87 | 70 | *p++ = htonl(entry->e_perm & S_IRWXO); | |
88 | return 0; | 71 | return 0; |
89 | } | 72 | } |
90 | 73 | ||
@@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
105 | .gid = inode->i_gid, | 88 | .gid = inode->i_gid, |
106 | }; | 89 | }; |
107 | int err; | 90 | int err; |
91 | struct posix_acl *acl2 = NULL; | ||
108 | 92 | ||
109 | if (entries > NFS_ACL_MAX_ENTRIES || | 93 | if (entries > NFS_ACL_MAX_ENTRIES || |
110 | xdr_encode_word(buf, base, entries)) | 94 | xdr_encode_word(buf, base, entries)) |
111 | return -EINVAL; | 95 | return -EINVAL; |
96 | if (encode_entries && acl && acl->a_count == 3) { | ||
97 | /* Fake up an ACL_MASK entry. */ | ||
98 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | ||
99 | if (!acl2) | ||
100 | return -ENOMEM; | ||
101 | /* Insert entries in canonical order: other orders seem | ||
102 | to confuse Solaris VxFS. */ | ||
103 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | ||
104 | acl2->a_entries[1] = acl->a_entries[1]; /* ACL_GROUP_OBJ */ | ||
105 | acl2->a_entries[2] = acl->a_entries[1]; /* ACL_MASK */ | ||
106 | acl2->a_entries[2].e_tag = ACL_MASK; | ||
107 | acl2->a_entries[3] = acl->a_entries[2]; /* ACL_OTHER */ | ||
108 | nfsacl_desc.acl = acl2; | ||
109 | } | ||
112 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 110 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
111 | if (acl2) | ||
112 | posix_acl_release(acl2); | ||
113 | if (!err) | 113 | if (!err) |
114 | err = 8 + nfsacl_desc.desc.elem_size * | 114 | err = 8 + nfsacl_desc.desc.elem_size * |
115 | nfsacl_desc.desc.array_len; | 115 | nfsacl_desc.desc.array_len; |
diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h index 51c5b316be55..c02d15aced91 100644 --- a/include/asm-powerpc/timex.h +++ b/include/asm-powerpc/timex.h | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/config.h> | 10 | #include <linux/config.h> |
11 | #include <asm/cputable.h> | 11 | #include <asm/cputable.h> |
12 | 12 | ||
13 | #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ | 13 | #define CLOCK_TICK_RATE 1024000 /* Underlying HZ */ |
14 | 14 | ||
15 | typedef unsigned long cycles_t; | 15 | typedef unsigned long cycles_t; |
16 | 16 | ||
diff --git a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h index 41d8f8425c04..e17c492c870b 100644 --- a/include/asm-ppc/cputable.h +++ b/include/asm-ppc/cputable.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define PPC_FEATURE_HAS_SPE 0x00800000 | 24 | #define PPC_FEATURE_HAS_SPE 0x00800000 |
25 | #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 | 25 | #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 |
26 | #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 | 26 | #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 |
27 | #define PPC_FEATURE_NO_TB 0x00100000 | ||
27 | 28 | ||
28 | #ifdef __KERNEL__ | 29 | #ifdef __KERNEL__ |
29 | 30 | ||
diff --git a/mm/fremap.c b/mm/fremap.c index 3235fb77c133..ab23a0673c35 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
@@ -89,6 +89,9 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
89 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 89 | size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
90 | if (!page->mapping || page->index >= size) | 90 | if (!page->mapping || page->index >= size) |
91 | goto err_unlock; | 91 | goto err_unlock; |
92 | err = -ENOMEM; | ||
93 | if (page_mapcount(page) > INT_MAX/2) | ||
94 | goto err_unlock; | ||
92 | 95 | ||
93 | zap_pte(mm, vma, addr, pte); | 96 | zap_pte(mm, vma, addr, pte); |
94 | 97 | ||
diff --git a/mm/madvise.c b/mm/madvise.c index 4454936f87d1..20e075d1c64c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
@@ -83,6 +83,9 @@ static long madvise_willneed(struct vm_area_struct * vma, | |||
83 | { | 83 | { |
84 | struct file *file = vma->vm_file; | 84 | struct file *file = vma->vm_file; |
85 | 85 | ||
86 | if (!file) | ||
87 | return -EBADF; | ||
88 | |||
86 | if (file->f_mapping->a_ops->get_xip_page) { | 89 | if (file->f_mapping->a_ops->get_xip_page) { |
87 | /* no bad return value, but ignore advice */ | 90 | /* no bad return value, but ignore advice */ |
88 | return 0; | 91 | return 0; |
@@ -141,11 +144,7 @@ static long | |||
141 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, | 144 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, |
142 | unsigned long start, unsigned long end, int behavior) | 145 | unsigned long start, unsigned long end, int behavior) |
143 | { | 146 | { |
144 | struct file *filp = vma->vm_file; | 147 | long error; |
145 | long error = -EBADF; | ||
146 | |||
147 | if (!filp) | ||
148 | goto out; | ||
149 | 148 | ||
150 | switch (behavior) { | 149 | switch (behavior) { |
151 | case MADV_NORMAL: | 150 | case MADV_NORMAL: |
@@ -166,8 +165,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, | |||
166 | error = -EINVAL; | 165 | error = -EINVAL; |
167 | break; | 166 | break; |
168 | } | 167 | } |
169 | |||
170 | out: | ||
171 | return error; | 168 | return error; |
172 | } | 169 | } |
173 | 170 | ||