diff options
235 files changed, 6104 insertions, 2355 deletions
diff --git a/Documentation/scsi/cxgb3i.txt b/Documentation/scsi/cxgb3i.txt index 8141fa01978e..7ac8032ee9b2 100644 --- a/Documentation/scsi/cxgb3i.txt +++ b/Documentation/scsi/cxgb3i.txt | |||
| @@ -4,7 +4,7 @@ Introduction | |||
| 4 | ============ | 4 | ============ |
| 5 | 5 | ||
| 6 | The Chelsio T3 ASIC based Adapters (S310, S320, S302, S304, Mezz cards, etc. | 6 | The Chelsio T3 ASIC based Adapters (S310, S320, S302, S304, Mezz cards, etc. |
| 7 | series of products) supports iSCSI acceleration and iSCSI Direct Data Placement | 7 | series of products) support iSCSI acceleration and iSCSI Direct Data Placement |
| 8 | (DDP) where the hardware handles the expensive byte touching operations, such | 8 | (DDP) where the hardware handles the expensive byte touching operations, such |
| 9 | as CRC computation and verification, and direct DMA to the final host memory | 9 | as CRC computation and verification, and direct DMA to the final host memory |
| 10 | destination: | 10 | destination: |
| @@ -31,9 +31,9 @@ destination: | |||
| 31 | the TCP segments onto the wire. It handles TCP retransmission if | 31 | the TCP segments onto the wire. It handles TCP retransmission if |
| 32 | needed. | 32 | needed. |
| 33 | 33 | ||
| 34 | On receving, S3 h/w recovers the iSCSI PDU by reassembling TCP | 34 | On receiving, S3 h/w recovers the iSCSI PDU by reassembling TCP |
| 35 | segments, separating the header and data, calculating and verifying | 35 | segments, separating the header and data, calculating and verifying |
| 36 | the digests, then forwards the header to the host. The payload data, | 36 | the digests, then forwarding the header to the host. The payload data, |
| 37 | if possible, will be directly placed into the pre-posted host DDP | 37 | if possible, will be directly placed into the pre-posted host DDP |
| 38 | buffer. Otherwise, the payload data will be sent to the host too. | 38 | buffer. Otherwise, the payload data will be sent to the host too. |
| 39 | 39 | ||
| @@ -68,9 +68,8 @@ The following steps need to be taken to accelerates the open-iscsi initiator: | |||
| 68 | sure the ip address is unique in the network. | 68 | sure the ip address is unique in the network. |
| 69 | 69 | ||
| 70 | 3. edit /etc/iscsi/iscsid.conf | 70 | 3. edit /etc/iscsi/iscsid.conf |
| 71 | The default setting for MaxRecvDataSegmentLength (131072) is too big, | 71 | The default setting for MaxRecvDataSegmentLength (131072) is too big; |
| 72 | replace "node.conn[0].iscsi.MaxRecvDataSegmentLength" to be a value no | 72 | replace with a value no bigger than 15360 (for example 8192): |
| 73 | bigger than 15360 (for example 8192): | ||
| 74 | 73 | ||
| 75 | node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192 | 74 | node.conn[0].iscsi.MaxRecvDataSegmentLength = 8192 |
| 76 | 75 | ||
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 12299697b7cd..e0203662f9e9 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt | |||
| @@ -543,7 +543,10 @@ Protocol: 2.08+ | |||
| 543 | 543 | ||
| 544 | The payload may be compressed. The format of both the compressed and | 544 | The payload may be compressed. The format of both the compressed and |
| 545 | uncompressed data should be determined using the standard magic | 545 | uncompressed data should be determined using the standard magic |
| 546 | numbers. Currently only gzip compressed ELF is used. | 546 | numbers. The currently supported compression formats are gzip |
| 547 | (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A) and LZMA | ||
| 548 | (magic number 5D 00). The uncompressed payload is currently always ELF | ||
| 549 | (magic number 7F 45 4C 46). | ||
| 547 | 550 | ||
| 548 | Field name: payload_length | 551 | Field name: payload_length |
| 549 | Type: read | 552 | Type: read |
diff --git a/MAINTAINERS b/MAINTAINERS index 59fd2d1d94a7..1c2ca1dc66f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2464,7 +2464,7 @@ S: Maintained | |||
| 2464 | 2464 | ||
| 2465 | ISDN SUBSYSTEM | 2465 | ISDN SUBSYSTEM |
| 2466 | P: Karsten Keil | 2466 | P: Karsten Keil |
| 2467 | M: kkeil@suse.de | 2467 | M: isdn@linux-pingi.de |
| 2468 | L: isdn4linux@listserv.isdn4linux.de (subscribers-only) | 2468 | L: isdn4linux@listserv.isdn4linux.de (subscribers-only) |
| 2469 | W: http://www.isdn4linux.de | 2469 | W: http://www.isdn4linux.de |
| 2470 | T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git | 2470 | T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 2 | 1 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 29 | 3 | SUBLEVEL = 29 |
| 4 | EXTRAVERSION = -rc6 | 4 | EXTRAVERSION = -rc7 |
| 5 | NAME = Erotic Pickled Herring | 5 | NAME = Erotic Pickled Herring |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 5d7a16eab312..af71d38c8e41 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c | |||
| @@ -189,9 +189,21 @@ callback_init(void * kernel_end) | |||
| 189 | 189 | ||
| 190 | if (alpha_using_srm) { | 190 | if (alpha_using_srm) { |
| 191 | static struct vm_struct console_remap_vm; | 191 | static struct vm_struct console_remap_vm; |
| 192 | unsigned long vaddr = VMALLOC_START; | 192 | unsigned long nr_pages = 0; |
| 193 | unsigned long vaddr; | ||
| 193 | unsigned long i, j; | 194 | unsigned long i, j; |
| 194 | 195 | ||
| 196 | /* calculate needed size */ | ||
| 197 | for (i = 0; i < crb->map_entries; ++i) | ||
| 198 | nr_pages += crb->map[i].count; | ||
| 199 | |||
| 200 | /* register the vm area */ | ||
| 201 | console_remap_vm.flags = VM_ALLOC; | ||
| 202 | console_remap_vm.size = nr_pages << PAGE_SHIFT; | ||
| 203 | vm_area_register_early(&console_remap_vm, PAGE_SIZE); | ||
| 204 | |||
| 205 | vaddr = (unsigned long)console_remap_vm.addr; | ||
| 206 | |||
| 195 | /* Set up the third level PTEs and update the virtual | 207 | /* Set up the third level PTEs and update the virtual |
| 196 | addresses of the CRB entries. */ | 208 | addresses of the CRB entries. */ |
| 197 | for (i = 0; i < crb->map_entries; ++i) { | 209 | for (i = 0; i < crb->map_entries; ++i) { |
| @@ -213,12 +225,6 @@ callback_init(void * kernel_end) | |||
| 213 | vaddr += PAGE_SIZE; | 225 | vaddr += PAGE_SIZE; |
| 214 | } | 226 | } |
| 215 | } | 227 | } |
| 216 | |||
| 217 | /* Let vmalloc know that we've allocated some space. */ | ||
| 218 | console_remap_vm.flags = VM_ALLOC; | ||
| 219 | console_remap_vm.addr = (void *) VMALLOC_START; | ||
| 220 | console_remap_vm.size = vaddr - VMALLOC_START; | ||
| 221 | vmlist = &console_remap_vm; | ||
| 222 | } | 228 | } |
| 223 | 229 | ||
| 224 | callback_init_done = 1; | 230 | callback_init_done = 1; |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7049815d66d5..68d6494c0389 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
| @@ -233,12 +233,13 @@ static void __init cacheid_init(void) | |||
| 233 | unsigned int cachetype = read_cpuid_cachetype(); | 233 | unsigned int cachetype = read_cpuid_cachetype(); |
| 234 | unsigned int arch = cpu_architecture(); | 234 | unsigned int arch = cpu_architecture(); |
| 235 | 235 | ||
| 236 | if (arch >= CPU_ARCH_ARMv7) { | 236 | if (arch >= CPU_ARCH_ARMv6) { |
| 237 | cacheid = CACHEID_VIPT_NONALIASING; | 237 | if ((cachetype & (7 << 29)) == 4 << 29) { |
| 238 | if ((cachetype & (3 << 14)) == 1 << 14) | 238 | /* ARMv7 register format */ |
| 239 | cacheid |= CACHEID_ASID_TAGGED; | 239 | cacheid = CACHEID_VIPT_NONALIASING; |
| 240 | } else if (arch >= CPU_ARCH_ARMv6) { | 240 | if ((cachetype & (3 << 14)) == 1 << 14) |
| 241 | if (cachetype & (1 << 23)) | 241 | cacheid |= CACHEID_ASID_TAGGED; |
| 242 | } else if (cachetype & (1 << 23)) | ||
| 242 | cacheid = CACHEID_VIPT_ALIASING; | 243 | cacheid = CACHEID_VIPT_ALIASING; |
| 243 | else | 244 | else |
| 244 | cacheid = CACHEID_VIPT_NONALIASING; | 245 | cacheid = CACHEID_VIPT_NONALIASING; |
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 9bb4f043aa22..7ac812dc055a 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
| @@ -332,7 +332,6 @@ static int at91_pm_enter(suspend_state_t state) | |||
| 332 | at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); | 332 | at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); |
| 333 | 333 | ||
| 334 | error: | 334 | error: |
| 335 | sdram_selfrefresh_disable(); | ||
| 336 | target_state = PM_SUSPEND_ON; | 335 | target_state = PM_SUSPEND_ON; |
| 337 | at91_irq_resume(); | 336 | at91_irq_resume(); |
| 338 | at91_gpio_resume(); | 337 | at91_gpio_resume(); |
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index 8a7f65ba14b7..94077fbd96b7 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S | |||
| @@ -23,7 +23,8 @@ ENTRY(v6_early_abort) | |||
| 23 | #ifdef CONFIG_CPU_32v6K | 23 | #ifdef CONFIG_CPU_32v6K |
| 24 | clrex | 24 | clrex |
| 25 | #else | 25 | #else |
| 26 | strex r0, r1, [sp] @ Clear the exclusive monitor | 26 | sub r1, sp, #4 @ Get unused stack location |
| 27 | strex r0, r1, [r1] @ Clear the exclusive monitor | ||
| 27 | #endif | 28 | #endif |
| 28 | mrc p15, 0, r1, c5, c0, 0 @ get FSR | 29 | mrc p15, 0, r1, c5, c0, 0 @ get FSR |
| 29 | mrc p15, 0, r0, c6, c0, 0 @ get FAR | 30 | mrc p15, 0, r0, c6, c0, 0 @ get FAR |
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index 1f7cc0067f5c..ebb305ce7689 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c | |||
| @@ -55,7 +55,7 @@ static void s3c_irq_eint_unmask(unsigned int irq) | |||
| 55 | u32 mask; | 55 | u32 mask; |
| 56 | 56 | ||
| 57 | mask = __raw_readl(S3C64XX_EINT0MASK); | 57 | mask = __raw_readl(S3C64XX_EINT0MASK); |
| 58 | mask |= eint_irq_to_bit(irq); | 58 | mask &= ~eint_irq_to_bit(irq); |
| 59 | __raw_writel(mask, S3C64XX_EINT0MASK); | 59 | __raw_writel(mask, S3C64XX_EINT0MASK); |
| 60 | } | 60 | } |
| 61 | 61 | ||
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index b189680d18b0..05fe3053dcae 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
| @@ -181,7 +181,7 @@ source "kernel/Kconfig.preempt" | |||
| 181 | config QUICKLIST | 181 | config QUICKLIST |
| 182 | def_bool y | 182 | def_bool y |
| 183 | 183 | ||
| 184 | config HAVE_ARCH_BOOTMEM_NODE | 184 | config HAVE_ARCH_BOOTMEM |
| 185 | def_bool n | 185 | def_bool n |
| 186 | 186 | ||
| 187 | config ARCH_HAVE_MEMORY_PRESENT | 187 | config ARCH_HAVE_MEMORY_PRESENT |
diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h index 36ed44070256..a6772e9507f5 100644 --- a/arch/mips/include/asm/seccomp.h +++ b/arch/mips/include/asm/seccomp.h | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #ifndef __ASM_SECCOMP_H | 1 | #ifndef __ASM_SECCOMP_H |
| 2 | 2 | ||
| 3 | #include <linux/thread_info.h> | ||
| 4 | #include <linux/unistd.h> | 3 | #include <linux/unistd.h> |
| 5 | 4 | ||
| 6 | #define __NR_seccomp_read __NR_read | 5 | #define __NR_seccomp_read __NR_read |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index d811a8cd7b58..4774c2f92232 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
| @@ -210,5 +210,10 @@ struct compat_shmid64_ds { | |||
| 210 | compat_ulong_t __unused6; | 210 | compat_ulong_t __unused6; |
| 211 | }; | 211 | }; |
| 212 | 212 | ||
| 213 | static inline int is_compat_task(void) | ||
| 214 | { | ||
| 215 | return test_thread_flag(TIF_32BIT); | ||
| 216 | } | ||
| 217 | |||
| 213 | #endif /* __KERNEL__ */ | 218 | #endif /* __KERNEL__ */ |
| 214 | #endif /* _ASM_POWERPC_COMPAT_H */ | 219 | #endif /* _ASM_POWERPC_COMPAT_H */ |
diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h index 853765eb1f65..00c1d9133cfe 100644 --- a/arch/powerpc/include/asm/seccomp.h +++ b/arch/powerpc/include/asm/seccomp.h | |||
| @@ -1,10 +1,6 @@ | |||
| 1 | #ifndef _ASM_POWERPC_SECCOMP_H | 1 | #ifndef _ASM_POWERPC_SECCOMP_H |
| 2 | #define _ASM_POWERPC_SECCOMP_H | 2 | #define _ASM_POWERPC_SECCOMP_H |
| 3 | 3 | ||
| 4 | #ifdef __KERNEL__ | ||
| 5 | #include <linux/thread_info.h> | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #include <linux/unistd.h> | 4 | #include <linux/unistd.h> |
| 9 | 5 | ||
| 10 | #define __NR_seccomp_read __NR_read | 6 | #define __NR_seccomp_read __NR_read |
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index fb371f5ce132..d6b772ba3b8f 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c | |||
| @@ -142,6 +142,10 @@ static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev) | |||
| 142 | { | 142 | { |
| 143 | unsigned int val; | 143 | unsigned int val; |
| 144 | 144 | ||
| 145 | /* Do not do the fixup on other platforms! */ | ||
| 146 | if (!machine_is(gef_sbc610)) | ||
| 147 | return; | ||
| 148 | |||
| 145 | printk(KERN_INFO "Running NEC uPD720101 Fixup\n"); | 149 | printk(KERN_INFO "Running NEC uPD720101 Fixup\n"); |
| 146 | 150 | ||
| 147 | /* Ensure ports 1, 2, 3, 4 & 5 are enabled */ | 151 | /* Ensure ports 1, 2, 3, 4 & 5 are enabled */ |
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index c42cd898f68b..6118890c946d 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c | |||
| @@ -556,7 +556,7 @@ static void __exit aes_s390_fini(void) | |||
| 556 | module_init(aes_s390_init); | 556 | module_init(aes_s390_init); |
| 557 | module_exit(aes_s390_fini); | 557 | module_exit(aes_s390_fini); |
| 558 | 558 | ||
| 559 | MODULE_ALIAS("aes"); | 559 | MODULE_ALIAS("aes-all"); |
| 560 | 560 | ||
| 561 | MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); | 561 | MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); |
| 562 | MODULE_LICENSE("GPL"); | 562 | MODULE_LICENSE("GPL"); |
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index f260b58f5ce9..0e706257918f 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
| @@ -240,4 +240,9 @@ struct compat_shmid64_ds { | |||
| 240 | unsigned int __unused2; | 240 | unsigned int __unused2; |
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | static inline int is_compat_task(void) | ||
| 244 | { | ||
| 245 | return test_thread_flag(TIF_32BIT); | ||
| 246 | } | ||
| 247 | |||
| 243 | #endif /* _ASM_SPARC64_COMPAT_H */ | 248 | #endif /* _ASM_SPARC64_COMPAT_H */ |
diff --git a/arch/sparc/include/asm/seccomp.h b/arch/sparc/include/asm/seccomp.h index 7fcd9968192b..adca1bce41d4 100644 --- a/arch/sparc/include/asm/seccomp.h +++ b/arch/sparc/include/asm/seccomp.h | |||
| @@ -1,11 +1,5 @@ | |||
| 1 | #ifndef _ASM_SECCOMP_H | 1 | #ifndef _ASM_SECCOMP_H |
| 2 | 2 | ||
| 3 | #include <linux/thread_info.h> /* already defines TIF_32BIT */ | ||
| 4 | |||
| 5 | #ifndef TIF_32BIT | ||
| 6 | #error "unexpected TIF_32BIT on sparc64" | ||
| 7 | #endif | ||
| 8 | |||
| 9 | #include <linux/unistd.h> | 3 | #include <linux/unistd.h> |
| 10 | 4 | ||
| 11 | #define __NR_seccomp_read __NR_read | 5 | #define __NR_seccomp_read __NR_read |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3afc94abe357..31758378bcd2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -40,6 +40,9 @@ config X86 | |||
| 40 | select HAVE_GENERIC_DMA_COHERENT if X86_32 | 40 | select HAVE_GENERIC_DMA_COHERENT if X86_32 |
| 41 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 41 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
| 42 | select USER_STACKTRACE_SUPPORT | 42 | select USER_STACKTRACE_SUPPORT |
| 43 | select HAVE_KERNEL_GZIP | ||
| 44 | select HAVE_KERNEL_BZIP2 | ||
| 45 | select HAVE_KERNEL_LZMA | ||
| 43 | 46 | ||
| 44 | config ARCH_DEFCONFIG | 47 | config ARCH_DEFCONFIG |
| 45 | string | 48 | string |
| @@ -135,6 +138,9 @@ config ARCH_HAS_CACHE_LINE_SIZE | |||
| 135 | config HAVE_SETUP_PER_CPU_AREA | 138 | config HAVE_SETUP_PER_CPU_AREA |
| 136 | def_bool y | 139 | def_bool y |
| 137 | 140 | ||
| 141 | config HAVE_DYNAMIC_PER_CPU_AREA | ||
| 142 | def_bool y | ||
| 143 | |||
| 138 | config HAVE_CPUMASK_OF_CPU_MAP | 144 | config HAVE_CPUMASK_OF_CPU_MAP |
| 139 | def_bool X86_64_SMP | 145 | def_bool X86_64_SMP |
| 140 | 146 | ||
| @@ -1127,7 +1133,7 @@ config NODES_SHIFT | |||
| 1127 | Specify the maximum number of NUMA Nodes available on the target | 1133 | Specify the maximum number of NUMA Nodes available on the target |
| 1128 | system. Increases memory reserved to accomodate various tables. | 1134 | system. Increases memory reserved to accomodate various tables. |
| 1129 | 1135 | ||
| 1130 | config HAVE_ARCH_BOOTMEM_NODE | 1136 | config HAVE_ARCH_BOOTMEM |
| 1131 | def_bool y | 1137 | def_bool y |
| 1132 | depends on X86_32 && NUMA | 1138 | depends on X86_32 && NUMA |
| 1133 | 1139 | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 1771c804e02f..3ca4c194b8e5 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | # create a compressed vmlinux image from the original vmlinux | 4 | # create a compressed vmlinux image from the original vmlinux |
| 5 | # | 5 | # |
| 6 | 6 | ||
| 7 | targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o | 7 | targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o |
| 8 | 8 | ||
| 9 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 | 9 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 |
| 10 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIC | 10 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIC |
| @@ -47,18 +47,35 @@ ifeq ($(CONFIG_X86_32),y) | |||
| 47 | ifdef CONFIG_RELOCATABLE | 47 | ifdef CONFIG_RELOCATABLE |
| 48 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE | 48 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE |
| 49 | $(call if_changed,gzip) | 49 | $(call if_changed,gzip) |
| 50 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE | ||
| 51 | $(call if_changed,bzip2) | ||
| 52 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE | ||
| 53 | $(call if_changed,lzma) | ||
| 50 | else | 54 | else |
| 51 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE | 55 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE |
| 52 | $(call if_changed,gzip) | 56 | $(call if_changed,gzip) |
| 57 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE | ||
| 58 | $(call if_changed,bzip2) | ||
| 59 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE | ||
| 60 | $(call if_changed,lzma) | ||
| 53 | endif | 61 | endif |
| 54 | LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T | 62 | LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T |
| 55 | 63 | ||
| 56 | else | 64 | else |
| 65 | |||
| 57 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE | 66 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE |
| 58 | $(call if_changed,gzip) | 67 | $(call if_changed,gzip) |
| 68 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE | ||
| 69 | $(call if_changed,bzip2) | ||
| 70 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE | ||
| 71 | $(call if_changed,lzma) | ||
| 59 | 72 | ||
| 60 | LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T | 73 | LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T |
| 61 | endif | 74 | endif |
| 62 | 75 | ||
| 63 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE | 76 | suffix_$(CONFIG_KERNEL_GZIP) = gz |
| 77 | suffix_$(CONFIG_KERNEL_BZIP2) = bz2 | ||
| 78 | suffix_$(CONFIG_KERNEL_LZMA) = lzma | ||
| 79 | |||
| 80 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE | ||
| 64 | $(call if_changed,ld) | 81 | $(call if_changed,ld) |
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index da062216948a..e45be73684ff 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
| @@ -116,71 +116,13 @@ | |||
| 116 | /* | 116 | /* |
| 117 | * gzip declarations | 117 | * gzip declarations |
| 118 | */ | 118 | */ |
| 119 | |||
| 120 | #define OF(args) args | ||
| 121 | #define STATIC static | 119 | #define STATIC static |
| 122 | 120 | ||
| 123 | #undef memset | 121 | #undef memset |
| 124 | #undef memcpy | 122 | #undef memcpy |
| 125 | #define memzero(s, n) memset((s), 0, (n)) | 123 | #define memzero(s, n) memset((s), 0, (n)) |
| 126 | 124 | ||
| 127 | typedef unsigned char uch; | ||
| 128 | typedef unsigned short ush; | ||
| 129 | typedef unsigned long ulg; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Window size must be at least 32k, and a power of two. | ||
| 133 | * We don't actually have a window just a huge output buffer, | ||
| 134 | * so we report a 2G window size, as that should always be | ||
| 135 | * larger than our output buffer: | ||
| 136 | */ | ||
| 137 | #define WSIZE 0x80000000 | ||
| 138 | |||
| 139 | /* Input buffer: */ | ||
| 140 | static unsigned char *inbuf; | ||
| 141 | |||
| 142 | /* Sliding window buffer (and final output buffer): */ | ||
| 143 | static unsigned char *window; | ||
| 144 | |||
| 145 | /* Valid bytes in inbuf: */ | ||
| 146 | static unsigned insize; | ||
| 147 | |||
| 148 | /* Index of next byte to be processed in inbuf: */ | ||
| 149 | static unsigned inptr; | ||
| 150 | |||
| 151 | /* Bytes in output buffer: */ | ||
| 152 | static unsigned outcnt; | ||
| 153 | |||
| 154 | /* gzip flag byte */ | ||
| 155 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ | ||
| 156 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gz file */ | ||
| 157 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | ||
| 158 | #define ORIG_NAM 0x08 /* bit 3 set: original file name present */ | ||
| 159 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | ||
| 160 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ | ||
| 161 | #define RESERVED 0xC0 /* bit 6, 7: reserved */ | ||
| 162 | |||
| 163 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | ||
| 164 | |||
| 165 | /* Diagnostic functions */ | ||
| 166 | #ifdef DEBUG | ||
| 167 | # define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) | ||
| 168 | # define Trace(x) do { fprintf x; } while (0) | ||
| 169 | # define Tracev(x) do { if (verbose) fprintf x ; } while (0) | ||
| 170 | # define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) | ||
| 171 | # define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) | ||
| 172 | # define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) | ||
| 173 | #else | ||
| 174 | # define Assert(cond, msg) | ||
| 175 | # define Trace(x) | ||
| 176 | # define Tracev(x) | ||
| 177 | # define Tracevv(x) | ||
| 178 | # define Tracec(c, x) | ||
| 179 | # define Tracecv(c, x) | ||
| 180 | #endif | ||
| 181 | 125 | ||
| 182 | static int fill_inbuf(void); | ||
| 183 | static void flush_window(void); | ||
| 184 | static void error(char *m); | 126 | static void error(char *m); |
| 185 | 127 | ||
| 186 | /* | 128 | /* |
| @@ -189,13 +131,8 @@ static void error(char *m); | |||
| 189 | static struct boot_params *real_mode; /* Pointer to real-mode data */ | 131 | static struct boot_params *real_mode; /* Pointer to real-mode data */ |
| 190 | static int quiet; | 132 | static int quiet; |
| 191 | 133 | ||
| 192 | extern unsigned char input_data[]; | ||
| 193 | extern int input_len; | ||
| 194 | |||
| 195 | static long bytes_out; | ||
| 196 | |||
| 197 | static void *memset(void *s, int c, unsigned n); | 134 | static void *memset(void *s, int c, unsigned n); |
| 198 | static void *memcpy(void *dest, const void *src, unsigned n); | 135 | void *memcpy(void *dest, const void *src, unsigned n); |
| 199 | 136 | ||
| 200 | static void __putstr(int, const char *); | 137 | static void __putstr(int, const char *); |
| 201 | #define putstr(__x) __putstr(0, __x) | 138 | #define putstr(__x) __putstr(0, __x) |
| @@ -213,7 +150,17 @@ static char *vidmem; | |||
| 213 | static int vidport; | 150 | static int vidport; |
| 214 | static int lines, cols; | 151 | static int lines, cols; |
| 215 | 152 | ||
| 216 | #include "../../../../lib/inflate.c" | 153 | #ifdef CONFIG_KERNEL_GZIP |
| 154 | #include "../../../../lib/decompress_inflate.c" | ||
| 155 | #endif | ||
| 156 | |||
| 157 | #ifdef CONFIG_KERNEL_BZIP2 | ||
| 158 | #include "../../../../lib/decompress_bunzip2.c" | ||
| 159 | #endif | ||
| 160 | |||
| 161 | #ifdef CONFIG_KERNEL_LZMA | ||
| 162 | #include "../../../../lib/decompress_unlzma.c" | ||
| 163 | #endif | ||
| 217 | 164 | ||
| 218 | static void scroll(void) | 165 | static void scroll(void) |
| 219 | { | 166 | { |
| @@ -282,7 +229,7 @@ static void *memset(void *s, int c, unsigned n) | |||
| 282 | return s; | 229 | return s; |
| 283 | } | 230 | } |
| 284 | 231 | ||
| 285 | static void *memcpy(void *dest, const void *src, unsigned n) | 232 | void *memcpy(void *dest, const void *src, unsigned n) |
| 286 | { | 233 | { |
| 287 | int i; | 234 | int i; |
| 288 | const char *s = src; | 235 | const char *s = src; |
| @@ -293,38 +240,6 @@ static void *memcpy(void *dest, const void *src, unsigned n) | |||
| 293 | return dest; | 240 | return dest; |
| 294 | } | 241 | } |
| 295 | 242 | ||
| 296 | /* =========================================================================== | ||
| 297 | * Fill the input buffer. This is called only when the buffer is empty | ||
| 298 | * and at least one byte is really needed. | ||
| 299 | */ | ||
| 300 | static int fill_inbuf(void) | ||
| 301 | { | ||
| 302 | error("ran out of input data"); | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* =========================================================================== | ||
| 307 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
| 308 | * (Used for the decompressed data only.) | ||
| 309 | */ | ||
| 310 | static void flush_window(void) | ||
| 311 | { | ||
| 312 | /* With my window equal to my output buffer | ||
| 313 | * I only need to compute the crc here. | ||
| 314 | */ | ||
| 315 | unsigned long c = crc; /* temporary variable */ | ||
| 316 | unsigned n; | ||
| 317 | unsigned char *in, ch; | ||
| 318 | |||
| 319 | in = window; | ||
| 320 | for (n = 0; n < outcnt; n++) { | ||
| 321 | ch = *in++; | ||
| 322 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
| 323 | } | ||
| 324 | crc = c; | ||
| 325 | bytes_out += (unsigned long)outcnt; | ||
| 326 | outcnt = 0; | ||
| 327 | } | ||
| 328 | 243 | ||
| 329 | static void error(char *x) | 244 | static void error(char *x) |
| 330 | { | 245 | { |
| @@ -407,12 +322,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
| 407 | lines = real_mode->screen_info.orig_video_lines; | 322 | lines = real_mode->screen_info.orig_video_lines; |
| 408 | cols = real_mode->screen_info.orig_video_cols; | 323 | cols = real_mode->screen_info.orig_video_cols; |
| 409 | 324 | ||
| 410 | window = output; /* Output buffer (Normally at 1M) */ | ||
| 411 | free_mem_ptr = heap; /* Heap */ | 325 | free_mem_ptr = heap; /* Heap */ |
| 412 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; | 326 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; |
| 413 | inbuf = input_data; /* Input buffer */ | ||
| 414 | insize = input_len; | ||
| 415 | inptr = 0; | ||
| 416 | 327 | ||
| 417 | #ifdef CONFIG_X86_64 | 328 | #ifdef CONFIG_X86_64 |
| 418 | if ((unsigned long)output & (__KERNEL_ALIGN - 1)) | 329 | if ((unsigned long)output & (__KERNEL_ALIGN - 1)) |
| @@ -430,10 +341,9 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
| 430 | #endif | 341 | #endif |
| 431 | #endif | 342 | #endif |
| 432 | 343 | ||
| 433 | makecrc(); | ||
| 434 | if (!quiet) | 344 | if (!quiet) |
| 435 | putstr("\nDecompressing Linux... "); | 345 | putstr("\nDecompressing Linux... "); |
| 436 | gunzip(); | 346 | decompress(input_data, input_len, NULL, NULL, output, NULL, error); |
| 437 | parse_elf(output); | 347 | parse_elf(output); |
| 438 | if (!quiet) | 348 | if (!quiet) |
| 439 | putstr("done.\nBooting the kernel.\n"); | 349 | putstr("done.\nBooting the kernel.\n"); |
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index a6208dc74633..4ef949c1972e 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
| @@ -75,7 +75,14 @@ static inline void default_inquire_remote_apic(int apicid) | |||
| 75 | #define setup_secondary_clock setup_secondary_APIC_clock | 75 | #define setup_secondary_clock setup_secondary_APIC_clock |
| 76 | #endif | 76 | #endif |
| 77 | 77 | ||
| 78 | #ifdef CONFIG_X86_VSMP | ||
| 78 | extern int is_vsmp_box(void); | 79 | extern int is_vsmp_box(void); |
| 80 | #else | ||
| 81 | static inline int is_vsmp_box(void) | ||
| 82 | { | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | #endif | ||
| 79 | extern void xapic_wait_icr_idle(void); | 86 | extern void xapic_wait_icr_idle(void); |
| 80 | extern u32 safe_xapic_wait_icr_idle(void); | 87 | extern u32 safe_xapic_wait_icr_idle(void); |
| 81 | extern void xapic_icr_write(u32, u32); | 88 | extern void xapic_icr_write(u32, u32); |
| @@ -306,7 +313,7 @@ struct apic { | |||
| 306 | void (*send_IPI_self)(int vector); | 313 | void (*send_IPI_self)(int vector); |
| 307 | 314 | ||
| 308 | /* wakeup_secondary_cpu */ | 315 | /* wakeup_secondary_cpu */ |
| 309 | int (*wakeup_cpu)(int apicid, unsigned long start_eip); | 316 | int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip); |
| 310 | 317 | ||
| 311 | int trampoline_phys_low; | 318 | int trampoline_phys_low; |
| 312 | int trampoline_phys_high; | 319 | int trampoline_phys_high; |
| @@ -324,8 +331,21 @@ struct apic { | |||
| 324 | u32 (*safe_wait_icr_idle)(void); | 331 | u32 (*safe_wait_icr_idle)(void); |
| 325 | }; | 332 | }; |
| 326 | 333 | ||
| 334 | /* | ||
| 335 | * Pointer to the local APIC driver in use on this system (there's | ||
| 336 | * always just one such driver in use - the kernel decides via an | ||
| 337 | * early probing process which one it picks - and then sticks to it): | ||
| 338 | */ | ||
| 327 | extern struct apic *apic; | 339 | extern struct apic *apic; |
| 328 | 340 | ||
| 341 | /* | ||
| 342 | * APIC functionality to boot other CPUs - only used on SMP: | ||
| 343 | */ | ||
| 344 | #ifdef CONFIG_SMP | ||
| 345 | extern atomic_t init_deasserted; | ||
| 346 | extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); | ||
| 347 | #endif | ||
| 348 | |||
| 329 | static inline u32 apic_read(u32 reg) | 349 | static inline u32 apic_read(u32 reg) |
| 330 | { | 350 | { |
| 331 | return apic->read(reg); | 351 | return apic->read(reg); |
| @@ -384,9 +404,7 @@ static inline unsigned default_get_apic_id(unsigned long x) | |||
| 384 | #define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467 | 404 | #define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467 |
| 385 | #define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469 | 405 | #define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469 |
| 386 | 406 | ||
| 387 | #ifdef CONFIG_X86_32 | 407 | #ifdef CONFIG_X86_64 |
| 388 | extern void es7000_update_apic_to_cluster(void); | ||
| 389 | #else | ||
| 390 | extern struct apic apic_flat; | 408 | extern struct apic apic_flat; |
| 391 | extern struct apic apic_physflat; | 409 | extern struct apic apic_physflat; |
| 392 | extern struct apic apic_x2apic_cluster; | 410 | extern struct apic apic_x2apic_cluster; |
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index dd61616cb73d..6526cf08b0e4 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h | |||
| @@ -10,17 +10,31 @@ | |||
| 10 | #define EXTENDED_VGA 0xfffe /* 80x50 mode */ | 10 | #define EXTENDED_VGA 0xfffe /* 80x50 mode */ |
| 11 | #define ASK_VGA 0xfffd /* ask for it at bootup */ | 11 | #define ASK_VGA 0xfffd /* ask for it at bootup */ |
| 12 | 12 | ||
| 13 | #ifdef __KERNEL__ | ||
| 14 | |||
| 13 | /* Physical address where kernel should be loaded. */ | 15 | /* Physical address where kernel should be loaded. */ |
| 14 | #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ | 16 | #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ |
| 15 | + (CONFIG_PHYSICAL_ALIGN - 1)) \ | 17 | + (CONFIG_PHYSICAL_ALIGN - 1)) \ |
| 16 | & ~(CONFIG_PHYSICAL_ALIGN - 1)) | 18 | & ~(CONFIG_PHYSICAL_ALIGN - 1)) |
| 17 | 19 | ||
| 20 | #ifdef CONFIG_KERNEL_BZIP2 | ||
| 21 | #define BOOT_HEAP_SIZE 0x400000 | ||
| 22 | #else /* !CONFIG_KERNEL_BZIP2 */ | ||
| 23 | |||
| 18 | #ifdef CONFIG_X86_64 | 24 | #ifdef CONFIG_X86_64 |
| 19 | #define BOOT_HEAP_SIZE 0x7000 | 25 | #define BOOT_HEAP_SIZE 0x7000 |
| 20 | #define BOOT_STACK_SIZE 0x4000 | ||
| 21 | #else | 26 | #else |
| 22 | #define BOOT_HEAP_SIZE 0x4000 | 27 | #define BOOT_HEAP_SIZE 0x4000 |
| 28 | #endif | ||
| 29 | |||
| 30 | #endif /* !CONFIG_KERNEL_BZIP2 */ | ||
| 31 | |||
| 32 | #ifdef CONFIG_X86_64 | ||
| 33 | #define BOOT_STACK_SIZE 0x4000 | ||
| 34 | #else | ||
| 23 | #define BOOT_STACK_SIZE 0x1000 | 35 | #define BOOT_STACK_SIZE 0x1000 |
| 24 | #endif | 36 | #endif |
| 25 | 37 | ||
| 38 | #endif /* __KERNEL__ */ | ||
| 39 | |||
| 26 | #endif /* _ASM_X86_BOOT_H */ | 40 | #endif /* _ASM_X86_BOOT_H */ |
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index 2f8466540fb5..5b301b7ff5f4 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h | |||
| @@ -5,24 +5,43 @@ | |||
| 5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
| 6 | 6 | ||
| 7 | /* Caches aren't brain-dead on the intel. */ | 7 | /* Caches aren't brain-dead on the intel. */ |
| 8 | #define flush_cache_all() do { } while (0) | 8 | static inline void flush_cache_all(void) { } |
| 9 | #define flush_cache_mm(mm) do { } while (0) | 9 | static inline void flush_cache_mm(struct mm_struct *mm) { } |
| 10 | #define flush_cache_dup_mm(mm) do { } while (0) | 10 | static inline void flush_cache_dup_mm(struct mm_struct *mm) { } |
| 11 | #define flush_cache_range(vma, start, end) do { } while (0) | 11 | static inline void flush_cache_range(struct vm_area_struct *vma, |
| 12 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 12 | unsigned long start, unsigned long end) { } |
| 13 | #define flush_dcache_page(page) do { } while (0) | 13 | static inline void flush_cache_page(struct vm_area_struct *vma, |
| 14 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 14 | unsigned long vmaddr, unsigned long pfn) { } |
| 15 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 15 | static inline void flush_dcache_page(struct page *page) { } |
| 16 | #define flush_icache_range(start, end) do { } while (0) | 16 | static inline void flush_dcache_mmap_lock(struct address_space *mapping) { } |
| 17 | #define flush_icache_page(vma, pg) do { } while (0) | 17 | static inline void flush_dcache_mmap_unlock(struct address_space *mapping) { } |
| 18 | #define flush_icache_user_range(vma, pg, adr, len) do { } while (0) | 18 | static inline void flush_icache_range(unsigned long start, |
| 19 | #define flush_cache_vmap(start, end) do { } while (0) | 19 | unsigned long end) { } |
| 20 | #define flush_cache_vunmap(start, end) do { } while (0) | 20 | static inline void flush_icache_page(struct vm_area_struct *vma, |
| 21 | struct page *page) { } | ||
| 22 | static inline void flush_icache_user_range(struct vm_area_struct *vma, | ||
| 23 | struct page *page, | ||
| 24 | unsigned long addr, | ||
| 25 | unsigned long len) { } | ||
| 26 | static inline void flush_cache_vmap(unsigned long start, unsigned long end) { } | ||
| 27 | static inline void flush_cache_vunmap(unsigned long start, | ||
| 28 | unsigned long end) { } | ||
| 21 | 29 | ||
| 22 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 30 | static inline void copy_to_user_page(struct vm_area_struct *vma, |
| 23 | memcpy((dst), (src), (len)) | 31 | struct page *page, unsigned long vaddr, |
| 24 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 32 | void *dst, const void *src, |
| 25 | memcpy((dst), (src), (len)) | 33 | unsigned long len) |
| 34 | { | ||
| 35 | memcpy(dst, src, len); | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline void copy_from_user_page(struct vm_area_struct *vma, | ||
| 39 | struct page *page, unsigned long vaddr, | ||
| 40 | void *dst, const void *src, | ||
| 41 | unsigned long len) | ||
| 42 | { | ||
| 43 | memcpy(dst, src, len); | ||
| 44 | } | ||
| 26 | 45 | ||
| 27 | #define PG_non_WB PG_arch_1 | 46 | #define PG_non_WB PG_arch_1 |
| 28 | PAGEFLAG(NonWB, non_WB) | 47 | PAGEFLAG(NonWB, non_WB) |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index ca5ffb2856b6..edc90f23e708 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
| @@ -37,8 +37,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); | |||
| 37 | 37 | ||
| 38 | #else /* !CONFIG_X86_32 */ | 38 | #else /* !CONFIG_X86_32 */ |
| 39 | 39 | ||
| 40 | #define MAX_EFI_IO_PAGES 100 | ||
| 41 | |||
| 42 | extern u64 efi_call0(void *fp); | 40 | extern u64 efi_call0(void *fp); |
| 43 | extern u64 efi_call1(void *fp, u64 arg1); | 41 | extern u64 efi_call1(void *fp, u64 arg1); |
| 44 | extern u64 efi_call2(void *fp, u64 arg1, u64 arg2); | 42 | extern u64 efi_call2(void *fp, u64 arg1, u64 arg2); |
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 23696d44a0af..63a79c77d220 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
| @@ -1,11 +1,145 @@ | |||
| 1 | /* | ||
| 2 | * fixmap.h: compile-time virtual memory allocation | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 1998 Ingo Molnar | ||
| 9 | * | ||
| 10 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | ||
| 11 | * x86_32 and x86_64 integration by Gustavo F. Padovan, February 2009 | ||
| 12 | */ | ||
| 13 | |||
| 1 | #ifndef _ASM_X86_FIXMAP_H | 14 | #ifndef _ASM_X86_FIXMAP_H |
| 2 | #define _ASM_X86_FIXMAP_H | 15 | #define _ASM_X86_FIXMAP_H |
| 3 | 16 | ||
| 17 | #ifndef __ASSEMBLY__ | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <asm/acpi.h> | ||
| 20 | #include <asm/apicdef.h> | ||
| 21 | #include <asm/page.h> | ||
| 22 | #ifdef CONFIG_X86_32 | ||
| 23 | #include <linux/threads.h> | ||
| 24 | #include <asm/kmap_types.h> | ||
| 25 | #else | ||
| 26 | #include <asm/vsyscall.h> | ||
| 27 | #endif | ||
| 28 | |||
| 29 | /* | ||
| 30 | * We can't declare FIXADDR_TOP as variable for x86_64 because vsyscall | ||
| 31 | * uses fixmaps that relies on FIXADDR_TOP for proper address calculation. | ||
| 32 | * Because of this, FIXADDR_TOP x86 integration was left as later work. | ||
| 33 | */ | ||
| 34 | #ifdef CONFIG_X86_32 | ||
| 35 | /* used by vmalloc.c, vsyscall.lds.S. | ||
| 36 | * | ||
| 37 | * Leave one empty page between vmalloc'ed areas and | ||
| 38 | * the start of the fixmap. | ||
| 39 | */ | ||
| 40 | extern unsigned long __FIXADDR_TOP; | ||
| 41 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) | ||
| 42 | |||
| 43 | #define FIXADDR_USER_START __fix_to_virt(FIX_VDSO) | ||
| 44 | #define FIXADDR_USER_END __fix_to_virt(FIX_VDSO - 1) | ||
| 45 | #else | ||
| 46 | #define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE) | ||
| 47 | |||
| 48 | /* Only covers 32bit vsyscalls currently. Need another set for 64bit. */ | ||
| 49 | #define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) | ||
| 50 | #define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) | ||
| 51 | #endif | ||
| 52 | |||
| 53 | |||
| 54 | /* | ||
| 55 | * Here we define all the compile-time 'special' virtual | ||
| 56 | * addresses. The point is to have a constant address at | ||
| 57 | * compile time, but to set the physical address only | ||
| 58 | * in the boot process. | ||
| 59 | * for x86_32: We allocate these special addresses | ||
| 60 | * from the end of virtual memory (0xfffff000) backwards. | ||
| 61 | * Also this lets us do fail-safe vmalloc(), we | ||
| 62 | * can guarantee that these special addresses and | ||
| 63 | * vmalloc()-ed addresses never overlap. | ||
| 64 | * | ||
| 65 | * These 'compile-time allocated' memory buffers are | ||
| 66 | * fixed-size 4k pages (or larger if used with an increment | ||
| 67 | * higher than 1). Use set_fixmap(idx,phys) to associate | ||
| 68 | * physical memory with fixmap indices. | ||
| 69 | * | ||
| 70 | * TLB entries of such buffers will not be flushed across | ||
| 71 | * task switches. | ||
| 72 | */ | ||
| 73 | enum fixed_addresses { | ||
| 4 | #ifdef CONFIG_X86_32 | 74 | #ifdef CONFIG_X86_32 |
| 5 | # include "fixmap_32.h" | 75 | FIX_HOLE, |
| 76 | FIX_VDSO, | ||
| 6 | #else | 77 | #else |
| 7 | # include "fixmap_64.h" | 78 | VSYSCALL_LAST_PAGE, |
| 79 | VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE | ||
| 80 | + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, | ||
| 81 | VSYSCALL_HPET, | ||
| 8 | #endif | 82 | #endif |
| 83 | FIX_DBGP_BASE, | ||
| 84 | FIX_EARLYCON_MEM_BASE, | ||
| 85 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 86 | FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ | ||
| 87 | #endif | ||
| 88 | #ifdef CONFIG_X86_IO_APIC | ||
| 89 | FIX_IO_APIC_BASE_0, | ||
| 90 | FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1, | ||
| 91 | #endif | ||
| 92 | #ifdef CONFIG_X86_VISWS_APIC | ||
| 93 | FIX_CO_CPU, /* Cobalt timer */ | ||
| 94 | FIX_CO_APIC, /* Cobalt APIC Redirection Table */ | ||
| 95 | FIX_LI_PCIA, /* Lithium PCI Bridge A */ | ||
| 96 | FIX_LI_PCIB, /* Lithium PCI Bridge B */ | ||
| 97 | #endif | ||
| 98 | #ifdef CONFIG_X86_F00F_BUG | ||
| 99 | FIX_F00F_IDT, /* Virtual mapping for IDT */ | ||
| 100 | #endif | ||
| 101 | #ifdef CONFIG_X86_CYCLONE_TIMER | ||
| 102 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ | ||
| 103 | #endif | ||
| 104 | #ifdef CONFIG_X86_32 | ||
| 105 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | ||
| 106 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | ||
| 107 | #ifdef CONFIG_PCI_MMCONFIG | ||
| 108 | FIX_PCIE_MCFG, | ||
| 109 | #endif | ||
| 110 | #endif | ||
| 111 | #ifdef CONFIG_PARAVIRT | ||
| 112 | FIX_PARAVIRT_BOOTMAP, | ||
| 113 | #endif | ||
| 114 | __end_of_permanent_fixed_addresses, | ||
| 115 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | ||
| 116 | FIX_OHCI1394_BASE, | ||
| 117 | #endif | ||
| 118 | /* | ||
| 119 | * 256 temporary boot-time mappings, used by early_ioremap(), | ||
| 120 | * before ioremap() is functional. | ||
| 121 | * | ||
| 122 | * We round it up to the next 256 pages boundary so that we | ||
| 123 | * can have a single pgd entry and a single pte table: | ||
| 124 | */ | ||
| 125 | #define NR_FIX_BTMAPS 64 | ||
| 126 | #define FIX_BTMAPS_SLOTS 4 | ||
| 127 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - | ||
| 128 | (__end_of_permanent_fixed_addresses & 255), | ||
| 129 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, | ||
| 130 | #ifdef CONFIG_X86_32 | ||
| 131 | FIX_WP_TEST, | ||
| 132 | #endif | ||
| 133 | __end_of_fixed_addresses | ||
| 134 | }; | ||
| 135 | |||
| 136 | |||
| 137 | extern void reserve_top_address(unsigned long reserve); | ||
| 138 | |||
| 139 | #define FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) | ||
| 140 | #define FIXADDR_BOOT_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | ||
| 141 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) | ||
| 142 | #define FIXADDR_BOOT_START (FIXADDR_TOP - FIXADDR_BOOT_SIZE) | ||
| 9 | 143 | ||
| 10 | extern int fixmaps_set; | 144 | extern int fixmaps_set; |
| 11 | 145 | ||
| @@ -69,4 +203,5 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr) | |||
| 69 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); | 203 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); |
| 70 | return __virt_to_fix(vaddr); | 204 | return __virt_to_fix(vaddr); |
| 71 | } | 205 | } |
| 206 | #endif /* !__ASSEMBLY__ */ | ||
| 72 | #endif /* _ASM_X86_FIXMAP_H */ | 207 | #endif /* _ASM_X86_FIXMAP_H */ |
diff --git a/arch/x86/include/asm/fixmap_32.h b/arch/x86/include/asm/fixmap_32.h deleted file mode 100644 index 047d9bab2b31..000000000000 --- a/arch/x86/include/asm/fixmap_32.h +++ /dev/null | |||
| @@ -1,115 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * fixmap.h: compile-time virtual memory allocation | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 1998 Ingo Molnar | ||
| 9 | * | ||
| 10 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _ASM_X86_FIXMAP_32_H | ||
| 14 | #define _ASM_X86_FIXMAP_32_H | ||
| 15 | |||
| 16 | |||
| 17 | /* used by vmalloc.c, vsyscall.lds.S. | ||
| 18 | * | ||
| 19 | * Leave one empty page between vmalloc'ed areas and | ||
| 20 | * the start of the fixmap. | ||
| 21 | */ | ||
| 22 | extern unsigned long __FIXADDR_TOP; | ||
| 23 | #define FIXADDR_USER_START __fix_to_virt(FIX_VDSO) | ||
| 24 | #define FIXADDR_USER_END __fix_to_virt(FIX_VDSO - 1) | ||
| 25 | |||
| 26 | #ifndef __ASSEMBLY__ | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <asm/acpi.h> | ||
| 29 | #include <asm/apicdef.h> | ||
| 30 | #include <asm/page.h> | ||
| 31 | #include <linux/threads.h> | ||
| 32 | #include <asm/kmap_types.h> | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Here we define all the compile-time 'special' virtual | ||
| 36 | * addresses. The point is to have a constant address at | ||
| 37 | * compile time, but to set the physical address only | ||
| 38 | * in the boot process. We allocate these special addresses | ||
| 39 | * from the end of virtual memory (0xfffff000) backwards. | ||
| 40 | * Also this lets us do fail-safe vmalloc(), we | ||
| 41 | * can guarantee that these special addresses and | ||
| 42 | * vmalloc()-ed addresses never overlap. | ||
| 43 | * | ||
| 44 | * these 'compile-time allocated' memory buffers are | ||
| 45 | * fixed-size 4k pages. (or larger if used with an increment | ||
| 46 | * highger than 1) use fixmap_set(idx,phys) to associate | ||
| 47 | * physical memory with fixmap indices. | ||
| 48 | * | ||
| 49 | * TLB entries of such buffers will not be flushed across | ||
| 50 | * task switches. | ||
| 51 | */ | ||
| 52 | enum fixed_addresses { | ||
| 53 | FIX_HOLE, | ||
| 54 | FIX_VDSO, | ||
| 55 | FIX_DBGP_BASE, | ||
| 56 | FIX_EARLYCON_MEM_BASE, | ||
| 57 | #ifdef CONFIG_X86_LOCAL_APIC | ||
| 58 | FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ | ||
| 59 | #endif | ||
| 60 | #ifdef CONFIG_X86_IO_APIC | ||
| 61 | FIX_IO_APIC_BASE_0, | ||
| 62 | FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1, | ||
| 63 | #endif | ||
| 64 | #ifdef CONFIG_X86_VISWS_APIC | ||
| 65 | FIX_CO_CPU, /* Cobalt timer */ | ||
| 66 | FIX_CO_APIC, /* Cobalt APIC Redirection Table */ | ||
| 67 | FIX_LI_PCIA, /* Lithium PCI Bridge A */ | ||
| 68 | FIX_LI_PCIB, /* Lithium PCI Bridge B */ | ||
| 69 | #endif | ||
| 70 | #ifdef CONFIG_X86_F00F_BUG | ||
| 71 | FIX_F00F_IDT, /* Virtual mapping for IDT */ | ||
| 72 | #endif | ||
| 73 | #ifdef CONFIG_X86_CYCLONE_TIMER | ||
| 74 | FIX_CYCLONE_TIMER, /*cyclone timer register*/ | ||
| 75 | #endif | ||
| 76 | FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ | ||
| 77 | FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, | ||
| 78 | #ifdef CONFIG_PCI_MMCONFIG | ||
| 79 | FIX_PCIE_MCFG, | ||
| 80 | #endif | ||
| 81 | #ifdef CONFIG_PARAVIRT | ||
| 82 | FIX_PARAVIRT_BOOTMAP, | ||
| 83 | #endif | ||
| 84 | __end_of_permanent_fixed_addresses, | ||
| 85 | /* | ||
| 86 | * 256 temporary boot-time mappings, used by early_ioremap(), | ||
| 87 | * before ioremap() is functional. | ||
| 88 | * | ||
| 89 | * We round it up to the next 256 pages boundary so that we | ||
| 90 | * can have a single pgd entry and a single pte table: | ||
| 91 | */ | ||
| 92 | #define NR_FIX_BTMAPS 64 | ||
| 93 | #define FIX_BTMAPS_SLOTS 4 | ||
| 94 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - | ||
| 95 | (__end_of_permanent_fixed_addresses & 255), | ||
| 96 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, | ||
| 97 | FIX_WP_TEST, | ||
| 98 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | ||
| 99 | FIX_OHCI1394_BASE, | ||
| 100 | #endif | ||
| 101 | __end_of_fixed_addresses | ||
| 102 | }; | ||
| 103 | |||
| 104 | extern void reserve_top_address(unsigned long reserve); | ||
| 105 | |||
| 106 | |||
| 107 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) | ||
| 108 | |||
| 109 | #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) | ||
| 110 | #define __FIXADDR_BOOT_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | ||
| 111 | #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE) | ||
| 112 | #define FIXADDR_BOOT_START (FIXADDR_TOP - __FIXADDR_BOOT_SIZE) | ||
| 113 | |||
| 114 | #endif /* !__ASSEMBLY__ */ | ||
| 115 | #endif /* _ASM_X86_FIXMAP_32_H */ | ||
diff --git a/arch/x86/include/asm/fixmap_64.h b/arch/x86/include/asm/fixmap_64.h deleted file mode 100644 index 298d9ba3faeb..000000000000 --- a/arch/x86/include/asm/fixmap_64.h +++ /dev/null | |||
| @@ -1,79 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * fixmap.h: compile-time virtual memory allocation | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 1998 Ingo Molnar | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _ASM_X86_FIXMAP_64_H | ||
| 12 | #define _ASM_X86_FIXMAP_64_H | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <asm/acpi.h> | ||
| 16 | #include <asm/apicdef.h> | ||
| 17 | #include <asm/page.h> | ||
| 18 | #include <asm/vsyscall.h> | ||
| 19 | #include <asm/efi.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Here we define all the compile-time 'special' virtual | ||
| 23 | * addresses. The point is to have a constant address at | ||
| 24 | * compile time, but to set the physical address only | ||
| 25 | * in the boot process. | ||
| 26 | * | ||
| 27 | * These 'compile-time allocated' memory buffers are | ||
| 28 | * fixed-size 4k pages (or larger if used with an increment | ||
| 29 | * higher than 1). Use set_fixmap(idx,phys) to associate | ||
| 30 | * physical memory with fixmap indices. | ||
| 31 | * | ||
| 32 | * TLB entries of such buffers will not be flushed across | ||
| 33 | * task switches. | ||
| 34 | */ | ||
| 35 | |||
| 36 | enum fixed_addresses { | ||
| 37 | VSYSCALL_LAST_PAGE, | ||
| 38 | VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE | ||
| 39 | + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1, | ||
| 40 | VSYSCALL_HPET, | ||
| 41 | FIX_DBGP_BASE, | ||
| 42 | FIX_EARLYCON_MEM_BASE, | ||
| 43 | FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ | ||
| 44 | FIX_IO_APIC_BASE_0, | ||
| 45 | FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1, | ||
| 46 | FIX_EFI_IO_MAP_LAST_PAGE, | ||
| 47 | FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE | ||
| 48 | + MAX_EFI_IO_PAGES - 1, | ||
| 49 | #ifdef CONFIG_PARAVIRT | ||
| 50 | FIX_PARAVIRT_BOOTMAP, | ||
| 51 | #endif | ||
| 52 | __end_of_permanent_fixed_addresses, | ||
| 53 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | ||
| 54 | FIX_OHCI1394_BASE, | ||
| 55 | #endif | ||
| 56 | /* | ||
| 57 | * 256 temporary boot-time mappings, used by early_ioremap(), | ||
| 58 | * before ioremap() is functional. | ||
| 59 | * | ||
| 60 | * We round it up to the next 256 pages boundary so that we | ||
| 61 | * can have a single pgd entry and a single pte table: | ||
| 62 | */ | ||
| 63 | #define NR_FIX_BTMAPS 64 | ||
| 64 | #define FIX_BTMAPS_SLOTS 4 | ||
| 65 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - | ||
| 66 | (__end_of_permanent_fixed_addresses & 255), | ||
| 67 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, | ||
| 68 | __end_of_fixed_addresses | ||
| 69 | }; | ||
| 70 | |||
| 71 | #define FIXADDR_TOP (VSYSCALL_END-PAGE_SIZE) | ||
| 72 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | ||
| 73 | #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) | ||
| 74 | |||
| 75 | /* Only covers 32bit vsyscalls currently. Need another set for 64bit. */ | ||
| 76 | #define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL) | ||
| 77 | #define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) | ||
| 78 | |||
| 79 | #endif /* _ASM_X86_FIXMAP_64_H */ | ||
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 48f0004db8c9..71c9e5183982 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -172,7 +172,13 @@ static inline void __save_init_fpu(struct task_struct *tsk) | |||
| 172 | 172 | ||
| 173 | #else /* CONFIG_X86_32 */ | 173 | #else /* CONFIG_X86_32 */ |
| 174 | 174 | ||
| 175 | extern void finit(void); | 175 | #ifdef CONFIG_MATH_EMULATION |
| 176 | extern void finit_task(struct task_struct *tsk); | ||
| 177 | #else | ||
| 178 | static inline void finit_task(struct task_struct *tsk) | ||
| 179 | { | ||
| 180 | } | ||
| 181 | #endif | ||
| 176 | 182 | ||
| 177 | static inline void tolerant_fwait(void) | 183 | static inline void tolerant_fwait(void) |
| 178 | { | 184 | { |
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 683d0b4c00fc..e5383e3d2f8c 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h | |||
| @@ -172,8 +172,6 @@ static inline void __iomem *ioremap(resource_size_t offset, unsigned long size) | |||
| 172 | 172 | ||
| 173 | extern void iounmap(volatile void __iomem *addr); | 173 | extern void iounmap(volatile void __iomem *addr); |
| 174 | 174 | ||
| 175 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); | ||
| 176 | |||
| 177 | 175 | ||
| 178 | #ifdef CONFIG_X86_32 | 176 | #ifdef CONFIG_X86_32 |
| 179 | # include "io_32.h" | 177 | # include "io_32.h" |
| @@ -198,7 +196,6 @@ extern void early_ioremap_reset(void); | |||
| 198 | extern void __iomem *early_ioremap(unsigned long offset, unsigned long size); | 196 | extern void __iomem *early_ioremap(unsigned long offset, unsigned long size); |
| 199 | extern void __iomem *early_memremap(unsigned long offset, unsigned long size); | 197 | extern void __iomem *early_memremap(unsigned long offset, unsigned long size); |
| 200 | extern void early_iounmap(void __iomem *addr, unsigned long size); | 198 | extern void early_iounmap(void __iomem *addr, unsigned long size); |
| 201 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); | ||
| 202 | 199 | ||
| 203 | #define IO_SPACE_LIMIT 0xffff | 200 | #define IO_SPACE_LIMIT 0xffff |
| 204 | 201 | ||
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 105fb90a0635..ede6998bd92c 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h | |||
| @@ -91,46 +91,9 @@ static inline int pfn_valid(int pfn) | |||
| 91 | #endif /* CONFIG_DISCONTIGMEM */ | 91 | #endif /* CONFIG_DISCONTIGMEM */ |
| 92 | 92 | ||
| 93 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 93 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
| 94 | 94 | /* always use node 0 for bootmem on this numa platform */ | |
| 95 | /* | 95 | #define bootmem_arch_preferred_node(__bdata, size, align, goal, limit) \ |
| 96 | * Following are macros that are specific to this numa platform. | 96 | (NODE_DATA(0)->bdata) |
| 97 | */ | ||
| 98 | #define reserve_bootmem(addr, size, flags) \ | ||
| 99 | reserve_bootmem_node(NODE_DATA(0), (addr), (size), (flags)) | ||
| 100 | #define alloc_bootmem(x) \ | ||
| 101 | __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) | ||
| 102 | #define alloc_bootmem_nopanic(x) \ | ||
| 103 | __alloc_bootmem_node_nopanic(NODE_DATA(0), (x), SMP_CACHE_BYTES, \ | ||
| 104 | __pa(MAX_DMA_ADDRESS)) | ||
| 105 | #define alloc_bootmem_low(x) \ | ||
| 106 | __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0) | ||
| 107 | #define alloc_bootmem_pages(x) \ | ||
| 108 | __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | ||
| 109 | #define alloc_bootmem_pages_nopanic(x) \ | ||
| 110 | __alloc_bootmem_node_nopanic(NODE_DATA(0), (x), PAGE_SIZE, \ | ||
| 111 | __pa(MAX_DMA_ADDRESS)) | ||
| 112 | #define alloc_bootmem_low_pages(x) \ | ||
| 113 | __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0) | ||
| 114 | #define alloc_bootmem_node(pgdat, x) \ | ||
| 115 | ({ \ | ||
| 116 | struct pglist_data __maybe_unused \ | ||
| 117 | *__alloc_bootmem_node__pgdat = (pgdat); \ | ||
| 118 | __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, \ | ||
| 119 | __pa(MAX_DMA_ADDRESS)); \ | ||
| 120 | }) | ||
| 121 | #define alloc_bootmem_pages_node(pgdat, x) \ | ||
| 122 | ({ \ | ||
| 123 | struct pglist_data __maybe_unused \ | ||
| 124 | *__alloc_bootmem_node__pgdat = (pgdat); \ | ||
| 125 | __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, \ | ||
| 126 | __pa(MAX_DMA_ADDRESS)); \ | ||
| 127 | }) | ||
| 128 | #define alloc_bootmem_low_pages_node(pgdat, x) \ | ||
| 129 | ({ \ | ||
| 130 | struct pglist_data __maybe_unused \ | ||
| 131 | *__alloc_bootmem_node__pgdat = (pgdat); \ | ||
| 132 | __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0); \ | ||
| 133 | }) | ||
| 134 | #endif /* CONFIG_NEED_MULTIPLE_NODES */ | 97 | #endif /* CONFIG_NEED_MULTIPLE_NODES */ |
| 135 | 98 | ||
| 136 | #endif /* _ASM_X86_MMZONE_32_H */ | 99 | #endif /* _ASM_X86_MMZONE_32_H */ |
diff --git a/arch/x86/include/asm/numa_32.h b/arch/x86/include/asm/numa_32.h index e9f5db796244..a37229011b56 100644 --- a/arch/x86/include/asm/numa_32.h +++ b/arch/x86/include/asm/numa_32.h | |||
| @@ -4,8 +4,12 @@ | |||
| 4 | extern int pxm_to_nid(int pxm); | 4 | extern int pxm_to_nid(int pxm); |
| 5 | extern void numa_remove_cpu(int cpu); | 5 | extern void numa_remove_cpu(int cpu); |
| 6 | 6 | ||
| 7 | #ifdef CONFIG_NUMA | 7 | #ifdef CONFIG_HIGHMEM |
| 8 | extern void set_highmem_pages_init(void); | 8 | extern void set_highmem_pages_init(void); |
| 9 | #else | ||
| 10 | static inline void set_highmem_pages_init(void) | ||
| 11 | { | ||
| 12 | } | ||
| 9 | #endif | 13 | #endif |
| 10 | 14 | ||
| 11 | #endif /* _ASM_X86_NUMA_32_H */ | 15 | #endif /* _ASM_X86_NUMA_32_H */ |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index aee103b26d01..8f1d2fbec1d4 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
| @@ -43,6 +43,14 @@ | |||
| 43 | #else /* ...!ASSEMBLY */ | 43 | #else /* ...!ASSEMBLY */ |
| 44 | 44 | ||
| 45 | #include <linux/stringify.h> | 45 | #include <linux/stringify.h> |
| 46 | #include <asm/sections.h> | ||
| 47 | |||
| 48 | #define __addr_to_pcpu_ptr(addr) \ | ||
| 49 | (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \ | ||
| 50 | + (unsigned long)__per_cpu_start) | ||
| 51 | #define __pcpu_ptr_to_addr(ptr) \ | ||
| 52 | (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \ | ||
| 53 | - (unsigned long)__per_cpu_start) | ||
| 46 | 54 | ||
| 47 | #ifdef CONFIG_SMP | 55 | #ifdef CONFIG_SMP |
| 48 | #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x | 56 | #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x |
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 1c097a3a6669..d0812e155f1d 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
| @@ -288,6 +288,8 @@ static inline int is_new_memtype_allowed(unsigned long flags, | |||
| 288 | return 1; | 288 | return 1; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | pmd_t *populate_extra_pmd(unsigned long vaddr); | ||
| 292 | pte_t *populate_extra_pte(unsigned long vaddr); | ||
| 291 | #endif /* __ASSEMBLY__ */ | 293 | #endif /* __ASSEMBLY__ */ |
| 292 | 294 | ||
| 293 | #ifdef CONFIG_X86_32 | 295 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c7a98f738210..76139506c3e4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -248,7 +248,6 @@ struct x86_hw_tss { | |||
| 248 | #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) | 248 | #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) |
| 249 | #define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap) | 249 | #define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap) |
| 250 | #define INVALID_IO_BITMAP_OFFSET 0x8000 | 250 | #define INVALID_IO_BITMAP_OFFSET 0x8000 |
| 251 | #define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000 | ||
| 252 | 251 | ||
| 253 | struct tss_struct { | 252 | struct tss_struct { |
| 254 | /* | 253 | /* |
| @@ -263,11 +262,6 @@ struct tss_struct { | |||
| 263 | * be within the limit. | 262 | * be within the limit. |
| 264 | */ | 263 | */ |
| 265 | unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; | 264 | unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; |
| 266 | /* | ||
| 267 | * Cache the current maximum and the last task that used the bitmap: | ||
| 268 | */ | ||
| 269 | unsigned long io_bitmap_max; | ||
| 270 | struct thread_struct *io_bitmap_owner; | ||
| 271 | 265 | ||
| 272 | /* | 266 | /* |
| 273 | * .. and then another 0x100 bytes for the emergency kernel stack: | 267 | * .. and then another 0x100 bytes for the emergency kernel stack: |
diff --git a/arch/x86/include/asm/seccomp_32.h b/arch/x86/include/asm/seccomp_32.h index a6ad87b352c4..b811d6f5780c 100644 --- a/arch/x86/include/asm/seccomp_32.h +++ b/arch/x86/include/asm/seccomp_32.h | |||
| @@ -1,12 +1,6 @@ | |||
| 1 | #ifndef _ASM_X86_SECCOMP_32_H | 1 | #ifndef _ASM_X86_SECCOMP_32_H |
| 2 | #define _ASM_X86_SECCOMP_32_H | 2 | #define _ASM_X86_SECCOMP_32_H |
| 3 | 3 | ||
| 4 | #include <linux/thread_info.h> | ||
| 5 | |||
| 6 | #ifdef TIF_32BIT | ||
| 7 | #error "unexpected TIF_32BIT on i386" | ||
| 8 | #endif | ||
| 9 | |||
| 10 | #include <linux/unistd.h> | 4 | #include <linux/unistd.h> |
| 11 | 5 | ||
| 12 | #define __NR_seccomp_read __NR_read | 6 | #define __NR_seccomp_read __NR_read |
diff --git a/arch/x86/include/asm/seccomp_64.h b/arch/x86/include/asm/seccomp_64.h index 4171bb794e9e..84ec1bd161a5 100644 --- a/arch/x86/include/asm/seccomp_64.h +++ b/arch/x86/include/asm/seccomp_64.h | |||
| @@ -1,14 +1,6 @@ | |||
| 1 | #ifndef _ASM_X86_SECCOMP_64_H | 1 | #ifndef _ASM_X86_SECCOMP_64_H |
| 2 | #define _ASM_X86_SECCOMP_64_H | 2 | #define _ASM_X86_SECCOMP_64_H |
| 3 | 3 | ||
| 4 | #include <linux/thread_info.h> | ||
| 5 | |||
| 6 | #ifdef TIF_32BIT | ||
| 7 | #error "unexpected TIF_32BIT on x86_64" | ||
| 8 | #else | ||
| 9 | #define TIF_32BIT TIF_IA32 | ||
| 10 | #endif | ||
| 11 | |||
| 12 | #include <linux/unistd.h> | 4 | #include <linux/unistd.h> |
| 13 | #include <asm/ia32_unistd.h> | 5 | #include <asm/ia32_unistd.h> |
| 14 | 6 | ||
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 66801cb72f69..05c6f6b11fd5 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
| @@ -31,7 +31,6 @@ struct x86_quirks { | |||
| 31 | void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable, | 31 | void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable, |
| 32 | unsigned short oemsize); | 32 | unsigned short oemsize); |
| 33 | int (*setup_ioapic_ids)(void); | 33 | int (*setup_ioapic_ids)(void); |
| 34 | int (*update_apic)(void); | ||
| 35 | }; | 34 | }; |
| 36 | 35 | ||
| 37 | extern void x86_quirk_pre_intr_init(void); | 36 | extern void x86_quirk_pre_intr_init(void); |
| @@ -65,7 +64,11 @@ extern void x86_quirk_time_init(void); | |||
| 65 | #include <asm/bootparam.h> | 64 | #include <asm/bootparam.h> |
| 66 | 65 | ||
| 67 | /* Interrupt control for vSMPowered x86_64 systems */ | 66 | /* Interrupt control for vSMPowered x86_64 systems */ |
| 67 | #ifdef CONFIG_X86_VSMP | ||
| 68 | void vsmp_init(void); | 68 | void vsmp_init(void); |
| 69 | #else | ||
| 70 | static inline void vsmp_init(void) { } | ||
| 71 | #endif | ||
| 69 | 72 | ||
| 70 | void setup_bios_corruption_check(void); | 73 | void setup_bios_corruption_check(void); |
| 71 | 74 | ||
| @@ -77,8 +80,6 @@ static inline void visws_early_detect(void) { } | |||
| 77 | static inline int is_visws_box(void) { return 0; } | 80 | static inline int is_visws_box(void) { return 0; } |
| 78 | #endif | 81 | #endif |
| 79 | 82 | ||
| 80 | extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); | ||
| 81 | extern int wakeup_secondary_cpu_via_init(int apicid, unsigned long start_eip); | ||
| 82 | extern struct x86_quirks *x86_quirks; | 83 | extern struct x86_quirks *x86_quirks; |
| 83 | extern unsigned long saved_video_mode; | 84 | extern unsigned long saved_video_mode; |
| 84 | 85 | ||
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index c00bfdbdd456..643c59b4bc6e 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | struct task_struct; /* one of the stranger aspects of C forward declarations */ | 20 | struct task_struct; /* one of the stranger aspects of C forward declarations */ |
| 21 | struct task_struct *__switch_to(struct task_struct *prev, | 21 | struct task_struct *__switch_to(struct task_struct *prev, |
| 22 | struct task_struct *next); | 22 | struct task_struct *next); |
| 23 | struct tss_struct; | ||
| 24 | void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
| 25 | struct tss_struct *tss); | ||
| 23 | 26 | ||
| 24 | #ifdef CONFIG_X86_32 | 27 | #ifdef CONFIG_X86_32 |
| 25 | 28 | ||
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index a0ba61386972..5e06259e90e5 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h | |||
| @@ -157,7 +157,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) | |||
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static __always_inline unsigned long __copy_from_user_nocache(void *to, | 159 | static __always_inline unsigned long __copy_from_user_nocache(void *to, |
| 160 | const void __user *from, unsigned long n, unsigned long total) | 160 | const void __user *from, unsigned long n) |
| 161 | { | 161 | { |
| 162 | might_fault(); | 162 | might_fault(); |
| 163 | if (__builtin_constant_p(n)) { | 163 | if (__builtin_constant_p(n)) { |
| @@ -180,7 +180,7 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to, | |||
| 180 | 180 | ||
| 181 | static __always_inline unsigned long | 181 | static __always_inline unsigned long |
| 182 | __copy_from_user_inatomic_nocache(void *to, const void __user *from, | 182 | __copy_from_user_inatomic_nocache(void *to, const void __user *from, |
| 183 | unsigned long n, unsigned long total) | 183 | unsigned long n) |
| 184 | { | 184 | { |
| 185 | return __copy_from_user_ll_nocache_nozero(to, from, n); | 185 | return __copy_from_user_ll_nocache_nozero(to, from, n); |
| 186 | } | 186 | } |
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index dcaa0404cf7b..8cc687326eb8 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h | |||
| @@ -188,29 +188,18 @@ __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size) | |||
| 188 | extern long __copy_user_nocache(void *dst, const void __user *src, | 188 | extern long __copy_user_nocache(void *dst, const void __user *src, |
| 189 | unsigned size, int zerorest); | 189 | unsigned size, int zerorest); |
| 190 | 190 | ||
| 191 | static inline int __copy_from_user_nocache(void *dst, const void __user *src, | 191 | static inline int |
| 192 | unsigned size, unsigned long total) | 192 | __copy_from_user_nocache(void *dst, const void __user *src, unsigned size) |
| 193 | { | 193 | { |
| 194 | might_sleep(); | 194 | might_sleep(); |
| 195 | /* | 195 | return __copy_user_nocache(dst, src, size, 1); |
| 196 | * In practice this limit means that large file write()s | ||
| 197 | * which get chunked to 4K copies get handled via | ||
| 198 | * non-temporal stores here. Smaller writes get handled | ||
| 199 | * via regular __copy_from_user(): | ||
| 200 | */ | ||
| 201 | if (likely(total >= PAGE_SIZE)) | ||
| 202 | return __copy_user_nocache(dst, src, size, 1); | ||
| 203 | else | ||
| 204 | return __copy_from_user(dst, src, size); | ||
| 205 | } | 196 | } |
| 206 | 197 | ||
| 207 | static inline int __copy_from_user_inatomic_nocache(void *dst, | 198 | static inline int |
| 208 | const void __user *src, unsigned size, unsigned total) | 199 | __copy_from_user_inatomic_nocache(void *dst, const void __user *src, |
| 200 | unsigned size) | ||
| 209 | { | 201 | { |
| 210 | if (likely(total >= PAGE_SIZE)) | 202 | return __copy_user_nocache(dst, src, size, 0); |
| 211 | return __copy_user_nocache(dst, src, size, 0); | ||
| 212 | else | ||
| 213 | return __copy_from_user_inatomic(dst, src, size); | ||
| 214 | } | 203 | } |
| 215 | 204 | ||
| 216 | unsigned long | 205 | unsigned long |
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index 8242bf965812..c0a01b5d985b 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h | |||
| @@ -12,7 +12,6 @@ extern enum uv_system_type get_uv_system_type(void); | |||
| 12 | extern int is_uv_system(void); | 12 | extern int is_uv_system(void); |
| 13 | extern void uv_cpu_init(void); | 13 | extern void uv_cpu_init(void); |
| 14 | extern void uv_system_init(void); | 14 | extern void uv_system_init(void); |
| 15 | extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); | ||
| 16 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | 15 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, |
| 17 | struct mm_struct *mm, | 16 | struct mm_struct *mm, |
| 18 | unsigned long va, | 17 | unsigned long va, |
| @@ -24,8 +23,6 @@ static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } | |||
| 24 | static inline int is_uv_system(void) { return 0; } | 23 | static inline int is_uv_system(void) { return 0; } |
| 25 | static inline void uv_cpu_init(void) { } | 24 | static inline void uv_cpu_init(void) { } |
| 26 | static inline void uv_system_init(void) { } | 25 | static inline void uv_system_init(void) { } |
| 27 | static inline int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) | ||
| 28 | { return 1; } | ||
| 29 | static inline const struct cpumask * | 26 | static inline const struct cpumask * |
| 30 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, | 27 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, |
| 31 | unsigned long va, unsigned int cpu) | 28 | unsigned long va, unsigned int cpu) |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 4bd990ee43df..1a918dde46b5 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
| @@ -164,6 +164,7 @@ static inline pte_t __pte_ma(pteval_t x) | |||
| 164 | 164 | ||
| 165 | 165 | ||
| 166 | xmaddr_t arbitrary_virt_to_machine(void *address); | 166 | xmaddr_t arbitrary_virt_to_machine(void *address); |
| 167 | unsigned long arbitrary_virt_to_mfn(void *vaddr); | ||
| 167 | void make_lowmem_page_readonly(void *vaddr); | 168 | void make_lowmem_page_readonly(void *vaddr); |
| 168 | void make_lowmem_page_readwrite(void *vaddr); | 169 | void make_lowmem_page_readwrite(void *vaddr); |
| 169 | 170 | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index de5657c039e9..95f216bbfaf1 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -70,7 +70,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | |||
| 70 | obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o | 70 | obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o |
| 71 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o | 71 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o |
| 72 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o | 72 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o |
| 73 | obj-y += vsmp_64.o | 73 | obj-$(CONFIG_X86_VSMP) += vsmp_64.o |
| 74 | obj-$(CONFIG_KPROBES) += kprobes.o | 74 | obj-$(CONFIG_KPROBES) += kprobes.o |
| 75 | obj-$(CONFIG_MODULES) += module_$(BITS).o | 75 | obj-$(CONFIG_MODULES) += module_$(BITS).o |
| 76 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 76 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 3b002995e145..f933822dba18 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c | |||
| @@ -222,7 +222,6 @@ struct apic apic_flat = { | |||
| 222 | .send_IPI_all = flat_send_IPI_all, | 222 | .send_IPI_all = flat_send_IPI_all, |
| 223 | .send_IPI_self = apic_send_IPI_self, | 223 | .send_IPI_self = apic_send_IPI_self, |
| 224 | 224 | ||
| 225 | .wakeup_cpu = NULL, | ||
| 226 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 225 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 227 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 226 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 228 | .wait_for_init_deassert = NULL, | 227 | .wait_for_init_deassert = NULL, |
| @@ -373,7 +372,6 @@ struct apic apic_physflat = { | |||
| 373 | .send_IPI_all = physflat_send_IPI_all, | 372 | .send_IPI_all = physflat_send_IPI_all, |
| 374 | .send_IPI_self = apic_send_IPI_self, | 373 | .send_IPI_self = apic_send_IPI_self, |
| 375 | 374 | ||
| 376 | .wakeup_cpu = NULL, | ||
| 377 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 375 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 378 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 376 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 379 | .wait_for_init_deassert = NULL, | 377 | .wait_for_init_deassert = NULL, |
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 0b1093394fdf..d806ecaa948f 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c | |||
| @@ -16,17 +16,17 @@ | |||
| 16 | #include <asm/apic.h> | 16 | #include <asm/apic.h> |
| 17 | #include <asm/ipi.h> | 17 | #include <asm/ipi.h> |
| 18 | 18 | ||
| 19 | static inline unsigned bigsmp_get_apic_id(unsigned long x) | 19 | static unsigned bigsmp_get_apic_id(unsigned long x) |
| 20 | { | 20 | { |
| 21 | return (x >> 24) & 0xFF; | 21 | return (x >> 24) & 0xFF; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | static inline int bigsmp_apic_id_registered(void) | 24 | static int bigsmp_apic_id_registered(void) |
| 25 | { | 25 | { |
| 26 | return 1; | 26 | return 1; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static inline const cpumask_t *bigsmp_target_cpus(void) | 29 | static const cpumask_t *bigsmp_target_cpus(void) |
| 30 | { | 30 | { |
| 31 | #ifdef CONFIG_SMP | 31 | #ifdef CONFIG_SMP |
| 32 | return &cpu_online_map; | 32 | return &cpu_online_map; |
| @@ -35,13 +35,12 @@ static inline const cpumask_t *bigsmp_target_cpus(void) | |||
| 35 | #endif | 35 | #endif |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static inline unsigned long | 38 | static unsigned long bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) |
| 39 | bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid) | ||
| 40 | { | 39 | { |
| 41 | return 0; | 40 | return 0; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | static inline unsigned long bigsmp_check_apicid_present(int bit) | 43 | static unsigned long bigsmp_check_apicid_present(int bit) |
| 45 | { | 44 | { |
| 46 | return 1; | 45 | return 1; |
| 47 | } | 46 | } |
| @@ -64,7 +63,7 @@ static inline unsigned long calculate_ldr(int cpu) | |||
| 64 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel | 63 | * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel |
| 65 | * document number 292116). So here it goes... | 64 | * document number 292116). So here it goes... |
| 66 | */ | 65 | */ |
| 67 | static inline void bigsmp_init_apic_ldr(void) | 66 | static void bigsmp_init_apic_ldr(void) |
| 68 | { | 67 | { |
| 69 | unsigned long val; | 68 | unsigned long val; |
| 70 | int cpu = smp_processor_id(); | 69 | int cpu = smp_processor_id(); |
| @@ -74,19 +73,19 @@ static inline void bigsmp_init_apic_ldr(void) | |||
| 74 | apic_write(APIC_LDR, val); | 73 | apic_write(APIC_LDR, val); |
| 75 | } | 74 | } |
| 76 | 75 | ||
| 77 | static inline void bigsmp_setup_apic_routing(void) | 76 | static void bigsmp_setup_apic_routing(void) |
| 78 | { | 77 | { |
| 79 | printk(KERN_INFO | 78 | printk(KERN_INFO |
| 80 | "Enabling APIC mode: Physflat. Using %d I/O APICs\n", | 79 | "Enabling APIC mode: Physflat. Using %d I/O APICs\n", |
| 81 | nr_ioapics); | 80 | nr_ioapics); |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | static inline int bigsmp_apicid_to_node(int logical_apicid) | 83 | static int bigsmp_apicid_to_node(int logical_apicid) |
| 85 | { | 84 | { |
| 86 | return apicid_2_node[hard_smp_processor_id()]; | 85 | return apicid_2_node[hard_smp_processor_id()]; |
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) | 88 | static int bigsmp_cpu_present_to_apicid(int mps_cpu) |
| 90 | { | 89 | { |
| 91 | if (mps_cpu < nr_cpu_ids) | 90 | if (mps_cpu < nr_cpu_ids) |
| 92 | return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); | 91 | return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu); |
| @@ -94,7 +93,7 @@ static inline int bigsmp_cpu_present_to_apicid(int mps_cpu) | |||
| 94 | return BAD_APICID; | 93 | return BAD_APICID; |
| 95 | } | 94 | } |
| 96 | 95 | ||
| 97 | static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid) | 96 | static physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid) |
| 98 | { | 97 | { |
| 99 | return physid_mask_of_physid(phys_apicid); | 98 | return physid_mask_of_physid(phys_apicid); |
| 100 | } | 99 | } |
| @@ -107,29 +106,24 @@ static inline int bigsmp_cpu_to_logical_apicid(int cpu) | |||
| 107 | return cpu_physical_id(cpu); | 106 | return cpu_physical_id(cpu); |
| 108 | } | 107 | } |
| 109 | 108 | ||
| 110 | static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) | 109 | static physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map) |
| 111 | { | 110 | { |
| 112 | /* For clustered we don't have a good way to do this yet - hack */ | 111 | /* For clustered we don't have a good way to do this yet - hack */ |
| 113 | return physids_promote(0xFFL); | 112 | return physids_promote(0xFFL); |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | static inline void bigsmp_setup_portio_remap(void) | 115 | static int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) |
| 117 | { | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) | ||
| 121 | { | 116 | { |
| 122 | return 1; | 117 | return 1; |
| 123 | } | 118 | } |
| 124 | 119 | ||
| 125 | /* As we are using single CPU as destination, pick only one CPU here */ | 120 | /* As we are using single CPU as destination, pick only one CPU here */ |
| 126 | static inline unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) | 121 | static unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) |
| 127 | { | 122 | { |
| 128 | return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); | 123 | return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); |
| 129 | } | 124 | } |
| 130 | 125 | ||
| 131 | static inline unsigned int | 126 | static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, |
| 132 | bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | ||
| 133 | const struct cpumask *andmask) | 127 | const struct cpumask *andmask) |
| 134 | { | 128 | { |
| 135 | int cpu; | 129 | int cpu; |
| @@ -148,7 +142,7 @@ bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, | |||
| 148 | return BAD_APICID; | 142 | return BAD_APICID; |
| 149 | } | 143 | } |
| 150 | 144 | ||
| 151 | static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | 145 | static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) |
| 152 | { | 146 | { |
| 153 | return cpuid_apic >> index_msb; | 147 | return cpuid_apic >> index_msb; |
| 154 | } | 148 | } |
| @@ -158,12 +152,12 @@ static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector) | |||
| 158 | default_send_IPI_mask_sequence_phys(mask, vector); | 152 | default_send_IPI_mask_sequence_phys(mask, vector); |
| 159 | } | 153 | } |
| 160 | 154 | ||
| 161 | static inline void bigsmp_send_IPI_allbutself(int vector) | 155 | static void bigsmp_send_IPI_allbutself(int vector) |
| 162 | { | 156 | { |
| 163 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | 157 | default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); |
| 164 | } | 158 | } |
| 165 | 159 | ||
| 166 | static inline void bigsmp_send_IPI_all(int vector) | 160 | static void bigsmp_send_IPI_all(int vector) |
| 167 | { | 161 | { |
| 168 | bigsmp_send_IPI_mask(cpu_online_mask, vector); | 162 | bigsmp_send_IPI_mask(cpu_online_mask, vector); |
| 169 | } | 163 | } |
| @@ -256,7 +250,6 @@ struct apic apic_bigsmp = { | |||
| 256 | .send_IPI_all = bigsmp_send_IPI_all, | 250 | .send_IPI_all = bigsmp_send_IPI_all, |
| 257 | .send_IPI_self = default_send_IPI_self, | 251 | .send_IPI_self = default_send_IPI_self, |
| 258 | 252 | ||
| 259 | .wakeup_cpu = NULL, | ||
| 260 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 253 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 261 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 254 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 262 | 255 | ||
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 320f2d2e4e54..19588f2770ee 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c | |||
| @@ -163,22 +163,17 @@ static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) | |||
| 163 | return 0; | 163 | return 0; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | static int __init es7000_update_apic(void) | 166 | static int es7000_apic_is_cluster(void) |
| 167 | { | 167 | { |
| 168 | apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; | ||
| 169 | |||
| 170 | /* MPENTIUMIII */ | 168 | /* MPENTIUMIII */ |
| 171 | if (boot_cpu_data.x86 == 6 && | 169 | if (boot_cpu_data.x86 == 6 && |
| 172 | (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) { | 170 | (boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) |
| 173 | es7000_update_apic_to_cluster(); | 171 | return 1; |
| 174 | apic->wait_for_init_deassert = NULL; | ||
| 175 | apic->wakeup_cpu = wakeup_secondary_cpu_via_mip; | ||
| 176 | } | ||
| 177 | 172 | ||
| 178 | return 0; | 173 | return 0; |
| 179 | } | 174 | } |
| 180 | 175 | ||
| 181 | static void __init setup_unisys(void) | 176 | static void setup_unisys(void) |
| 182 | { | 177 | { |
| 183 | /* | 178 | /* |
| 184 | * Determine the generation of the ES7000 currently running. | 179 | * Determine the generation of the ES7000 currently running. |
| @@ -192,14 +187,12 @@ static void __init setup_unisys(void) | |||
| 192 | else | 187 | else |
| 193 | es7000_plat = ES7000_CLASSIC; | 188 | es7000_plat = ES7000_CLASSIC; |
| 194 | ioapic_renumber_irq = es7000_rename_gsi; | 189 | ioapic_renumber_irq = es7000_rename_gsi; |
| 195 | |||
| 196 | x86_quirks->update_apic = es7000_update_apic; | ||
| 197 | } | 190 | } |
| 198 | 191 | ||
| 199 | /* | 192 | /* |
| 200 | * Parse the OEM Table: | 193 | * Parse the OEM Table: |
| 201 | */ | 194 | */ |
| 202 | static int __init parse_unisys_oem(char *oemptr) | 195 | static int parse_unisys_oem(char *oemptr) |
| 203 | { | 196 | { |
| 204 | int i; | 197 | int i; |
| 205 | int success = 0; | 198 | int success = 0; |
| @@ -261,7 +254,7 @@ static int __init parse_unisys_oem(char *oemptr) | |||
| 261 | } | 254 | } |
| 262 | 255 | ||
| 263 | #ifdef CONFIG_ACPI | 256 | #ifdef CONFIG_ACPI |
| 264 | static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) | 257 | static int find_unisys_acpi_oem_table(unsigned long *oem_addr) |
| 265 | { | 258 | { |
| 266 | struct acpi_table_header *header = NULL; | 259 | struct acpi_table_header *header = NULL; |
| 267 | struct es7000_oem_table *table; | 260 | struct es7000_oem_table *table; |
| @@ -292,7 +285,7 @@ static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) | |||
| 292 | return 0; | 285 | return 0; |
| 293 | } | 286 | } |
| 294 | 287 | ||
| 295 | static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) | 288 | static void unmap_unisys_acpi_oem_table(unsigned long oem_addr) |
| 296 | { | 289 | { |
| 297 | if (!oem_addr) | 290 | if (!oem_addr) |
| 298 | return; | 291 | return; |
| @@ -310,8 +303,10 @@ static int es7000_check_dsdt(void) | |||
| 310 | return 0; | 303 | return 0; |
| 311 | } | 304 | } |
| 312 | 305 | ||
| 306 | static int es7000_acpi_ret; | ||
| 307 | |||
| 313 | /* Hook from generic ACPI tables.c */ | 308 | /* Hook from generic ACPI tables.c */ |
| 314 | static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 309 | static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
| 315 | { | 310 | { |
| 316 | unsigned long oem_addr = 0; | 311 | unsigned long oem_addr = 0; |
| 317 | int check_dsdt; | 312 | int check_dsdt; |
| @@ -332,10 +327,26 @@ static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 332 | */ | 327 | */ |
| 333 | unmap_unisys_acpi_oem_table(oem_addr); | 328 | unmap_unisys_acpi_oem_table(oem_addr); |
| 334 | } | 329 | } |
| 335 | return ret; | 330 | |
| 331 | es7000_acpi_ret = ret; | ||
| 332 | |||
| 333 | return ret && !es7000_apic_is_cluster(); | ||
| 336 | } | 334 | } |
| 335 | |||
| 336 | static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id) | ||
| 337 | { | ||
| 338 | int ret = es7000_acpi_ret; | ||
| 339 | |||
| 340 | return ret && es7000_apic_is_cluster(); | ||
| 341 | } | ||
| 342 | |||
| 337 | #else /* !CONFIG_ACPI: */ | 343 | #else /* !CONFIG_ACPI: */ |
| 338 | static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 344 | static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
| 345 | { | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id) | ||
| 339 | { | 350 | { |
| 340 | return 0; | 351 | return 0; |
| 341 | } | 352 | } |
| @@ -349,8 +360,7 @@ static void es7000_spin(int n) | |||
| 349 | rep_nop(); | 360 | rep_nop(); |
| 350 | } | 361 | } |
| 351 | 362 | ||
| 352 | static int __init | 363 | static int es7000_mip_write(struct mip_reg *mip_reg) |
| 353 | es7000_mip_write(struct mip_reg *mip_reg) | ||
| 354 | { | 364 | { |
| 355 | int status = 0; | 365 | int status = 0; |
| 356 | int spin; | 366 | int spin; |
| @@ -383,7 +393,7 @@ es7000_mip_write(struct mip_reg *mip_reg) | |||
| 383 | return status; | 393 | return status; |
| 384 | } | 394 | } |
| 385 | 395 | ||
| 386 | static void __init es7000_enable_apic_mode(void) | 396 | static void es7000_enable_apic_mode(void) |
| 387 | { | 397 | { |
| 388 | struct mip_reg es7000_mip_reg; | 398 | struct mip_reg es7000_mip_reg; |
| 389 | int mip_status; | 399 | int mip_status; |
| @@ -416,11 +426,8 @@ static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) | |||
| 416 | 426 | ||
| 417 | static void es7000_wait_for_init_deassert(atomic_t *deassert) | 427 | static void es7000_wait_for_init_deassert(atomic_t *deassert) |
| 418 | { | 428 | { |
| 419 | #ifndef CONFIG_ES7000_CLUSTERED_APIC | ||
| 420 | while (!atomic_read(deassert)) | 429 | while (!atomic_read(deassert)) |
| 421 | cpu_relax(); | 430 | cpu_relax(); |
| 422 | #endif | ||
| 423 | return; | ||
| 424 | } | 431 | } |
| 425 | 432 | ||
| 426 | static unsigned int es7000_get_apic_id(unsigned long x) | 433 | static unsigned int es7000_get_apic_id(unsigned long x) |
| @@ -565,72 +572,24 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid) | |||
| 565 | return 1; | 572 | return 1; |
| 566 | } | 573 | } |
| 567 | 574 | ||
| 568 | static unsigned int | ||
| 569 | es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask) | ||
| 570 | { | ||
| 571 | int cpus_found = 0; | ||
| 572 | int num_bits_set; | ||
| 573 | int apicid; | ||
| 574 | int cpu; | ||
| 575 | |||
| 576 | num_bits_set = cpumask_weight(cpumask); | ||
| 577 | /* Return id to all */ | ||
| 578 | if (num_bits_set == nr_cpu_ids) | ||
| 579 | return 0xFF; | ||
| 580 | /* | ||
| 581 | * The cpus in the mask must all be on the apic cluster. If are not | ||
| 582 | * on the same apicid cluster return default value of target_cpus(): | ||
| 583 | */ | ||
| 584 | cpu = cpumask_first(cpumask); | ||
| 585 | apicid = es7000_cpu_to_logical_apicid(cpu); | ||
| 586 | |||
| 587 | while (cpus_found < num_bits_set) { | ||
| 588 | if (cpumask_test_cpu(cpu, cpumask)) { | ||
| 589 | int new_apicid = es7000_cpu_to_logical_apicid(cpu); | ||
| 590 | |||
| 591 | if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | ||
| 592 | WARN(1, "Not a valid mask!"); | ||
| 593 | |||
| 594 | return 0xFF; | ||
| 595 | } | ||
| 596 | apicid = new_apicid; | ||
| 597 | cpus_found++; | ||
| 598 | } | ||
| 599 | cpu++; | ||
| 600 | } | ||
| 601 | return apicid; | ||
| 602 | } | ||
| 603 | |||
| 604 | static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) | 575 | static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) |
| 605 | { | 576 | { |
| 606 | int cpus_found = 0; | 577 | unsigned int round = 0; |
| 607 | int num_bits_set; | 578 | int cpu, uninitialized_var(apicid); |
| 608 | int apicid; | ||
| 609 | int cpu; | ||
| 610 | 579 | ||
| 611 | num_bits_set = cpus_weight(*cpumask); | ||
| 612 | /* Return id to all */ | ||
| 613 | if (num_bits_set == nr_cpu_ids) | ||
| 614 | return es7000_cpu_to_logical_apicid(0); | ||
| 615 | /* | 580 | /* |
| 616 | * The cpus in the mask must all be on the apic cluster. If are not | 581 | * The cpus in the mask must all be on the apic cluster. |
| 617 | * on the same apicid cluster return default value of target_cpus(): | ||
| 618 | */ | 582 | */ |
| 619 | cpu = first_cpu(*cpumask); | 583 | for_each_cpu(cpu, cpumask) { |
| 620 | apicid = es7000_cpu_to_logical_apicid(cpu); | 584 | int new_apicid = es7000_cpu_to_logical_apicid(cpu); |
| 621 | while (cpus_found < num_bits_set) { | ||
| 622 | if (cpu_isset(cpu, *cpumask)) { | ||
| 623 | int new_apicid = es7000_cpu_to_logical_apicid(cpu); | ||
| 624 | 585 | ||
| 625 | if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | 586 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { |
| 626 | printk("%s: Not a valid mask!\n", __func__); | 587 | WARN(1, "Not a valid mask!"); |
| 627 | 588 | ||
| 628 | return es7000_cpu_to_logical_apicid(0); | 589 | return BAD_APICID; |
| 629 | } | ||
| 630 | apicid = new_apicid; | ||
| 631 | cpus_found++; | ||
| 632 | } | 590 | } |
| 633 | cpu++; | 591 | apicid = new_apicid; |
| 592 | round++; | ||
| 634 | } | 593 | } |
| 635 | return apicid; | 594 | return apicid; |
| 636 | } | 595 | } |
| @@ -659,37 +618,103 @@ static int es7000_phys_pkg_id(int cpuid_apic, int index_msb) | |||
| 659 | return cpuid_apic >> index_msb; | 618 | return cpuid_apic >> index_msb; |
| 660 | } | 619 | } |
| 661 | 620 | ||
| 662 | void __init es7000_update_apic_to_cluster(void) | ||
| 663 | { | ||
| 664 | apic->target_cpus = target_cpus_cluster; | ||
| 665 | apic->irq_delivery_mode = dest_LowestPrio; | ||
| 666 | /* logical delivery broadcast to all procs: */ | ||
| 667 | apic->irq_dest_mode = 1; | ||
| 668 | |||
| 669 | apic->init_apic_ldr = es7000_init_apic_ldr_cluster; | ||
| 670 | |||
| 671 | apic->cpu_mask_to_apicid = es7000_cpu_mask_to_apicid_cluster; | ||
| 672 | } | ||
| 673 | |||
| 674 | static int probe_es7000(void) | 621 | static int probe_es7000(void) |
| 675 | { | 622 | { |
| 676 | /* probed later in mptable/ACPI hooks */ | 623 | /* probed later in mptable/ACPI hooks */ |
| 677 | return 0; | 624 | return 0; |
| 678 | } | 625 | } |
| 679 | 626 | ||
| 680 | static __init int | 627 | static int es7000_mps_ret; |
| 681 | es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | 628 | static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem, |
| 629 | char *productid) | ||
| 682 | { | 630 | { |
| 631 | int ret = 0; | ||
| 632 | |||
| 683 | if (mpc->oemptr) { | 633 | if (mpc->oemptr) { |
| 684 | struct mpc_oemtable *oem_table = | 634 | struct mpc_oemtable *oem_table = |
| 685 | (struct mpc_oemtable *)mpc->oemptr; | 635 | (struct mpc_oemtable *)mpc->oemptr; |
| 686 | 636 | ||
| 687 | if (!strncmp(oem, "UNISYS", 6)) | 637 | if (!strncmp(oem, "UNISYS", 6)) |
| 688 | return parse_unisys_oem((char *)oem_table); | 638 | ret = parse_unisys_oem((char *)oem_table); |
| 689 | } | 639 | } |
| 690 | return 0; | 640 | |
| 641 | es7000_mps_ret = ret; | ||
| 642 | |||
| 643 | return ret && !es7000_apic_is_cluster(); | ||
| 691 | } | 644 | } |
| 692 | 645 | ||
| 646 | static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem, | ||
| 647 | char *productid) | ||
| 648 | { | ||
| 649 | int ret = es7000_mps_ret; | ||
| 650 | |||
| 651 | return ret && es7000_apic_is_cluster(); | ||
| 652 | } | ||
| 653 | |||
| 654 | struct apic apic_es7000_cluster = { | ||
| 655 | |||
| 656 | .name = "es7000", | ||
| 657 | .probe = probe_es7000, | ||
| 658 | .acpi_madt_oem_check = es7000_acpi_madt_oem_check_cluster, | ||
| 659 | .apic_id_registered = es7000_apic_id_registered, | ||
| 660 | |||
| 661 | .irq_delivery_mode = dest_LowestPrio, | ||
| 662 | /* logical delivery broadcast to all procs: */ | ||
| 663 | .irq_dest_mode = 1, | ||
| 664 | |||
| 665 | .target_cpus = target_cpus_cluster, | ||
| 666 | .disable_esr = 1, | ||
| 667 | .dest_logical = 0, | ||
| 668 | .check_apicid_used = es7000_check_apicid_used, | ||
| 669 | .check_apicid_present = es7000_check_apicid_present, | ||
| 670 | |||
| 671 | .vector_allocation_domain = es7000_vector_allocation_domain, | ||
| 672 | .init_apic_ldr = es7000_init_apic_ldr_cluster, | ||
| 673 | |||
| 674 | .ioapic_phys_id_map = es7000_ioapic_phys_id_map, | ||
| 675 | .setup_apic_routing = es7000_setup_apic_routing, | ||
| 676 | .multi_timer_check = NULL, | ||
| 677 | .apicid_to_node = es7000_apicid_to_node, | ||
| 678 | .cpu_to_logical_apicid = es7000_cpu_to_logical_apicid, | ||
| 679 | .cpu_present_to_apicid = es7000_cpu_present_to_apicid, | ||
| 680 | .apicid_to_cpu_present = es7000_apicid_to_cpu_present, | ||
| 681 | .setup_portio_remap = NULL, | ||
| 682 | .check_phys_apicid_present = es7000_check_phys_apicid_present, | ||
| 683 | .enable_apic_mode = es7000_enable_apic_mode, | ||
| 684 | .phys_pkg_id = es7000_phys_pkg_id, | ||
| 685 | .mps_oem_check = es7000_mps_oem_check_cluster, | ||
| 686 | |||
| 687 | .get_apic_id = es7000_get_apic_id, | ||
| 688 | .set_apic_id = NULL, | ||
| 689 | .apic_id_mask = 0xFF << 24, | ||
| 690 | |||
| 691 | .cpu_mask_to_apicid = es7000_cpu_mask_to_apicid, | ||
| 692 | .cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and, | ||
| 693 | |||
| 694 | .send_IPI_mask = es7000_send_IPI_mask, | ||
| 695 | .send_IPI_mask_allbutself = NULL, | ||
| 696 | .send_IPI_allbutself = es7000_send_IPI_allbutself, | ||
| 697 | .send_IPI_all = es7000_send_IPI_all, | ||
| 698 | .send_IPI_self = default_send_IPI_self, | ||
| 699 | |||
| 700 | .wakeup_secondary_cpu = wakeup_secondary_cpu_via_mip, | ||
| 701 | |||
| 702 | .trampoline_phys_low = 0x467, | ||
| 703 | .trampoline_phys_high = 0x469, | ||
| 704 | |||
| 705 | .wait_for_init_deassert = NULL, | ||
| 706 | |||
| 707 | /* Nothing to do for most platforms, since cleared by the INIT cycle: */ | ||
| 708 | .smp_callin_clear_local_apic = NULL, | ||
| 709 | .inquire_remote_apic = default_inquire_remote_apic, | ||
| 710 | |||
| 711 | .read = native_apic_mem_read, | ||
| 712 | .write = native_apic_mem_write, | ||
| 713 | .icr_read = native_apic_icr_read, | ||
| 714 | .icr_write = native_apic_icr_write, | ||
| 715 | .wait_icr_idle = native_apic_wait_icr_idle, | ||
| 716 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | ||
| 717 | }; | ||
| 693 | 718 | ||
| 694 | struct apic apic_es7000 = { | 719 | struct apic apic_es7000 = { |
| 695 | 720 | ||
| @@ -737,8 +762,6 @@ struct apic apic_es7000 = { | |||
| 737 | .send_IPI_all = es7000_send_IPI_all, | 762 | .send_IPI_all = es7000_send_IPI_all, |
| 738 | .send_IPI_self = default_send_IPI_self, | 763 | .send_IPI_self = default_send_IPI_self, |
| 739 | 764 | ||
| 740 | .wakeup_cpu = NULL, | ||
| 741 | |||
| 742 | .trampoline_phys_low = 0x467, | 765 | .trampoline_phys_low = 0x467, |
| 743 | .trampoline_phys_high = 0x469, | 766 | .trampoline_phys_high = 0x469, |
| 744 | 767 | ||
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index d9d6d61eed82..ba2fc6465534 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c | |||
| @@ -69,7 +69,7 @@ struct mpc_trans { | |||
| 69 | /* x86_quirks member */ | 69 | /* x86_quirks member */ |
| 70 | static int mpc_record; | 70 | static int mpc_record; |
| 71 | 71 | ||
| 72 | static __cpuinitdata struct mpc_trans *translation_table[MAX_MPC_ENTRY]; | 72 | static struct mpc_trans *translation_table[MAX_MPC_ENTRY]; |
| 73 | 73 | ||
| 74 | int mp_bus_id_to_node[MAX_MP_BUSSES]; | 74 | int mp_bus_id_to_node[MAX_MP_BUSSES]; |
| 75 | int mp_bus_id_to_local[MAX_MP_BUSSES]; | 75 | int mp_bus_id_to_local[MAX_MP_BUSSES]; |
| @@ -256,13 +256,6 @@ static int __init numaq_setup_ioapic_ids(void) | |||
| 256 | return 1; | 256 | return 1; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static int __init numaq_update_apic(void) | ||
| 260 | { | ||
| 261 | apic->wakeup_cpu = wakeup_secondary_cpu_via_nmi; | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static struct x86_quirks numaq_x86_quirks __initdata = { | 259 | static struct x86_quirks numaq_x86_quirks __initdata = { |
| 267 | .arch_pre_time_init = numaq_pre_time_init, | 260 | .arch_pre_time_init = numaq_pre_time_init, |
| 268 | .arch_time_init = NULL, | 261 | .arch_time_init = NULL, |
| @@ -278,7 +271,6 @@ static struct x86_quirks numaq_x86_quirks __initdata = { | |||
| 278 | .mpc_oem_pci_bus = mpc_oem_pci_bus, | 271 | .mpc_oem_pci_bus = mpc_oem_pci_bus, |
| 279 | .smp_read_mpc_oem = smp_read_mpc_oem, | 272 | .smp_read_mpc_oem = smp_read_mpc_oem, |
| 280 | .setup_ioapic_ids = numaq_setup_ioapic_ids, | 273 | .setup_ioapic_ids = numaq_setup_ioapic_ids, |
| 281 | .update_apic = numaq_update_apic, | ||
| 282 | }; | 274 | }; |
| 283 | 275 | ||
| 284 | static __init void early_check_numaq(void) | 276 | static __init void early_check_numaq(void) |
| @@ -546,7 +538,7 @@ struct apic apic_numaq = { | |||
| 546 | .send_IPI_all = numaq_send_IPI_all, | 538 | .send_IPI_all = numaq_send_IPI_all, |
| 547 | .send_IPI_self = default_send_IPI_self, | 539 | .send_IPI_self = default_send_IPI_self, |
| 548 | 540 | ||
| 549 | .wakeup_cpu = NULL, | 541 | .wakeup_secondary_cpu = wakeup_secondary_cpu_via_nmi, |
| 550 | .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, | 542 | .trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW, |
| 551 | .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, | 543 | .trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH, |
| 552 | 544 | ||
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 3a730fa574bb..141c99a1c264 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
| @@ -138,7 +138,6 @@ struct apic apic_default = { | |||
| 138 | .send_IPI_all = default_send_IPI_all, | 138 | .send_IPI_all = default_send_IPI_all, |
| 139 | .send_IPI_self = default_send_IPI_self, | 139 | .send_IPI_self = default_send_IPI_self, |
| 140 | 140 | ||
| 141 | .wakeup_cpu = NULL, | ||
| 142 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 141 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 143 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 142 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 144 | 143 | ||
| @@ -159,6 +158,7 @@ extern struct apic apic_numaq; | |||
| 159 | extern struct apic apic_summit; | 158 | extern struct apic apic_summit; |
| 160 | extern struct apic apic_bigsmp; | 159 | extern struct apic apic_bigsmp; |
| 161 | extern struct apic apic_es7000; | 160 | extern struct apic apic_es7000; |
| 161 | extern struct apic apic_es7000_cluster; | ||
| 162 | extern struct apic apic_default; | 162 | extern struct apic apic_default; |
| 163 | 163 | ||
| 164 | struct apic *apic = &apic_default; | 164 | struct apic *apic = &apic_default; |
| @@ -176,6 +176,7 @@ static struct apic *apic_probe[] __initdata = { | |||
| 176 | #endif | 176 | #endif |
| 177 | #ifdef CONFIG_X86_ES7000 | 177 | #ifdef CONFIG_X86_ES7000 |
| 178 | &apic_es7000, | 178 | &apic_es7000, |
| 179 | &apic_es7000_cluster, | ||
| 179 | #endif | 180 | #endif |
| 180 | &apic_default, /* must be last */ | 181 | &apic_default, /* must be last */ |
| 181 | NULL, | 182 | NULL, |
| @@ -197,9 +198,6 @@ static int __init parse_apic(char *arg) | |||
| 197 | } | 198 | } |
| 198 | } | 199 | } |
| 199 | 200 | ||
| 200 | if (x86_quirks->update_apic) | ||
| 201 | x86_quirks->update_apic(); | ||
| 202 | |||
| 203 | /* Parsed again by __setup for debug/verbose */ | 201 | /* Parsed again by __setup for debug/verbose */ |
| 204 | return 0; | 202 | return 0; |
| 205 | } | 203 | } |
| @@ -218,8 +216,6 @@ void __init generic_bigsmp_probe(void) | |||
| 218 | if (!cmdline_apic && apic == &apic_default) { | 216 | if (!cmdline_apic && apic == &apic_default) { |
| 219 | if (apic_bigsmp.probe()) { | 217 | if (apic_bigsmp.probe()) { |
| 220 | apic = &apic_bigsmp; | 218 | apic = &apic_bigsmp; |
| 221 | if (x86_quirks->update_apic) | ||
| 222 | x86_quirks->update_apic(); | ||
| 223 | printk(KERN_INFO "Overriding APIC driver with %s\n", | 219 | printk(KERN_INFO "Overriding APIC driver with %s\n", |
| 224 | apic->name); | 220 | apic->name); |
| 225 | } | 221 | } |
| @@ -240,9 +236,6 @@ void __init generic_apic_probe(void) | |||
| 240 | /* Not visible without early console */ | 236 | /* Not visible without early console */ |
| 241 | if (!apic_probe[i]) | 237 | if (!apic_probe[i]) |
| 242 | panic("Didn't find an APIC driver"); | 238 | panic("Didn't find an APIC driver"); |
| 243 | |||
| 244 | if (x86_quirks->update_apic) | ||
| 245 | x86_quirks->update_apic(); | ||
| 246 | } | 239 | } |
| 247 | printk(KERN_INFO "Using APIC driver %s\n", apic->name); | 240 | printk(KERN_INFO "Using APIC driver %s\n", apic->name); |
| 248 | } | 241 | } |
| @@ -262,8 +255,6 @@ generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | |||
| 262 | 255 | ||
| 263 | if (!cmdline_apic) { | 256 | if (!cmdline_apic) { |
| 264 | apic = apic_probe[i]; | 257 | apic = apic_probe[i]; |
| 265 | if (x86_quirks->update_apic) | ||
| 266 | x86_quirks->update_apic(); | ||
| 267 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", | 258 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
| 268 | apic->name); | 259 | apic->name); |
| 269 | } | 260 | } |
| @@ -284,8 +275,6 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 284 | 275 | ||
| 285 | if (!cmdline_apic) { | 276 | if (!cmdline_apic) { |
| 286 | apic = apic_probe[i]; | 277 | apic = apic_probe[i]; |
| 287 | if (x86_quirks->update_apic) | ||
| 288 | x86_quirks->update_apic(); | ||
| 289 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", | 278 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
| 290 | apic->name); | 279 | apic->name); |
| 291 | } | 280 | } |
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index e7c163661c77..8d7748efe6a8 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
| @@ -68,9 +68,6 @@ void __init default_setup_apic_routing(void) | |||
| 68 | apic = &apic_physflat; | 68 | apic = &apic_physflat; |
| 69 | printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); | 69 | printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); |
| 70 | } | 70 | } |
| 71 | |||
| 72 | if (x86_quirks->update_apic) | ||
| 73 | x86_quirks->update_apic(); | ||
| 74 | } | 71 | } |
| 75 | 72 | ||
| 76 | /* Same for both flat and physical. */ | 73 | /* Same for both flat and physical. */ |
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index 32838b57a945..aac52fa873ff 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c | |||
| @@ -77,9 +77,9 @@ static void summit_send_IPI_all(int vector) | |||
| 77 | extern int use_cyclone; | 77 | extern int use_cyclone; |
| 78 | 78 | ||
| 79 | #ifdef CONFIG_X86_SUMMIT_NUMA | 79 | #ifdef CONFIG_X86_SUMMIT_NUMA |
| 80 | extern void setup_summit(void); | 80 | static void setup_summit(void); |
| 81 | #else | 81 | #else |
| 82 | #define setup_summit() {} | 82 | static inline void setup_summit(void) {} |
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | static int summit_mps_oem_check(struct mpc_table *mpc, char *oem, | 85 | static int summit_mps_oem_check(struct mpc_table *mpc, char *oem, |
| @@ -291,33 +291,21 @@ static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) | |||
| 291 | 291 | ||
| 292 | static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) | 292 | static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) |
| 293 | { | 293 | { |
| 294 | int cpus_found = 0; | 294 | unsigned int round = 0; |
| 295 | int num_bits_set; | 295 | int cpu, apicid = 0; |
| 296 | int apicid; | ||
| 297 | int cpu; | ||
| 298 | 296 | ||
| 299 | num_bits_set = cpus_weight(*cpumask); | ||
| 300 | if (num_bits_set >= nr_cpu_ids) | ||
| 301 | return BAD_APICID; | ||
| 302 | /* | 297 | /* |
| 303 | * The cpus in the mask must all be on the apic cluster. | 298 | * The cpus in the mask must all be on the apic cluster. |
| 304 | */ | 299 | */ |
| 305 | cpu = first_cpu(*cpumask); | 300 | for_each_cpu(cpu, cpumask) { |
| 306 | apicid = summit_cpu_to_logical_apicid(cpu); | 301 | int new_apicid = summit_cpu_to_logical_apicid(cpu); |
| 307 | |||
| 308 | while (cpus_found < num_bits_set) { | ||
| 309 | if (cpu_isset(cpu, *cpumask)) { | ||
| 310 | int new_apicid = summit_cpu_to_logical_apicid(cpu); | ||
| 311 | 302 | ||
| 312 | if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { | 303 | if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) { |
| 313 | printk("%s: Not a valid mask!\n", __func__); | 304 | printk("%s: Not a valid mask!\n", __func__); |
| 314 | 305 | return BAD_APICID; | |
| 315 | return BAD_APICID; | ||
| 316 | } | ||
| 317 | apicid = apicid | new_apicid; | ||
| 318 | cpus_found++; | ||
| 319 | } | 306 | } |
| 320 | cpu++; | 307 | apicid |= new_apicid; |
| 308 | round++; | ||
| 321 | } | 309 | } |
| 322 | return apicid; | 310 | return apicid; |
| 323 | } | 311 | } |
| @@ -372,15 +360,15 @@ static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) | |||
| 372 | } | 360 | } |
| 373 | 361 | ||
| 374 | #ifdef CONFIG_X86_SUMMIT_NUMA | 362 | #ifdef CONFIG_X86_SUMMIT_NUMA |
| 375 | static struct rio_table_hdr *rio_table_hdr __initdata; | 363 | static struct rio_table_hdr *rio_table_hdr; |
| 376 | static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; | 364 | static struct scal_detail *scal_devs[MAX_NUMNODES]; |
| 377 | static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata; | 365 | static struct rio_detail *rio_devs[MAX_NUMNODES*4]; |
| 378 | 366 | ||
| 379 | #ifndef CONFIG_X86_NUMAQ | 367 | #ifndef CONFIG_X86_NUMAQ |
| 380 | static int mp_bus_id_to_node[MAX_MP_BUSSES] __initdata; | 368 | static int mp_bus_id_to_node[MAX_MP_BUSSES]; |
| 381 | #endif | 369 | #endif |
| 382 | 370 | ||
| 383 | static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) | 371 | static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) |
| 384 | { | 372 | { |
| 385 | int twister = 0, node = 0; | 373 | int twister = 0, node = 0; |
| 386 | int i, bus, num_buses; | 374 | int i, bus, num_buses; |
| @@ -442,7 +430,7 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus) | |||
| 442 | return bus; | 430 | return bus; |
| 443 | } | 431 | } |
| 444 | 432 | ||
| 445 | static int __init build_detail_arrays(void) | 433 | static int build_detail_arrays(void) |
| 446 | { | 434 | { |
| 447 | unsigned long ptr; | 435 | unsigned long ptr; |
| 448 | int i, scal_detail_size, rio_detail_size; | 436 | int i, scal_detail_size, rio_detail_size; |
| @@ -476,7 +464,7 @@ static int __init build_detail_arrays(void) | |||
| 476 | return 1; | 464 | return 1; |
| 477 | } | 465 | } |
| 478 | 466 | ||
| 479 | void __init setup_summit(void) | 467 | void setup_summit(void) |
| 480 | { | 468 | { |
| 481 | unsigned long ptr; | 469 | unsigned long ptr; |
| 482 | unsigned short offset; | 470 | unsigned short offset; |
| @@ -574,7 +562,6 @@ struct apic apic_summit = { | |||
| 574 | .send_IPI_all = summit_send_IPI_all, | 562 | .send_IPI_all = summit_send_IPI_all, |
| 575 | .send_IPI_self = default_send_IPI_self, | 563 | .send_IPI_self = default_send_IPI_self, |
| 576 | 564 | ||
| 577 | .wakeup_cpu = NULL, | ||
| 578 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 565 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 579 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 566 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 580 | 567 | ||
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 354b9c45601d..8fb87b6dd633 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
| @@ -224,7 +224,6 @@ struct apic apic_x2apic_cluster = { | |||
| 224 | .send_IPI_all = x2apic_send_IPI_all, | 224 | .send_IPI_all = x2apic_send_IPI_all, |
| 225 | .send_IPI_self = x2apic_send_IPI_self, | 225 | .send_IPI_self = x2apic_send_IPI_self, |
| 226 | 226 | ||
| 227 | .wakeup_cpu = NULL, | ||
| 228 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 227 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 229 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 228 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 230 | .wait_for_init_deassert = NULL, | 229 | .wait_for_init_deassert = NULL, |
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 5bcb174409bc..23625b9f98b2 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c | |||
| @@ -213,7 +213,6 @@ struct apic apic_x2apic_phys = { | |||
| 213 | .send_IPI_all = x2apic_send_IPI_all, | 213 | .send_IPI_all = x2apic_send_IPI_all, |
| 214 | .send_IPI_self = x2apic_send_IPI_self, | 214 | .send_IPI_self = x2apic_send_IPI_self, |
| 215 | 215 | ||
| 216 | .wakeup_cpu = NULL, | ||
| 217 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 216 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 218 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 217 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 219 | .wait_for_init_deassert = NULL, | 218 | .wait_for_init_deassert = NULL, |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 20b4ad07c3a1..1bd6da1f8fad 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
| @@ -7,28 +7,28 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. | 8 | * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. |
| 9 | */ | 9 | */ |
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/threads.h> | ||
| 13 | #include <linux/cpu.h> | ||
| 14 | #include <linux/cpumask.h> | 10 | #include <linux/cpumask.h> |
| 11 | #include <linux/hardirq.h> | ||
| 12 | #include <linux/proc_fs.h> | ||
| 13 | #include <linux/threads.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 15 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 16 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/hardirq.h> | ||
| 21 | #include <linux/timer.h> | 19 | #include <linux/timer.h> |
| 22 | #include <linux/proc_fs.h> | 20 | #include <linux/cpu.h> |
| 23 | #include <asm/current.h> | 21 | #include <linux/init.h> |
| 24 | #include <asm/smp.h> | 22 | |
| 25 | #include <asm/apic.h> | ||
| 26 | #include <asm/ipi.h> | ||
| 27 | #include <asm/pgtable.h> | ||
| 28 | #include <asm/uv/uv.h> | ||
| 29 | #include <asm/uv/uv_mmrs.h> | 23 | #include <asm/uv/uv_mmrs.h> |
| 30 | #include <asm/uv/uv_hub.h> | 24 | #include <asm/uv/uv_hub.h> |
| 25 | #include <asm/current.h> | ||
| 26 | #include <asm/pgtable.h> | ||
| 31 | #include <asm/uv/bios.h> | 27 | #include <asm/uv/bios.h> |
| 28 | #include <asm/uv/uv.h> | ||
| 29 | #include <asm/apic.h> | ||
| 30 | #include <asm/ipi.h> | ||
| 31 | #include <asm/smp.h> | ||
| 32 | 32 | ||
| 33 | DEFINE_PER_CPU(int, x2apic_extra_bits); | 33 | DEFINE_PER_CPU(int, x2apic_extra_bits); |
| 34 | 34 | ||
| @@ -91,24 +91,28 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask) | |||
| 91 | cpumask_set_cpu(cpu, retmask); | 91 | cpumask_set_cpu(cpu, retmask); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) | 94 | static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) |
| 95 | { | 95 | { |
| 96 | #ifdef CONFIG_SMP | ||
| 96 | unsigned long val; | 97 | unsigned long val; |
| 97 | int pnode; | 98 | int pnode; |
| 98 | 99 | ||
| 99 | pnode = uv_apicid_to_pnode(phys_apicid); | 100 | pnode = uv_apicid_to_pnode(phys_apicid); |
| 100 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | | 101 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
| 101 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | | 102 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
| 102 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | | 103 | ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | |
| 103 | APIC_DM_INIT; | 104 | APIC_DM_INIT; |
| 104 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); | 105 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
| 105 | mdelay(10); | 106 | mdelay(10); |
| 106 | 107 | ||
| 107 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | | 108 | val = (1UL << UVH_IPI_INT_SEND_SHFT) | |
| 108 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | | 109 | (phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) | |
| 109 | (((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | | 110 | ((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) | |
| 110 | APIC_DM_STARTUP; | 111 | APIC_DM_STARTUP; |
| 111 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); | 112 | uv_write_global_mmr64(pnode, UVH_IPI_INT, val); |
| 113 | |||
| 114 | atomic_set(&init_deasserted, 1); | ||
| 115 | #endif | ||
| 112 | return 0; | 116 | return 0; |
| 113 | } | 117 | } |
| 114 | 118 | ||
| @@ -285,7 +289,7 @@ struct apic apic_x2apic_uv_x = { | |||
| 285 | .send_IPI_all = uv_send_IPI_all, | 289 | .send_IPI_all = uv_send_IPI_all, |
| 286 | .send_IPI_self = uv_send_IPI_self, | 290 | .send_IPI_self = uv_send_IPI_self, |
| 287 | 291 | ||
| 288 | .wakeup_cpu = NULL, | 292 | .wakeup_secondary_cpu = uv_wakeup_secondary, |
| 289 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, | 293 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 290 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, | 294 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 291 | .wait_for_init_deassert = NULL, | 295 | .wait_for_init_deassert = NULL, |
| @@ -365,7 +369,7 @@ static __init void map_high(char *id, unsigned long base, int shift, | |||
| 365 | paddr = base << shift; | 369 | paddr = base << shift; |
| 366 | bytes = (1UL << shift) * (max_pnode + 1); | 370 | bytes = (1UL << shift) * (max_pnode + 1); |
| 367 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, | 371 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, |
| 368 | paddr + bytes); | 372 | paddr + bytes); |
| 369 | if (map_type == map_uc) | 373 | if (map_type == map_uc) |
| 370 | init_extra_mapping_uc(paddr, bytes); | 374 | init_extra_mapping_uc(paddr, bytes); |
| 371 | else | 375 | else |
| @@ -528,7 +532,7 @@ late_initcall(uv_init_heartbeat); | |||
| 528 | 532 | ||
| 529 | /* | 533 | /* |
| 530 | * Called on each cpu to initialize the per_cpu UV data area. | 534 | * Called on each cpu to initialize the per_cpu UV data area. |
| 531 | * ZZZ hotplug not supported yet | 535 | * FIXME: hotplug not supported yet |
| 532 | */ | 536 | */ |
| 533 | void __cpuinit uv_cpu_init(void) | 537 | void __cpuinit uv_cpu_init(void) |
| 534 | { | 538 | { |
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 4b1c319d30c3..22590cf688ae 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
| @@ -601,7 +601,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 601 | if (!data) | 601 | if (!data) |
| 602 | return -ENOMEM; | 602 | return -ENOMEM; |
| 603 | 603 | ||
| 604 | data->acpi_data = percpu_ptr(acpi_perf_data, cpu); | 604 | data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu); |
| 605 | per_cpu(drv_data, cpu) = data; | 605 | per_cpu(drv_data, cpu) = data; |
| 606 | 606 | ||
| 607 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) | 607 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) |
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 01b1244ef1c0..d67e0e48bc2d 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
| @@ -7,11 +7,10 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * Get CPU information for use by the procfs. | 8 | * Get CPU information for use by the procfs. |
| 9 | */ | 9 | */ |
| 10 | #ifdef CONFIG_X86_32 | ||
| 11 | static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, | 10 | static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, |
| 12 | unsigned int cpu) | 11 | unsigned int cpu) |
| 13 | { | 12 | { |
| 14 | #ifdef CONFIG_X86_HT | 13 | #ifdef CONFIG_SMP |
| 15 | if (c->x86_max_cores * smp_num_siblings > 1) { | 14 | if (c->x86_max_cores * smp_num_siblings > 1) { |
| 16 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); | 15 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); |
| 17 | seq_printf(m, "siblings\t: %d\n", | 16 | seq_printf(m, "siblings\t: %d\n", |
| @@ -24,6 +23,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, | |||
| 24 | #endif | 23 | #endif |
| 25 | } | 24 | } |
| 26 | 25 | ||
| 26 | #ifdef CONFIG_X86_32 | ||
| 27 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) | 27 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) |
| 28 | { | 28 | { |
| 29 | /* | 29 | /* |
| @@ -50,22 +50,6 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) | |||
| 50 | c->wp_works_ok ? "yes" : "no"); | 50 | c->wp_works_ok ? "yes" : "no"); |
| 51 | } | 51 | } |
| 52 | #else | 52 | #else |
| 53 | static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, | ||
| 54 | unsigned int cpu) | ||
| 55 | { | ||
| 56 | #ifdef CONFIG_SMP | ||
| 57 | if (c->x86_max_cores * smp_num_siblings > 1) { | ||
| 58 | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); | ||
| 59 | seq_printf(m, "siblings\t: %d\n", | ||
| 60 | cpus_weight(per_cpu(cpu_core_map, cpu))); | ||
| 61 | seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); | ||
| 62 | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); | ||
| 63 | seq_printf(m, "apicid\t\t: %d\n", c->apicid); | ||
| 64 | seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); | ||
| 65 | } | ||
| 66 | #endif | ||
| 67 | } | ||
| 68 | |||
| 69 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) | 53 | static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) |
| 70 | { | 54 | { |
| 71 | seq_printf(m, | 55 | seq_printf(m, |
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index b205272ad394..1736acc4d7aa 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c | |||
| @@ -469,7 +469,7 @@ void __init efi_enter_virtual_mode(void) | |||
| 469 | efi_memory_desc_t *md; | 469 | efi_memory_desc_t *md; |
| 470 | efi_status_t status; | 470 | efi_status_t status; |
| 471 | unsigned long size; | 471 | unsigned long size; |
| 472 | u64 end, systab, addr, npages; | 472 | u64 end, systab, addr, npages, end_pfn; |
| 473 | void *p, *va; | 473 | void *p, *va; |
| 474 | 474 | ||
| 475 | efi.systab = NULL; | 475 | efi.systab = NULL; |
| @@ -481,7 +481,10 @@ void __init efi_enter_virtual_mode(void) | |||
| 481 | size = md->num_pages << EFI_PAGE_SHIFT; | 481 | size = md->num_pages << EFI_PAGE_SHIFT; |
| 482 | end = md->phys_addr + size; | 482 | end = md->phys_addr + size; |
| 483 | 483 | ||
| 484 | if (PFN_UP(end) <= max_low_pfn_mapped) | 484 | end_pfn = PFN_UP(end); |
| 485 | if (end_pfn <= max_low_pfn_mapped | ||
| 486 | || (end_pfn > (1UL << (32 - PAGE_SHIFT)) | ||
| 487 | && end_pfn <= max_pfn_mapped)) | ||
| 485 | va = __va(md->phys_addr); | 488 | va = __va(md->phys_addr); |
| 486 | else | 489 | else |
| 487 | va = efi_ioremap(md->phys_addr, size); | 490 | va = efi_ioremap(md->phys_addr, size); |
diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c index a4ee29127fdf..22c3b7828c50 100644 --- a/arch/x86/kernel/efi_64.c +++ b/arch/x86/kernel/efi_64.c | |||
| @@ -100,24 +100,11 @@ void __init efi_call_phys_epilog(void) | |||
| 100 | 100 | ||
| 101 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size) | 101 | void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size) |
| 102 | { | 102 | { |
| 103 | static unsigned pages_mapped __initdata; | 103 | unsigned long last_map_pfn; |
| 104 | unsigned i, pages; | ||
| 105 | unsigned long offset; | ||
| 106 | 104 | ||
| 107 | pages = PFN_UP(phys_addr + size) - PFN_DOWN(phys_addr); | 105 | last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); |
| 108 | offset = phys_addr & ~PAGE_MASK; | 106 | if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) |
| 109 | phys_addr &= PAGE_MASK; | ||
| 110 | |||
| 111 | if (pages_mapped + pages > MAX_EFI_IO_PAGES) | ||
| 112 | return NULL; | 107 | return NULL; |
| 113 | 108 | ||
| 114 | for (i = 0; i < pages; i++) { | 109 | return (void __iomem *)__va(phys_addr); |
| 115 | __set_fixmap(FIX_EFI_IO_MAP_FIRST_PAGE - pages_mapped, | ||
| 116 | phys_addr, PAGE_KERNEL); | ||
| 117 | phys_addr += PAGE_SIZE; | ||
| 118 | pages_mapped++; | ||
| 119 | } | ||
| 120 | |||
| 121 | return (void __iomem *)__fix_to_virt(FIX_EFI_IO_MAP_FIRST_PAGE - \ | ||
| 122 | (pages_mapped - pages)) + offset; | ||
| 123 | } | 110 | } |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index b0f61f0dcd0a..f2f8540a7f3d 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -136,7 +136,7 @@ int init_fpu(struct task_struct *tsk) | |||
| 136 | #ifdef CONFIG_X86_32 | 136 | #ifdef CONFIG_X86_32 |
| 137 | if (!HAVE_HWFP) { | 137 | if (!HAVE_HWFP) { |
| 138 | memset(tsk->thread.xstate, 0, xstate_size); | 138 | memset(tsk->thread.xstate, 0, xstate_size); |
| 139 | finit(); | 139 | finit_task(tsk); |
| 140 | set_stopped_child_used_math(tsk); | 140 | set_stopped_child_used_math(tsk); |
| 141 | return 0; | 141 | return 0; |
| 142 | } | 142 | } |
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index e41980a373ab..99c4d308f16b 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c | |||
| @@ -85,19 +85,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
| 85 | 85 | ||
| 86 | t->io_bitmap_max = bytes; | 86 | t->io_bitmap_max = bytes; |
| 87 | 87 | ||
| 88 | #ifdef CONFIG_X86_32 | ||
| 89 | /* | ||
| 90 | * Sets the lazy trigger so that the next I/O operation will | ||
| 91 | * reload the correct bitmap. | ||
| 92 | * Reset the owner so that a process switch will not set | ||
| 93 | * tss->io_bitmap_base to IO_BITMAP_OFFSET. | ||
| 94 | */ | ||
| 95 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; | ||
| 96 | tss->io_bitmap_owner = NULL; | ||
| 97 | #else | ||
| 98 | /* Update the TSS: */ | 88 | /* Update the TSS: */ |
| 99 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); | 89 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); |
| 100 | #endif | ||
| 101 | 90 | ||
| 102 | put_cpu(); | 91 | put_cpu(); |
| 103 | 92 | ||
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 9dc6b2b24275..3b09634a5153 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/uaccess.h> | 18 | #include <linux/uaccess.h> |
| 19 | #include <linux/percpu.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/apic.h> | 21 | #include <asm/apic.h> |
| 21 | 22 | ||
| @@ -55,13 +56,13 @@ static inline void print_stack_overflow(void) { } | |||
| 55 | union irq_ctx { | 56 | union irq_ctx { |
| 56 | struct thread_info tinfo; | 57 | struct thread_info tinfo; |
| 57 | u32 stack[THREAD_SIZE/sizeof(u32)]; | 58 | u32 stack[THREAD_SIZE/sizeof(u32)]; |
| 58 | }; | 59 | } __attribute__((aligned(PAGE_SIZE))); |
| 59 | 60 | ||
| 60 | static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; | 61 | static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx); |
| 61 | static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; | 62 | static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx); |
| 62 | 63 | ||
| 63 | static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; | 64 | static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack); |
| 64 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; | 65 | static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack); |
| 65 | 66 | ||
| 66 | static void call_on_stack(void *func, void *stack) | 67 | static void call_on_stack(void *func, void *stack) |
| 67 | { | 68 | { |
| @@ -81,7 +82,7 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) | |||
| 81 | u32 *isp, arg1, arg2; | 82 | u32 *isp, arg1, arg2; |
| 82 | 83 | ||
| 83 | curctx = (union irq_ctx *) current_thread_info(); | 84 | curctx = (union irq_ctx *) current_thread_info(); |
| 84 | irqctx = hardirq_ctx[smp_processor_id()]; | 85 | irqctx = __get_cpu_var(hardirq_ctx); |
| 85 | 86 | ||
| 86 | /* | 87 | /* |
| 87 | * this is where we switch to the IRQ stack. However, if we are | 88 | * this is where we switch to the IRQ stack. However, if we are |
| @@ -125,34 +126,34 @@ void __cpuinit irq_ctx_init(int cpu) | |||
| 125 | { | 126 | { |
| 126 | union irq_ctx *irqctx; | 127 | union irq_ctx *irqctx; |
| 127 | 128 | ||
| 128 | if (hardirq_ctx[cpu]) | 129 | if (per_cpu(hardirq_ctx, cpu)) |
| 129 | return; | 130 | return; |
| 130 | 131 | ||
| 131 | irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE]; | 132 | irqctx = &per_cpu(hardirq_stack, cpu); |
| 132 | irqctx->tinfo.task = NULL; | 133 | irqctx->tinfo.task = NULL; |
| 133 | irqctx->tinfo.exec_domain = NULL; | 134 | irqctx->tinfo.exec_domain = NULL; |
| 134 | irqctx->tinfo.cpu = cpu; | 135 | irqctx->tinfo.cpu = cpu; |
| 135 | irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; | 136 | irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; |
| 136 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); | 137 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); |
| 137 | 138 | ||
| 138 | hardirq_ctx[cpu] = irqctx; | 139 | per_cpu(hardirq_ctx, cpu) = irqctx; |
| 139 | 140 | ||
| 140 | irqctx = (union irq_ctx *) &softirq_stack[cpu*THREAD_SIZE]; | 141 | irqctx = &per_cpu(softirq_stack, cpu); |
| 141 | irqctx->tinfo.task = NULL; | 142 | irqctx->tinfo.task = NULL; |
| 142 | irqctx->tinfo.exec_domain = NULL; | 143 | irqctx->tinfo.exec_domain = NULL; |
| 143 | irqctx->tinfo.cpu = cpu; | 144 | irqctx->tinfo.cpu = cpu; |
| 144 | irqctx->tinfo.preempt_count = 0; | 145 | irqctx->tinfo.preempt_count = 0; |
| 145 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); | 146 | irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); |
| 146 | 147 | ||
| 147 | softirq_ctx[cpu] = irqctx; | 148 | per_cpu(softirq_ctx, cpu) = irqctx; |
| 148 | 149 | ||
| 149 | printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n", | 150 | printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n", |
| 150 | cpu, hardirq_ctx[cpu], softirq_ctx[cpu]); | 151 | cpu, per_cpu(hardirq_ctx, cpu), per_cpu(softirq_ctx, cpu)); |
| 151 | } | 152 | } |
| 152 | 153 | ||
| 153 | void irq_ctx_exit(int cpu) | 154 | void irq_ctx_exit(int cpu) |
| 154 | { | 155 | { |
| 155 | hardirq_ctx[cpu] = NULL; | 156 | per_cpu(hardirq_ctx, cpu) = NULL; |
| 156 | } | 157 | } |
| 157 | 158 | ||
| 158 | asmlinkage void do_softirq(void) | 159 | asmlinkage void do_softirq(void) |
| @@ -169,7 +170,7 @@ asmlinkage void do_softirq(void) | |||
| 169 | 170 | ||
| 170 | if (local_softirq_pending()) { | 171 | if (local_softirq_pending()) { |
| 171 | curctx = current_thread_info(); | 172 | curctx = current_thread_info(); |
| 172 | irqctx = softirq_ctx[smp_processor_id()]; | 173 | irqctx = __get_cpu_var(softirq_ctx); |
| 173 | irqctx->tinfo.task = curctx->task; | 174 | irqctx->tinfo.task = curctx->task; |
| 174 | irqctx->tinfo.previous_esp = current_stack_pointer; | 175 | irqctx->tinfo.previous_esp = current_stack_pointer; |
| 175 | 176 | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 87b69d4fac16..6afa5232dbb7 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | #include <linux/errno.h> | 1 | #include <linux/errno.h> |
| 2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
| 3 | #include <linux/mm.h> | 3 | #include <linux/mm.h> |
| 4 | #include <asm/idle.h> | ||
| 5 | #include <linux/smp.h> | 4 | #include <linux/smp.h> |
| 5 | #include <linux/prctl.h> | ||
| 6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
| 7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| @@ -11,6 +11,9 @@ | |||
| 11 | #include <linux/ftrace.h> | 11 | #include <linux/ftrace.h> |
| 12 | #include <asm/system.h> | 12 | #include <asm/system.h> |
| 13 | #include <asm/apic.h> | 13 | #include <asm/apic.h> |
| 14 | #include <asm/idle.h> | ||
| 15 | #include <asm/uaccess.h> | ||
| 16 | #include <asm/i387.h> | ||
| 14 | 17 | ||
| 15 | unsigned long idle_halt; | 18 | unsigned long idle_halt; |
| 16 | EXPORT_SYMBOL(idle_halt); | 19 | EXPORT_SYMBOL(idle_halt); |
| @@ -56,6 +59,192 @@ void arch_task_cache_init(void) | |||
| 56 | } | 59 | } |
| 57 | 60 | ||
| 58 | /* | 61 | /* |
| 62 | * Free current thread data structures etc.. | ||
| 63 | */ | ||
| 64 | void exit_thread(void) | ||
| 65 | { | ||
| 66 | struct task_struct *me = current; | ||
| 67 | struct thread_struct *t = &me->thread; | ||
| 68 | |||
| 69 | if (me->thread.io_bitmap_ptr) { | ||
| 70 | struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); | ||
| 71 | |||
| 72 | kfree(t->io_bitmap_ptr); | ||
| 73 | t->io_bitmap_ptr = NULL; | ||
| 74 | clear_thread_flag(TIF_IO_BITMAP); | ||
| 75 | /* | ||
| 76 | * Careful, clear this in the TSS too: | ||
| 77 | */ | ||
| 78 | memset(tss->io_bitmap, 0xff, t->io_bitmap_max); | ||
| 79 | t->io_bitmap_max = 0; | ||
| 80 | put_cpu(); | ||
| 81 | } | ||
| 82 | |||
| 83 | ds_exit_thread(current); | ||
| 84 | } | ||
| 85 | |||
| 86 | void flush_thread(void) | ||
| 87 | { | ||
| 88 | struct task_struct *tsk = current; | ||
| 89 | |||
| 90 | #ifdef CONFIG_X86_64 | ||
| 91 | if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) { | ||
| 92 | clear_tsk_thread_flag(tsk, TIF_ABI_PENDING); | ||
| 93 | if (test_tsk_thread_flag(tsk, TIF_IA32)) { | ||
| 94 | clear_tsk_thread_flag(tsk, TIF_IA32); | ||
| 95 | } else { | ||
| 96 | set_tsk_thread_flag(tsk, TIF_IA32); | ||
| 97 | current_thread_info()->status |= TS_COMPAT; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | #endif | ||
| 101 | |||
| 102 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | ||
| 103 | |||
| 104 | tsk->thread.debugreg0 = 0; | ||
| 105 | tsk->thread.debugreg1 = 0; | ||
| 106 | tsk->thread.debugreg2 = 0; | ||
| 107 | tsk->thread.debugreg3 = 0; | ||
| 108 | tsk->thread.debugreg6 = 0; | ||
| 109 | tsk->thread.debugreg7 = 0; | ||
| 110 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | ||
| 111 | /* | ||
| 112 | * Forget coprocessor state.. | ||
| 113 | */ | ||
| 114 | tsk->fpu_counter = 0; | ||
| 115 | clear_fpu(tsk); | ||
| 116 | clear_used_math(); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void hard_disable_TSC(void) | ||
| 120 | { | ||
| 121 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 122 | } | ||
| 123 | |||
| 124 | void disable_TSC(void) | ||
| 125 | { | ||
| 126 | preempt_disable(); | ||
| 127 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
| 128 | /* | ||
| 129 | * Must flip the CPU state synchronously with | ||
| 130 | * TIF_NOTSC in the current running context. | ||
| 131 | */ | ||
| 132 | hard_disable_TSC(); | ||
| 133 | preempt_enable(); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void hard_enable_TSC(void) | ||
| 137 | { | ||
| 138 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 139 | } | ||
| 140 | |||
| 141 | static void enable_TSC(void) | ||
| 142 | { | ||
| 143 | preempt_disable(); | ||
| 144 | if (test_and_clear_thread_flag(TIF_NOTSC)) | ||
| 145 | /* | ||
| 146 | * Must flip the CPU state synchronously with | ||
| 147 | * TIF_NOTSC in the current running context. | ||
| 148 | */ | ||
| 149 | hard_enable_TSC(); | ||
| 150 | preempt_enable(); | ||
| 151 | } | ||
| 152 | |||
| 153 | int get_tsc_mode(unsigned long adr) | ||
| 154 | { | ||
| 155 | unsigned int val; | ||
| 156 | |||
| 157 | if (test_thread_flag(TIF_NOTSC)) | ||
| 158 | val = PR_TSC_SIGSEGV; | ||
| 159 | else | ||
| 160 | val = PR_TSC_ENABLE; | ||
| 161 | |||
| 162 | return put_user(val, (unsigned int __user *)adr); | ||
| 163 | } | ||
| 164 | |||
| 165 | int set_tsc_mode(unsigned int val) | ||
| 166 | { | ||
| 167 | if (val == PR_TSC_SIGSEGV) | ||
| 168 | disable_TSC(); | ||
| 169 | else if (val == PR_TSC_ENABLE) | ||
| 170 | enable_TSC(); | ||
| 171 | else | ||
| 172 | return -EINVAL; | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
| 178 | struct tss_struct *tss) | ||
| 179 | { | ||
| 180 | struct thread_struct *prev, *next; | ||
| 181 | |||
| 182 | prev = &prev_p->thread; | ||
| 183 | next = &next_p->thread; | ||
| 184 | |||
| 185 | if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) || | ||
| 186 | test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR)) | ||
| 187 | ds_switch_to(prev_p, next_p); | ||
| 188 | else if (next->debugctlmsr != prev->debugctlmsr) | ||
| 189 | update_debugctlmsr(next->debugctlmsr); | ||
| 190 | |||
| 191 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
| 192 | set_debugreg(next->debugreg0, 0); | ||
| 193 | set_debugreg(next->debugreg1, 1); | ||
| 194 | set_debugreg(next->debugreg2, 2); | ||
| 195 | set_debugreg(next->debugreg3, 3); | ||
| 196 | /* no 4 and 5 */ | ||
| 197 | set_debugreg(next->debugreg6, 6); | ||
| 198 | set_debugreg(next->debugreg7, 7); | ||
| 199 | } | ||
| 200 | |||
| 201 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
| 202 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
| 203 | /* prev and next are different */ | ||
| 204 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
| 205 | hard_disable_TSC(); | ||
| 206 | else | ||
| 207 | hard_enable_TSC(); | ||
| 208 | } | ||
| 209 | |||
| 210 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
| 211 | /* | ||
| 212 | * Copy the relevant range of the IO bitmap. | ||
| 213 | * Normally this is 128 bytes or less: | ||
| 214 | */ | ||
| 215 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
| 216 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
| 217 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { | ||
| 218 | /* | ||
| 219 | * Clear any possible leftover bits: | ||
| 220 | */ | ||
| 221 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | int sys_fork(struct pt_regs *regs) | ||
| 226 | { | ||
| 227 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
| 228 | } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * This is trivial, and on the face of it looks like it | ||
| 232 | * could equally well be done in user mode. | ||
| 233 | * | ||
| 234 | * Not so, for quite unobvious reasons - register pressure. | ||
| 235 | * In user mode vfork() cannot have a stack frame, and if | ||
| 236 | * done by calling the "clone()" system call directly, you | ||
| 237 | * do not have enough call-clobbered registers to hold all | ||
| 238 | * the information you need. | ||
| 239 | */ | ||
| 240 | int sys_vfork(struct pt_regs *regs) | ||
| 241 | { | ||
| 242 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, | ||
| 243 | NULL, NULL); | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | /* | ||
| 59 | * Idle related variables and functions | 248 | * Idle related variables and functions |
| 60 | */ | 249 | */ |
| 61 | unsigned long boot_option_idle_override = 0; | 250 | unsigned long boot_option_idle_override = 0; |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 646da41a620a..14014d766cad 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -230,55 +230,6 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |||
| 230 | } | 230 | } |
| 231 | EXPORT_SYMBOL(kernel_thread); | 231 | EXPORT_SYMBOL(kernel_thread); |
| 232 | 232 | ||
| 233 | /* | ||
| 234 | * Free current thread data structures etc.. | ||
| 235 | */ | ||
| 236 | void exit_thread(void) | ||
| 237 | { | ||
| 238 | /* The process may have allocated an io port bitmap... nuke it. */ | ||
| 239 | if (unlikely(test_thread_flag(TIF_IO_BITMAP))) { | ||
| 240 | struct task_struct *tsk = current; | ||
| 241 | struct thread_struct *t = &tsk->thread; | ||
| 242 | int cpu = get_cpu(); | ||
| 243 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | ||
| 244 | |||
| 245 | kfree(t->io_bitmap_ptr); | ||
| 246 | t->io_bitmap_ptr = NULL; | ||
| 247 | clear_thread_flag(TIF_IO_BITMAP); | ||
| 248 | /* | ||
| 249 | * Careful, clear this in the TSS too: | ||
| 250 | */ | ||
| 251 | memset(tss->io_bitmap, 0xff, tss->io_bitmap_max); | ||
| 252 | t->io_bitmap_max = 0; | ||
| 253 | tss->io_bitmap_owner = NULL; | ||
| 254 | tss->io_bitmap_max = 0; | ||
| 255 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | ||
| 256 | put_cpu(); | ||
| 257 | } | ||
| 258 | |||
| 259 | ds_exit_thread(current); | ||
| 260 | } | ||
| 261 | |||
| 262 | void flush_thread(void) | ||
| 263 | { | ||
| 264 | struct task_struct *tsk = current; | ||
| 265 | |||
| 266 | tsk->thread.debugreg0 = 0; | ||
| 267 | tsk->thread.debugreg1 = 0; | ||
| 268 | tsk->thread.debugreg2 = 0; | ||
| 269 | tsk->thread.debugreg3 = 0; | ||
| 270 | tsk->thread.debugreg6 = 0; | ||
| 271 | tsk->thread.debugreg7 = 0; | ||
| 272 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | ||
| 273 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | ||
| 274 | /* | ||
| 275 | * Forget coprocessor state.. | ||
| 276 | */ | ||
| 277 | tsk->fpu_counter = 0; | ||
| 278 | clear_fpu(tsk); | ||
| 279 | clear_used_math(); | ||
| 280 | } | ||
| 281 | |||
| 282 | void release_thread(struct task_struct *dead_task) | 233 | void release_thread(struct task_struct *dead_task) |
| 283 | { | 234 | { |
| 284 | BUG_ON(dead_task->mm); | 235 | BUG_ON(dead_task->mm); |
| @@ -366,127 +317,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
| 366 | } | 317 | } |
| 367 | EXPORT_SYMBOL_GPL(start_thread); | 318 | EXPORT_SYMBOL_GPL(start_thread); |
| 368 | 319 | ||
| 369 | static void hard_disable_TSC(void) | ||
| 370 | { | ||
| 371 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 372 | } | ||
| 373 | |||
| 374 | void disable_TSC(void) | ||
| 375 | { | ||
| 376 | preempt_disable(); | ||
| 377 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
| 378 | /* | ||
| 379 | * Must flip the CPU state synchronously with | ||
| 380 | * TIF_NOTSC in the current running context. | ||
| 381 | */ | ||
| 382 | hard_disable_TSC(); | ||
| 383 | preempt_enable(); | ||
| 384 | } | ||
| 385 | |||
| 386 | static void hard_enable_TSC(void) | ||
| 387 | { | ||
| 388 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 389 | } | ||
| 390 | |||
| 391 | static void enable_TSC(void) | ||
| 392 | { | ||
| 393 | preempt_disable(); | ||
| 394 | if (test_and_clear_thread_flag(TIF_NOTSC)) | ||
| 395 | /* | ||
| 396 | * Must flip the CPU state synchronously with | ||
| 397 | * TIF_NOTSC in the current running context. | ||
| 398 | */ | ||
| 399 | hard_enable_TSC(); | ||
| 400 | preempt_enable(); | ||
| 401 | } | ||
| 402 | |||
| 403 | int get_tsc_mode(unsigned long adr) | ||
| 404 | { | ||
| 405 | unsigned int val; | ||
| 406 | |||
| 407 | if (test_thread_flag(TIF_NOTSC)) | ||
| 408 | val = PR_TSC_SIGSEGV; | ||
| 409 | else | ||
| 410 | val = PR_TSC_ENABLE; | ||
| 411 | |||
| 412 | return put_user(val, (unsigned int __user *)adr); | ||
| 413 | } | ||
| 414 | |||
| 415 | int set_tsc_mode(unsigned int val) | ||
| 416 | { | ||
| 417 | if (val == PR_TSC_SIGSEGV) | ||
| 418 | disable_TSC(); | ||
| 419 | else if (val == PR_TSC_ENABLE) | ||
| 420 | enable_TSC(); | ||
| 421 | else | ||
| 422 | return -EINVAL; | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 427 | static noinline void | ||
| 428 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
| 429 | struct tss_struct *tss) | ||
| 430 | { | ||
| 431 | struct thread_struct *prev, *next; | ||
| 432 | |||
| 433 | prev = &prev_p->thread; | ||
| 434 | next = &next_p->thread; | ||
| 435 | |||
| 436 | if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) || | ||
| 437 | test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR)) | ||
| 438 | ds_switch_to(prev_p, next_p); | ||
| 439 | else if (next->debugctlmsr != prev->debugctlmsr) | ||
| 440 | update_debugctlmsr(next->debugctlmsr); | ||
| 441 | |||
| 442 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
| 443 | set_debugreg(next->debugreg0, 0); | ||
| 444 | set_debugreg(next->debugreg1, 1); | ||
| 445 | set_debugreg(next->debugreg2, 2); | ||
| 446 | set_debugreg(next->debugreg3, 3); | ||
| 447 | /* no 4 and 5 */ | ||
| 448 | set_debugreg(next->debugreg6, 6); | ||
| 449 | set_debugreg(next->debugreg7, 7); | ||
| 450 | } | ||
| 451 | |||
| 452 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
| 453 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
| 454 | /* prev and next are different */ | ||
| 455 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
| 456 | hard_disable_TSC(); | ||
| 457 | else | ||
| 458 | hard_enable_TSC(); | ||
| 459 | } | ||
| 460 | |||
| 461 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
| 462 | /* | ||
| 463 | * Disable the bitmap via an invalid offset. We still cache | ||
| 464 | * the previous bitmap owner and the IO bitmap contents: | ||
| 465 | */ | ||
| 466 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | ||
| 467 | return; | ||
| 468 | } | ||
| 469 | |||
| 470 | if (likely(next == tss->io_bitmap_owner)) { | ||
| 471 | /* | ||
| 472 | * Previous owner of the bitmap (hence the bitmap content) | ||
| 473 | * matches the next task, we dont have to do anything but | ||
| 474 | * to set a valid offset in the TSS: | ||
| 475 | */ | ||
| 476 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | /* | ||
| 480 | * Lazy TSS's I/O bitmap copy. We set an invalid offset here | ||
| 481 | * and we let the task to get a GPF in case an I/O instruction | ||
| 482 | * is performed. The handler of the GPF will verify that the | ||
| 483 | * faulting task has a valid I/O bitmap and, it true, does the | ||
| 484 | * real copy and restart the instruction. This will save us | ||
| 485 | * redundant copies when the currently switched task does not | ||
| 486 | * perform any I/O during its timeslice. | ||
| 487 | */ | ||
| 488 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; | ||
| 489 | } | ||
| 490 | 320 | ||
| 491 | /* | 321 | /* |
| 492 | * switch_to(x,yn) should switch tasks from x to y. | 322 | * switch_to(x,yn) should switch tasks from x to y. |
| @@ -600,11 +430,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 600 | return prev_p; | 430 | return prev_p; |
| 601 | } | 431 | } |
| 602 | 432 | ||
| 603 | int sys_fork(struct pt_regs *regs) | ||
| 604 | { | ||
| 605 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
| 606 | } | ||
| 607 | |||
| 608 | int sys_clone(struct pt_regs *regs) | 433 | int sys_clone(struct pt_regs *regs) |
| 609 | { | 434 | { |
| 610 | unsigned long clone_flags; | 435 | unsigned long clone_flags; |
| @@ -621,21 +446,6 @@ int sys_clone(struct pt_regs *regs) | |||
| 621 | } | 446 | } |
| 622 | 447 | ||
| 623 | /* | 448 | /* |
| 624 | * This is trivial, and on the face of it looks like it | ||
| 625 | * could equally well be done in user mode. | ||
| 626 | * | ||
| 627 | * Not so, for quite unobvious reasons - register pressure. | ||
| 628 | * In user mode vfork() cannot have a stack frame, and if | ||
| 629 | * done by calling the "clone()" system call directly, you | ||
| 630 | * do not have enough call-clobbered registers to hold all | ||
| 631 | * the information you need. | ||
| 632 | */ | ||
| 633 | int sys_vfork(struct pt_regs *regs) | ||
| 634 | { | ||
| 635 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
| 636 | } | ||
| 637 | |||
| 638 | /* | ||
| 639 | * sys_execve() executes a new program. | 449 | * sys_execve() executes a new program. |
| 640 | */ | 450 | */ |
| 641 | int sys_execve(struct pt_regs *regs) | 451 | int sys_execve(struct pt_regs *regs) |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 836ef6575f01..abb7e6a7f0c6 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -237,61 +237,6 @@ void show_regs(struct pt_regs *regs) | |||
| 237 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); | 237 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | /* | ||
| 241 | * Free current thread data structures etc.. | ||
| 242 | */ | ||
| 243 | void exit_thread(void) | ||
| 244 | { | ||
| 245 | struct task_struct *me = current; | ||
| 246 | struct thread_struct *t = &me->thread; | ||
| 247 | |||
| 248 | if (me->thread.io_bitmap_ptr) { | ||
| 249 | struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); | ||
| 250 | |||
| 251 | kfree(t->io_bitmap_ptr); | ||
| 252 | t->io_bitmap_ptr = NULL; | ||
| 253 | clear_thread_flag(TIF_IO_BITMAP); | ||
| 254 | /* | ||
| 255 | * Careful, clear this in the TSS too: | ||
| 256 | */ | ||
| 257 | memset(tss->io_bitmap, 0xff, t->io_bitmap_max); | ||
| 258 | t->io_bitmap_max = 0; | ||
| 259 | put_cpu(); | ||
| 260 | } | ||
| 261 | |||
| 262 | ds_exit_thread(current); | ||
| 263 | } | ||
| 264 | |||
| 265 | void flush_thread(void) | ||
| 266 | { | ||
| 267 | struct task_struct *tsk = current; | ||
| 268 | |||
| 269 | if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) { | ||
| 270 | clear_tsk_thread_flag(tsk, TIF_ABI_PENDING); | ||
| 271 | if (test_tsk_thread_flag(tsk, TIF_IA32)) { | ||
| 272 | clear_tsk_thread_flag(tsk, TIF_IA32); | ||
| 273 | } else { | ||
| 274 | set_tsk_thread_flag(tsk, TIF_IA32); | ||
| 275 | current_thread_info()->status |= TS_COMPAT; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | ||
| 279 | |||
| 280 | tsk->thread.debugreg0 = 0; | ||
| 281 | tsk->thread.debugreg1 = 0; | ||
| 282 | tsk->thread.debugreg2 = 0; | ||
| 283 | tsk->thread.debugreg3 = 0; | ||
| 284 | tsk->thread.debugreg6 = 0; | ||
| 285 | tsk->thread.debugreg7 = 0; | ||
| 286 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | ||
| 287 | /* | ||
| 288 | * Forget coprocessor state.. | ||
| 289 | */ | ||
| 290 | tsk->fpu_counter = 0; | ||
| 291 | clear_fpu(tsk); | ||
| 292 | clear_used_math(); | ||
| 293 | } | ||
| 294 | |||
| 295 | void release_thread(struct task_struct *dead_task) | 240 | void release_thread(struct task_struct *dead_task) |
| 296 | { | 241 | { |
| 297 | if (dead_task->mm) { | 242 | if (dead_task->mm) { |
| @@ -425,118 +370,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
| 425 | } | 370 | } |
| 426 | EXPORT_SYMBOL_GPL(start_thread); | 371 | EXPORT_SYMBOL_GPL(start_thread); |
| 427 | 372 | ||
| 428 | static void hard_disable_TSC(void) | ||
| 429 | { | ||
| 430 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 431 | } | ||
| 432 | |||
| 433 | void disable_TSC(void) | ||
| 434 | { | ||
| 435 | preempt_disable(); | ||
| 436 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
| 437 | /* | ||
| 438 | * Must flip the CPU state synchronously with | ||
| 439 | * TIF_NOTSC in the current running context. | ||
| 440 | */ | ||
| 441 | hard_disable_TSC(); | ||
| 442 | preempt_enable(); | ||
| 443 | } | ||
| 444 | |||
| 445 | static void hard_enable_TSC(void) | ||
| 446 | { | ||
| 447 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 448 | } | ||
| 449 | |||
| 450 | static void enable_TSC(void) | ||
| 451 | { | ||
| 452 | preempt_disable(); | ||
| 453 | if (test_and_clear_thread_flag(TIF_NOTSC)) | ||
| 454 | /* | ||
| 455 | * Must flip the CPU state synchronously with | ||
| 456 | * TIF_NOTSC in the current running context. | ||
| 457 | */ | ||
| 458 | hard_enable_TSC(); | ||
| 459 | preempt_enable(); | ||
| 460 | } | ||
| 461 | |||
| 462 | int get_tsc_mode(unsigned long adr) | ||
| 463 | { | ||
| 464 | unsigned int val; | ||
| 465 | |||
| 466 | if (test_thread_flag(TIF_NOTSC)) | ||
| 467 | val = PR_TSC_SIGSEGV; | ||
| 468 | else | ||
| 469 | val = PR_TSC_ENABLE; | ||
| 470 | |||
| 471 | return put_user(val, (unsigned int __user *)adr); | ||
| 472 | } | ||
| 473 | |||
| 474 | int set_tsc_mode(unsigned int val) | ||
| 475 | { | ||
| 476 | if (val == PR_TSC_SIGSEGV) | ||
| 477 | disable_TSC(); | ||
| 478 | else if (val == PR_TSC_ENABLE) | ||
| 479 | enable_TSC(); | ||
| 480 | else | ||
| 481 | return -EINVAL; | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | /* | ||
| 487 | * This special macro can be used to load a debugging register | ||
| 488 | */ | ||
| 489 | #define loaddebug(thread, r) set_debugreg(thread->debugreg ## r, r) | ||
| 490 | |||
| 491 | static inline void __switch_to_xtra(struct task_struct *prev_p, | ||
| 492 | struct task_struct *next_p, | ||
| 493 | struct tss_struct *tss) | ||
| 494 | { | ||
| 495 | struct thread_struct *prev, *next; | ||
| 496 | |||
| 497 | prev = &prev_p->thread, | ||
| 498 | next = &next_p->thread; | ||
| 499 | |||
| 500 | if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) || | ||
| 501 | test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR)) | ||
| 502 | ds_switch_to(prev_p, next_p); | ||
| 503 | else if (next->debugctlmsr != prev->debugctlmsr) | ||
| 504 | update_debugctlmsr(next->debugctlmsr); | ||
| 505 | |||
| 506 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
| 507 | loaddebug(next, 0); | ||
| 508 | loaddebug(next, 1); | ||
| 509 | loaddebug(next, 2); | ||
| 510 | loaddebug(next, 3); | ||
| 511 | /* no 4 and 5 */ | ||
| 512 | loaddebug(next, 6); | ||
| 513 | loaddebug(next, 7); | ||
| 514 | } | ||
| 515 | |||
| 516 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
| 517 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
| 518 | /* prev and next are different */ | ||
| 519 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
| 520 | hard_disable_TSC(); | ||
| 521 | else | ||
| 522 | hard_enable_TSC(); | ||
| 523 | } | ||
| 524 | |||
| 525 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
| 526 | /* | ||
| 527 | * Copy the relevant range of the IO bitmap. | ||
| 528 | * Normally this is 128 bytes or less: | ||
| 529 | */ | ||
| 530 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
| 531 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
| 532 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { | ||
| 533 | /* | ||
| 534 | * Clear any possible leftover bits: | ||
| 535 | */ | ||
| 536 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | /* | 373 | /* |
| 541 | * switch_to(x,y) should switch tasks from x to y. | 374 | * switch_to(x,y) should switch tasks from x to y. |
| 542 | * | 375 | * |
| @@ -694,11 +527,6 @@ void set_personality_64bit(void) | |||
| 694 | current->personality &= ~READ_IMPLIES_EXEC; | 527 | current->personality &= ~READ_IMPLIES_EXEC; |
| 695 | } | 528 | } |
| 696 | 529 | ||
| 697 | asmlinkage long sys_fork(struct pt_regs *regs) | ||
| 698 | { | ||
| 699 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
| 700 | } | ||
| 701 | |||
| 702 | asmlinkage long | 530 | asmlinkage long |
| 703 | sys_clone(unsigned long clone_flags, unsigned long newsp, | 531 | sys_clone(unsigned long clone_flags, unsigned long newsp, |
| 704 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | 532 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) |
| @@ -708,22 +536,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
| 708 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | 536 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); |
| 709 | } | 537 | } |
| 710 | 538 | ||
| 711 | /* | ||
| 712 | * This is trivial, and on the face of it looks like it | ||
| 713 | * could equally well be done in user mode. | ||
| 714 | * | ||
| 715 | * Not so, for quite unobvious reasons - register pressure. | ||
| 716 | * In user mode vfork() cannot have a stack frame, and if | ||
| 717 | * done by calling the "clone()" system call directly, you | ||
| 718 | * do not have enough call-clobbered registers to hold all | ||
| 719 | * the information you need. | ||
| 720 | */ | ||
| 721 | asmlinkage long sys_vfork(struct pt_regs *regs) | ||
| 722 | { | ||
| 723 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, | ||
| 724 | NULL, NULL); | ||
| 725 | } | ||
| 726 | |||
| 727 | unsigned long get_wchan(struct task_struct *p) | 539 | unsigned long get_wchan(struct task_struct *p) |
| 728 | { | 540 | { |
| 729 | unsigned long stack; | 541 | unsigned long stack; |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index fb2159a5c817..3d9672e59c16 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
| @@ -1383,7 +1383,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | |||
| 1383 | #ifdef CONFIG_X86_32 | 1383 | #ifdef CONFIG_X86_32 |
| 1384 | # define IS_IA32 1 | 1384 | # define IS_IA32 1 |
| 1385 | #elif defined CONFIG_IA32_EMULATION | 1385 | #elif defined CONFIG_IA32_EMULATION |
| 1386 | # define IS_IA32 test_thread_flag(TIF_IA32) | 1386 | # define IS_IA32 is_compat_task() |
| 1387 | #else | 1387 | #else |
| 1388 | # define IS_IA32 0 | 1388 | # define IS_IA32 0 |
| 1389 | #endif | 1389 | #endif |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 1cc18d439bbb..2aef36d8aca2 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
| @@ -216,6 +216,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { | |||
| 216 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), | 216 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), |
| 217 | }, | 217 | }, |
| 218 | }, | 218 | }, |
| 219 | { /* Handle problems with rebooting on Dell XPS710 */ | ||
| 220 | .callback = set_bios_reboot, | ||
| 221 | .ident = "Dell XPS710", | ||
| 222 | .matches = { | ||
| 223 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 224 | DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), | ||
| 225 | }, | ||
| 226 | }, | ||
| 219 | { } | 227 | { } |
| 220 | }; | 228 | }; |
| 221 | 229 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5b85759e7972..b746deb9ebc6 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -600,19 +600,7 @@ static int __init setup_elfcorehdr(char *arg) | |||
| 600 | early_param("elfcorehdr", setup_elfcorehdr); | 600 | early_param("elfcorehdr", setup_elfcorehdr); |
| 601 | #endif | 601 | #endif |
| 602 | 602 | ||
| 603 | static int __init default_update_apic(void) | 603 | static struct x86_quirks default_x86_quirks __initdata; |
| 604 | { | ||
| 605 | #ifdef CONFIG_SMP | ||
| 606 | if (!apic->wakeup_cpu) | ||
| 607 | apic->wakeup_cpu = wakeup_secondary_cpu_via_init; | ||
| 608 | #endif | ||
| 609 | |||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | |||
| 613 | static struct x86_quirks default_x86_quirks __initdata = { | ||
| 614 | .update_apic = default_update_apic, | ||
| 615 | }; | ||
| 616 | 604 | ||
| 617 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; | 605 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; |
| 618 | 606 | ||
| @@ -782,6 +770,9 @@ void __init setup_arch(char **cmdline_p) | |||
| 782 | 770 | ||
| 783 | finish_e820_parsing(); | 771 | finish_e820_parsing(); |
| 784 | 772 | ||
| 773 | if (efi_enabled) | ||
| 774 | efi_init(); | ||
| 775 | |||
| 785 | dmi_scan_machine(); | 776 | dmi_scan_machine(); |
| 786 | 777 | ||
| 787 | dmi_check_system(bad_bios_dmi_table); | 778 | dmi_check_system(bad_bios_dmi_table); |
| @@ -801,8 +792,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 801 | insert_resource(&iomem_resource, &data_resource); | 792 | insert_resource(&iomem_resource, &data_resource); |
| 802 | insert_resource(&iomem_resource, &bss_resource); | 793 | insert_resource(&iomem_resource, &bss_resource); |
| 803 | 794 | ||
| 804 | if (efi_enabled) | ||
| 805 | efi_init(); | ||
| 806 | 795 | ||
| 807 | #ifdef CONFIG_X86_32 | 796 | #ifdef CONFIG_X86_32 |
| 808 | if (ppro_with_ram_bug()) { | 797 | if (ppro_with_ram_bug()) { |
| @@ -875,9 +864,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 875 | 864 | ||
| 876 | reserve_initrd(); | 865 | reserve_initrd(); |
| 877 | 866 | ||
| 878 | #ifdef CONFIG_X86_64 | ||
| 879 | vsmp_init(); | 867 | vsmp_init(); |
| 880 | #endif | ||
| 881 | 868 | ||
| 882 | io_delay_init(); | 869 | io_delay_init(); |
| 883 | 870 | ||
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index d992e6cff730..c29f301d3885 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/crash_dump.h> | 7 | #include <linux/crash_dump.h> |
| 8 | #include <linux/smp.h> | 8 | #include <linux/smp.h> |
| 9 | #include <linux/topology.h> | 9 | #include <linux/topology.h> |
| 10 | #include <linux/pfn.h> | ||
| 10 | #include <asm/sections.h> | 11 | #include <asm/sections.h> |
| 11 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
| 12 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
| @@ -41,6 +42,321 @@ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = { | |||
| 41 | }; | 42 | }; |
| 42 | EXPORT_SYMBOL(__per_cpu_offset); | 43 | EXPORT_SYMBOL(__per_cpu_offset); |
| 43 | 44 | ||
| 45 | /** | ||
| 46 | * pcpu_need_numa - determine percpu allocation needs to consider NUMA | ||
| 47 | * | ||
| 48 | * If NUMA is not configured or there is only one NUMA node available, | ||
| 49 | * there is no reason to consider NUMA. This function determines | ||
| 50 | * whether percpu allocation should consider NUMA or not. | ||
| 51 | * | ||
| 52 | * RETURNS: | ||
| 53 | * true if NUMA should be considered; otherwise, false. | ||
| 54 | */ | ||
| 55 | static bool __init pcpu_need_numa(void) | ||
| 56 | { | ||
| 57 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 58 | pg_data_t *last = NULL; | ||
| 59 | unsigned int cpu; | ||
| 60 | |||
| 61 | for_each_possible_cpu(cpu) { | ||
| 62 | int node = early_cpu_to_node(cpu); | ||
| 63 | |||
| 64 | if (node_online(node) && NODE_DATA(node) && | ||
| 65 | last && last != NODE_DATA(node)) | ||
| 66 | return true; | ||
| 67 | |||
| 68 | last = NODE_DATA(node); | ||
| 69 | } | ||
| 70 | #endif | ||
| 71 | return false; | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 75 | * pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu | ||
| 76 | * @cpu: cpu to allocate for | ||
| 77 | * @size: size allocation in bytes | ||
| 78 | * @align: alignment | ||
| 79 | * | ||
| 80 | * Allocate @size bytes aligned at @align for cpu @cpu. This wrapper | ||
| 81 | * does the right thing for NUMA regardless of the current | ||
| 82 | * configuration. | ||
| 83 | * | ||
| 84 | * RETURNS: | ||
| 85 | * Pointer to the allocated area on success, NULL on failure. | ||
| 86 | */ | ||
| 87 | static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, | ||
| 88 | unsigned long align) | ||
| 89 | { | ||
| 90 | const unsigned long goal = __pa(MAX_DMA_ADDRESS); | ||
| 91 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 92 | int node = early_cpu_to_node(cpu); | ||
| 93 | void *ptr; | ||
| 94 | |||
| 95 | if (!node_online(node) || !NODE_DATA(node)) { | ||
| 96 | ptr = __alloc_bootmem_nopanic(size, align, goal); | ||
| 97 | pr_info("cpu %d has no node %d or node-local memory\n", | ||
| 98 | cpu, node); | ||
| 99 | pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n", | ||
| 100 | cpu, size, __pa(ptr)); | ||
| 101 | } else { | ||
| 102 | ptr = __alloc_bootmem_node_nopanic(NODE_DATA(node), | ||
| 103 | size, align, goal); | ||
| 104 | pr_debug("per cpu data for cpu%d %lu bytes on node%d at " | ||
| 105 | "%016lx\n", cpu, size, node, __pa(ptr)); | ||
| 106 | } | ||
| 107 | return ptr; | ||
| 108 | #else | ||
| 109 | return __alloc_bootmem_nopanic(size, align, goal); | ||
| 110 | #endif | ||
| 111 | } | ||
| 112 | |||
| 113 | /* | ||
| 114 | * Remap allocator | ||
| 115 | * | ||
| 116 | * This allocator uses PMD page as unit. A PMD page is allocated for | ||
| 117 | * each cpu and each is remapped into vmalloc area using PMD mapping. | ||
| 118 | * As PMD page is quite large, only part of it is used for the first | ||
| 119 | * chunk. Unused part is returned to the bootmem allocator. | ||
| 120 | * | ||
| 121 | * So, the PMD pages are mapped twice - once to the physical mapping | ||
| 122 | * and to the vmalloc area for the first percpu chunk. The double | ||
| 123 | * mapping does add one more PMD TLB entry pressure but still is much | ||
| 124 | * better than only using 4k mappings while still being NUMA friendly. | ||
| 125 | */ | ||
| 126 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 127 | static size_t pcpur_size __initdata; | ||
| 128 | static void **pcpur_ptrs __initdata; | ||
| 129 | |||
| 130 | static struct page * __init pcpur_get_page(unsigned int cpu, int pageno) | ||
| 131 | { | ||
| 132 | size_t off = (size_t)pageno << PAGE_SHIFT; | ||
| 133 | |||
| 134 | if (off >= pcpur_size) | ||
| 135 | return NULL; | ||
| 136 | |||
| 137 | return virt_to_page(pcpur_ptrs[cpu] + off); | ||
| 138 | } | ||
| 139 | |||
| 140 | static ssize_t __init setup_pcpu_remap(size_t static_size) | ||
| 141 | { | ||
| 142 | static struct vm_struct vm; | ||
| 143 | pg_data_t *last; | ||
| 144 | size_t ptrs_size; | ||
| 145 | unsigned int cpu; | ||
| 146 | ssize_t ret; | ||
| 147 | |||
| 148 | /* | ||
| 149 | * If large page isn't supported, there's no benefit in doing | ||
| 150 | * this. Also, on non-NUMA, embedding is better. | ||
| 151 | */ | ||
| 152 | if (!cpu_has_pse || pcpu_need_numa()) | ||
| 153 | return -EINVAL; | ||
| 154 | |||
| 155 | last = NULL; | ||
| 156 | for_each_possible_cpu(cpu) { | ||
| 157 | int node = early_cpu_to_node(cpu); | ||
| 158 | |||
| 159 | if (node_online(node) && NODE_DATA(node) && | ||
| 160 | last && last != NODE_DATA(node)) | ||
| 161 | goto proceed; | ||
| 162 | |||
| 163 | last = NODE_DATA(node); | ||
| 164 | } | ||
| 165 | return -EINVAL; | ||
| 166 | |||
| 167 | proceed: | ||
| 168 | /* | ||
| 169 | * Currently supports only single page. Supporting multiple | ||
| 170 | * pages won't be too difficult if it ever becomes necessary. | ||
| 171 | */ | ||
| 172 | pcpur_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); | ||
| 173 | if (pcpur_size > PMD_SIZE) { | ||
| 174 | pr_warning("PERCPU: static data is larger than large page, " | ||
| 175 | "can't use large page\n"); | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | |||
| 179 | /* allocate pointer array and alloc large pages */ | ||
| 180 | ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); | ||
| 181 | pcpur_ptrs = alloc_bootmem(ptrs_size); | ||
| 182 | |||
| 183 | for_each_possible_cpu(cpu) { | ||
| 184 | pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); | ||
| 185 | if (!pcpur_ptrs[cpu]) | ||
| 186 | goto enomem; | ||
| 187 | |||
| 188 | /* | ||
| 189 | * Only use pcpur_size bytes and give back the rest. | ||
| 190 | * | ||
| 191 | * Ingo: The 2MB up-rounding bootmem is needed to make | ||
| 192 | * sure the partial 2MB page is still fully RAM - it's | ||
| 193 | * not well-specified to have a PAT-incompatible area | ||
| 194 | * (unmapped RAM, device memory, etc.) in that hole. | ||
| 195 | */ | ||
| 196 | free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size), | ||
| 197 | PMD_SIZE - pcpur_size); | ||
| 198 | |||
| 199 | memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size); | ||
| 200 | } | ||
| 201 | |||
| 202 | /* allocate address and map */ | ||
| 203 | vm.flags = VM_ALLOC; | ||
| 204 | vm.size = num_possible_cpus() * PMD_SIZE; | ||
| 205 | vm_area_register_early(&vm, PMD_SIZE); | ||
| 206 | |||
| 207 | for_each_possible_cpu(cpu) { | ||
| 208 | pmd_t *pmd; | ||
| 209 | |||
| 210 | pmd = populate_extra_pmd((unsigned long)vm.addr | ||
| 211 | + cpu * PMD_SIZE); | ||
| 212 | set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])), | ||
| 213 | PAGE_KERNEL_LARGE)); | ||
| 214 | } | ||
| 215 | |||
| 216 | /* we're ready, commit */ | ||
| 217 | pr_info("PERCPU: Remapped at %p with large pages, static data " | ||
| 218 | "%zu bytes\n", vm.addr, static_size); | ||
| 219 | |||
| 220 | ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, PMD_SIZE, | ||
| 221 | pcpur_size - static_size, vm.addr, NULL); | ||
| 222 | goto out_free_ar; | ||
| 223 | |||
| 224 | enomem: | ||
| 225 | for_each_possible_cpu(cpu) | ||
| 226 | if (pcpur_ptrs[cpu]) | ||
| 227 | free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE); | ||
| 228 | ret = -ENOMEM; | ||
| 229 | out_free_ar: | ||
| 230 | free_bootmem(__pa(pcpur_ptrs), ptrs_size); | ||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | #else | ||
| 234 | static ssize_t __init setup_pcpu_remap(size_t static_size) | ||
| 235 | { | ||
| 236 | return -EINVAL; | ||
| 237 | } | ||
| 238 | #endif | ||
| 239 | |||
| 240 | /* | ||
| 241 | * Embedding allocator | ||
| 242 | * | ||
| 243 | * The first chunk is sized to just contain the static area plus | ||
| 244 | * PERCPU_DYNAMIC_RESERVE and allocated as a contiguous area using | ||
| 245 | * bootmem allocator and used as-is without being mapped into vmalloc | ||
| 246 | * area. This enables the first chunk to piggy back on the linear | ||
| 247 | * physical PMD mapping and doesn't add any additional pressure to | ||
| 248 | * TLB. | ||
| 249 | */ | ||
| 250 | static void *pcpue_ptr __initdata; | ||
| 251 | static size_t pcpue_unit_size __initdata; | ||
| 252 | |||
| 253 | static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) | ||
| 254 | { | ||
| 255 | return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size | ||
| 256 | + ((size_t)pageno << PAGE_SHIFT)); | ||
| 257 | } | ||
| 258 | |||
| 259 | static ssize_t __init setup_pcpu_embed(size_t static_size) | ||
| 260 | { | ||
| 261 | unsigned int cpu; | ||
| 262 | |||
| 263 | /* | ||
| 264 | * If large page isn't supported, there's no benefit in doing | ||
| 265 | * this. Also, embedding allocation doesn't play well with | ||
| 266 | * NUMA. | ||
| 267 | */ | ||
| 268 | if (!cpu_has_pse || pcpu_need_numa()) | ||
| 269 | return -EINVAL; | ||
| 270 | |||
| 271 | /* allocate and copy */ | ||
| 272 | pcpue_unit_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); | ||
| 273 | pcpue_unit_size = max_t(size_t, pcpue_unit_size, PCPU_MIN_UNIT_SIZE); | ||
| 274 | pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, | ||
| 275 | PAGE_SIZE); | ||
| 276 | if (!pcpue_ptr) | ||
| 277 | return -ENOMEM; | ||
| 278 | |||
| 279 | for_each_possible_cpu(cpu) | ||
| 280 | memcpy(pcpue_ptr + cpu * pcpue_unit_size, __per_cpu_load, | ||
| 281 | static_size); | ||
| 282 | |||
| 283 | /* we're ready, commit */ | ||
| 284 | pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", | ||
| 285 | pcpue_unit_size >> PAGE_SHIFT, pcpue_ptr, static_size); | ||
| 286 | |||
| 287 | return pcpu_setup_first_chunk(pcpue_get_page, static_size, | ||
| 288 | pcpue_unit_size, | ||
| 289 | pcpue_unit_size - static_size, pcpue_ptr, | ||
| 290 | NULL); | ||
| 291 | } | ||
| 292 | |||
| 293 | /* | ||
| 294 | * 4k page allocator | ||
| 295 | * | ||
| 296 | * This is the basic allocator. Static percpu area is allocated | ||
| 297 | * page-by-page and most of initialization is done by the generic | ||
| 298 | * setup function. | ||
| 299 | */ | ||
| 300 | static struct page **pcpu4k_pages __initdata; | ||
| 301 | static int pcpu4k_nr_static_pages __initdata; | ||
| 302 | |||
| 303 | static struct page * __init pcpu4k_get_page(unsigned int cpu, int pageno) | ||
| 304 | { | ||
| 305 | if (pageno < pcpu4k_nr_static_pages) | ||
| 306 | return pcpu4k_pages[cpu * pcpu4k_nr_static_pages + pageno]; | ||
| 307 | return NULL; | ||
| 308 | } | ||
| 309 | |||
| 310 | static void __init pcpu4k_populate_pte(unsigned long addr) | ||
| 311 | { | ||
| 312 | populate_extra_pte(addr); | ||
| 313 | } | ||
| 314 | |||
| 315 | static ssize_t __init setup_pcpu_4k(size_t static_size) | ||
| 316 | { | ||
| 317 | size_t pages_size; | ||
| 318 | unsigned int cpu; | ||
| 319 | int i, j; | ||
| 320 | ssize_t ret; | ||
| 321 | |||
| 322 | pcpu4k_nr_static_pages = PFN_UP(static_size); | ||
| 323 | |||
| 324 | /* unaligned allocations can't be freed, round up to page size */ | ||
| 325 | pages_size = PFN_ALIGN(pcpu4k_nr_static_pages * num_possible_cpus() | ||
| 326 | * sizeof(pcpu4k_pages[0])); | ||
| 327 | pcpu4k_pages = alloc_bootmem(pages_size); | ||
| 328 | |||
| 329 | /* allocate and copy */ | ||
| 330 | j = 0; | ||
| 331 | for_each_possible_cpu(cpu) | ||
| 332 | for (i = 0; i < pcpu4k_nr_static_pages; i++) { | ||
| 333 | void *ptr; | ||
| 334 | |||
| 335 | ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); | ||
| 336 | if (!ptr) | ||
| 337 | goto enomem; | ||
| 338 | |||
| 339 | memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); | ||
| 340 | pcpu4k_pages[j++] = virt_to_page(ptr); | ||
| 341 | } | ||
| 342 | |||
| 343 | /* we're ready, commit */ | ||
| 344 | pr_info("PERCPU: Allocated %d 4k pages, static data %zu bytes\n", | ||
| 345 | pcpu4k_nr_static_pages, static_size); | ||
| 346 | |||
| 347 | ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, 0, 0, NULL, | ||
| 348 | pcpu4k_populate_pte); | ||
| 349 | goto out_free_ar; | ||
| 350 | |||
| 351 | enomem: | ||
| 352 | while (--j >= 0) | ||
| 353 | free_bootmem(__pa(page_address(pcpu4k_pages[j])), PAGE_SIZE); | ||
| 354 | ret = -ENOMEM; | ||
| 355 | out_free_ar: | ||
| 356 | free_bootmem(__pa(pcpu4k_pages), pages_size); | ||
| 357 | return ret; | ||
| 358 | } | ||
| 359 | |||
| 44 | static inline void setup_percpu_segment(int cpu) | 360 | static inline void setup_percpu_segment(int cpu) |
| 45 | { | 361 | { |
| 46 | #ifdef CONFIG_X86_32 | 362 | #ifdef CONFIG_X86_32 |
| @@ -61,38 +377,35 @@ static inline void setup_percpu_segment(int cpu) | |||
| 61 | */ | 377 | */ |
| 62 | void __init setup_per_cpu_areas(void) | 378 | void __init setup_per_cpu_areas(void) |
| 63 | { | 379 | { |
| 64 | ssize_t size; | 380 | size_t static_size = __per_cpu_end - __per_cpu_start; |
| 65 | char *ptr; | 381 | unsigned int cpu; |
| 66 | int cpu; | 382 | unsigned long delta; |
| 67 | 383 | size_t pcpu_unit_size; | |
| 68 | /* Copy section for each CPU (we discard the original) */ | 384 | ssize_t ret; |
| 69 | size = roundup(PERCPU_ENOUGH_ROOM, PAGE_SIZE); | ||
| 70 | 385 | ||
| 71 | pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n", | 386 | pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n", |
| 72 | NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids); | 387 | NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids); |
| 73 | 388 | ||
| 74 | pr_info("PERCPU: Allocating %zd bytes of per cpu data\n", size); | 389 | /* |
| 390 | * Allocate percpu area. If PSE is supported, try to make use | ||
| 391 | * of large page mappings. Please read comments on top of | ||
| 392 | * each allocator for details. | ||
| 393 | */ | ||
| 394 | ret = setup_pcpu_remap(static_size); | ||
| 395 | if (ret < 0) | ||
| 396 | ret = setup_pcpu_embed(static_size); | ||
| 397 | if (ret < 0) | ||
| 398 | ret = setup_pcpu_4k(static_size); | ||
| 399 | if (ret < 0) | ||
| 400 | panic("cannot allocate static percpu area (%zu bytes, err=%zd)", | ||
| 401 | static_size, ret); | ||
| 75 | 402 | ||
| 76 | for_each_possible_cpu(cpu) { | 403 | pcpu_unit_size = ret; |
| 77 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
| 78 | ptr = alloc_bootmem_pages(size); | ||
| 79 | #else | ||
| 80 | int node = early_cpu_to_node(cpu); | ||
| 81 | if (!node_online(node) || !NODE_DATA(node)) { | ||
| 82 | ptr = alloc_bootmem_pages(size); | ||
| 83 | pr_info("cpu %d has no node %d or node-local memory\n", | ||
| 84 | cpu, node); | ||
| 85 | pr_debug("per cpu data for cpu%d at %016lx\n", | ||
| 86 | cpu, __pa(ptr)); | ||
| 87 | } else { | ||
| 88 | ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); | ||
| 89 | pr_debug("per cpu data for cpu%d on node%d at %016lx\n", | ||
| 90 | cpu, node, __pa(ptr)); | ||
| 91 | } | ||
| 92 | #endif | ||
| 93 | 404 | ||
| 94 | memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start); | 405 | /* alrighty, percpu areas up and running */ |
| 95 | per_cpu_offset(cpu) = ptr - __per_cpu_start; | 406 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; |
| 407 | for_each_possible_cpu(cpu) { | ||
| 408 | per_cpu_offset(cpu) = delta + cpu * pcpu_unit_size; | ||
| 96 | per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); | 409 | per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu); |
| 97 | per_cpu(cpu_number, cpu) = cpu; | 410 | per_cpu(cpu_number, cpu) = cpu; |
| 98 | setup_percpu_segment(cpu); | 411 | setup_percpu_segment(cpu); |
| @@ -125,8 +438,6 @@ void __init setup_per_cpu_areas(void) | |||
| 125 | */ | 438 | */ |
| 126 | if (cpu == boot_cpu_id) | 439 | if (cpu == boot_cpu_id) |
| 127 | switch_to_new_gdt(cpu); | 440 | switch_to_new_gdt(cpu); |
| 128 | |||
| 129 | DBG("PERCPU: cpu %4d %p\n", cpu, ptr); | ||
| 130 | } | 441 | } |
| 131 | 442 | ||
| 132 | /* indicate the early static arrays will soon be gone */ | 443 | /* indicate the early static arrays will soon be gone */ |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 7cdcd16885ed..d2cc6428c587 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
| @@ -187,40 +187,35 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, | |||
| 187 | /* | 187 | /* |
| 188 | * Set up a signal frame. | 188 | * Set up a signal frame. |
| 189 | */ | 189 | */ |
| 190 | #ifdef CONFIG_X86_32 | ||
| 191 | static const struct { | ||
| 192 | u16 poplmovl; | ||
| 193 | u32 val; | ||
| 194 | u16 int80; | ||
| 195 | } __attribute__((packed)) retcode = { | ||
| 196 | 0xb858, /* popl %eax; movl $..., %eax */ | ||
| 197 | __NR_sigreturn, | ||
| 198 | 0x80cd, /* int $0x80 */ | ||
| 199 | }; | ||
| 200 | |||
| 201 | static const struct { | ||
| 202 | u8 movl; | ||
| 203 | u32 val; | ||
| 204 | u16 int80; | ||
| 205 | u8 pad; | ||
| 206 | } __attribute__((packed)) rt_retcode = { | ||
| 207 | 0xb8, /* movl $..., %eax */ | ||
| 208 | __NR_rt_sigreturn, | ||
| 209 | 0x80cd, /* int $0x80 */ | ||
| 210 | 0 | ||
| 211 | }; | ||
| 212 | 190 | ||
| 213 | /* | 191 | /* |
| 214 | * Determine which stack to use.. | 192 | * Determine which stack to use.. |
| 215 | */ | 193 | */ |
| 194 | static unsigned long align_sigframe(unsigned long sp) | ||
| 195 | { | ||
| 196 | #ifdef CONFIG_X86_32 | ||
| 197 | /* | ||
| 198 | * Align the stack pointer according to the i386 ABI, | ||
| 199 | * i.e. so that on function entry ((sp + 4) & 15) == 0. | ||
| 200 | */ | ||
| 201 | sp = ((sp + 4) & -16ul) - 4; | ||
| 202 | #else /* !CONFIG_X86_32 */ | ||
| 203 | sp = round_down(sp, 16) - 8; | ||
| 204 | #endif | ||
| 205 | return sp; | ||
| 206 | } | ||
| 207 | |||
| 216 | static inline void __user * | 208 | static inline void __user * |
| 217 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | 209 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, |
| 218 | void **fpstate) | 210 | void __user **fpstate) |
| 219 | { | 211 | { |
| 220 | unsigned long sp; | ||
| 221 | |||
| 222 | /* Default to using normal stack */ | 212 | /* Default to using normal stack */ |
| 223 | sp = regs->sp; | 213 | unsigned long sp = regs->sp; |
| 214 | |||
| 215 | #ifdef CONFIG_X86_64 | ||
| 216 | /* redzone */ | ||
| 217 | sp -= 128; | ||
| 218 | #endif /* CONFIG_X86_64 */ | ||
| 224 | 219 | ||
| 225 | /* | 220 | /* |
| 226 | * If we are on the alternate signal stack and would overflow it, don't. | 221 | * If we are on the alternate signal stack and would overflow it, don't. |
| @@ -234,30 +229,52 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
| 234 | if (sas_ss_flags(sp) == 0) | 229 | if (sas_ss_flags(sp) == 0) |
| 235 | sp = current->sas_ss_sp + current->sas_ss_size; | 230 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 236 | } else { | 231 | } else { |
| 232 | #ifdef CONFIG_X86_32 | ||
| 237 | /* This is the legacy signal stack switching. */ | 233 | /* This is the legacy signal stack switching. */ |
| 238 | if ((regs->ss & 0xffff) != __USER_DS && | 234 | if ((regs->ss & 0xffff) != __USER_DS && |
| 239 | !(ka->sa.sa_flags & SA_RESTORER) && | 235 | !(ka->sa.sa_flags & SA_RESTORER) && |
| 240 | ka->sa.sa_restorer) | 236 | ka->sa.sa_restorer) |
| 241 | sp = (unsigned long) ka->sa.sa_restorer; | 237 | sp = (unsigned long) ka->sa.sa_restorer; |
| 238 | #endif /* CONFIG_X86_32 */ | ||
| 242 | } | 239 | } |
| 243 | 240 | ||
| 244 | if (used_math()) { | 241 | if (used_math()) { |
| 245 | sp = sp - sig_xstate_size; | 242 | sp -= sig_xstate_size; |
| 246 | *fpstate = (struct _fpstate *) sp; | 243 | #ifdef CONFIG_X86_64 |
| 244 | sp = round_down(sp, 64); | ||
| 245 | #endif /* CONFIG_X86_64 */ | ||
| 246 | *fpstate = (void __user *)sp; | ||
| 247 | |||
| 247 | if (save_i387_xstate(*fpstate) < 0) | 248 | if (save_i387_xstate(*fpstate) < 0) |
| 248 | return (void __user *)-1L; | 249 | return (void __user *)-1L; |
| 249 | } | 250 | } |
| 250 | 251 | ||
| 251 | sp -= frame_size; | 252 | return (void __user *)align_sigframe(sp - frame_size); |
| 252 | /* | ||
| 253 | * Align the stack pointer according to the i386 ABI, | ||
| 254 | * i.e. so that on function entry ((sp + 4) & 15) == 0. | ||
| 255 | */ | ||
| 256 | sp = ((sp + 4) & -16ul) - 4; | ||
| 257 | |||
| 258 | return (void __user *) sp; | ||
| 259 | } | 253 | } |
| 260 | 254 | ||
| 255 | #ifdef CONFIG_X86_32 | ||
| 256 | static const struct { | ||
| 257 | u16 poplmovl; | ||
| 258 | u32 val; | ||
| 259 | u16 int80; | ||
| 260 | } __attribute__((packed)) retcode = { | ||
| 261 | 0xb858, /* popl %eax; movl $..., %eax */ | ||
| 262 | __NR_sigreturn, | ||
| 263 | 0x80cd, /* int $0x80 */ | ||
| 264 | }; | ||
| 265 | |||
| 266 | static const struct { | ||
| 267 | u8 movl; | ||
| 268 | u32 val; | ||
| 269 | u16 int80; | ||
| 270 | u8 pad; | ||
| 271 | } __attribute__((packed)) rt_retcode = { | ||
| 272 | 0xb8, /* movl $..., %eax */ | ||
| 273 | __NR_rt_sigreturn, | ||
| 274 | 0x80cd, /* int $0x80 */ | ||
| 275 | 0 | ||
| 276 | }; | ||
| 277 | |||
| 261 | static int | 278 | static int |
| 262 | __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 279 | __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
| 263 | struct pt_regs *regs) | 280 | struct pt_regs *regs) |
| @@ -388,24 +405,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 388 | return 0; | 405 | return 0; |
| 389 | } | 406 | } |
| 390 | #else /* !CONFIG_X86_32 */ | 407 | #else /* !CONFIG_X86_32 */ |
| 391 | /* | ||
| 392 | * Determine which stack to use.. | ||
| 393 | */ | ||
| 394 | static void __user * | ||
| 395 | get_stack(struct k_sigaction *ka, unsigned long sp, unsigned long size) | ||
| 396 | { | ||
| 397 | /* Default to using normal stack - redzone*/ | ||
| 398 | sp -= 128; | ||
| 399 | |||
| 400 | /* This is the X/Open sanctioned signal stack switching. */ | ||
| 401 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
| 402 | if (sas_ss_flags(sp) == 0) | ||
| 403 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
| 404 | } | ||
| 405 | |||
| 406 | return (void __user *)round_down(sp - size, 64); | ||
| 407 | } | ||
| 408 | |||
| 409 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 408 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 410 | sigset_t *set, struct pt_regs *regs) | 409 | sigset_t *set, struct pt_regs *regs) |
| 411 | { | 410 | { |
| @@ -414,15 +413,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 414 | int err = 0; | 413 | int err = 0; |
| 415 | struct task_struct *me = current; | 414 | struct task_struct *me = current; |
| 416 | 415 | ||
| 417 | if (used_math()) { | 416 | frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe), &fp); |
| 418 | fp = get_stack(ka, regs->sp, sig_xstate_size); | ||
| 419 | frame = (void __user *)round_down( | ||
| 420 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | ||
| 421 | |||
| 422 | if (save_i387_xstate(fp) < 0) | ||
| 423 | return -EFAULT; | ||
| 424 | } else | ||
| 425 | frame = get_stack(ka, regs->sp, sizeof(struct rt_sigframe)) - 8; | ||
| 426 | 417 | ||
| 427 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 418 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
| 428 | return -EFAULT; | 419 | return -EFAULT; |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 9ce666387f37..249334f5080a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -112,7 +112,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); | |||
| 112 | DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); | 112 | DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); |
| 113 | EXPORT_PER_CPU_SYMBOL(cpu_info); | 113 | EXPORT_PER_CPU_SYMBOL(cpu_info); |
| 114 | 114 | ||
| 115 | static atomic_t init_deasserted; | 115 | atomic_t init_deasserted; |
| 116 | 116 | ||
| 117 | 117 | ||
| 118 | /* Set if we find a B stepping CPU */ | 118 | /* Set if we find a B stepping CPU */ |
| @@ -614,12 +614,6 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) | |||
| 614 | unsigned long send_status, accept_status = 0; | 614 | unsigned long send_status, accept_status = 0; |
| 615 | int maxlvt, num_starts, j; | 615 | int maxlvt, num_starts, j; |
| 616 | 616 | ||
| 617 | if (get_uv_system_type() == UV_NON_UNIQUE_APIC) { | ||
| 618 | send_status = uv_wakeup_secondary(phys_apicid, start_eip); | ||
| 619 | atomic_set(&init_deasserted, 1); | ||
| 620 | return send_status; | ||
| 621 | } | ||
| 622 | |||
| 623 | maxlvt = lapic_get_maxlvt(); | 617 | maxlvt = lapic_get_maxlvt(); |
| 624 | 618 | ||
| 625 | /* | 619 | /* |
| @@ -748,7 +742,8 @@ static void __cpuinit do_fork_idle(struct work_struct *work) | |||
| 748 | /* | 742 | /* |
| 749 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad | 743 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad |
| 750 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. | 744 | * (ie clustered apic addressing mode), this is a LOGICAL apic ID. |
| 751 | * Returns zero if CPU booted OK, else error code from ->wakeup_cpu. | 745 | * Returns zero if CPU booted OK, else error code from |
| 746 | * ->wakeup_secondary_cpu. | ||
| 752 | */ | 747 | */ |
| 753 | static int __cpuinit do_boot_cpu(int apicid, int cpu) | 748 | static int __cpuinit do_boot_cpu(int apicid, int cpu) |
| 754 | { | 749 | { |
| @@ -835,9 +830,13 @@ do_rest: | |||
| 835 | } | 830 | } |
| 836 | 831 | ||
| 837 | /* | 832 | /* |
| 838 | * Starting actual IPI sequence... | 833 | * Kick the secondary CPU. Use the method in the APIC driver |
| 834 | * if it's defined - or use an INIT boot APIC message otherwise: | ||
| 839 | */ | 835 | */ |
| 840 | boot_error = apic->wakeup_cpu(apicid, start_ip); | 836 | if (apic->wakeup_secondary_cpu) |
| 837 | boot_error = apic->wakeup_secondary_cpu(apicid, start_ip); | ||
| 838 | else | ||
| 839 | boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip); | ||
| 841 | 840 | ||
| 842 | if (!boot_error) { | 841 | if (!boot_error) { |
| 843 | /* | 842 | /* |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index c05430ac1b44..a1d288327ff0 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -118,47 +118,6 @@ die_if_kernel(const char *str, struct pt_regs *regs, long err) | |||
| 118 | if (!user_mode_vm(regs)) | 118 | if (!user_mode_vm(regs)) |
| 119 | die(str, regs, err); | 119 | die(str, regs, err); |
| 120 | } | 120 | } |
| 121 | |||
| 122 | /* | ||
| 123 | * Perform the lazy TSS's I/O bitmap copy. If the TSS has an | ||
| 124 | * invalid offset set (the LAZY one) and the faulting thread has | ||
| 125 | * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS, | ||
| 126 | * we set the offset field correctly and return 1. | ||
| 127 | */ | ||
| 128 | static int lazy_iobitmap_copy(void) | ||
| 129 | { | ||
| 130 | struct thread_struct *thread; | ||
| 131 | struct tss_struct *tss; | ||
| 132 | int cpu; | ||
| 133 | |||
| 134 | cpu = get_cpu(); | ||
| 135 | tss = &per_cpu(init_tss, cpu); | ||
| 136 | thread = ¤t->thread; | ||
| 137 | |||
| 138 | if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && | ||
| 139 | thread->io_bitmap_ptr) { | ||
| 140 | memcpy(tss->io_bitmap, thread->io_bitmap_ptr, | ||
| 141 | thread->io_bitmap_max); | ||
| 142 | /* | ||
| 143 | * If the previously set map was extending to higher ports | ||
| 144 | * than the current one, pad extra space with 0xff (no access). | ||
| 145 | */ | ||
| 146 | if (thread->io_bitmap_max < tss->io_bitmap_max) { | ||
| 147 | memset((char *) tss->io_bitmap + | ||
| 148 | thread->io_bitmap_max, 0xff, | ||
| 149 | tss->io_bitmap_max - thread->io_bitmap_max); | ||
| 150 | } | ||
| 151 | tss->io_bitmap_max = thread->io_bitmap_max; | ||
| 152 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; | ||
| 153 | tss->io_bitmap_owner = thread; | ||
| 154 | put_cpu(); | ||
| 155 | |||
| 156 | return 1; | ||
| 157 | } | ||
| 158 | put_cpu(); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | #endif | 121 | #endif |
| 163 | 122 | ||
| 164 | static void __kprobes | 123 | static void __kprobes |
| @@ -309,11 +268,6 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
| 309 | conditional_sti(regs); | 268 | conditional_sti(regs); |
| 310 | 269 | ||
| 311 | #ifdef CONFIG_X86_32 | 270 | #ifdef CONFIG_X86_32 |
| 312 | if (lazy_iobitmap_copy()) { | ||
| 313 | /* restart the faulting instruction */ | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | |||
| 317 | if (regs->flags & X86_VM_MASK) | 271 | if (regs->flags & X86_VM_MASK) |
| 318 | goto gp_in_vm86; | 272 | goto gp_in_vm86; |
| 319 | #endif | 273 | #endif |
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index c609205df594..74de562812cc 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <asm/paravirt.h> | 22 | #include <asm/paravirt.h> |
| 23 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
| 24 | 24 | ||
| 25 | #if defined CONFIG_PCI && defined CONFIG_PARAVIRT | 25 | #ifdef CONFIG_PARAVIRT |
| 26 | /* | 26 | /* |
| 27 | * Interrupt control on vSMPowered systems: | 27 | * Interrupt control on vSMPowered systems: |
| 28 | * ~AC is a shadow of IF. If IF is 'on' AC should be 'off' | 28 | * ~AC is a shadow of IF. If IF is 'on' AC should be 'off' |
| @@ -114,7 +114,6 @@ static void __init set_vsmp_pv_ops(void) | |||
| 114 | } | 114 | } |
| 115 | #endif | 115 | #endif |
| 116 | 116 | ||
| 117 | #ifdef CONFIG_PCI | ||
| 118 | static int is_vsmp = -1; | 117 | static int is_vsmp = -1; |
| 119 | 118 | ||
| 120 | static void __init detect_vsmp_box(void) | 119 | static void __init detect_vsmp_box(void) |
| @@ -139,15 +138,6 @@ int is_vsmp_box(void) | |||
| 139 | return 0; | 138 | return 0; |
| 140 | } | 139 | } |
| 141 | } | 140 | } |
| 142 | #else | ||
| 143 | static void __init detect_vsmp_box(void) | ||
| 144 | { | ||
| 145 | } | ||
| 146 | int is_vsmp_box(void) | ||
| 147 | { | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | #endif | ||
| 151 | 141 | ||
| 152 | void __init vsmp_init(void) | 142 | void __init vsmp_init(void) |
| 153 | { | 143 | { |
diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c index 491e737ce547..aa0987088774 100644 --- a/arch/x86/math-emu/fpu_aux.c +++ b/arch/x86/math-emu/fpu_aux.c | |||
| @@ -30,20 +30,29 @@ static void fclex(void) | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | /* Needs to be externally visible */ | 32 | /* Needs to be externally visible */ |
| 33 | void finit(void) | 33 | void finit_task(struct task_struct *tsk) |
| 34 | { | 34 | { |
| 35 | control_word = 0x037f; | 35 | struct i387_soft_struct *soft = &tsk->thread.xstate->soft; |
| 36 | partial_status = 0; | 36 | struct address *oaddr, *iaddr; |
| 37 | top = 0; /* We don't keep top in the status word internally. */ | 37 | soft->cwd = 0x037f; |
| 38 | fpu_tag_word = 0xffff; | 38 | soft->swd = 0; |
| 39 | soft->ftop = 0; /* We don't keep top in the status word internally. */ | ||
| 40 | soft->twd = 0xffff; | ||
| 39 | /* The behaviour is different from that detailed in | 41 | /* The behaviour is different from that detailed in |
| 40 | Section 15.1.6 of the Intel manual */ | 42 | Section 15.1.6 of the Intel manual */ |
| 41 | operand_address.offset = 0; | 43 | oaddr = (struct address *)&soft->foo; |
| 42 | operand_address.selector = 0; | 44 | oaddr->offset = 0; |
| 43 | instruction_address.offset = 0; | 45 | oaddr->selector = 0; |
| 44 | instruction_address.selector = 0; | 46 | iaddr = (struct address *)&soft->fip; |
| 45 | instruction_address.opcode = 0; | 47 | iaddr->offset = 0; |
| 46 | no_ip_update = 1; | 48 | iaddr->selector = 0; |
| 49 | iaddr->opcode = 0; | ||
| 50 | soft->no_update = 1; | ||
| 51 | } | ||
| 52 | |||
| 53 | void finit(void) | ||
| 54 | { | ||
| 55 | finit_task(current); | ||
| 47 | } | 56 | } |
| 48 | 57 | ||
| 49 | /* | 58 | /* |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 2b938a384910..08537747cb58 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | obj-y := init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ | 1 | obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \ |
| 2 | pat.o pgtable.o gup.o | 2 | pat.o pgtable.o gup.o |
| 3 | 3 | ||
| 4 | obj-$(CONFIG_SMP) += tlb.o | 4 | obj-$(CONFIG_SMP) += tlb.o |
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index bcc079c282dd..00f127c80b0e 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include <linux/highmem.h> | 1 | #include <linux/highmem.h> |
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/swap.h> /* for totalram_pages */ | ||
| 3 | 4 | ||
| 4 | void *kmap(struct page *page) | 5 | void *kmap(struct page *page) |
| 5 | { | 6 | { |
| @@ -156,3 +157,36 @@ EXPORT_SYMBOL(kmap); | |||
| 156 | EXPORT_SYMBOL(kunmap); | 157 | EXPORT_SYMBOL(kunmap); |
| 157 | EXPORT_SYMBOL(kmap_atomic); | 158 | EXPORT_SYMBOL(kmap_atomic); |
| 158 | EXPORT_SYMBOL(kunmap_atomic); | 159 | EXPORT_SYMBOL(kunmap_atomic); |
| 160 | |||
| 161 | #ifdef CONFIG_NUMA | ||
| 162 | void __init set_highmem_pages_init(void) | ||
| 163 | { | ||
| 164 | struct zone *zone; | ||
| 165 | int nid; | ||
| 166 | |||
| 167 | for_each_zone(zone) { | ||
| 168 | unsigned long zone_start_pfn, zone_end_pfn; | ||
| 169 | |||
| 170 | if (!is_highmem(zone)) | ||
| 171 | continue; | ||
| 172 | |||
| 173 | zone_start_pfn = zone->zone_start_pfn; | ||
| 174 | zone_end_pfn = zone_start_pfn + zone->spanned_pages; | ||
| 175 | |||
| 176 | nid = zone_to_nid(zone); | ||
| 177 | printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n", | ||
| 178 | zone->name, nid, zone_start_pfn, zone_end_pfn); | ||
| 179 | |||
| 180 | add_highpages_with_active_regions(nid, zone_start_pfn, | ||
| 181 | zone_end_pfn); | ||
| 182 | } | ||
| 183 | totalram_pages += totalhigh_pages; | ||
| 184 | } | ||
| 185 | #else | ||
| 186 | void __init set_highmem_pages_init(void) | ||
| 187 | { | ||
| 188 | add_highpages_with_active_regions(0, highstart_pfn, highend_pfn); | ||
| 189 | |||
| 190 | totalram_pages += totalhigh_pages; | ||
| 191 | } | ||
| 192 | #endif /* CONFIG_NUMA */ | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c new file mode 100644 index 000000000000..ce6a722587d8 --- /dev/null +++ b/arch/x86/mm/init.c | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | #include <linux/swap.h> | ||
| 2 | #include <asm/cacheflush.h> | ||
| 3 | #include <asm/page.h> | ||
| 4 | #include <asm/sections.h> | ||
| 5 | #include <asm/system.h> | ||
| 6 | |||
| 7 | void free_init_pages(char *what, unsigned long begin, unsigned long end) | ||
| 8 | { | ||
| 9 | unsigned long addr = begin; | ||
| 10 | |||
| 11 | if (addr >= end) | ||
| 12 | return; | ||
| 13 | |||
| 14 | /* | ||
| 15 | * If debugging page accesses then do not free this memory but | ||
| 16 | * mark them not present - any buggy init-section access will | ||
| 17 | * create a kernel page fault: | ||
| 18 | */ | ||
| 19 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
| 20 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", | ||
| 21 | begin, PAGE_ALIGN(end)); | ||
| 22 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); | ||
| 23 | #else | ||
| 24 | /* | ||
| 25 | * We just marked the kernel text read only above, now that | ||
| 26 | * we are going to free part of that, we need to make that | ||
| 27 | * writeable first. | ||
| 28 | */ | ||
| 29 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); | ||
| 30 | |||
| 31 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); | ||
| 32 | |||
| 33 | for (; addr < end; addr += PAGE_SIZE) { | ||
| 34 | ClearPageReserved(virt_to_page(addr)); | ||
| 35 | init_page_count(virt_to_page(addr)); | ||
| 36 | memset((void *)(addr & ~(PAGE_SIZE-1)), | ||
| 37 | POISON_FREE_INITMEM, PAGE_SIZE); | ||
| 38 | free_page(addr); | ||
| 39 | totalram_pages++; | ||
| 40 | } | ||
| 41 | #endif | ||
| 42 | } | ||
| 43 | |||
| 44 | void free_initmem(void) | ||
| 45 | { | ||
| 46 | free_init_pages("unused kernel memory", | ||
| 47 | (unsigned long)(&__init_begin), | ||
| 48 | (unsigned long)(&__init_end)); | ||
| 49 | } | ||
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 06708ee94aa4..47df0e1bbeb9 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
| @@ -50,8 +50,6 @@ | |||
| 50 | #include <asm/setup.h> | 50 | #include <asm/setup.h> |
| 51 | #include <asm/cacheflush.h> | 51 | #include <asm/cacheflush.h> |
| 52 | 52 | ||
| 53 | unsigned int __VMALLOC_RESERVE = 128 << 20; | ||
| 54 | |||
| 55 | unsigned long max_low_pfn_mapped; | 53 | unsigned long max_low_pfn_mapped; |
| 56 | unsigned long max_pfn_mapped; | 54 | unsigned long max_pfn_mapped; |
| 57 | 55 | ||
| @@ -137,6 +135,23 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) | |||
| 137 | return pte_offset_kernel(pmd, 0); | 135 | return pte_offset_kernel(pmd, 0); |
| 138 | } | 136 | } |
| 139 | 137 | ||
| 138 | pmd_t * __init populate_extra_pmd(unsigned long vaddr) | ||
| 139 | { | ||
| 140 | int pgd_idx = pgd_index(vaddr); | ||
| 141 | int pmd_idx = pmd_index(vaddr); | ||
| 142 | |||
| 143 | return one_md_table_init(swapper_pg_dir + pgd_idx) + pmd_idx; | ||
| 144 | } | ||
| 145 | |||
| 146 | pte_t * __init populate_extra_pte(unsigned long vaddr) | ||
| 147 | { | ||
| 148 | int pte_idx = pte_index(vaddr); | ||
| 149 | pmd_t *pmd; | ||
| 150 | |||
| 151 | pmd = populate_extra_pmd(vaddr); | ||
| 152 | return one_page_table_init(pmd) + pte_idx; | ||
| 153 | } | ||
| 154 | |||
| 140 | static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd, | 155 | static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd, |
| 141 | unsigned long vaddr, pte_t *lastpte) | 156 | unsigned long vaddr, pte_t *lastpte) |
| 142 | { | 157 | { |
| @@ -469,22 +484,10 @@ void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn, | |||
| 469 | work_with_active_regions(nid, add_highpages_work_fn, &data); | 484 | work_with_active_regions(nid, add_highpages_work_fn, &data); |
| 470 | } | 485 | } |
| 471 | 486 | ||
| 472 | #ifndef CONFIG_NUMA | ||
| 473 | static void __init set_highmem_pages_init(void) | ||
| 474 | { | ||
| 475 | add_highpages_with_active_regions(0, highstart_pfn, highend_pfn); | ||
| 476 | |||
| 477 | totalram_pages += totalhigh_pages; | ||
| 478 | } | ||
| 479 | #endif /* !CONFIG_NUMA */ | ||
| 480 | |||
| 481 | #else | 487 | #else |
| 482 | static inline void permanent_kmaps_init(pgd_t *pgd_base) | 488 | static inline void permanent_kmaps_init(pgd_t *pgd_base) |
| 483 | { | 489 | { |
| 484 | } | 490 | } |
| 485 | static inline void set_highmem_pages_init(void) | ||
| 486 | { | ||
| 487 | } | ||
| 488 | #endif /* CONFIG_HIGHMEM */ | 491 | #endif /* CONFIG_HIGHMEM */ |
| 489 | 492 | ||
| 490 | void __init native_pagetable_setup_start(pgd_t *base) | 493 | void __init native_pagetable_setup_start(pgd_t *base) |
| @@ -847,10 +850,10 @@ static void __init find_early_table_space(unsigned long end, int use_pse) | |||
| 847 | unsigned long puds, pmds, ptes, tables, start; | 850 | unsigned long puds, pmds, ptes, tables, start; |
| 848 | 851 | ||
| 849 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | 852 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; |
| 850 | tables = PAGE_ALIGN(puds * sizeof(pud_t)); | 853 | tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); |
| 851 | 854 | ||
| 852 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; | 855 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; |
| 853 | tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); | 856 | tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); |
| 854 | 857 | ||
| 855 | if (use_pse) { | 858 | if (use_pse) { |
| 856 | unsigned long extra; | 859 | unsigned long extra; |
| @@ -861,10 +864,10 @@ static void __init find_early_table_space(unsigned long end, int use_pse) | |||
| 861 | } else | 864 | } else |
| 862 | ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; | 865 | ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 863 | 866 | ||
| 864 | tables += PAGE_ALIGN(ptes * sizeof(pte_t)); | 867 | tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); |
| 865 | 868 | ||
| 866 | /* for fixmap */ | 869 | /* for fixmap */ |
| 867 | tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t)); | 870 | tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE); |
| 868 | 871 | ||
| 869 | /* | 872 | /* |
| 870 | * RED-PEN putting page tables only on node 0 could | 873 | * RED-PEN putting page tables only on node 0 could |
| @@ -1214,45 +1217,6 @@ void mark_rodata_ro(void) | |||
| 1214 | } | 1217 | } |
| 1215 | #endif | 1218 | #endif |
| 1216 | 1219 | ||
| 1217 | void free_init_pages(char *what, unsigned long begin, unsigned long end) | ||
| 1218 | { | ||
| 1219 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
| 1220 | /* | ||
| 1221 | * If debugging page accesses then do not free this memory but | ||
| 1222 | * mark them not present - any buggy init-section access will | ||
| 1223 | * create a kernel page fault: | ||
| 1224 | */ | ||
| 1225 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", | ||
| 1226 | begin, PAGE_ALIGN(end)); | ||
| 1227 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); | ||
| 1228 | #else | ||
| 1229 | unsigned long addr; | ||
| 1230 | |||
| 1231 | /* | ||
| 1232 | * We just marked the kernel text read only above, now that | ||
| 1233 | * we are going to free part of that, we need to make that | ||
| 1234 | * writeable first. | ||
| 1235 | */ | ||
| 1236 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); | ||
| 1237 | |||
| 1238 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
| 1239 | ClearPageReserved(virt_to_page(addr)); | ||
| 1240 | init_page_count(virt_to_page(addr)); | ||
| 1241 | memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); | ||
| 1242 | free_page(addr); | ||
| 1243 | totalram_pages++; | ||
| 1244 | } | ||
| 1245 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); | ||
| 1246 | #endif | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | void free_initmem(void) | ||
| 1250 | { | ||
| 1251 | free_init_pages("unused kernel memory", | ||
| 1252 | (unsigned long)(&__init_begin), | ||
| 1253 | (unsigned long)(&__init_end)); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | #ifdef CONFIG_BLK_DEV_INITRD | 1220 | #ifdef CONFIG_BLK_DEV_INITRD |
| 1257 | void free_initrd_mem(unsigned long start, unsigned long end) | 1221 | void free_initrd_mem(unsigned long start, unsigned long end) |
| 1258 | { | 1222 | { |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index e6d36b490250..07f44d491df1 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
| @@ -168,34 +168,51 @@ static __ref void *spp_getpage(void) | |||
| 168 | return ptr; | 168 | return ptr; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | void | 171 | static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) |
| 172 | set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | ||
| 173 | { | 172 | { |
| 174 | pud_t *pud; | 173 | if (pgd_none(*pgd)) { |
| 175 | pmd_t *pmd; | 174 | pud_t *pud = (pud_t *)spp_getpage(); |
| 176 | pte_t *pte; | 175 | pgd_populate(&init_mm, pgd, pud); |
| 176 | if (pud != pud_offset(pgd, 0)) | ||
| 177 | printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", | ||
| 178 | pud, pud_offset(pgd, 0)); | ||
| 179 | } | ||
| 180 | return pud_offset(pgd, vaddr); | ||
| 181 | } | ||
| 177 | 182 | ||
| 178 | pud = pud_page + pud_index(vaddr); | 183 | static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) |
| 184 | { | ||
| 179 | if (pud_none(*pud)) { | 185 | if (pud_none(*pud)) { |
| 180 | pmd = (pmd_t *) spp_getpage(); | 186 | pmd_t *pmd = (pmd_t *) spp_getpage(); |
| 181 | pud_populate(&init_mm, pud, pmd); | 187 | pud_populate(&init_mm, pud, pmd); |
| 182 | if (pmd != pmd_offset(pud, 0)) { | 188 | if (pmd != pmd_offset(pud, 0)) |
| 183 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", | 189 | printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", |
| 184 | pmd, pmd_offset(pud, 0)); | 190 | pmd, pmd_offset(pud, 0)); |
| 185 | return; | ||
| 186 | } | ||
| 187 | } | 191 | } |
| 188 | pmd = pmd_offset(pud, vaddr); | 192 | return pmd_offset(pud, vaddr); |
| 193 | } | ||
| 194 | |||
| 195 | static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr) | ||
| 196 | { | ||
| 189 | if (pmd_none(*pmd)) { | 197 | if (pmd_none(*pmd)) { |
| 190 | pte = (pte_t *) spp_getpage(); | 198 | pte_t *pte = (pte_t *) spp_getpage(); |
| 191 | pmd_populate_kernel(&init_mm, pmd, pte); | 199 | pmd_populate_kernel(&init_mm, pmd, pte); |
| 192 | if (pte != pte_offset_kernel(pmd, 0)) { | 200 | if (pte != pte_offset_kernel(pmd, 0)) |
| 193 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); | 201 | printk(KERN_ERR "PAGETABLE BUG #02!\n"); |
| 194 | return; | ||
| 195 | } | ||
| 196 | } | 202 | } |
| 203 | return pte_offset_kernel(pmd, vaddr); | ||
| 204 | } | ||
| 205 | |||
| 206 | void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | ||
| 207 | { | ||
| 208 | pud_t *pud; | ||
| 209 | pmd_t *pmd; | ||
| 210 | pte_t *pte; | ||
| 211 | |||
| 212 | pud = pud_page + pud_index(vaddr); | ||
| 213 | pmd = fill_pmd(pud, vaddr); | ||
| 214 | pte = fill_pte(pmd, vaddr); | ||
| 197 | 215 | ||
| 198 | pte = pte_offset_kernel(pmd, vaddr); | ||
| 199 | set_pte(pte, new_pte); | 216 | set_pte(pte, new_pte); |
| 200 | 217 | ||
| 201 | /* | 218 | /* |
| @@ -205,8 +222,7 @@ set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | |||
| 205 | __flush_tlb_one(vaddr); | 222 | __flush_tlb_one(vaddr); |
| 206 | } | 223 | } |
| 207 | 224 | ||
| 208 | void | 225 | void set_pte_vaddr(unsigned long vaddr, pte_t pteval) |
| 209 | set_pte_vaddr(unsigned long vaddr, pte_t pteval) | ||
| 210 | { | 226 | { |
| 211 | pgd_t *pgd; | 227 | pgd_t *pgd; |
| 212 | pud_t *pud_page; | 228 | pud_t *pud_page; |
| @@ -223,6 +239,24 @@ set_pte_vaddr(unsigned long vaddr, pte_t pteval) | |||
| 223 | set_pte_vaddr_pud(pud_page, vaddr, pteval); | 239 | set_pte_vaddr_pud(pud_page, vaddr, pteval); |
| 224 | } | 240 | } |
| 225 | 241 | ||
| 242 | pmd_t * __init populate_extra_pmd(unsigned long vaddr) | ||
| 243 | { | ||
| 244 | pgd_t *pgd; | ||
| 245 | pud_t *pud; | ||
| 246 | |||
| 247 | pgd = pgd_offset_k(vaddr); | ||
| 248 | pud = fill_pud(pgd, vaddr); | ||
| 249 | return fill_pmd(pud, vaddr); | ||
| 250 | } | ||
| 251 | |||
| 252 | pte_t * __init populate_extra_pte(unsigned long vaddr) | ||
| 253 | { | ||
| 254 | pmd_t *pmd; | ||
| 255 | |||
| 256 | pmd = populate_extra_pmd(vaddr); | ||
| 257 | return fill_pte(pmd, vaddr); | ||
| 258 | } | ||
| 259 | |||
| 226 | /* | 260 | /* |
| 227 | * Create large page table mappings for a range of physical addresses. | 261 | * Create large page table mappings for a range of physical addresses. |
| 228 | */ | 262 | */ |
| @@ -714,6 +748,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
| 714 | pos = start_pfn << PAGE_SHIFT; | 748 | pos = start_pfn << PAGE_SHIFT; |
| 715 | end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT) | 749 | end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT) |
| 716 | << (PMD_SHIFT - PAGE_SHIFT); | 750 | << (PMD_SHIFT - PAGE_SHIFT); |
| 751 | if (end_pfn > (end >> PAGE_SHIFT)) | ||
| 752 | end_pfn = end >> PAGE_SHIFT; | ||
| 717 | if (start_pfn < end_pfn) { | 753 | if (start_pfn < end_pfn) { |
| 718 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); | 754 | nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0); |
| 719 | pos = end_pfn << PAGE_SHIFT; | 755 | pos = end_pfn << PAGE_SHIFT; |
| @@ -945,43 +981,6 @@ void __init mem_init(void) | |||
| 945 | initsize >> 10); | 981 | initsize >> 10); |
| 946 | } | 982 | } |
| 947 | 983 | ||
| 948 | void free_init_pages(char *what, unsigned long begin, unsigned long end) | ||
| 949 | { | ||
| 950 | unsigned long addr = begin; | ||
| 951 | |||
| 952 | if (addr >= end) | ||
| 953 | return; | ||
| 954 | |||
| 955 | /* | ||
| 956 | * If debugging page accesses then do not free this memory but | ||
| 957 | * mark them not present - any buggy init-section access will | ||
| 958 | * create a kernel page fault: | ||
| 959 | */ | ||
| 960 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
| 961 | printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", | ||
| 962 | begin, PAGE_ALIGN(end)); | ||
| 963 | set_memory_np(begin, (end - begin) >> PAGE_SHIFT); | ||
| 964 | #else | ||
| 965 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); | ||
| 966 | |||
| 967 | for (; addr < end; addr += PAGE_SIZE) { | ||
| 968 | ClearPageReserved(virt_to_page(addr)); | ||
| 969 | init_page_count(virt_to_page(addr)); | ||
| 970 | memset((void *)(addr & ~(PAGE_SIZE-1)), | ||
| 971 | POISON_FREE_INITMEM, PAGE_SIZE); | ||
| 972 | free_page(addr); | ||
| 973 | totalram_pages++; | ||
| 974 | } | ||
| 975 | #endif | ||
| 976 | } | ||
| 977 | |||
| 978 | void free_initmem(void) | ||
| 979 | { | ||
| 980 | free_init_pages("unused kernel memory", | ||
| 981 | (unsigned long)(&__init_begin), | ||
| 982 | (unsigned long)(&__init_end)); | ||
| 983 | } | ||
| 984 | |||
| 985 | #ifdef CONFIG_DEBUG_RODATA | 984 | #ifdef CONFIG_DEBUG_RODATA |
| 986 | const int rodata_test_data = 0xC3; | 985 | const int rodata_test_data = 0xC3; |
| 987 | EXPORT_SYMBOL_GPL(rodata_test_data); | 986 | EXPORT_SYMBOL_GPL(rodata_test_data); |
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 93d82038af4b..9f205030d9aa 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c | |||
| @@ -32,11 +32,14 @@ struct kmmio_fault_page { | |||
| 32 | struct list_head list; | 32 | struct list_head list; |
| 33 | struct kmmio_fault_page *release_next; | 33 | struct kmmio_fault_page *release_next; |
| 34 | unsigned long page; /* location of the fault page */ | 34 | unsigned long page; /* location of the fault page */ |
| 35 | bool old_presence; /* page presence prior to arming */ | ||
| 36 | bool armed; | ||
| 35 | 37 | ||
| 36 | /* | 38 | /* |
| 37 | * Number of times this page has been registered as a part | 39 | * Number of times this page has been registered as a part |
| 38 | * of a probe. If zero, page is disarmed and this may be freed. | 40 | * of a probe. If zero, page is disarmed and this may be freed. |
| 39 | * Used only by writers (RCU). | 41 | * Used only by writers (RCU) and post_kmmio_handler(). |
| 42 | * Protected by kmmio_lock, when linked into kmmio_page_table. | ||
| 40 | */ | 43 | */ |
| 41 | int count; | 44 | int count; |
| 42 | }; | 45 | }; |
| @@ -105,57 +108,85 @@ static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page) | |||
| 105 | return NULL; | 108 | return NULL; |
| 106 | } | 109 | } |
| 107 | 110 | ||
| 108 | static void set_page_present(unsigned long addr, bool present, | 111 | static void set_pmd_presence(pmd_t *pmd, bool present, bool *old) |
| 109 | unsigned int *pglevel) | 112 | { |
| 113 | pmdval_t v = pmd_val(*pmd); | ||
| 114 | *old = !!(v & _PAGE_PRESENT); | ||
| 115 | v &= ~_PAGE_PRESENT; | ||
| 116 | if (present) | ||
| 117 | v |= _PAGE_PRESENT; | ||
| 118 | set_pmd(pmd, __pmd(v)); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void set_pte_presence(pte_t *pte, bool present, bool *old) | ||
| 122 | { | ||
| 123 | pteval_t v = pte_val(*pte); | ||
| 124 | *old = !!(v & _PAGE_PRESENT); | ||
| 125 | v &= ~_PAGE_PRESENT; | ||
| 126 | if (present) | ||
| 127 | v |= _PAGE_PRESENT; | ||
| 128 | set_pte_atomic(pte, __pte(v)); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int set_page_presence(unsigned long addr, bool present, bool *old) | ||
| 110 | { | 132 | { |
| 111 | pteval_t pteval; | ||
| 112 | pmdval_t pmdval; | ||
| 113 | unsigned int level; | 133 | unsigned int level; |
| 114 | pmd_t *pmd; | ||
| 115 | pte_t *pte = lookup_address(addr, &level); | 134 | pte_t *pte = lookup_address(addr, &level); |
| 116 | 135 | ||
| 117 | if (!pte) { | 136 | if (!pte) { |
| 118 | pr_err("kmmio: no pte for page 0x%08lx\n", addr); | 137 | pr_err("kmmio: no pte for page 0x%08lx\n", addr); |
| 119 | return; | 138 | return -1; |
| 120 | } | 139 | } |
| 121 | 140 | ||
| 122 | if (pglevel) | ||
| 123 | *pglevel = level; | ||
| 124 | |||
| 125 | switch (level) { | 141 | switch (level) { |
| 126 | case PG_LEVEL_2M: | 142 | case PG_LEVEL_2M: |
| 127 | pmd = (pmd_t *)pte; | 143 | set_pmd_presence((pmd_t *)pte, present, old); |
| 128 | pmdval = pmd_val(*pmd) & ~_PAGE_PRESENT; | ||
| 129 | if (present) | ||
| 130 | pmdval |= _PAGE_PRESENT; | ||
| 131 | set_pmd(pmd, __pmd(pmdval)); | ||
| 132 | break; | 144 | break; |
| 133 | |||
| 134 | case PG_LEVEL_4K: | 145 | case PG_LEVEL_4K: |
| 135 | pteval = pte_val(*pte) & ~_PAGE_PRESENT; | 146 | set_pte_presence(pte, present, old); |
| 136 | if (present) | ||
| 137 | pteval |= _PAGE_PRESENT; | ||
| 138 | set_pte_atomic(pte, __pte(pteval)); | ||
| 139 | break; | 147 | break; |
| 140 | |||
| 141 | default: | 148 | default: |
| 142 | pr_err("kmmio: unexpected page level 0x%x.\n", level); | 149 | pr_err("kmmio: unexpected page level 0x%x.\n", level); |
| 143 | return; | 150 | return -1; |
| 144 | } | 151 | } |
| 145 | 152 | ||
| 146 | __flush_tlb_one(addr); | 153 | __flush_tlb_one(addr); |
| 154 | return 0; | ||
| 147 | } | 155 | } |
| 148 | 156 | ||
| 149 | /** Mark the given page as not present. Access to it will trigger a fault. */ | 157 | /* |
| 150 | static void arm_kmmio_fault_page(unsigned long page, unsigned int *pglevel) | 158 | * Mark the given page as not present. Access to it will trigger a fault. |
| 159 | * | ||
| 160 | * Struct kmmio_fault_page is protected by RCU and kmmio_lock, but the | ||
| 161 | * protection is ignored here. RCU read lock is assumed held, so the struct | ||
| 162 | * will not disappear unexpectedly. Furthermore, the caller must guarantee, | ||
| 163 | * that double arming the same virtual address (page) cannot occur. | ||
| 164 | * | ||
| 165 | * Double disarming on the other hand is allowed, and may occur when a fault | ||
| 166 | * and mmiotrace shutdown happen simultaneously. | ||
| 167 | */ | ||
| 168 | static int arm_kmmio_fault_page(struct kmmio_fault_page *f) | ||
| 151 | { | 169 | { |
| 152 | set_page_present(page & PAGE_MASK, false, pglevel); | 170 | int ret; |
| 171 | WARN_ONCE(f->armed, KERN_ERR "kmmio page already armed.\n"); | ||
| 172 | if (f->armed) { | ||
| 173 | pr_warning("kmmio double-arm: page 0x%08lx, ref %d, old %d\n", | ||
| 174 | f->page, f->count, f->old_presence); | ||
| 175 | } | ||
| 176 | ret = set_page_presence(f->page, false, &f->old_presence); | ||
| 177 | WARN_ONCE(ret < 0, KERN_ERR "kmmio arming 0x%08lx failed.\n", f->page); | ||
| 178 | f->armed = true; | ||
| 179 | return ret; | ||
| 153 | } | 180 | } |
| 154 | 181 | ||
| 155 | /** Mark the given page as present. */ | 182 | /** Restore the given page to saved presence state. */ |
| 156 | static void disarm_kmmio_fault_page(unsigned long page, unsigned int *pglevel) | 183 | static void disarm_kmmio_fault_page(struct kmmio_fault_page *f) |
| 157 | { | 184 | { |
| 158 | set_page_present(page & PAGE_MASK, true, pglevel); | 185 | bool tmp; |
| 186 | int ret = set_page_presence(f->page, f->old_presence, &tmp); | ||
| 187 | WARN_ONCE(ret < 0, | ||
| 188 | KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page); | ||
| 189 | f->armed = false; | ||
| 159 | } | 190 | } |
| 160 | 191 | ||
| 161 | /* | 192 | /* |
| @@ -202,28 +233,32 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) | |||
| 202 | 233 | ||
| 203 | ctx = &get_cpu_var(kmmio_ctx); | 234 | ctx = &get_cpu_var(kmmio_ctx); |
| 204 | if (ctx->active) { | 235 | if (ctx->active) { |
| 205 | disarm_kmmio_fault_page(faultpage->page, NULL); | ||
| 206 | if (addr == ctx->addr) { | 236 | if (addr == ctx->addr) { |
| 207 | /* | 237 | /* |
| 208 | * On SMP we sometimes get recursive probe hits on the | 238 | * A second fault on the same page means some other |
| 209 | * same address. Context is already saved, fall out. | 239 | * condition needs handling by do_page_fault(), the |
| 240 | * page really not being present is the most common. | ||
| 210 | */ | 241 | */ |
| 211 | pr_debug("kmmio: duplicate probe hit on CPU %d, for " | 242 | pr_debug("kmmio: secondary hit for 0x%08lx CPU %d.\n", |
| 212 | "address 0x%08lx.\n", | 243 | addr, smp_processor_id()); |
| 213 | smp_processor_id(), addr); | 244 | |
| 214 | ret = 1; | 245 | if (!faultpage->old_presence) |
| 215 | goto no_kmmio_ctx; | 246 | pr_info("kmmio: unexpected secondary hit for " |
| 216 | } | 247 | "address 0x%08lx on CPU %d.\n", addr, |
| 217 | /* | 248 | smp_processor_id()); |
| 218 | * Prevent overwriting already in-flight context. | 249 | } else { |
| 219 | * This should not happen, let's hope disarming at least | 250 | /* |
| 220 | * prevents a panic. | 251 | * Prevent overwriting already in-flight context. |
| 221 | */ | 252 | * This should not happen, let's hope disarming at |
| 222 | pr_emerg("kmmio: recursive probe hit on CPU %d, " | 253 | * least prevents a panic. |
| 254 | */ | ||
| 255 | pr_emerg("kmmio: recursive probe hit on CPU %d, " | ||
| 223 | "for address 0x%08lx. Ignoring.\n", | 256 | "for address 0x%08lx. Ignoring.\n", |
| 224 | smp_processor_id(), addr); | 257 | smp_processor_id(), addr); |
| 225 | pr_emerg("kmmio: previous hit was at 0x%08lx.\n", | 258 | pr_emerg("kmmio: previous hit was at 0x%08lx.\n", |
| 226 | ctx->addr); | 259 | ctx->addr); |
| 260 | disarm_kmmio_fault_page(faultpage); | ||
| 261 | } | ||
| 227 | goto no_kmmio_ctx; | 262 | goto no_kmmio_ctx; |
| 228 | } | 263 | } |
| 229 | ctx->active++; | 264 | ctx->active++; |
| @@ -244,7 +279,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr) | |||
| 244 | regs->flags &= ~X86_EFLAGS_IF; | 279 | regs->flags &= ~X86_EFLAGS_IF; |
| 245 | 280 | ||
| 246 | /* Now we set present bit in PTE and single step. */ | 281 | /* Now we set present bit in PTE and single step. */ |
| 247 | disarm_kmmio_fault_page(ctx->fpage->page, NULL); | 282 | disarm_kmmio_fault_page(ctx->fpage); |
| 248 | 283 | ||
| 249 | /* | 284 | /* |
| 250 | * If another cpu accesses the same page while we are stepping, | 285 | * If another cpu accesses the same page while we are stepping, |
| @@ -275,7 +310,7 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) | |||
| 275 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); | 310 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); |
| 276 | 311 | ||
| 277 | if (!ctx->active) { | 312 | if (!ctx->active) { |
| 278 | pr_debug("kmmio: spurious debug trap on CPU %d.\n", | 313 | pr_warning("kmmio: spurious debug trap on CPU %d.\n", |
| 279 | smp_processor_id()); | 314 | smp_processor_id()); |
| 280 | goto out; | 315 | goto out; |
| 281 | } | 316 | } |
| @@ -283,7 +318,11 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) | |||
| 283 | if (ctx->probe && ctx->probe->post_handler) | 318 | if (ctx->probe && ctx->probe->post_handler) |
| 284 | ctx->probe->post_handler(ctx->probe, condition, regs); | 319 | ctx->probe->post_handler(ctx->probe, condition, regs); |
| 285 | 320 | ||
| 286 | arm_kmmio_fault_page(ctx->fpage->page, NULL); | 321 | /* Prevent racing against release_kmmio_fault_page(). */ |
| 322 | spin_lock(&kmmio_lock); | ||
| 323 | if (ctx->fpage->count) | ||
| 324 | arm_kmmio_fault_page(ctx->fpage); | ||
| 325 | spin_unlock(&kmmio_lock); | ||
| 287 | 326 | ||
| 288 | regs->flags &= ~X86_EFLAGS_TF; | 327 | regs->flags &= ~X86_EFLAGS_TF; |
| 289 | regs->flags |= ctx->saved_flags; | 328 | regs->flags |= ctx->saved_flags; |
| @@ -315,20 +354,24 @@ static int add_kmmio_fault_page(unsigned long page) | |||
| 315 | f = get_kmmio_fault_page(page); | 354 | f = get_kmmio_fault_page(page); |
| 316 | if (f) { | 355 | if (f) { |
| 317 | if (!f->count) | 356 | if (!f->count) |
| 318 | arm_kmmio_fault_page(f->page, NULL); | 357 | arm_kmmio_fault_page(f); |
| 319 | f->count++; | 358 | f->count++; |
| 320 | return 0; | 359 | return 0; |
| 321 | } | 360 | } |
| 322 | 361 | ||
| 323 | f = kmalloc(sizeof(*f), GFP_ATOMIC); | 362 | f = kzalloc(sizeof(*f), GFP_ATOMIC); |
| 324 | if (!f) | 363 | if (!f) |
| 325 | return -1; | 364 | return -1; |
| 326 | 365 | ||
| 327 | f->count = 1; | 366 | f->count = 1; |
| 328 | f->page = page; | 367 | f->page = page; |
| 329 | list_add_rcu(&f->list, kmmio_page_list(f->page)); | ||
| 330 | 368 | ||
| 331 | arm_kmmio_fault_page(f->page, NULL); | 369 | if (arm_kmmio_fault_page(f)) { |
| 370 | kfree(f); | ||
| 371 | return -1; | ||
| 372 | } | ||
| 373 | |||
| 374 | list_add_rcu(&f->list, kmmio_page_list(f->page)); | ||
| 332 | 375 | ||
| 333 | return 0; | 376 | return 0; |
| 334 | } | 377 | } |
| @@ -347,7 +390,7 @@ static void release_kmmio_fault_page(unsigned long page, | |||
| 347 | f->count--; | 390 | f->count--; |
| 348 | BUG_ON(f->count < 0); | 391 | BUG_ON(f->count < 0); |
| 349 | if (!f->count) { | 392 | if (!f->count) { |
| 350 | disarm_kmmio_fault_page(f->page, NULL); | 393 | disarm_kmmio_fault_page(f); |
| 351 | f->release_next = *release_list; | 394 | f->release_next = *release_list; |
| 352 | *release_list = f; | 395 | *release_list = f; |
| 353 | } | 396 | } |
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 3957cd6d6454..451fe95a0352 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c | |||
| @@ -423,32 +423,6 @@ void __init initmem_init(unsigned long start_pfn, | |||
| 423 | setup_bootmem_allocator(); | 423 | setup_bootmem_allocator(); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | void __init set_highmem_pages_init(void) | ||
| 427 | { | ||
| 428 | #ifdef CONFIG_HIGHMEM | ||
| 429 | struct zone *zone; | ||
| 430 | int nid; | ||
| 431 | |||
| 432 | for_each_zone(zone) { | ||
| 433 | unsigned long zone_start_pfn, zone_end_pfn; | ||
| 434 | |||
| 435 | if (!is_highmem(zone)) | ||
| 436 | continue; | ||
| 437 | |||
| 438 | zone_start_pfn = zone->zone_start_pfn; | ||
| 439 | zone_end_pfn = zone_start_pfn + zone->spanned_pages; | ||
| 440 | |||
| 441 | nid = zone_to_nid(zone); | ||
| 442 | printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n", | ||
| 443 | zone->name, nid, zone_start_pfn, zone_end_pfn); | ||
| 444 | |||
| 445 | add_highpages_with_active_regions(nid, zone_start_pfn, | ||
| 446 | zone_end_pfn); | ||
| 447 | } | ||
| 448 | totalram_pages += totalhigh_pages; | ||
| 449 | #endif | ||
| 450 | } | ||
| 451 | |||
| 452 | #ifdef CONFIG_MEMORY_HOTPLUG | 426 | #ifdef CONFIG_MEMORY_HOTPLUG |
| 453 | static int paddr_to_nid(u64 addr) | 427 | static int paddr_to_nid(u64 addr) |
| 454 | { | 428 | { |
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 86f2ffc43c3d..5b7c7c8464fe 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
| @@ -313,6 +313,24 @@ int ptep_clear_flush_young(struct vm_area_struct *vma, | |||
| 313 | return young; | 313 | return young; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /** | ||
| 317 | * reserve_top_address - reserves a hole in the top of kernel address space | ||
| 318 | * @reserve - size of hole to reserve | ||
| 319 | * | ||
| 320 | * Can be used to relocate the fixmap area and poke a hole in the top | ||
| 321 | * of kernel address space to make room for a hypervisor. | ||
| 322 | */ | ||
| 323 | void __init reserve_top_address(unsigned long reserve) | ||
| 324 | { | ||
| 325 | #ifdef CONFIG_X86_32 | ||
| 326 | BUG_ON(fixmaps_set > 0); | ||
| 327 | printk(KERN_INFO "Reserving virtual address space above 0x%08x\n", | ||
| 328 | (int)-reserve); | ||
| 329 | __FIXADDR_TOP = -reserve - PAGE_SIZE; | ||
| 330 | __VMALLOC_RESERVE += reserve; | ||
| 331 | #endif | ||
| 332 | } | ||
| 333 | |||
| 316 | int fixmaps_set; | 334 | int fixmaps_set; |
| 317 | 335 | ||
| 318 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte) | 336 | void __native_set_fixmap(enum fixed_addresses idx, pte_t pte) |
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index 0951db9ee519..f2e477c91c1b 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #include <asm/tlb.h> | 20 | #include <asm/tlb.h> |
| 21 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
| 22 | 22 | ||
| 23 | unsigned int __VMALLOC_RESERVE = 128 << 20; | ||
| 24 | |||
| 23 | /* | 25 | /* |
| 24 | * Associate a virtual page frame with a given physical page frame | 26 | * Associate a virtual page frame with a given physical page frame |
| 25 | * and protection flags for that frame. | 27 | * and protection flags for that frame. |
| @@ -97,22 +99,6 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) | |||
| 97 | unsigned long __FIXADDR_TOP = 0xfffff000; | 99 | unsigned long __FIXADDR_TOP = 0xfffff000; |
| 98 | EXPORT_SYMBOL(__FIXADDR_TOP); | 100 | EXPORT_SYMBOL(__FIXADDR_TOP); |
| 99 | 101 | ||
| 100 | /** | ||
| 101 | * reserve_top_address - reserves a hole in the top of kernel address space | ||
| 102 | * @reserve - size of hole to reserve | ||
| 103 | * | ||
| 104 | * Can be used to relocate the fixmap area and poke a hole in the top | ||
| 105 | * of kernel address space to make room for a hypervisor. | ||
| 106 | */ | ||
| 107 | void __init reserve_top_address(unsigned long reserve) | ||
| 108 | { | ||
| 109 | BUG_ON(fixmaps_set > 0); | ||
| 110 | printk(KERN_INFO "Reserving virtual address space above 0x%08x\n", | ||
| 111 | (int)-reserve); | ||
| 112 | __FIXADDR_TOP = -reserve - PAGE_SIZE; | ||
| 113 | __VMALLOC_RESERVE += reserve; | ||
| 114 | } | ||
| 115 | |||
| 116 | /* | 102 | /* |
| 117 | * vmalloc=size forces the vmalloc area to be exactly 'size' | 103 | * vmalloc=size forces the vmalloc area to be exactly 'size' |
| 118 | * bytes. This can be used to increase (or decrease) the | 104 | * bytes. This can be used to increase (or decrease) the |
diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index ab50a8d7402c..427fd1b56df5 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Written by Pekka Paalanen, 2008 <pq@iki.fi> | 2 | * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi> |
| 3 | */ | 3 | */ |
| 4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
| @@ -9,35 +9,74 @@ | |||
| 9 | 9 | ||
| 10 | static unsigned long mmio_address; | 10 | static unsigned long mmio_address; |
| 11 | module_param(mmio_address, ulong, 0); | 11 | module_param(mmio_address, ulong, 0); |
| 12 | MODULE_PARM_DESC(mmio_address, "Start address of the mapping of 16 kB."); | 12 | MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB " |
| 13 | "(or 8 MB if read_far is non-zero)."); | ||
| 14 | |||
| 15 | static unsigned long read_far = 0x400100; | ||
| 16 | module_param(read_far, ulong, 0); | ||
| 17 | MODULE_PARM_DESC(read_far, " Offset of a 32-bit read within 8 MB " | ||
| 18 | "(default: 0x400100)."); | ||
| 19 | |||
| 20 | static unsigned v16(unsigned i) | ||
| 21 | { | ||
| 22 | return i * 12 + 7; | ||
| 23 | } | ||
| 24 | |||
| 25 | static unsigned v32(unsigned i) | ||
| 26 | { | ||
| 27 | return i * 212371 + 13; | ||
| 28 | } | ||
| 13 | 29 | ||
| 14 | static void do_write_test(void __iomem *p) | 30 | static void do_write_test(void __iomem *p) |
| 15 | { | 31 | { |
| 16 | unsigned int i; | 32 | unsigned int i; |
| 33 | pr_info(MODULE_NAME ": write test.\n"); | ||
| 17 | mmiotrace_printk("Write test.\n"); | 34 | mmiotrace_printk("Write test.\n"); |
| 35 | |||
| 18 | for (i = 0; i < 256; i++) | 36 | for (i = 0; i < 256; i++) |
| 19 | iowrite8(i, p + i); | 37 | iowrite8(i, p + i); |
| 38 | |||
| 20 | for (i = 1024; i < (5 * 1024); i += 2) | 39 | for (i = 1024; i < (5 * 1024); i += 2) |
| 21 | iowrite16(i * 12 + 7, p + i); | 40 | iowrite16(v16(i), p + i); |
| 41 | |||
| 22 | for (i = (5 * 1024); i < (16 * 1024); i += 4) | 42 | for (i = (5 * 1024); i < (16 * 1024); i += 4) |
| 23 | iowrite32(i * 212371 + 13, p + i); | 43 | iowrite32(v32(i), p + i); |
| 24 | } | 44 | } |
| 25 | 45 | ||
| 26 | static void do_read_test(void __iomem *p) | 46 | static void do_read_test(void __iomem *p) |
| 27 | { | 47 | { |
| 28 | unsigned int i; | 48 | unsigned int i; |
| 49 | unsigned errs[3] = { 0 }; | ||
| 50 | pr_info(MODULE_NAME ": read test.\n"); | ||
| 29 | mmiotrace_printk("Read test.\n"); | 51 | mmiotrace_printk("Read test.\n"); |
| 52 | |||
| 30 | for (i = 0; i < 256; i++) | 53 | for (i = 0; i < 256; i++) |
| 31 | ioread8(p + i); | 54 | if (ioread8(p + i) != i) |
| 55 | ++errs[0]; | ||
| 56 | |||
| 32 | for (i = 1024; i < (5 * 1024); i += 2) | 57 | for (i = 1024; i < (5 * 1024); i += 2) |
| 33 | ioread16(p + i); | 58 | if (ioread16(p + i) != v16(i)) |
| 59 | ++errs[1]; | ||
| 60 | |||
| 34 | for (i = (5 * 1024); i < (16 * 1024); i += 4) | 61 | for (i = (5 * 1024); i < (16 * 1024); i += 4) |
| 35 | ioread32(p + i); | 62 | if (ioread32(p + i) != v32(i)) |
| 63 | ++errs[2]; | ||
| 64 | |||
| 65 | mmiotrace_printk("Read errors: 8-bit %d, 16-bit %d, 32-bit %d.\n", | ||
| 66 | errs[0], errs[1], errs[2]); | ||
| 36 | } | 67 | } |
| 37 | 68 | ||
| 38 | static void do_test(void) | 69 | static void do_read_far_test(void __iomem *p) |
| 39 | { | 70 | { |
| 40 | void __iomem *p = ioremap_nocache(mmio_address, 0x4000); | 71 | pr_info(MODULE_NAME ": read far test.\n"); |
| 72 | mmiotrace_printk("Read far test.\n"); | ||
| 73 | |||
| 74 | ioread32(p + read_far); | ||
| 75 | } | ||
| 76 | |||
| 77 | static void do_test(unsigned long size) | ||
| 78 | { | ||
| 79 | void __iomem *p = ioremap_nocache(mmio_address, size); | ||
| 41 | if (!p) { | 80 | if (!p) { |
| 42 | pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); | 81 | pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); |
| 43 | return; | 82 | return; |
| @@ -45,11 +84,15 @@ static void do_test(void) | |||
| 45 | mmiotrace_printk("ioremap returned %p.\n", p); | 84 | mmiotrace_printk("ioremap returned %p.\n", p); |
| 46 | do_write_test(p); | 85 | do_write_test(p); |
| 47 | do_read_test(p); | 86 | do_read_test(p); |
| 87 | if (read_far && read_far < size - 4) | ||
| 88 | do_read_far_test(p); | ||
| 48 | iounmap(p); | 89 | iounmap(p); |
| 49 | } | 90 | } |
| 50 | 91 | ||
| 51 | static int __init init(void) | 92 | static int __init init(void) |
| 52 | { | 93 | { |
| 94 | unsigned long size = (read_far) ? (8 << 20) : (16 << 10); | ||
| 95 | |||
| 53 | if (mmio_address == 0) { | 96 | if (mmio_address == 0) { |
| 54 | pr_err(MODULE_NAME ": you have to use the module argument " | 97 | pr_err(MODULE_NAME ": you have to use the module argument " |
| 55 | "mmio_address.\n"); | 98 | "mmio_address.\n"); |
| @@ -58,10 +101,11 @@ static int __init init(void) | |||
| 58 | return -ENXIO; | 101 | return -ENXIO; |
| 59 | } | 102 | } |
| 60 | 103 | ||
| 61 | pr_warning(MODULE_NAME ": WARNING: mapping 16 kB @ 0x%08lx " | 104 | pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI " |
| 62 | "in PCI address space, and writing " | 105 | "address space, and writing 16 kB of rubbish in there.\n", |
| 63 | "rubbish in there.\n", mmio_address); | 106 | size >> 10, mmio_address); |
| 64 | do_test(); | 107 | do_test(size); |
| 108 | pr_info(MODULE_NAME ": All done.\n"); | ||
| 65 | return 0; | 109 | return 0; |
| 66 | } | 110 | } |
| 67 | 111 | ||
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index e9f80c744cf3..10131fbdaada 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c | |||
| @@ -78,8 +78,18 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs) | |||
| 78 | if (cpu_has_arch_perfmon) { | 78 | if (cpu_has_arch_perfmon) { |
| 79 | union cpuid10_eax eax; | 79 | union cpuid10_eax eax; |
| 80 | eax.full = cpuid_eax(0xa); | 80 | eax.full = cpuid_eax(0xa); |
| 81 | if (counter_width < eax.split.bit_width) | 81 | |
| 82 | counter_width = eax.split.bit_width; | 82 | /* |
| 83 | * For Core2 (family 6, model 15), don't reset the | ||
| 84 | * counter width: | ||
| 85 | */ | ||
| 86 | if (!(eax.split.version_id == 0 && | ||
| 87 | current_cpu_data.x86 == 6 && | ||
| 88 | current_cpu_data.x86_model == 15)) { | ||
| 89 | |||
| 90 | if (counter_width < eax.split.bit_width) | ||
| 91 | counter_width = eax.split.bit_width; | ||
| 92 | } | ||
| 83 | } | 93 | } |
| 84 | 94 | ||
| 85 | /* clear all counters */ | 95 | /* clear all counters */ |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c52f4034c7fd..82cd39a6cbd3 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -103,7 +103,7 @@ static void xen_vcpu_setup(int cpu) | |||
| 103 | 103 | ||
| 104 | vcpup = &per_cpu(xen_vcpu_info, cpu); | 104 | vcpup = &per_cpu(xen_vcpu_info, cpu); |
| 105 | 105 | ||
| 106 | info.mfn = virt_to_mfn(vcpup); | 106 | info.mfn = arbitrary_virt_to_mfn(vcpup); |
| 107 | info.offset = offset_in_page(vcpup); | 107 | info.offset = offset_in_page(vcpup); |
| 108 | 108 | ||
| 109 | printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %llx, offset %d\n", | 109 | printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %llx, offset %d\n", |
| @@ -301,8 +301,10 @@ static void xen_load_gdt(const struct desc_ptr *dtr) | |||
| 301 | frames = mcs.args; | 301 | frames = mcs.args; |
| 302 | 302 | ||
| 303 | for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { | 303 | for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { |
| 304 | frames[f] = virt_to_mfn(va); | 304 | frames[f] = arbitrary_virt_to_mfn((void *)va); |
| 305 | |||
| 305 | make_lowmem_page_readonly((void *)va); | 306 | make_lowmem_page_readonly((void *)va); |
| 307 | make_lowmem_page_readonly(mfn_to_virt(frames[f])); | ||
| 306 | } | 308 | } |
| 307 | 309 | ||
| 308 | MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct)); | 310 | MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct)); |
| @@ -314,7 +316,7 @@ static void load_TLS_descriptor(struct thread_struct *t, | |||
| 314 | unsigned int cpu, unsigned int i) | 316 | unsigned int cpu, unsigned int i) |
| 315 | { | 317 | { |
| 316 | struct desc_struct *gdt = get_cpu_gdt_table(cpu); | 318 | struct desc_struct *gdt = get_cpu_gdt_table(cpu); |
| 317 | xmaddr_t maddr = virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); | 319 | xmaddr_t maddr = arbitrary_virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); |
| 318 | struct multicall_space mc = __xen_mc_entry(0); | 320 | struct multicall_space mc = __xen_mc_entry(0); |
| 319 | 321 | ||
| 320 | MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); | 322 | MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); |
| @@ -488,7 +490,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, | |||
| 488 | break; | 490 | break; |
| 489 | 491 | ||
| 490 | default: { | 492 | default: { |
| 491 | xmaddr_t maddr = virt_to_machine(&dt[entry]); | 493 | xmaddr_t maddr = arbitrary_virt_to_machine(&dt[entry]); |
| 492 | 494 | ||
| 493 | xen_mc_flush(); | 495 | xen_mc_flush(); |
| 494 | if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc)) | 496 | if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc)) |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 319bd40a57c2..cb6afa4ec95c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -276,6 +276,13 @@ void set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
| 276 | p2m_top[topidx][idx] = mfn; | 276 | p2m_top[topidx][idx] = mfn; |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | unsigned long arbitrary_virt_to_mfn(void *vaddr) | ||
| 280 | { | ||
| 281 | xmaddr_t maddr = arbitrary_virt_to_machine(vaddr); | ||
| 282 | |||
| 283 | return PFN_DOWN(maddr.maddr); | ||
| 284 | } | ||
| 285 | |||
| 279 | xmaddr_t arbitrary_virt_to_machine(void *vaddr) | 286 | xmaddr_t arbitrary_virt_to_machine(void *vaddr) |
| 280 | { | 287 | { |
| 281 | unsigned long address = (unsigned long)vaddr; | 288 | unsigned long address = (unsigned long)vaddr; |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 035582ae815d..8d470562ffc9 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
| @@ -219,6 +219,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) | |||
| 219 | { | 219 | { |
| 220 | struct vcpu_guest_context *ctxt; | 220 | struct vcpu_guest_context *ctxt; |
| 221 | struct desc_struct *gdt; | 221 | struct desc_struct *gdt; |
| 222 | unsigned long gdt_mfn; | ||
| 222 | 223 | ||
| 223 | if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) | 224 | if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map)) |
| 224 | return 0; | 225 | return 0; |
| @@ -248,9 +249,12 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) | |||
| 248 | ctxt->ldt_ents = 0; | 249 | ctxt->ldt_ents = 0; |
| 249 | 250 | ||
| 250 | BUG_ON((unsigned long)gdt & ~PAGE_MASK); | 251 | BUG_ON((unsigned long)gdt & ~PAGE_MASK); |
| 252 | |||
| 253 | gdt_mfn = arbitrary_virt_to_mfn(gdt); | ||
| 251 | make_lowmem_page_readonly(gdt); | 254 | make_lowmem_page_readonly(gdt); |
| 255 | make_lowmem_page_readonly(mfn_to_virt(gdt_mfn)); | ||
| 252 | 256 | ||
| 253 | ctxt->gdt_frames[0] = virt_to_mfn(gdt); | 257 | ctxt->gdt_frames[0] = gdt_mfn; |
| 254 | ctxt->gdt_ents = GDT_ENTRIES; | 258 | ctxt->gdt_ents = GDT_ENTRIES; |
| 255 | 259 | ||
| 256 | ctxt->user_regs.cs = __KERNEL_CS; | 260 | ctxt->user_regs.cs = __KERNEL_CS; |
diff --git a/block/blktrace.c b/block/blktrace.c index 7cf9d1ff45a0..028120a0965a 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
| @@ -363,7 +363,7 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
| 363 | if (!bt->sequence) | 363 | if (!bt->sequence) |
| 364 | goto err; | 364 | goto err; |
| 365 | 365 | ||
| 366 | bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG); | 366 | bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char)); |
| 367 | if (!bt->msg_data) | 367 | if (!bt->msg_data) |
| 368 | goto err; | 368 | goto err; |
| 369 | 369 | ||
diff --git a/crypto/api.c b/crypto/api.c index efe77df6863f..38a2bc02a98c 100644 --- a/crypto/api.c +++ b/crypto/api.c | |||
| @@ -215,8 +215,19 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) | |||
| 215 | mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); | 215 | mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); |
| 216 | type &= mask; | 216 | type &= mask; |
| 217 | 217 | ||
| 218 | alg = try_then_request_module(crypto_alg_lookup(name, type, mask), | 218 | alg = crypto_alg_lookup(name, type, mask); |
| 219 | name); | 219 | if (!alg) { |
| 220 | char tmp[CRYPTO_MAX_ALG_NAME]; | ||
| 221 | |||
| 222 | request_module(name); | ||
| 223 | |||
| 224 | if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask) && | ||
| 225 | snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp)) | ||
| 226 | request_module(tmp); | ||
| 227 | |||
| 228 | alg = crypto_alg_lookup(name, type, mask); | ||
| 229 | } | ||
| 230 | |||
| 220 | if (alg) | 231 | if (alg) |
| 221 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; | 232 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; |
| 222 | 233 | ||
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 9cc769b587ff..68fd3d292799 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -516,12 +516,12 @@ int acpi_processor_preregister_performance( | |||
| 516 | continue; | 516 | continue; |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | if (!performance || !percpu_ptr(performance, i)) { | 519 | if (!performance || !per_cpu_ptr(performance, i)) { |
| 520 | retval = -EINVAL; | 520 | retval = -EINVAL; |
| 521 | continue; | 521 | continue; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | pr->performance = percpu_ptr(performance, i); | 524 | pr->performance = per_cpu_ptr(performance, i); |
| 525 | cpumask_set_cpu(i, pr->performance->shared_cpu_map); | 525 | cpumask_set_cpu(i, pr->performance->shared_cpu_map); |
| 526 | if (acpi_processor_get_psd(pr)) { | 526 | if (acpi_processor_get_psd(pr)) { |
| 527 | retval = -EINVAL; | 527 | retval = -EINVAL; |
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 2d637e0fbc03..d9e751be8c5f 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c | |||
| @@ -457,10 +457,12 @@ static int init_ixp_crypto(void) | |||
| 457 | if (!ctx_pool) { | 457 | if (!ctx_pool) { |
| 458 | goto err; | 458 | goto err; |
| 459 | } | 459 | } |
| 460 | ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0); | 460 | ret = qmgr_request_queue(SEND_QID, NPE_QLEN_TOTAL, 0, 0, |
| 461 | "ixp_crypto:out", NULL); | ||
| 461 | if (ret) | 462 | if (ret) |
| 462 | goto err; | 463 | goto err; |
| 463 | ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0); | 464 | ret = qmgr_request_queue(RECV_QID, NPE_QLEN, 0, 0, |
| 465 | "ixp_crypto:in", NULL); | ||
| 464 | if (ret) { | 466 | if (ret) { |
| 465 | qmgr_release_queue(SEND_QID); | 467 | qmgr_release_queue(SEND_QID); |
| 466 | goto err; | 468 | goto err; |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 856b3cc25583..3f0fdd18255d 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
| @@ -489,4 +489,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); | |||
| 489 | MODULE_LICENSE("GPL"); | 489 | MODULE_LICENSE("GPL"); |
| 490 | MODULE_AUTHOR("Michal Ludvig"); | 490 | MODULE_AUTHOR("Michal Ludvig"); |
| 491 | 491 | ||
| 492 | MODULE_ALIAS("aes"); | 492 | MODULE_ALIAS("aes-all"); |
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index a7fbadebf623..a2c8e8514b63 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
| @@ -304,7 +304,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); | |||
| 304 | MODULE_LICENSE("GPL"); | 304 | MODULE_LICENSE("GPL"); |
| 305 | MODULE_AUTHOR("Michal Ludvig"); | 305 | MODULE_AUTHOR("Michal Ludvig"); |
| 306 | 306 | ||
| 307 | MODULE_ALIAS("sha1"); | 307 | MODULE_ALIAS("sha1-all"); |
| 308 | MODULE_ALIAS("sha256"); | 308 | MODULE_ALIAS("sha256-all"); |
| 309 | MODULE_ALIAS("sha1-padlock"); | 309 | MODULE_ALIAS("sha1-padlock"); |
| 310 | MODULE_ALIAS("sha256-padlock"); | 310 | MODULE_ALIAS("sha256-padlock"); |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index ea5440dd10dc..647374acba94 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
| @@ -1401,7 +1401,7 @@ MODULE_ALIAS("platform:iop-adma"); | |||
| 1401 | 1401 | ||
| 1402 | static struct platform_driver iop_adma_driver = { | 1402 | static struct platform_driver iop_adma_driver = { |
| 1403 | .probe = iop_adma_probe, | 1403 | .probe = iop_adma_probe, |
| 1404 | .remove = iop_adma_remove, | 1404 | .remove = __devexit_p(iop_adma_remove), |
| 1405 | .driver = { | 1405 | .driver = { |
| 1406 | .owner = THIS_MODULE, | 1406 | .owner = THIS_MODULE, |
| 1407 | .name = "iop-adma", | 1407 | .name = "iop-adma", |
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index d35cbd1ff0b3..5d5d5b31867f 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
| @@ -1287,7 +1287,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp, | |||
| 1287 | 1287 | ||
| 1288 | static struct platform_driver mv_xor_driver = { | 1288 | static struct platform_driver mv_xor_driver = { |
| 1289 | .probe = mv_xor_probe, | 1289 | .probe = mv_xor_probe, |
| 1290 | .remove = mv_xor_remove, | 1290 | .remove = __devexit_p(mv_xor_remove), |
| 1291 | .driver = { | 1291 | .driver = { |
| 1292 | .owner = THIS_MODULE, | 1292 | .owner = THIS_MODULE, |
| 1293 | .name = MV_XOR_NAME, | 1293 | .name = MV_XOR_NAME, |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 72c667f9bee1..12715d3c078d 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
| @@ -420,7 +420,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
| 420 | dev->sigdata.lock = NULL; | 420 | dev->sigdata.lock = NULL; |
| 421 | master->lock.hw_lock = NULL; /* SHM removed */ | 421 | master->lock.hw_lock = NULL; /* SHM removed */ |
| 422 | master->lock.file_priv = NULL; | 422 | master->lock.file_priv = NULL; |
| 423 | wake_up_interruptible(&master->lock.lock_queue); | 423 | wake_up_interruptible_all(&master->lock.lock_queue); |
| 424 | } | 424 | } |
| 425 | break; | 425 | break; |
| 426 | case _DRM_AGP: | 426 | case _DRM_AGP: |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 6c020fe5431c..f52663ebe016 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -484,6 +484,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 484 | mutex_lock(&dev->struct_mutex); | 484 | mutex_lock(&dev->struct_mutex); |
| 485 | 485 | ||
| 486 | if (file_priv->is_master) { | 486 | if (file_priv->is_master) { |
| 487 | struct drm_master *master = file_priv->master; | ||
| 487 | struct drm_file *temp; | 488 | struct drm_file *temp; |
| 488 | list_for_each_entry(temp, &dev->filelist, lhead) { | 489 | list_for_each_entry(temp, &dev->filelist, lhead) { |
| 489 | if ((temp->master == file_priv->master) && | 490 | if ((temp->master == file_priv->master) && |
| @@ -491,6 +492,19 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 491 | temp->authenticated = 0; | 492 | temp->authenticated = 0; |
| 492 | } | 493 | } |
| 493 | 494 | ||
| 495 | /** | ||
| 496 | * Since the master is disappearing, so is the | ||
| 497 | * possibility to lock. | ||
| 498 | */ | ||
| 499 | |||
| 500 | if (master->lock.hw_lock) { | ||
| 501 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 502 | dev->sigdata.lock = NULL; | ||
| 503 | master->lock.hw_lock = NULL; | ||
| 504 | master->lock.file_priv = NULL; | ||
| 505 | wake_up_interruptible_all(&master->lock.lock_queue); | ||
| 506 | } | ||
| 507 | |||
| 494 | if (file_priv->minor->master == file_priv->master) { | 508 | if (file_priv->minor->master == file_priv->master) { |
| 495 | /* drop the reference held my the minor */ | 509 | /* drop the reference held my the minor */ |
| 496 | drm_master_put(&file_priv->minor->master); | 510 | drm_master_put(&file_priv->minor->master); |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 46e7b28f0707..e2f70a516c34 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 80 | __set_current_state(TASK_INTERRUPTIBLE); | 80 | __set_current_state(TASK_INTERRUPTIBLE); |
| 81 | if (!master->lock.hw_lock) { | 81 | if (!master->lock.hw_lock) { |
| 82 | /* Device has been unregistered */ | 82 | /* Device has been unregistered */ |
| 83 | send_sig(SIGTERM, current, 0); | ||
| 83 | ret = -EINTR; | 84 | ret = -EINTR; |
| 84 | break; | 85 | break; |
| 85 | } | 86 | } |
| @@ -93,7 +94,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 93 | /* Contention */ | 94 | /* Contention */ |
| 94 | schedule(); | 95 | schedule(); |
| 95 | if (signal_pending(current)) { | 96 | if (signal_pending(current)) { |
| 96 | ret = -ERESTARTSYS; | 97 | ret = -EINTR; |
| 97 | break; | 98 | break; |
| 98 | } | 99 | } |
| 99 | } | 100 | } |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 46bb923b097c..7c8b15b22bf2 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
| @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref) | |||
| 146 | 146 | ||
| 147 | drm_ht_remove(&master->magiclist); | 147 | drm_ht_remove(&master->magiclist); |
| 148 | 148 | ||
| 149 | if (master->lock.hw_lock) { | ||
| 150 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
| 151 | dev->sigdata.lock = NULL; | ||
| 152 | master->lock.hw_lock = NULL; | ||
| 153 | master->lock.file_priv = NULL; | ||
| 154 | wake_up_interruptible(&master->lock.lock_queue); | ||
| 155 | } | ||
| 156 | |||
| 157 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); | 149 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); |
| 158 | } | 150 | } |
| 159 | 151 | ||
| @@ -176,7 +168,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, | |||
| 176 | file_priv->minor->master != file_priv->master) { | 168 | file_priv->minor->master != file_priv->master) { |
| 177 | mutex_lock(&dev->struct_mutex); | 169 | mutex_lock(&dev->struct_mutex); |
| 178 | file_priv->minor->master = drm_master_get(file_priv->master); | 170 | file_priv->minor->master = drm_master_get(file_priv->master); |
| 179 | mutex_lock(&dev->struct_mutex); | 171 | mutex_unlock(&dev->struct_mutex); |
| 180 | } | 172 | } |
| 181 | 173 | ||
| 182 | return 0; | 174 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c29feb97c36d..85685bfd12da 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -211,7 +211,7 @@ fast_user_write(struct io_mapping *mapping, | |||
| 211 | 211 | ||
| 212 | vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); | 212 | vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); |
| 213 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, | 213 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, |
| 214 | user_data, length, length); | 214 | user_data, length); |
| 215 | io_mapping_unmap_atomic(vaddr_atomic); | 215 | io_mapping_unmap_atomic(vaddr_atomic); |
| 216 | if (unwritten) | 216 | if (unwritten) |
| 217 | return -EFAULT; | 217 | return -EFAULT; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 548ff2c66431..87b6b603469e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -383,12 +383,13 @@ int i915_irq_emit(struct drm_device *dev, void *data, | |||
| 383 | drm_i915_irq_emit_t *emit = data; | 383 | drm_i915_irq_emit_t *emit = data; |
| 384 | int result; | 384 | int result; |
| 385 | 385 | ||
| 386 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 387 | |||
| 388 | if (!dev_priv) { | 386 | if (!dev_priv) { |
| 389 | DRM_ERROR("called with no initialization\n"); | 387 | DRM_ERROR("called with no initialization\n"); |
| 390 | return -EINVAL; | 388 | return -EINVAL; |
| 391 | } | 389 | } |
| 390 | |||
| 391 | RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
| 392 | |||
| 392 | mutex_lock(&dev->struct_mutex); | 393 | mutex_lock(&dev->struct_mutex); |
| 393 | result = i915_emit_irq(dev); | 394 | result = i915_emit_irq(dev); |
| 394 | mutex_unlock(&dev->struct_mutex); | 395 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index eeda276f8f16..7f186bbcb99d 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
| @@ -482,7 +482,7 @@ mv64xxx_i2c_map_regs(struct platform_device *pd, | |||
| 482 | return 0; | 482 | return 0; |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | static void __devexit | 485 | static void |
| 486 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) | 486 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) |
| 487 | { | 487 | { |
| 488 | if (drv_data->reg_base) { | 488 | if (drv_data->reg_base) { |
| @@ -577,7 +577,7 @@ mv64xxx_i2c_remove(struct platform_device *dev) | |||
| 577 | 577 | ||
| 578 | static struct platform_driver mv64xxx_i2c_driver = { | 578 | static struct platform_driver mv64xxx_i2c_driver = { |
| 579 | .probe = mv64xxx_i2c_probe, | 579 | .probe = mv64xxx_i2c_probe, |
| 580 | .remove = mv64xxx_i2c_remove, | 580 | .remove = __devexit_p(mv64xxx_i2c_remove), |
| 581 | .driver = { | 581 | .driver = { |
| 582 | .owner = THIS_MODULE, | 582 | .owner = THIS_MODULE, |
| 583 | .name = MV64XXX_I2C_CTLR_NAME, | 583 | .name = MV64XXX_I2C_CTLR_NAME, |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index c3c8b9bc40ae..45470f18d7e9 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -839,7 +839,7 @@ static void atkbd_disconnect(struct serio *serio) | |||
| 839 | */ | 839 | */ |
| 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | 840 | static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) |
| 841 | { | 841 | { |
| 842 | const unsigned int forced_release_keys[] = { | 842 | static const unsigned int forced_release_keys[] = { |
| 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, | 843 | 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, |
| 844 | }; | 844 | }; |
| 845 | int i; | 845 | int i; |
| @@ -856,7 +856,7 @@ static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) | |||
| 856 | */ | 856 | */ |
| 857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) | 857 | static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) |
| 858 | { | 858 | { |
| 859 | const unsigned int forced_release_keys[] = { | 859 | static const unsigned int forced_release_keys[] = { |
| 860 | 0x94, | 860 | 0x94, |
| 861 | }; | 861 | }; |
| 862 | int i; | 862 | int i; |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 19284016e0f4..ee855c5202e8 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
| @@ -209,8 +209,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
| 209 | goto out; | 209 | goto out; |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT || | 212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
| 213 | !pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) { | 213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
| 214 | printk(KERN_ERR DRV_NAME | 214 | printk(KERN_ERR DRV_NAME |
| 215 | ": Invalid Debounce/Columdrive Time from pdata\n"); | 215 | ": Invalid Debounce/Columdrive Time from pdata\n"); |
| 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index c8ed065ea0cb..abb04c82c622 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
| @@ -288,7 +288,7 @@ static int corgikbd_resume(struct platform_device *dev) | |||
| 288 | #define corgikbd_resume NULL | 288 | #define corgikbd_resume NULL |
| 289 | #endif | 289 | #endif |
| 290 | 290 | ||
| 291 | static int __init corgikbd_probe(struct platform_device *pdev) | 291 | static int __devinit corgikbd_probe(struct platform_device *pdev) |
| 292 | { | 292 | { |
| 293 | struct corgikbd *corgikbd; | 293 | struct corgikbd *corgikbd; |
| 294 | struct input_dev *input_dev; | 294 | struct input_dev *input_dev; |
| @@ -368,7 +368,7 @@ static int __init corgikbd_probe(struct platform_device *pdev) | |||
| 368 | return err; | 368 | return err; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static int corgikbd_remove(struct platform_device *pdev) | 371 | static int __devexit corgikbd_remove(struct platform_device *pdev) |
| 372 | { | 372 | { |
| 373 | int i; | 373 | int i; |
| 374 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); | 374 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); |
| @@ -388,7 +388,7 @@ static int corgikbd_remove(struct platform_device *pdev) | |||
| 388 | 388 | ||
| 389 | static struct platform_driver corgikbd_driver = { | 389 | static struct platform_driver corgikbd_driver = { |
| 390 | .probe = corgikbd_probe, | 390 | .probe = corgikbd_probe, |
| 391 | .remove = corgikbd_remove, | 391 | .remove = __devexit_p(corgikbd_remove), |
| 392 | .suspend = corgikbd_suspend, | 392 | .suspend = corgikbd_suspend, |
| 393 | .resume = corgikbd_resume, | 393 | .resume = corgikbd_resume, |
| 394 | .driver = { | 394 | .driver = { |
| @@ -397,7 +397,7 @@ static struct platform_driver corgikbd_driver = { | |||
| 397 | }, | 397 | }, |
| 398 | }; | 398 | }; |
| 399 | 399 | ||
| 400 | static int __devinit corgikbd_init(void) | 400 | static int __init corgikbd_init(void) |
| 401 | { | 401 | { |
| 402 | return platform_driver_register(&corgikbd_driver); | 402 | return platform_driver_register(&corgikbd_driver); |
| 403 | } | 403 | } |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 3f3d1198cdb1..058fa8b02c21 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
| @@ -279,7 +279,7 @@ static int omap_kp_resume(struct platform_device *dev) | |||
| 279 | #define omap_kp_resume NULL | 279 | #define omap_kp_resume NULL |
| 280 | #endif | 280 | #endif |
| 281 | 281 | ||
| 282 | static int __init omap_kp_probe(struct platform_device *pdev) | 282 | static int __devinit omap_kp_probe(struct platform_device *pdev) |
| 283 | { | 283 | { |
| 284 | struct omap_kp *omap_kp; | 284 | struct omap_kp *omap_kp; |
| 285 | struct input_dev *input_dev; | 285 | struct input_dev *input_dev; |
| @@ -422,7 +422,7 @@ err1: | |||
| 422 | return -EINVAL; | 422 | return -EINVAL; |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | static int omap_kp_remove(struct platform_device *pdev) | 425 | static int __devexit omap_kp_remove(struct platform_device *pdev) |
| 426 | { | 426 | { |
| 427 | struct omap_kp *omap_kp = platform_get_drvdata(pdev); | 427 | struct omap_kp *omap_kp = platform_get_drvdata(pdev); |
| 428 | 428 | ||
| @@ -454,7 +454,7 @@ static int omap_kp_remove(struct platform_device *pdev) | |||
| 454 | 454 | ||
| 455 | static struct platform_driver omap_kp_driver = { | 455 | static struct platform_driver omap_kp_driver = { |
| 456 | .probe = omap_kp_probe, | 456 | .probe = omap_kp_probe, |
| 457 | .remove = omap_kp_remove, | 457 | .remove = __devexit_p(omap_kp_remove), |
| 458 | .suspend = omap_kp_suspend, | 458 | .suspend = omap_kp_suspend, |
| 459 | .resume = omap_kp_resume, | 459 | .resume = omap_kp_resume, |
| 460 | .driver = { | 460 | .driver = { |
| @@ -463,7 +463,7 @@ static struct platform_driver omap_kp_driver = { | |||
| 463 | }, | 463 | }, |
| 464 | }; | 464 | }; |
| 465 | 465 | ||
| 466 | static int __devinit omap_kp_init(void) | 466 | static int __init omap_kp_init(void) |
| 467 | { | 467 | { |
| 468 | printk(KERN_INFO "OMAP Keypad Driver\n"); | 468 | printk(KERN_INFO "OMAP Keypad Driver\n"); |
| 469 | return platform_driver_register(&omap_kp_driver); | 469 | return platform_driver_register(&omap_kp_driver); |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index c48b76a46a58..9d1781a618e9 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c | |||
| @@ -343,7 +343,7 @@ static int spitzkbd_resume(struct platform_device *dev) | |||
| 343 | #define spitzkbd_resume NULL | 343 | #define spitzkbd_resume NULL |
| 344 | #endif | 344 | #endif |
| 345 | 345 | ||
| 346 | static int __init spitzkbd_probe(struct platform_device *dev) | 346 | static int __devinit spitzkbd_probe(struct platform_device *dev) |
| 347 | { | 347 | { |
| 348 | struct spitzkbd *spitzkbd; | 348 | struct spitzkbd *spitzkbd; |
| 349 | struct input_dev *input_dev; | 349 | struct input_dev *input_dev; |
| @@ -444,7 +444,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) | |||
| 444 | return err; | 444 | return err; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static int spitzkbd_remove(struct platform_device *dev) | 447 | static int __devexit spitzkbd_remove(struct platform_device *dev) |
| 448 | { | 448 | { |
| 449 | int i; | 449 | int i; |
| 450 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | 450 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); |
| @@ -470,7 +470,7 @@ static int spitzkbd_remove(struct platform_device *dev) | |||
| 470 | 470 | ||
| 471 | static struct platform_driver spitzkbd_driver = { | 471 | static struct platform_driver spitzkbd_driver = { |
| 472 | .probe = spitzkbd_probe, | 472 | .probe = spitzkbd_probe, |
| 473 | .remove = spitzkbd_remove, | 473 | .remove = __devexit_p(spitzkbd_remove), |
| 474 | .suspend = spitzkbd_suspend, | 474 | .suspend = spitzkbd_suspend, |
| 475 | .resume = spitzkbd_resume, | 475 | .resume = spitzkbd_resume, |
| 476 | .driver = { | 476 | .driver = { |
| @@ -479,7 +479,7 @@ static struct platform_driver spitzkbd_driver = { | |||
| 479 | }, | 479 | }, |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | static int __devinit spitzkbd_init(void) | 482 | static int __init spitzkbd_init(void) |
| 483 | { | 483 | { |
| 484 | return platform_driver_register(&spitzkbd_driver); | 484 | return platform_driver_register(&spitzkbd_driver); |
| 485 | } | 485 | } |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 9bef935ef19f..4f38e6f7dfdd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS | |||
| 70 | config MOUSE_PS2_LIFEBOOK | 70 | config MOUSE_PS2_LIFEBOOK |
| 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED |
| 72 | default y | 72 | default y |
| 73 | depends on MOUSE_PS2 | 73 | depends on MOUSE_PS2 && X86 |
| 74 | help | 74 | help |
| 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 | 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 |
| 76 | TouchScreen connected to your system. | 76 | TouchScreen connected to your system. |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b9a25d57bc5e..6ab0eb1ada1c 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -542,7 +542,7 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) | |||
| 542 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 542 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
| 543 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 543 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
| 544 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 544 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
| 545 | pr_err("elantech.c: sending Elantech magic knock failed.\n"); | 545 | pr_debug("elantech.c: sending Elantech magic knock failed.\n"); |
| 546 | return -1; | 546 | return -1; |
| 547 | } | 547 | } |
| 548 | 548 | ||
| @@ -551,8 +551,27 @@ int elantech_detect(struct psmouse *psmouse, int set_properties) | |||
| 551 | * set of magic numbers | 551 | * set of magic numbers |
| 552 | */ | 552 | */ |
| 553 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { | 553 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { |
| 554 | pr_info("elantech.c: unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | 554 | pr_debug("elantech.c: " |
| 555 | param[0], param[1], param[2]); | 555 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", |
| 556 | param[0], param[1], param[2]); | ||
| 557 | return -1; | ||
| 558 | } | ||
| 559 | |||
| 560 | /* | ||
| 561 | * Query touchpad's firmware version and see if it reports known | ||
| 562 | * value to avoid mis-detection. Logitech mice are known to respond | ||
| 563 | * to Elantech magic knock and there might be more. | ||
| 564 | */ | ||
| 565 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | ||
| 566 | pr_debug("elantech.c: failed to query firmware version.\n"); | ||
| 567 | return -1; | ||
| 568 | } | ||
| 569 | |||
| 570 | pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | ||
| 571 | param[0], param[1], param[2]); | ||
| 572 | |||
| 573 | if (param[0] == 0 || param[1] != 0) { | ||
| 574 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | ||
| 556 | return -1; | 575 | return -1; |
| 557 | } | 576 | } |
| 558 | 577 | ||
| @@ -600,8 +619,7 @@ int elantech_init(struct psmouse *psmouse) | |||
| 600 | int i, error; | 619 | int i, error; |
| 601 | unsigned char param[3]; | 620 | unsigned char param[3]; |
| 602 | 621 | ||
| 603 | etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 622 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
| 604 | psmouse->private = etd; | ||
| 605 | if (!etd) | 623 | if (!etd) |
| 606 | return -1; | 624 | return -1; |
| 607 | 625 | ||
| @@ -610,14 +628,12 @@ int elantech_init(struct psmouse *psmouse) | |||
| 610 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; | 628 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; |
| 611 | 629 | ||
| 612 | /* | 630 | /* |
| 613 | * Find out what version hardware this is | 631 | * Do the version query again so we can store the result |
| 614 | */ | 632 | */ |
| 615 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 633 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
| 616 | pr_err("elantech.c: failed to query firmware version.\n"); | 634 | pr_err("elantech.c: failed to query firmware version.\n"); |
| 617 | goto init_fail; | 635 | goto init_fail; |
| 618 | } | 636 | } |
| 619 | pr_info("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | ||
| 620 | param[0], param[1], param[2]); | ||
| 621 | etd->fw_version_maj = param[0]; | 637 | etd->fw_version_maj = param[0]; |
| 622 | etd->fw_version_min = param[2]; | 638 | etd->fw_version_min = param[2]; |
| 623 | 639 | ||
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index d297accf9a7f..1e827ad0afbe 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c | |||
| @@ -83,7 +83,7 @@ static int write_tbcr(struct pxa930_trkball *trkball, int v) | |||
| 83 | 83 | ||
| 84 | __raw_writel(v, trkball->mmio_base + TBCR); | 84 | __raw_writel(v, trkball->mmio_base + TBCR); |
| 85 | 85 | ||
| 86 | while (i--) { | 86 | while (--i) { |
| 87 | if (__raw_readl(trkball->mmio_base + TBCR) == v) | 87 | if (__raw_readl(trkball->mmio_base + TBCR) == v) |
| 88 | break; | 88 | break; |
| 89 | msleep(1); | 89 | msleep(1); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 865fc69e9bc3..f3e4f7b0240d 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -182,11 +182,6 @@ static int synaptics_identify(struct psmouse *psmouse) | |||
| 182 | 182 | ||
| 183 | static int synaptics_query_hardware(struct psmouse *psmouse) | 183 | static int synaptics_query_hardware(struct psmouse *psmouse) |
| 184 | { | 184 | { |
| 185 | int retries = 0; | ||
| 186 | |||
| 187 | while ((retries++ < 3) && psmouse_reset(psmouse)) | ||
| 188 | /* empty */; | ||
| 189 | |||
| 190 | if (synaptics_identify(psmouse)) | 185 | if (synaptics_identify(psmouse)) |
| 191 | return -1; | 186 | return -1; |
| 192 | if (synaptics_model_id(psmouse)) | 187 | if (synaptics_model_id(psmouse)) |
| @@ -582,6 +577,8 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
| 582 | struct synaptics_data *priv = psmouse->private; | 577 | struct synaptics_data *priv = psmouse->private; |
| 583 | struct synaptics_data old_priv = *priv; | 578 | struct synaptics_data old_priv = *priv; |
| 584 | 579 | ||
| 580 | psmouse_reset(psmouse); | ||
| 581 | |||
| 585 | if (synaptics_detect(psmouse, 0)) | 582 | if (synaptics_detect(psmouse, 0)) |
| 586 | return -1; | 583 | return -1; |
| 587 | 584 | ||
| @@ -640,6 +637,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 640 | if (!priv) | 637 | if (!priv) |
| 641 | return -1; | 638 | return -1; |
| 642 | 639 | ||
| 640 | psmouse_reset(psmouse); | ||
| 641 | |||
| 643 | if (synaptics_query_hardware(psmouse)) { | 642 | if (synaptics_query_hardware(psmouse)) { |
| 644 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 643 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); |
| 645 | goto init_fail; | 644 | goto init_fail; |
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index b10ffae7c39b..e29cdc13a199 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
| @@ -57,7 +57,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val) | |||
| 57 | struct amba_kmi_port *kmi = io->port_data; | 57 | struct amba_kmi_port *kmi = io->port_data; |
| 58 | unsigned int timeleft = 10000; /* timeout in 100ms */ | 58 | unsigned int timeleft = 10000; /* timeout in 100ms */ |
| 59 | 59 | ||
| 60 | while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) | 60 | while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && --timeleft) |
| 61 | udelay(10); | 61 | udelay(10); |
| 62 | 62 | ||
| 63 | if (timeleft) | 63 | if (timeleft) |
| @@ -129,8 +129,8 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) | |||
| 129 | io->write = amba_kmi_write; | 129 | io->write = amba_kmi_write; |
| 130 | io->open = amba_kmi_open; | 130 | io->open = amba_kmi_open; |
| 131 | io->close = amba_kmi_close; | 131 | io->close = amba_kmi_close; |
| 132 | strlcpy(io->name, dev->dev.bus_id, sizeof(io->name)); | 132 | strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name)); |
| 133 | strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys)); | 133 | strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys)); |
| 134 | io->port_data = kmi; | 134 | io->port_data = kmi; |
| 135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
| 136 | 136 | ||
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index adc3bd6e7f7b..bd0f92d9f40f 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
| @@ -359,7 +359,7 @@ static int __init gscps2_probe(struct parisc_device *dev) | |||
| 359 | 359 | ||
| 360 | snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", | 360 | snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s", |
| 361 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); | 361 | (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse"); |
| 362 | strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); | 362 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); |
| 363 | serio->id.type = SERIO_8042; | 363 | serio->id.type = SERIO_8042; |
| 364 | serio->write = gscps2_write; | 364 | serio->write = gscps2_write; |
| 365 | serio->open = gscps2_open; | 365 | serio->open = gscps2_open; |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2ad88780a170..57953c0eb82f 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
| @@ -246,8 +246,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) | |||
| 246 | serio->write = ps2_write; | 246 | serio->write = ps2_write; |
| 247 | serio->open = ps2_open; | 247 | serio->open = ps2_open; |
| 248 | serio->close = ps2_close; | 248 | serio->close = ps2_close; |
| 249 | strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name)); | 249 | strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name)); |
| 250 | strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys)); | 250 | strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys)); |
| 251 | serio->port_data = ps2if; | 251 | serio->port_data = ps2if; |
| 252 | serio->dev.parent = &dev->dev; | 252 | serio->dev.parent = &dev->dev; |
| 253 | ps2if->io = serio; | 253 | ps2if->io = serio; |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index a89a6a8f05e6..055969e8be13 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -236,7 +236,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 236 | ts_dev->bufferedmeasure = 0; | 236 | ts_dev->bufferedmeasure = 0; |
| 237 | 237 | ||
| 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), | 238 | snprintf(ts_dev->phys, sizeof(ts_dev->phys), |
| 239 | "%s/input0", pdev->dev.bus_id); | 239 | "%s/input0", dev_name(&pdev->dev)); |
| 240 | 240 | ||
| 241 | input_dev->name = "atmel touch screen controller"; | 241 | input_dev->name = "atmel touch screen controller"; |
| 242 | input_dev->phys = ts_dev->phys; | 242 | input_dev->phys = ts_dev->phys; |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 65202c9f63ff..3fb51b54fe61 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c | |||
| @@ -268,7 +268,7 @@ static int corgits_resume(struct platform_device *dev) | |||
| 268 | #define corgits_resume NULL | 268 | #define corgits_resume NULL |
| 269 | #endif | 269 | #endif |
| 270 | 270 | ||
| 271 | static int __init corgits_probe(struct platform_device *pdev) | 271 | static int __devinit corgits_probe(struct platform_device *pdev) |
| 272 | { | 272 | { |
| 273 | struct corgi_ts *corgi_ts; | 273 | struct corgi_ts *corgi_ts; |
| 274 | struct input_dev *input_dev; | 274 | struct input_dev *input_dev; |
| @@ -343,7 +343,7 @@ static int __init corgits_probe(struct platform_device *pdev) | |||
| 343 | return err; | 343 | return err; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static int corgits_remove(struct platform_device *pdev) | 346 | static int __devexit corgits_remove(struct platform_device *pdev) |
| 347 | { | 347 | { |
| 348 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); | 348 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); |
| 349 | 349 | ||
| @@ -352,12 +352,13 @@ static int corgits_remove(struct platform_device *pdev) | |||
| 352 | corgi_ts->machinfo->put_hsync(); | 352 | corgi_ts->machinfo->put_hsync(); |
| 353 | input_unregister_device(corgi_ts->input); | 353 | input_unregister_device(corgi_ts->input); |
| 354 | kfree(corgi_ts); | 354 | kfree(corgi_ts); |
| 355 | |||
| 355 | return 0; | 356 | return 0; |
| 356 | } | 357 | } |
| 357 | 358 | ||
| 358 | static struct platform_driver corgits_driver = { | 359 | static struct platform_driver corgits_driver = { |
| 359 | .probe = corgits_probe, | 360 | .probe = corgits_probe, |
| 360 | .remove = corgits_remove, | 361 | .remove = __devexit_p(corgits_remove), |
| 361 | .suspend = corgits_suspend, | 362 | .suspend = corgits_suspend, |
| 362 | .resume = corgits_resume, | 363 | .resume = corgits_resume, |
| 363 | .driver = { | 364 | .driver = { |
| @@ -366,7 +367,7 @@ static struct platform_driver corgits_driver = { | |||
| 366 | }, | 367 | }, |
| 367 | }; | 368 | }; |
| 368 | 369 | ||
| 369 | static int __devinit corgits_init(void) | 370 | static int __init corgits_init(void) |
| 370 | { | 371 | { |
| 371 | return platform_driver_register(&corgits_driver); | 372 | return platform_driver_register(&corgits_driver); |
| 372 | } | 373 | } |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index b75dc2990574..4ab070246892 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
| @@ -289,7 +289,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 289 | 289 | ||
| 290 | pdata->init_platform_hw(); | 290 | pdata->init_platform_hw(); |
| 291 | 291 | ||
| 292 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id); | 292 | snprintf(ts->phys, sizeof(ts->phys), |
| 293 | "%s/input0", dev_name(&client->dev)); | ||
| 293 | 294 | ||
| 294 | input_dev->name = "TSC2007 Touchscreen"; | 295 | input_dev->name = "TSC2007 Touchscreen"; |
| 295 | input_dev->phys = ts->phys; | 296 | input_dev->phys = ts->phys; |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 5080b26ba160..fb7cb9bdfbd5 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -60,6 +60,10 @@ static int swap_xy; | |||
| 60 | module_param(swap_xy, bool, 0644); | 60 | module_param(swap_xy, bool, 0644); |
| 61 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 61 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); |
| 62 | 62 | ||
| 63 | static int hwcalib_xy; | ||
| 64 | module_param(hwcalib_xy, bool, 0644); | ||
| 65 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | ||
| 66 | |||
| 63 | /* device specifc data/functions */ | 67 | /* device specifc data/functions */ |
| 64 | struct usbtouch_usb; | 68 | struct usbtouch_usb; |
| 65 | struct usbtouch_device_info { | 69 | struct usbtouch_device_info { |
| @@ -118,6 +122,7 @@ enum { | |||
| 118 | 122 | ||
| 119 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| 120 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ | 124 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ |
| 125 | | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | ||
| 121 | | USB_DEVICE_ID_MATCH_DEVICE, \ | 126 | | USB_DEVICE_ID_MATCH_DEVICE, \ |
| 122 | .idVendor = (vend), \ | 127 | .idVendor = (vend), \ |
| 123 | .idProduct = (prod), \ | 128 | .idProduct = (prod), \ |
| @@ -260,8 +265,13 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 260 | 265 | ||
| 261 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 266 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
| 262 | { | 267 | { |
| 263 | dev->x = (pkt[8] << 8) | pkt[7]; | 268 | if (hwcalib_xy) { |
| 264 | dev->y = (pkt[10] << 8) | pkt[9]; | 269 | dev->x = (pkt[4] << 8) | pkt[3]; |
| 270 | dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); | ||
| 271 | } else { | ||
| 272 | dev->x = (pkt[8] << 8) | pkt[7]; | ||
| 273 | dev->y = (pkt[10] << 8) | pkt[9]; | ||
| 274 | } | ||
| 265 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; | 275 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; |
| 266 | 276 | ||
| 267 | return 1; | 277 | return 1; |
| @@ -294,6 +304,12 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
| 294 | return ret; | 304 | return ret; |
| 295 | } | 305 | } |
| 296 | 306 | ||
| 307 | /* Default min/max xy are the raw values, override if using hw-calib */ | ||
| 308 | if (hwcalib_xy) { | ||
| 309 | input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); | ||
| 310 | input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); | ||
| 311 | } | ||
| 312 | |||
| 297 | return 0; | 313 | return 0; |
| 298 | } | 314 | } |
| 299 | #endif | 315 | #endif |
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index c1e4ae27c613..c705f248da88 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c | |||
| @@ -46,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev) | |||
| 46 | usb_to_input_id(udev, &input->id); | 46 | usb_to_input_id(udev, &input->id); |
| 47 | input->dev.parent = &dev->intf->dev; | 47 | input->dev.parent = &dev->intf->dev; |
| 48 | 48 | ||
| 49 | set_bit(EV_KEY, input->evbit); | 49 | __set_bit(EV_KEY, input->evbit); |
| 50 | set_bit(BTN_0, input->keybit); | 50 | __set_bit(KEY_CAMERA, input->keybit); |
| 51 | 51 | ||
| 52 | if ((ret = input_register_device(input)) < 0) | 52 | if ((ret = input_register_device(input)) < 0) |
| 53 | goto error; | 53 | goto error; |
| @@ -70,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) | |||
| 70 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, | 70 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, |
| 71 | int value) | 71 | int value) |
| 72 | { | 72 | { |
| 73 | if (dev->input) | 73 | if (dev->input) { |
| 74 | input_report_key(dev->input, code, value); | 74 | input_report_key(dev->input, code, value); |
| 75 | input_sync(dev->input); | ||
| 76 | } | ||
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | #else | 79 | #else |
| @@ -96,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) | |||
| 96 | return; | 98 | return; |
| 97 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", | 99 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", |
| 98 | data[1], data[3] ? "pressed" : "released", len); | 100 | data[1], data[3] ? "pressed" : "released", len); |
| 99 | uvc_input_report_key(dev, BTN_0, data[3]); | 101 | uvc_input_report_key(dev, KEY_CAMERA, data[3]); |
| 100 | } else { | 102 | } else { |
| 101 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " | 103 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " |
| 102 | "len %d.\n", data[1], data[2], data[3], len); | 104 | "len %d.\n", data[1], data[2], data[3], len); |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 96ac88317b8e..ea3aafbbda44 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
| @@ -91,9 +91,9 @@ MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \ | |||
| 91 | controllers (default=0)"); | 91 | controllers (default=0)"); |
| 92 | 92 | ||
| 93 | static int mpt_msi_enable_sas; | 93 | static int mpt_msi_enable_sas; |
| 94 | module_param(mpt_msi_enable_sas, int, 1); | 94 | module_param(mpt_msi_enable_sas, int, 0); |
| 95 | MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ | 95 | MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \ |
| 96 | controllers (default=1)"); | 96 | controllers (default=0)"); |
| 97 | 97 | ||
| 98 | 98 | ||
| 99 | static int mpt_channel_mapping; | 99 | static int mpt_channel_mapping; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8cff5f5e7f86..406da9a8d453 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -107,6 +107,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { | |||
| 107 | 107 | ||
| 108 | static const struct sdhci_pci_fixes sdhci_cafe = { | 108 | static const struct sdhci_pci_fixes sdhci_cafe = { |
| 109 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | 109 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | |
| 110 | SDHCI_QUIRK_NO_BUSY_IRQ | | ||
| 110 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, | 111 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, |
| 111 | }; | 112 | }; |
| 112 | 113 | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f52f3053ed92..accb592764ed 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -1291,8 +1291,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
| 1291 | if (host->cmd->data) | 1291 | if (host->cmd->data) |
| 1292 | DBG("Cannot wait for busy signal when also " | 1292 | DBG("Cannot wait for busy signal when also " |
| 1293 | "doing a data transfer"); | 1293 | "doing a data transfer"); |
| 1294 | else | 1294 | else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)) |
| 1295 | return; | 1295 | return; |
| 1296 | |||
| 1297 | /* The controller does not support the end-of-busy IRQ, | ||
| 1298 | * fall through and take the SDHCI_INT_RESPONSE */ | ||
| 1296 | } | 1299 | } |
| 1297 | 1300 | ||
| 1298 | if (intmask & SDHCI_INT_RESPONSE) | 1301 | if (intmask & SDHCI_INT_RESPONSE) |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index ebb83657e27a..43c37c68d07a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -208,6 +208,8 @@ struct sdhci_host { | |||
| 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) |
| 209 | /* Controller has an issue with buffer bits for small transfers */ | 209 | /* Controller has an issue with buffer bits for small transfers */ |
| 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) |
| 211 | /* Controller does not provide transfer-complete interrupt when not busy */ | ||
| 212 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | ||
| 211 | 213 | ||
| 212 | int irq; /* Device IRQ */ | 214 | int irq; /* Device IRQ */ |
| 213 | void __iomem * ioaddr; /* Mapped address */ | 215 | void __iomem * ioaddr; /* Mapped address */ |
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 917cf8d3ae95..c2dfd3ea353d 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
| @@ -149,7 +149,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev) | |||
| 149 | 149 | ||
| 150 | static struct platform_driver orion_nand_driver = { | 150 | static struct platform_driver orion_nand_driver = { |
| 151 | .probe = orion_nand_probe, | 151 | .probe = orion_nand_probe, |
| 152 | .remove = orion_nand_remove, | 152 | .remove = __devexit_p(orion_nand_remove), |
| 153 | .driver = { | 153 | .driver = { |
| 154 | .name = "orion_nand", | 154 | .name = "orion_nand", |
| 155 | .owner = THIS_MODULE, | 155 | .owner = THIS_MODULE, |
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile index c69c0cdba4a2..811a3ccd14c1 100644 --- a/drivers/net/arm/Makefile +++ b/drivers/net/arm/Makefile | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o | 6 | obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o |
| 7 | obj-$(CONFIG_ARM_ETHERH) += etherh.o ../8390.o | 7 | obj-$(CONFIG_ARM_ETHERH) += etherh.o |
| 8 | obj-$(CONFIG_ARM_ETHER3) += ether3.o | 8 | obj-$(CONFIG_ARM_ETHER3) += ether3.o |
| 9 | obj-$(CONFIG_ARM_ETHER1) += ether1.o | 9 | obj-$(CONFIG_ARM_ETHER1) += ether1.o |
| 10 | obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o | 10 | obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o |
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 54b52e5b1821..f52f668c49bf 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c | |||
| @@ -641,15 +641,15 @@ static const struct net_device_ops etherh_netdev_ops = { | |||
| 641 | .ndo_open = etherh_open, | 641 | .ndo_open = etherh_open, |
| 642 | .ndo_stop = etherh_close, | 642 | .ndo_stop = etherh_close, |
| 643 | .ndo_set_config = etherh_set_config, | 643 | .ndo_set_config = etherh_set_config, |
| 644 | .ndo_start_xmit = ei_start_xmit, | 644 | .ndo_start_xmit = __ei_start_xmit, |
| 645 | .ndo_tx_timeout = ei_tx_timeout, | 645 | .ndo_tx_timeout = __ei_tx_timeout, |
| 646 | .ndo_get_stats = ei_get_stats, | 646 | .ndo_get_stats = __ei_get_stats, |
| 647 | .ndo_set_multicast_list = ei_set_multicast_list, | 647 | .ndo_set_multicast_list = __ei_set_multicast_list, |
| 648 | .ndo_validate_addr = eth_validate_addr, | 648 | .ndo_validate_addr = eth_validate_addr, |
| 649 | .ndo_set_mac_address = eth_mac_addr, | 649 | .ndo_set_mac_address = eth_mac_addr, |
| 650 | .ndo_change_mtu = eth_change_mtu, | 650 | .ndo_change_mtu = eth_change_mtu, |
| 651 | #ifdef CONFIG_NET_POLL_CONTROLLER | 651 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 652 | .ndo_poll_controller = ei_poll, | 652 | .ndo_poll_controller = __ei_poll, |
| 653 | #endif | 653 | #endif |
| 654 | }; | 654 | }; |
| 655 | 655 | ||
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c38512ebcea6..dc5f051005fa 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
| @@ -1264,8 +1264,14 @@ static void b44_clear_stats(struct b44 *bp) | |||
| 1264 | static void b44_chip_reset(struct b44 *bp, int reset_kind) | 1264 | static void b44_chip_reset(struct b44 *bp, int reset_kind) |
| 1265 | { | 1265 | { |
| 1266 | struct ssb_device *sdev = bp->sdev; | 1266 | struct ssb_device *sdev = bp->sdev; |
| 1267 | bool was_enabled; | ||
| 1267 | 1268 | ||
| 1268 | if (ssb_device_is_enabled(bp->sdev)) { | 1269 | was_enabled = ssb_device_is_enabled(bp->sdev); |
| 1270 | |||
| 1271 | ssb_device_enable(bp->sdev, 0); | ||
| 1272 | ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); | ||
| 1273 | |||
| 1274 | if (was_enabled) { | ||
| 1269 | bw32(bp, B44_RCV_LAZY, 0); | 1275 | bw32(bp, B44_RCV_LAZY, 0); |
| 1270 | bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); | 1276 | bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE); |
| 1271 | b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); | 1277 | b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1); |
| @@ -1277,10 +1283,8 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind) | |||
| 1277 | } | 1283 | } |
| 1278 | bw32(bp, B44_DMARX_CTRL, 0); | 1284 | bw32(bp, B44_DMARX_CTRL, 0); |
| 1279 | bp->rx_prod = bp->rx_cons = 0; | 1285 | bp->rx_prod = bp->rx_cons = 0; |
| 1280 | } else | 1286 | } |
| 1281 | ssb_pcicore_dev_irqvecs_enable(&sdev->bus->pcicore, sdev); | ||
| 1282 | 1287 | ||
| 1283 | ssb_device_enable(bp->sdev, 0); | ||
| 1284 | b44_clear_stats(bp); | 1288 | b44_clear_stats(bp); |
| 1285 | 1289 | ||
| 1286 | /* | 1290 | /* |
| @@ -2236,6 +2240,7 @@ static void __devexit b44_remove_one(struct ssb_device *sdev) | |||
| 2236 | struct net_device *dev = ssb_get_drvdata(sdev); | 2240 | struct net_device *dev = ssb_get_drvdata(sdev); |
| 2237 | 2241 | ||
| 2238 | unregister_netdev(dev); | 2242 | unregister_netdev(dev); |
| 2243 | ssb_device_disable(sdev, 0); | ||
| 2239 | ssb_bus_may_powerdown(sdev->bus); | 2244 | ssb_bus_may_powerdown(sdev->bus); |
| 2240 | free_netdev(dev); | 2245 | free_netdev(dev); |
| 2241 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); | 2246 | ssb_pcihost_set_power_state(sdev, PCI_D3hot); |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 9b12a13a640f..9831b3f408aa 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -1284,7 +1284,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1284 | spin_lock_irqsave(&priv->txlock, flags); | 1284 | spin_lock_irqsave(&priv->txlock, flags); |
| 1285 | 1285 | ||
| 1286 | /* check if there is space to queue this packet */ | 1286 | /* check if there is space to queue this packet */ |
| 1287 | if (nr_frags > priv->num_txbdfree) { | 1287 | if ((nr_frags+1) > priv->num_txbdfree) { |
| 1288 | /* no space, stop the queue */ | 1288 | /* no space, stop the queue */ |
| 1289 | netif_stop_queue(dev); | 1289 | netif_stop_queue(dev); |
| 1290 | dev->stats.tx_fifo_errors++; | 1290 | dev->stats.tx_fifo_errors++; |
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 5e070f446635..0486cbe01adb 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c | |||
| @@ -467,7 +467,7 @@ init_module(void) | |||
| 467 | if (this_dev != 0) break; /* only autoprobe 1st one */ | 467 | if (this_dev != 0) break; /* only autoprobe 1st one */ |
| 468 | printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); | 468 | printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n"); |
| 469 | } | 469 | } |
| 470 | dev = alloc_ei_netdev(); | 470 | dev = alloc_eip_netdev(); |
| 471 | if (!dev) | 471 | if (!dev) |
| 472 | break; | 472 | break; |
| 473 | dev->irq = irq[this_dev]; | 473 | dev->irq = irq[this_dev]; |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 9f33e442f403..13087782ac40 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
| @@ -588,7 +588,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 588 | adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; | 588 | adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; |
| 589 | adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; | 589 | adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; |
| 590 | 590 | ||
| 591 | mem_ptr0 = ioremap(mem_base, mem_len); | 591 | mem_ptr0 = pci_ioremap_bar(pdev, 0); |
| 592 | if (mem_ptr0 == NULL) { | ||
| 593 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); | ||
| 594 | return -EIO; | ||
| 595 | } | ||
| 596 | |||
| 592 | pci_len0 = mem_len; | 597 | pci_len0 = mem_len; |
| 593 | first_page_group_start = 0; | 598 | first_page_group_start = 0; |
| 594 | first_page_group_end = 0; | 599 | first_page_group_end = 0; |
| @@ -795,9 +800,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 795 | * See if the firmware gave us a virtual-physical port mapping. | 800 | * See if the firmware gave us a virtual-physical port mapping. |
| 796 | */ | 801 | */ |
| 797 | adapter->physical_port = adapter->portnum; | 802 | adapter->physical_port = adapter->portnum; |
| 798 | i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum)); | 803 | if (adapter->fw_major < 4) { |
| 799 | if (i != 0x55555555) | 804 | i = adapter->pci_read_normalize(adapter, |
| 800 | adapter->physical_port = i; | 805 | CRB_V2P(adapter->portnum)); |
| 806 | if (i != 0x55555555) | ||
| 807 | adapter->physical_port = i; | ||
| 808 | } | ||
| 801 | 809 | ||
| 802 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); | 810 | adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); |
| 803 | 811 | ||
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0771eb6fc6eb..b3473401c83a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32; | |||
| 81 | #define RTL8169_TX_TIMEOUT (6*HZ) | 81 | #define RTL8169_TX_TIMEOUT (6*HZ) |
| 82 | #define RTL8169_PHY_TIMEOUT (10*HZ) | 82 | #define RTL8169_PHY_TIMEOUT (10*HZ) |
| 83 | 83 | ||
| 84 | #define RTL_EEPROM_SIG cpu_to_le32(0x8129) | 84 | #define RTL_EEPROM_SIG 0x8129 |
| 85 | #define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) | ||
| 86 | #define RTL_EEPROM_SIG_ADDR 0x0000 | 85 | #define RTL_EEPROM_SIG_ADDR 0x0000 |
| 86 | #define RTL_EEPROM_MAC_ADDR 0x0007 | ||
| 87 | 87 | ||
| 88 | /* write/read MMIO register */ | 88 | /* write/read MMIO register */ |
| 89 | #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) | 89 | #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) |
| @@ -293,6 +293,11 @@ enum rtl_register_content { | |||
| 293 | /* Cfg9346Bits */ | 293 | /* Cfg9346Bits */ |
| 294 | Cfg9346_Lock = 0x00, | 294 | Cfg9346_Lock = 0x00, |
| 295 | Cfg9346_Unlock = 0xc0, | 295 | Cfg9346_Unlock = 0xc0, |
| 296 | Cfg9346_Program = 0x80, /* Programming mode */ | ||
| 297 | Cfg9346_EECS = 0x08, /* Chip select */ | ||
| 298 | Cfg9346_EESK = 0x04, /* Serial data clock */ | ||
| 299 | Cfg9346_EEDI = 0x02, /* Data input */ | ||
| 300 | Cfg9346_EEDO = 0x01, /* Data output */ | ||
| 296 | 301 | ||
| 297 | /* rx_mode_bits */ | 302 | /* rx_mode_bits */ |
| 298 | AcceptErr = 0x20, | 303 | AcceptErr = 0x20, |
| @@ -305,6 +310,7 @@ enum rtl_register_content { | |||
| 305 | /* RxConfigBits */ | 310 | /* RxConfigBits */ |
| 306 | RxCfgFIFOShift = 13, | 311 | RxCfgFIFOShift = 13, |
| 307 | RxCfgDMAShift = 8, | 312 | RxCfgDMAShift = 8, |
| 313 | RxCfg9356SEL = 6, /* EEPROM type: 0 = 9346, 1 = 9356 */ | ||
| 308 | 314 | ||
| 309 | /* TxConfigBits */ | 315 | /* TxConfigBits */ |
| 310 | TxInterFrameGapShift = 24, | 316 | TxInterFrameGapShift = 24, |
| @@ -1963,6 +1969,108 @@ static const struct net_device_ops rtl8169_netdev_ops = { | |||
| 1963 | 1969 | ||
| 1964 | }; | 1970 | }; |
| 1965 | 1971 | ||
| 1972 | /* Delay between EEPROM clock transitions. Force out buffered PCI writes. */ | ||
| 1973 | #define RTL_EEPROM_DELAY() RTL_R8(Cfg9346) | ||
| 1974 | #define RTL_EEPROM_READ_CMD 6 | ||
| 1975 | |||
| 1976 | /* read 16bit word stored in EEPROM. EEPROM is addressed by words. */ | ||
| 1977 | static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr) | ||
| 1978 | { | ||
| 1979 | u16 result = 0; | ||
| 1980 | int cmd, cmd_len, i; | ||
| 1981 | |||
| 1982 | /* check for EEPROM address size (in bits) */ | ||
| 1983 | if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) { | ||
| 1984 | /* EEPROM is 93C56 */ | ||
| 1985 | cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */ | ||
| 1986 | cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff); | ||
| 1987 | } else { | ||
| 1988 | /* EEPROM is 93C46 */ | ||
| 1989 | cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */ | ||
| 1990 | cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f); | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | /* enter programming mode */ | ||
| 1994 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 1995 | RTL_EEPROM_DELAY(); | ||
| 1996 | |||
| 1997 | /* write command and requested address */ | ||
| 1998 | while (cmd_len--) { | ||
| 1999 | u8 x = Cfg9346_Program | Cfg9346_EECS; | ||
| 2000 | |||
| 2001 | x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0; | ||
| 2002 | |||
| 2003 | /* write a bit */ | ||
| 2004 | RTL_W8(Cfg9346, x); | ||
| 2005 | RTL_EEPROM_DELAY(); | ||
| 2006 | |||
| 2007 | /* raise clock */ | ||
| 2008 | RTL_W8(Cfg9346, x | Cfg9346_EESK); | ||
| 2009 | RTL_EEPROM_DELAY(); | ||
| 2010 | } | ||
| 2011 | |||
| 2012 | /* lower clock */ | ||
| 2013 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 2014 | RTL_EEPROM_DELAY(); | ||
| 2015 | |||
| 2016 | /* read back 16bit value */ | ||
| 2017 | for (i = 16; i > 0; i--) { | ||
| 2018 | /* raise clock */ | ||
| 2019 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK); | ||
| 2020 | RTL_EEPROM_DELAY(); | ||
| 2021 | |||
| 2022 | result <<= 1; | ||
| 2023 | result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0; | ||
| 2024 | |||
| 2025 | /* lower clock */ | ||
| 2026 | RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); | ||
| 2027 | RTL_EEPROM_DELAY(); | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | RTL_W8(Cfg9346, Cfg9346_Program); | ||
| 2031 | /* leave programming mode */ | ||
| 2032 | RTL_W8(Cfg9346, Cfg9346_Lock); | ||
| 2033 | |||
| 2034 | return result; | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | static void rtl_init_mac_address(struct rtl8169_private *tp, | ||
| 2038 | void __iomem *ioaddr) | ||
| 2039 | { | ||
| 2040 | struct pci_dev *pdev = tp->pci_dev; | ||
| 2041 | u16 x; | ||
| 2042 | u8 mac[8]; | ||
| 2043 | |||
| 2044 | /* read EEPROM signature */ | ||
| 2045 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR); | ||
| 2046 | |||
| 2047 | if (x != RTL_EEPROM_SIG) { | ||
| 2048 | dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x); | ||
| 2049 | return; | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | /* read MAC address */ | ||
| 2053 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR); | ||
| 2054 | mac[0] = x & 0xff; | ||
| 2055 | mac[1] = x >> 8; | ||
| 2056 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1); | ||
| 2057 | mac[2] = x & 0xff; | ||
| 2058 | mac[3] = x >> 8; | ||
| 2059 | x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2); | ||
| 2060 | mac[4] = x & 0xff; | ||
| 2061 | mac[5] = x >> 8; | ||
| 2062 | |||
| 2063 | if (netif_msg_probe(tp)) { | ||
| 2064 | DECLARE_MAC_BUF(buf); | ||
| 2065 | |||
| 2066 | dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n", | ||
| 2067 | print_mac(buf, mac)); | ||
| 2068 | } | ||
| 2069 | |||
| 2070 | if (is_valid_ether_addr(mac)) | ||
| 2071 | rtl_rar_set(tp, mac); | ||
| 2072 | } | ||
| 2073 | |||
| 1966 | static int __devinit | 2074 | static int __devinit |
| 1967 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2075 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 1968 | { | 2076 | { |
| @@ -2141,6 +2249,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2141 | 2249 | ||
| 2142 | tp->mmio_addr = ioaddr; | 2250 | tp->mmio_addr = ioaddr; |
| 2143 | 2251 | ||
| 2252 | rtl_init_mac_address(tp, ioaddr); | ||
| 2253 | |||
| 2144 | /* Get MAC address */ | 2254 | /* Get MAC address */ |
| 2145 | for (i = 0; i < MAC_ADDR_LEN; i++) | 2255 | for (i = 0; i < MAC_ADDR_LEN; i++) |
| 2146 | dev->dev_addr[i] = RTL_R8(MAC0 + i); | 2256 | dev->dev_addr[i] = RTL_R8(MAC0 + i); |
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e009481c606c..396f821b5ff0 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
| @@ -1451,6 +1451,14 @@ static const struct usb_device_id products [] = { | |||
| 1451 | // Cables-to-Go USB Ethernet Adapter | 1451 | // Cables-to-Go USB Ethernet Adapter |
| 1452 | USB_DEVICE(0x0b95, 0x772a), | 1452 | USB_DEVICE(0x0b95, 0x772a), |
| 1453 | .driver_info = (unsigned long) &ax88772_info, | 1453 | .driver_info = (unsigned long) &ax88772_info, |
| 1454 | }, { | ||
| 1455 | // ABOCOM for pci | ||
| 1456 | USB_DEVICE(0x14ea, 0xab11), | ||
| 1457 | .driver_info = (unsigned long) &ax88178_info, | ||
| 1458 | }, { | ||
| 1459 | // ASIX 88772a | ||
| 1460 | USB_DEVICE(0x0db0, 0xa877), | ||
| 1461 | .driver_info = (unsigned long) &ax88772_info, | ||
| 1454 | }, | 1462 | }, |
| 1455 | { }, // END | 1463 | { }, // END |
| 1456 | }; | 1464 | }; |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 0e061dfea78d..55e8ecc3a9e5 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -559,6 +559,11 @@ static const struct usb_device_id products [] = { | |||
| 559 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, | 559 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, |
| 560 | USB_CDC_PROTO_NONE), | 560 | USB_CDC_PROTO_NONE), |
| 561 | .driver_info = (unsigned long) &cdc_info, | 561 | .driver_info = (unsigned long) &cdc_info, |
| 562 | }, { | ||
| 563 | /* Ericsson F3507g */ | ||
| 564 | USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1900, USB_CLASS_COMM, | ||
| 565 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 566 | .driver_info = (unsigned long) &cdc_info, | ||
| 562 | }, | 567 | }, |
| 563 | { }, // END | 568 | { }, // END |
| 564 | }; | 569 | }; |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index aa3149078888..c32284ff3f54 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -723,8 +723,8 @@ u32 usbnet_get_link (struct net_device *net) | |||
| 723 | if (dev->mii.mdio_read) | 723 | if (dev->mii.mdio_read) |
| 724 | return mii_link_ok(&dev->mii); | 724 | return mii_link_ok(&dev->mii); |
| 725 | 725 | ||
| 726 | /* Otherwise, say we're up (to avoid breaking scripts) */ | 726 | /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */ |
| 727 | return 1; | 727 | return ethtool_op_get_link(net); |
| 728 | } | 728 | } |
| 729 | EXPORT_SYMBOL_GPL(usbnet_get_link); | 729 | EXPORT_SYMBOL_GPL(usbnet_get_link); |
| 730 | 730 | ||
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index e24f7b3ace4b..04882c8f9bf1 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c | |||
| @@ -341,6 +341,11 @@ static const struct usb_device_id products [] = { | |||
| 341 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, | 341 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, |
| 342 | USB_CDC_PROTO_NONE), | 342 | USB_CDC_PROTO_NONE), |
| 343 | .driver_info = (unsigned long) &bogus_mdlm_info, | 343 | .driver_info = (unsigned long) &bogus_mdlm_info, |
| 344 | }, { | ||
| 345 | /* Motorola MOTOMAGX phones */ | ||
| 346 | USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, | ||
| 347 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | ||
| 348 | .driver_info = (unsigned long) &bogus_mdlm_info, | ||
| 344 | }, | 349 | }, |
| 345 | 350 | ||
| 346 | /* Olympus has some models with a Zaurus-compatible option. | 351 | /* Olympus has some models with a Zaurus-compatible option. |
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 108bbbeacfb6..124fe75b8a8a 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -239,6 +239,16 @@ static int veth_open(struct net_device *dev) | |||
| 239 | return 0; | 239 | return 0; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | static int veth_close(struct net_device *dev) | ||
| 243 | { | ||
| 244 | struct veth_priv *priv = netdev_priv(dev); | ||
| 245 | |||
| 246 | netif_carrier_off(dev); | ||
| 247 | netif_carrier_off(priv->peer); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 242 | static int veth_dev_init(struct net_device *dev) | 252 | static int veth_dev_init(struct net_device *dev) |
| 243 | { | 253 | { |
| 244 | struct veth_net_stats *stats; | 254 | struct veth_net_stats *stats; |
| @@ -265,6 +275,7 @@ static void veth_dev_free(struct net_device *dev) | |||
| 265 | static const struct net_device_ops veth_netdev_ops = { | 275 | static const struct net_device_ops veth_netdev_ops = { |
| 266 | .ndo_init = veth_dev_init, | 276 | .ndo_init = veth_dev_init, |
| 267 | .ndo_open = veth_open, | 277 | .ndo_open = veth_open, |
| 278 | .ndo_stop = veth_close, | ||
| 268 | .ndo_start_xmit = veth_xmit, | 279 | .ndo_start_xmit = veth_xmit, |
| 269 | .ndo_get_stats = veth_get_stats, | 280 | .ndo_get_stats = veth_get_stats, |
| 270 | .ndo_set_mac_address = eth_mac_addr, | 281 | .ndo_set_mac_address = eth_mac_addr, |
| @@ -280,44 +291,6 @@ static void veth_setup(struct net_device *dev) | |||
| 280 | dev->destructor = veth_dev_free; | 291 | dev->destructor = veth_dev_free; |
| 281 | } | 292 | } |
| 282 | 293 | ||
| 283 | static void veth_change_state(struct net_device *dev) | ||
| 284 | { | ||
| 285 | struct net_device *peer; | ||
| 286 | struct veth_priv *priv; | ||
| 287 | |||
| 288 | priv = netdev_priv(dev); | ||
| 289 | peer = priv->peer; | ||
| 290 | |||
| 291 | if (netif_carrier_ok(peer)) { | ||
| 292 | if (!netif_carrier_ok(dev)) | ||
| 293 | netif_carrier_on(dev); | ||
| 294 | } else { | ||
| 295 | if (netif_carrier_ok(dev)) | ||
| 296 | netif_carrier_off(dev); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | static int veth_device_event(struct notifier_block *unused, | ||
| 301 | unsigned long event, void *ptr) | ||
| 302 | { | ||
| 303 | struct net_device *dev = ptr; | ||
| 304 | |||
| 305 | if (dev->netdev_ops->ndo_open != veth_open) | ||
| 306 | goto out; | ||
| 307 | |||
| 308 | switch (event) { | ||
| 309 | case NETDEV_CHANGE: | ||
| 310 | veth_change_state(dev); | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | out: | ||
| 314 | return NOTIFY_DONE; | ||
| 315 | } | ||
| 316 | |||
| 317 | static struct notifier_block veth_notifier_block __read_mostly = { | ||
| 318 | .notifier_call = veth_device_event, | ||
| 319 | }; | ||
| 320 | |||
| 321 | /* | 294 | /* |
| 322 | * netlink interface | 295 | * netlink interface |
| 323 | */ | 296 | */ |
| @@ -468,14 +441,12 @@ static struct rtnl_link_ops veth_link_ops = { | |||
| 468 | 441 | ||
| 469 | static __init int veth_init(void) | 442 | static __init int veth_init(void) |
| 470 | { | 443 | { |
| 471 | register_netdevice_notifier(&veth_notifier_block); | ||
| 472 | return rtnl_link_register(&veth_link_ops); | 444 | return rtnl_link_register(&veth_link_ops); |
| 473 | } | 445 | } |
| 474 | 446 | ||
| 475 | static __exit void veth_exit(void) | 447 | static __exit void veth_exit(void) |
| 476 | { | 448 | { |
| 477 | rtnl_link_unregister(&veth_link_ops); | 449 | rtnl_link_unregister(&veth_link_ops); |
| 478 | unregister_netdevice_notifier(&veth_notifier_block); | ||
| 479 | } | 450 | } |
| 480 | 451 | ||
| 481 | module_init(veth_init); | 452 | module_init(veth_init); |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 727f067aca4f..0e80990d8e84 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
| @@ -1538,6 +1538,7 @@ bad2: | |||
| 1538 | bad: | 1538 | bad: |
| 1539 | if (ah) | 1539 | if (ah) |
| 1540 | ath9k_hw_detach(ah); | 1540 | ath9k_hw_detach(ah); |
| 1541 | ath9k_exit_debug(sc); | ||
| 1541 | 1542 | ||
| 1542 | return error; | 1543 | return error; |
| 1543 | } | 1544 | } |
| @@ -1545,7 +1546,7 @@ bad: | |||
| 1545 | static int ath_attach(u16 devid, struct ath_softc *sc) | 1546 | static int ath_attach(u16 devid, struct ath_softc *sc) |
| 1546 | { | 1547 | { |
| 1547 | struct ieee80211_hw *hw = sc->hw; | 1548 | struct ieee80211_hw *hw = sc->hw; |
| 1548 | int error = 0; | 1549 | int error = 0, i; |
| 1549 | 1550 | ||
| 1550 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); | 1551 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); |
| 1551 | 1552 | ||
| @@ -1589,11 +1590,11 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1589 | /* initialize tx/rx engine */ | 1590 | /* initialize tx/rx engine */ |
| 1590 | error = ath_tx_init(sc, ATH_TXBUF); | 1591 | error = ath_tx_init(sc, ATH_TXBUF); |
| 1591 | if (error != 0) | 1592 | if (error != 0) |
| 1592 | goto detach; | 1593 | goto error_attach; |
| 1593 | 1594 | ||
| 1594 | error = ath_rx_init(sc, ATH_RXBUF); | 1595 | error = ath_rx_init(sc, ATH_RXBUF); |
| 1595 | if (error != 0) | 1596 | if (error != 0) |
| 1596 | goto detach; | 1597 | goto error_attach; |
| 1597 | 1598 | ||
| 1598 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 1599 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
| 1599 | /* Initialze h/w Rfkill */ | 1600 | /* Initialze h/w Rfkill */ |
| @@ -1601,8 +1602,9 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1601 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); | 1602 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); |
| 1602 | 1603 | ||
| 1603 | /* Initialize s/w rfkill */ | 1604 | /* Initialize s/w rfkill */ |
| 1604 | if (ath_init_sw_rfkill(sc)) | 1605 | error = ath_init_sw_rfkill(sc); |
| 1605 | goto detach; | 1606 | if (error) |
| 1607 | goto error_attach; | ||
| 1606 | #endif | 1608 | #endif |
| 1607 | 1609 | ||
| 1608 | error = ieee80211_register_hw(hw); | 1610 | error = ieee80211_register_hw(hw); |
| @@ -1611,8 +1613,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
| 1611 | ath_init_leds(sc); | 1613 | ath_init_leds(sc); |
| 1612 | 1614 | ||
| 1613 | return 0; | 1615 | return 0; |
| 1614 | detach: | 1616 | |
| 1615 | ath_detach(sc); | 1617 | error_attach: |
| 1618 | /* cleanup tx queues */ | ||
| 1619 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
| 1620 | if (ATH_TXQ_SETUP(sc, i)) | ||
| 1621 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
| 1622 | |||
| 1623 | ath9k_hw_detach(sc->sc_ah); | ||
| 1624 | ath9k_exit_debug(sc); | ||
| 1625 | |||
| 1616 | return error; | 1626 | return error; |
| 1617 | } | 1627 | } |
| 1618 | 1628 | ||
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 61d2f50470c8..b118a35ec605 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
| @@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= { | |||
| 23 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, | 23 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, |
| 24 | struct ethtool_drvinfo *info) | 24 | struct ethtool_drvinfo *info) |
| 25 | { | 25 | { |
| 26 | struct lbs_private *priv = netdev_priv(dev); | 26 | struct lbs_private *priv = dev->ml_priv; |
| 27 | 27 | ||
| 28 | snprintf(info->fw_version, 32, "%u.%u.%u.p%u", | 28 | snprintf(info->fw_version, 32, "%u.%u.%u.p%u", |
| 29 | priv->fwrelease >> 24 & 0xff, | 29 | priv->fwrelease >> 24 & 0xff, |
| @@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev) | |||
| 47 | static int lbs_ethtool_get_eeprom(struct net_device *dev, | 47 | static int lbs_ethtool_get_eeprom(struct net_device *dev, |
| 48 | struct ethtool_eeprom *eeprom, u8 * bytes) | 48 | struct ethtool_eeprom *eeprom, u8 * bytes) |
| 49 | { | 49 | { |
| 50 | struct lbs_private *priv = netdev_priv(dev); | 50 | struct lbs_private *priv = dev->ml_priv; |
| 51 | struct cmd_ds_802_11_eeprom_access cmd; | 51 | struct cmd_ds_802_11_eeprom_access cmd; |
| 52 | int ret; | 52 | int ret; |
| 53 | 53 | ||
| @@ -76,7 +76,7 @@ out: | |||
| 76 | static void lbs_ethtool_get_stats(struct net_device *dev, | 76 | static void lbs_ethtool_get_stats(struct net_device *dev, |
| 77 | struct ethtool_stats *stats, uint64_t *data) | 77 | struct ethtool_stats *stats, uint64_t *data) |
| 78 | { | 78 | { |
| 79 | struct lbs_private *priv = netdev_priv(dev); | 79 | struct lbs_private *priv = dev->ml_priv; |
| 80 | struct cmd_ds_mesh_access mesh_access; | 80 | struct cmd_ds_mesh_access mesh_access; |
| 81 | int ret; | 81 | int ret; |
| 82 | 82 | ||
| @@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev, | |||
| 113 | 113 | ||
| 114 | static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) | 114 | static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) |
| 115 | { | 115 | { |
| 116 | struct lbs_private *priv = netdev_priv(dev); | 116 | struct lbs_private *priv = dev->ml_priv; |
| 117 | 117 | ||
| 118 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) | 118 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) |
| 119 | return MESH_STATS_NUM; | 119 | return MESH_STATS_NUM; |
| @@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev, | |||
| 143 | static void lbs_ethtool_get_wol(struct net_device *dev, | 143 | static void lbs_ethtool_get_wol(struct net_device *dev, |
| 144 | struct ethtool_wolinfo *wol) | 144 | struct ethtool_wolinfo *wol) |
| 145 | { | 145 | { |
| 146 | struct lbs_private *priv = netdev_priv(dev); | 146 | struct lbs_private *priv = dev->ml_priv; |
| 147 | 147 | ||
| 148 | if (priv->wol_criteria == 0xffffffff) { | 148 | if (priv->wol_criteria == 0xffffffff) { |
| 149 | /* Interface driver didn't configure wake */ | 149 | /* Interface driver didn't configure wake */ |
| @@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev, | |||
| 166 | static int lbs_ethtool_set_wol(struct net_device *dev, | 166 | static int lbs_ethtool_set_wol(struct net_device *dev, |
| 167 | struct ethtool_wolinfo *wol) | 167 | struct ethtool_wolinfo *wol) |
| 168 | { | 168 | { |
| 169 | struct lbs_private *priv = netdev_priv(dev); | 169 | struct lbs_private *priv = dev->ml_priv; |
| 170 | uint32_t criteria = 0; | 170 | uint32_t criteria = 0; |
| 171 | 171 | ||
| 172 | if (priv->wol_criteria == 0xffffffff && wol->wolopts) | 172 | if (priv->wol_criteria == 0xffffffff && wol->wolopts) |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 2fc637ad85c7..ea3dc038be76 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
| @@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); | |||
| 59 | static ssize_t if_usb_firmware_set(struct device *dev, | 59 | static ssize_t if_usb_firmware_set(struct device *dev, |
| 60 | struct device_attribute *attr, const char *buf, size_t count) | 60 | struct device_attribute *attr, const char *buf, size_t count) |
| 61 | { | 61 | { |
| 62 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 62 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 63 | struct if_usb_card *cardp = priv->card; | 63 | struct if_usb_card *cardp = priv->card; |
| 64 | char fwname[FIRMWARE_NAME_MAX]; | 64 | char fwname[FIRMWARE_NAME_MAX]; |
| 65 | int ret; | 65 | int ret; |
| @@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); | |||
| 86 | static ssize_t if_usb_boot2_set(struct device *dev, | 86 | static ssize_t if_usb_boot2_set(struct device *dev, |
| 87 | struct device_attribute *attr, const char *buf, size_t count) | 87 | struct device_attribute *attr, const char *buf, size_t count) |
| 88 | { | 88 | { |
| 89 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 89 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 90 | struct if_usb_card *cardp = priv->card; | 90 | struct if_usb_card *cardp = priv->card; |
| 91 | char fwname[FIRMWARE_NAME_MAX]; | 91 | char fwname[FIRMWARE_NAME_MAX]; |
| 92 | int ret; | 92 | int ret; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4e0007d20030..f76623e0ff9a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
| @@ -222,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate) | |||
| 222 | static ssize_t lbs_anycast_get(struct device *dev, | 222 | static ssize_t lbs_anycast_get(struct device *dev, |
| 223 | struct device_attribute *attr, char * buf) | 223 | struct device_attribute *attr, char * buf) |
| 224 | { | 224 | { |
| 225 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 225 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 226 | struct cmd_ds_mesh_access mesh_access; | 226 | struct cmd_ds_mesh_access mesh_access; |
| 227 | int ret; | 227 | int ret; |
| 228 | 228 | ||
| @@ -241,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev, | |||
| 241 | static ssize_t lbs_anycast_set(struct device *dev, | 241 | static ssize_t lbs_anycast_set(struct device *dev, |
| 242 | struct device_attribute *attr, const char * buf, size_t count) | 242 | struct device_attribute *attr, const char * buf, size_t count) |
| 243 | { | 243 | { |
| 244 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 244 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 245 | struct cmd_ds_mesh_access mesh_access; | 245 | struct cmd_ds_mesh_access mesh_access; |
| 246 | uint32_t datum; | 246 | uint32_t datum; |
| 247 | int ret; | 247 | int ret; |
| @@ -263,7 +263,7 @@ static ssize_t lbs_anycast_set(struct device *dev, | |||
| 263 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | 263 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, |
| 264 | struct device_attribute *attr, char *buf) | 264 | struct device_attribute *attr, char *buf) |
| 265 | { | 265 | { |
| 266 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 266 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 267 | struct cmd_ds_mesh_access mesh_access; | 267 | struct cmd_ds_mesh_access mesh_access; |
| 268 | int ret; | 268 | int ret; |
| 269 | u32 retry_limit; | 269 | u32 retry_limit; |
| @@ -286,7 +286,7 @@ static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | |||
| 286 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, | 286 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, |
| 287 | struct device_attribute *attr, const char *buf, size_t count) | 287 | struct device_attribute *attr, const char *buf, size_t count) |
| 288 | { | 288 | { |
| 289 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 289 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 290 | struct cmd_ds_mesh_access mesh_access; | 290 | struct cmd_ds_mesh_access mesh_access; |
| 291 | int ret; | 291 | int ret; |
| 292 | unsigned long retry_limit; | 292 | unsigned long retry_limit; |
| @@ -321,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv); | |||
| 321 | static ssize_t lbs_rtap_get(struct device *dev, | 321 | static ssize_t lbs_rtap_get(struct device *dev, |
| 322 | struct device_attribute *attr, char * buf) | 322 | struct device_attribute *attr, char * buf) |
| 323 | { | 323 | { |
| 324 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 324 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 325 | return snprintf(buf, 5, "0x%X\n", priv->monitormode); | 325 | return snprintf(buf, 5, "0x%X\n", priv->monitormode); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| @@ -332,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
| 332 | struct device_attribute *attr, const char * buf, size_t count) | 332 | struct device_attribute *attr, const char * buf, size_t count) |
| 333 | { | 333 | { |
| 334 | int monitor_mode; | 334 | int monitor_mode; |
| 335 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 335 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 336 | 336 | ||
| 337 | sscanf(buf, "%x", &monitor_mode); | 337 | sscanf(buf, "%x", &monitor_mode); |
| 338 | if (monitor_mode) { | 338 | if (monitor_mode) { |
| @@ -383,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); | |||
| 383 | static ssize_t lbs_mesh_get(struct device *dev, | 383 | static ssize_t lbs_mesh_get(struct device *dev, |
| 384 | struct device_attribute *attr, char * buf) | 384 | struct device_attribute *attr, char * buf) |
| 385 | { | 385 | { |
| 386 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 386 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 387 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); | 387 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| @@ -393,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev, | |||
| 393 | static ssize_t lbs_mesh_set(struct device *dev, | 393 | static ssize_t lbs_mesh_set(struct device *dev, |
| 394 | struct device_attribute *attr, const char * buf, size_t count) | 394 | struct device_attribute *attr, const char * buf, size_t count) |
| 395 | { | 395 | { |
| 396 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 396 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 397 | int enable; | 397 | int enable; |
| 398 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; | 398 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; |
| 399 | 399 | ||
| @@ -452,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = { | |||
| 452 | */ | 452 | */ |
| 453 | static int lbs_dev_open(struct net_device *dev) | 453 | static int lbs_dev_open(struct net_device *dev) |
| 454 | { | 454 | { |
| 455 | struct lbs_private *priv = netdev_priv(dev) ; | 455 | struct lbs_private *priv = dev->ml_priv; |
| 456 | int ret = 0; | 456 | int ret = 0; |
| 457 | 457 | ||
| 458 | lbs_deb_enter(LBS_DEB_NET); | 458 | lbs_deb_enter(LBS_DEB_NET); |
| @@ -521,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev) | |||
| 521 | */ | 521 | */ |
| 522 | static int lbs_eth_stop(struct net_device *dev) | 522 | static int lbs_eth_stop(struct net_device *dev) |
| 523 | { | 523 | { |
| 524 | struct lbs_private *priv = netdev_priv(dev); | 524 | struct lbs_private *priv = dev->ml_priv; |
| 525 | 525 | ||
| 526 | lbs_deb_enter(LBS_DEB_NET); | 526 | lbs_deb_enter(LBS_DEB_NET); |
| 527 | 527 | ||
| @@ -538,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev) | |||
| 538 | 538 | ||
| 539 | static void lbs_tx_timeout(struct net_device *dev) | 539 | static void lbs_tx_timeout(struct net_device *dev) |
| 540 | { | 540 | { |
| 541 | struct lbs_private *priv = netdev_priv(dev); | 541 | struct lbs_private *priv = dev->ml_priv; |
| 542 | 542 | ||
| 543 | lbs_deb_enter(LBS_DEB_TX); | 543 | lbs_deb_enter(LBS_DEB_TX); |
| 544 | 544 | ||
| @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done); | |||
| 590 | */ | 590 | */ |
| 591 | static struct net_device_stats *lbs_get_stats(struct net_device *dev) | 591 | static struct net_device_stats *lbs_get_stats(struct net_device *dev) |
| 592 | { | 592 | { |
| 593 | struct lbs_private *priv = netdev_priv(dev); | 593 | struct lbs_private *priv = dev->ml_priv; |
| 594 | 594 | ||
| 595 | lbs_deb_enter(LBS_DEB_NET); | 595 | lbs_deb_enter(LBS_DEB_NET); |
| 596 | return &priv->stats; | 596 | return &priv->stats; |
| @@ -599,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev) | |||
| 599 | static int lbs_set_mac_address(struct net_device *dev, void *addr) | 599 | static int lbs_set_mac_address(struct net_device *dev, void *addr) |
| 600 | { | 600 | { |
| 601 | int ret = 0; | 601 | int ret = 0; |
| 602 | struct lbs_private *priv = netdev_priv(dev); | 602 | struct lbs_private *priv = dev->ml_priv; |
| 603 | struct sockaddr *phwaddr = addr; | 603 | struct sockaddr *phwaddr = addr; |
| 604 | struct cmd_ds_802_11_mac_address cmd; | 604 | struct cmd_ds_802_11_mac_address cmd; |
| 605 | 605 | ||
| @@ -732,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work) | |||
| 732 | 732 | ||
| 733 | static void lbs_set_multicast_list(struct net_device *dev) | 733 | static void lbs_set_multicast_list(struct net_device *dev) |
| 734 | { | 734 | { |
| 735 | struct lbs_private *priv = netdev_priv(dev); | 735 | struct lbs_private *priv = dev->ml_priv; |
| 736 | 736 | ||
| 737 | schedule_work(&priv->mcast_work); | 737 | schedule_work(&priv->mcast_work); |
| 738 | } | 738 | } |
| @@ -748,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev) | |||
| 748 | static int lbs_thread(void *data) | 748 | static int lbs_thread(void *data) |
| 749 | { | 749 | { |
| 750 | struct net_device *dev = data; | 750 | struct net_device *dev = data; |
| 751 | struct lbs_private *priv = netdev_priv(dev); | 751 | struct lbs_private *priv = dev->ml_priv; |
| 752 | wait_queue_t wait; | 752 | wait_queue_t wait; |
| 753 | 753 | ||
| 754 | lbs_deb_enter(LBS_DEB_THREAD); | 754 | lbs_deb_enter(LBS_DEB_THREAD); |
| @@ -1184,6 +1184,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
| 1184 | goto done; | 1184 | goto done; |
| 1185 | } | 1185 | } |
| 1186 | priv = netdev_priv(dev); | 1186 | priv = netdev_priv(dev); |
| 1187 | dev->ml_priv = priv; | ||
| 1187 | 1188 | ||
| 1188 | if (lbs_init_adapter(priv)) { | 1189 | if (lbs_init_adapter(priv)) { |
| 1189 | lbs_pr_err("failed to initialize adapter structure.\n"); | 1190 | lbs_pr_err("failed to initialize adapter structure.\n"); |
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c index d42b7a5a1b3f..18fe29faf99b 100644 --- a/drivers/net/wireless/libertas/persistcfg.c +++ b/drivers/net/wireless/libertas/persistcfg.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | static int mesh_get_default_parameters(struct device *dev, | 18 | static int mesh_get_default_parameters(struct device *dev, |
| 19 | struct mrvl_mesh_defaults *defs) | 19 | struct mrvl_mesh_defaults *defs) |
| 20 | { | 20 | { |
| 21 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 21 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 22 | struct cmd_ds_mesh_config cmd; | 22 | struct cmd_ds_mesh_config cmd; |
| 23 | int ret; | 23 | int ret; |
| 24 | 24 | ||
| @@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev, | |||
| 57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, | 57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, |
| 58 | const char *buf, size_t count) | 58 | const char *buf, size_t count) |
| 59 | { | 59 | { |
| 60 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 60 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 61 | struct cmd_ds_mesh_config cmd; | 61 | struct cmd_ds_mesh_config cmd; |
| 62 | uint32_t datum; | 62 | uint32_t datum; |
| 63 | int ret; | 63 | int ret; |
| @@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev, | |||
| 100 | static ssize_t boottime_set(struct device *dev, | 100 | static ssize_t boottime_set(struct device *dev, |
| 101 | struct device_attribute *attr, const char *buf, size_t count) | 101 | struct device_attribute *attr, const char *buf, size_t count) |
| 102 | { | 102 | { |
| 103 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 103 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 104 | struct cmd_ds_mesh_config cmd; | 104 | struct cmd_ds_mesh_config cmd; |
| 105 | uint32_t datum; | 105 | uint32_t datum; |
| 106 | int ret; | 106 | int ret; |
| @@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev, | |||
| 152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, | 152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, |
| 153 | const char *buf, size_t count) | 153 | const char *buf, size_t count) |
| 154 | { | 154 | { |
| 155 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 155 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 156 | struct cmd_ds_mesh_config cmd; | 156 | struct cmd_ds_mesh_config cmd; |
| 157 | uint32_t datum; | 157 | uint32_t datum; |
| 158 | int ret; | 158 | int ret; |
| @@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | |||
| 210 | struct cmd_ds_mesh_config cmd; | 210 | struct cmd_ds_mesh_config cmd; |
| 211 | struct mrvl_mesh_defaults defs; | 211 | struct mrvl_mesh_defaults defs; |
| 212 | struct mrvl_meshie *ie; | 212 | struct mrvl_meshie *ie; |
| 213 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 213 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 214 | int len; | 214 | int len; |
| 215 | int ret; | 215 | int ret; |
| 216 | 216 | ||
| @@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev, | |||
| 269 | struct cmd_ds_mesh_config cmd; | 269 | struct cmd_ds_mesh_config cmd; |
| 270 | struct mrvl_mesh_defaults defs; | 270 | struct mrvl_mesh_defaults defs; |
| 271 | struct mrvl_meshie *ie; | 271 | struct mrvl_meshie *ie; |
| 272 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 272 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 273 | uint32_t datum; | 273 | uint32_t datum; |
| 274 | int ret; | 274 | int ret; |
| 275 | 275 | ||
| @@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, | |||
| 323 | struct cmd_ds_mesh_config cmd; | 323 | struct cmd_ds_mesh_config cmd; |
| 324 | struct mrvl_mesh_defaults defs; | 324 | struct mrvl_mesh_defaults defs; |
| 325 | struct mrvl_meshie *ie; | 325 | struct mrvl_meshie *ie; |
| 326 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 326 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 327 | uint32_t datum; | 327 | uint32_t datum; |
| 328 | int ret; | 328 | int ret; |
| 329 | 329 | ||
| @@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr, | |||
| 377 | struct cmd_ds_mesh_config cmd; | 377 | struct cmd_ds_mesh_config cmd; |
| 378 | struct mrvl_mesh_defaults defs; | 378 | struct mrvl_mesh_defaults defs; |
| 379 | struct mrvl_meshie *ie; | 379 | struct mrvl_meshie *ie; |
| 380 | struct lbs_private *priv = netdev_priv(to_net_dev(dev)); | 380 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; |
| 381 | uint32_t datum; | 381 | uint32_t datum; |
| 382 | int ret; | 382 | int ret; |
| 383 | 383 | ||
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 57f6c12cda20..9014950f4328 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
| @@ -945,7 +945,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
| 945 | union iwreq_data *wrqu, char *extra) | 945 | union iwreq_data *wrqu, char *extra) |
| 946 | { | 946 | { |
| 947 | DECLARE_SSID_BUF(ssid); | 947 | DECLARE_SSID_BUF(ssid); |
| 948 | struct lbs_private *priv = netdev_priv(dev); | 948 | struct lbs_private *priv = dev->ml_priv; |
| 949 | int ret = 0; | 949 | int ret = 0; |
| 950 | 950 | ||
| 951 | lbs_deb_enter(LBS_DEB_WEXT); | 951 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1008,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
| 1008 | struct iw_point *dwrq, char *extra) | 1008 | struct iw_point *dwrq, char *extra) |
| 1009 | { | 1009 | { |
| 1010 | #define SCAN_ITEM_SIZE 128 | 1010 | #define SCAN_ITEM_SIZE 128 |
| 1011 | struct lbs_private *priv = netdev_priv(dev); | 1011 | struct lbs_private *priv = dev->ml_priv; |
| 1012 | int err = 0; | 1012 | int err = 0; |
| 1013 | char *ev = extra; | 1013 | char *ev = extra; |
| 1014 | char *stop = ev + dwrq->length; | 1014 | char *stop = ev + dwrq->length; |
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index dac462641170..68bec31ae03b 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
| @@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate) | |||
| 60 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 60 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
| 61 | { | 61 | { |
| 62 | unsigned long flags; | 62 | unsigned long flags; |
| 63 | struct lbs_private *priv = netdev_priv(dev); | 63 | struct lbs_private *priv = dev->ml_priv; |
| 64 | struct txpd *txpd; | 64 | struct txpd *txpd; |
| 65 | char *p802x_hdr; | 65 | char *p802x_hdr; |
| 66 | uint16_t pkt_len; | 66 | uint16_t pkt_len; |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6102e08179e..f16d136ab4bb 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
| @@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, | |||
| 163 | static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | 163 | static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, |
| 164 | struct iw_freq *fwrq, char *extra) | 164 | struct iw_freq *fwrq, char *extra) |
| 165 | { | 165 | { |
| 166 | struct lbs_private *priv = netdev_priv(dev); | 166 | struct lbs_private *priv = dev->ml_priv; |
| 167 | struct chan_freq_power *cfp; | 167 | struct chan_freq_power *cfp; |
| 168 | 168 | ||
| 169 | lbs_deb_enter(LBS_DEB_WEXT); | 169 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | |||
| 189 | static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, | 189 | static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, |
| 190 | struct sockaddr *awrq, char *extra) | 190 | struct sockaddr *awrq, char *extra) |
| 191 | { | 191 | { |
| 192 | struct lbs_private *priv = netdev_priv(dev); | 192 | struct lbs_private *priv = dev->ml_priv; |
| 193 | 193 | ||
| 194 | lbs_deb_enter(LBS_DEB_WEXT); | 194 | lbs_deb_enter(LBS_DEB_WEXT); |
| 195 | 195 | ||
| @@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, | |||
| 207 | static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, | 207 | static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, |
| 208 | struct iw_point *dwrq, char *extra) | 208 | struct iw_point *dwrq, char *extra) |
| 209 | { | 209 | { |
| 210 | struct lbs_private *priv = netdev_priv(dev); | 210 | struct lbs_private *priv = dev->ml_priv; |
| 211 | 211 | ||
| 212 | lbs_deb_enter(LBS_DEB_WEXT); | 212 | lbs_deb_enter(LBS_DEB_WEXT); |
| 213 | 213 | ||
| @@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, | |||
| 231 | static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | 231 | static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, |
| 232 | struct iw_point *dwrq, char *extra) | 232 | struct iw_point *dwrq, char *extra) |
| 233 | { | 233 | { |
| 234 | struct lbs_private *priv = netdev_priv(dev); | 234 | struct lbs_private *priv = dev->ml_priv; |
| 235 | 235 | ||
| 236 | lbs_deb_enter(LBS_DEB_WEXT); | 236 | lbs_deb_enter(LBS_DEB_WEXT); |
| 237 | 237 | ||
| @@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
| 248 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | 248 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, |
| 249 | struct iw_point *dwrq, char *extra) | 249 | struct iw_point *dwrq, char *extra) |
| 250 | { | 250 | { |
| 251 | struct lbs_private *priv = netdev_priv(dev); | 251 | struct lbs_private *priv = dev->ml_priv; |
| 252 | 252 | ||
| 253 | lbs_deb_enter(LBS_DEB_WEXT); | 253 | lbs_deb_enter(LBS_DEB_WEXT); |
| 254 | 254 | ||
| @@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | |||
| 273 | struct iw_param *vwrq, char *extra) | 273 | struct iw_param *vwrq, char *extra) |
| 274 | { | 274 | { |
| 275 | int ret = 0; | 275 | int ret = 0; |
| 276 | struct lbs_private *priv = netdev_priv(dev); | 276 | struct lbs_private *priv = dev->ml_priv; |
| 277 | u32 val = vwrq->value; | 277 | u32 val = vwrq->value; |
| 278 | 278 | ||
| 279 | lbs_deb_enter(LBS_DEB_WEXT); | 279 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | |||
| 293 | static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, | 293 | static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, |
| 294 | struct iw_param *vwrq, char *extra) | 294 | struct iw_param *vwrq, char *extra) |
| 295 | { | 295 | { |
| 296 | struct lbs_private *priv = netdev_priv(dev); | 296 | struct lbs_private *priv = dev->ml_priv; |
| 297 | int ret = 0; | 297 | int ret = 0; |
| 298 | u16 val = 0; | 298 | u16 val = 0; |
| 299 | 299 | ||
| @@ -315,7 +315,7 @@ out: | |||
| 315 | static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, | 315 | static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, |
| 316 | struct iw_param *vwrq, char *extra) | 316 | struct iw_param *vwrq, char *extra) |
| 317 | { | 317 | { |
| 318 | struct lbs_private *priv = netdev_priv(dev); | 318 | struct lbs_private *priv = dev->ml_priv; |
| 319 | int ret = 0; | 319 | int ret = 0; |
| 320 | u32 val = vwrq->value; | 320 | u32 val = vwrq->value; |
| 321 | 321 | ||
| @@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, | |||
| 336 | static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, | 336 | static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, |
| 337 | struct iw_param *vwrq, char *extra) | 337 | struct iw_param *vwrq, char *extra) |
| 338 | { | 338 | { |
| 339 | struct lbs_private *priv = netdev_priv(dev); | 339 | struct lbs_private *priv = dev->ml_priv; |
| 340 | int ret = 0; | 340 | int ret = 0; |
| 341 | u16 val = 0; | 341 | u16 val = 0; |
| 342 | 342 | ||
| @@ -359,7 +359,7 @@ out: | |||
| 359 | static int lbs_get_mode(struct net_device *dev, | 359 | static int lbs_get_mode(struct net_device *dev, |
| 360 | struct iw_request_info *info, u32 * uwrq, char *extra) | 360 | struct iw_request_info *info, u32 * uwrq, char *extra) |
| 361 | { | 361 | { |
| 362 | struct lbs_private *priv = netdev_priv(dev); | 362 | struct lbs_private *priv = dev->ml_priv; |
| 363 | 363 | ||
| 364 | lbs_deb_enter(LBS_DEB_WEXT); | 364 | lbs_deb_enter(LBS_DEB_WEXT); |
| 365 | 365 | ||
| @@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev, | |||
| 385 | struct iw_request_info *info, | 385 | struct iw_request_info *info, |
| 386 | struct iw_param *vwrq, char *extra) | 386 | struct iw_param *vwrq, char *extra) |
| 387 | { | 387 | { |
| 388 | struct lbs_private *priv = netdev_priv(dev); | 388 | struct lbs_private *priv = dev->ml_priv; |
| 389 | s16 curlevel = 0; | 389 | s16 curlevel = 0; |
| 390 | int ret = 0; | 390 | int ret = 0; |
| 391 | 391 | ||
| @@ -418,7 +418,7 @@ out: | |||
| 418 | static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, | 418 | static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, |
| 419 | struct iw_param *vwrq, char *extra) | 419 | struct iw_param *vwrq, char *extra) |
| 420 | { | 420 | { |
| 421 | struct lbs_private *priv = netdev_priv(dev); | 421 | struct lbs_private *priv = dev->ml_priv; |
| 422 | int ret = 0; | 422 | int ret = 0; |
| 423 | u16 slimit = 0, llimit = 0; | 423 | u16 slimit = 0, llimit = 0; |
| 424 | 424 | ||
| @@ -466,7 +466,7 @@ out: | |||
| 466 | static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, | 466 | static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, |
| 467 | struct iw_param *vwrq, char *extra) | 467 | struct iw_param *vwrq, char *extra) |
| 468 | { | 468 | { |
| 469 | struct lbs_private *priv = netdev_priv(dev); | 469 | struct lbs_private *priv = dev->ml_priv; |
| 470 | int ret = 0; | 470 | int ret = 0; |
| 471 | u16 val = 0; | 471 | u16 val = 0; |
| 472 | 472 | ||
| @@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
| 542 | struct iw_point *dwrq, char *extra) | 542 | struct iw_point *dwrq, char *extra) |
| 543 | { | 543 | { |
| 544 | int i, j; | 544 | int i, j; |
| 545 | struct lbs_private *priv = netdev_priv(dev); | 545 | struct lbs_private *priv = dev->ml_priv; |
| 546 | struct iw_range *range = (struct iw_range *)extra; | 546 | struct iw_range *range = (struct iw_range *)extra; |
| 547 | struct chan_freq_power *cfp; | 547 | struct chan_freq_power *cfp; |
| 548 | u8 rates[MAX_RATES + 1]; | 548 | u8 rates[MAX_RATES + 1]; |
| @@ -708,7 +708,7 @@ out: | |||
| 708 | static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | 708 | static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, |
| 709 | struct iw_param *vwrq, char *extra) | 709 | struct iw_param *vwrq, char *extra) |
| 710 | { | 710 | { |
| 711 | struct lbs_private *priv = netdev_priv(dev); | 711 | struct lbs_private *priv = dev->ml_priv; |
| 712 | 712 | ||
| 713 | lbs_deb_enter(LBS_DEB_WEXT); | 713 | lbs_deb_enter(LBS_DEB_WEXT); |
| 714 | 714 | ||
| @@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
| 758 | static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, | 758 | static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, |
| 759 | struct iw_param *vwrq, char *extra) | 759 | struct iw_param *vwrq, char *extra) |
| 760 | { | 760 | { |
| 761 | struct lbs_private *priv = netdev_priv(dev); | 761 | struct lbs_private *priv = dev->ml_priv; |
| 762 | 762 | ||
| 763 | lbs_deb_enter(LBS_DEB_WEXT); | 763 | lbs_deb_enter(LBS_DEB_WEXT); |
| 764 | 764 | ||
| @@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
| 781 | EXCELLENT = 95, | 781 | EXCELLENT = 95, |
| 782 | PERFECT = 100 | 782 | PERFECT = 100 |
| 783 | }; | 783 | }; |
| 784 | struct lbs_private *priv = netdev_priv(dev); | 784 | struct lbs_private *priv = dev->ml_priv; |
| 785 | u32 rssi_qual; | 785 | u32 rssi_qual; |
| 786 | u32 tx_qual; | 786 | u32 tx_qual; |
| 787 | u32 quality = 0; | 787 | u32 quality = 0; |
| @@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, | |||
| 886 | struct iw_freq *fwrq, char *extra) | 886 | struct iw_freq *fwrq, char *extra) |
| 887 | { | 887 | { |
| 888 | int ret = -EINVAL; | 888 | int ret = -EINVAL; |
| 889 | struct lbs_private *priv = netdev_priv(dev); | 889 | struct lbs_private *priv = dev->ml_priv; |
| 890 | struct chan_freq_power *cfp; | 890 | struct chan_freq_power *cfp; |
| 891 | struct assoc_request * assoc_req; | 891 | struct assoc_request * assoc_req; |
| 892 | 892 | ||
| @@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
| 943 | struct iw_request_info *info, | 943 | struct iw_request_info *info, |
| 944 | struct iw_freq *fwrq, char *extra) | 944 | struct iw_freq *fwrq, char *extra) |
| 945 | { | 945 | { |
| 946 | struct lbs_private *priv = netdev_priv(dev); | 946 | struct lbs_private *priv = dev->ml_priv; |
| 947 | struct chan_freq_power *cfp; | 947 | struct chan_freq_power *cfp; |
| 948 | int ret = -EINVAL; | 948 | int ret = -EINVAL; |
| 949 | 949 | ||
| @@ -994,7 +994,7 @@ out: | |||
| 994 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | 994 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, |
| 995 | struct iw_param *vwrq, char *extra) | 995 | struct iw_param *vwrq, char *extra) |
| 996 | { | 996 | { |
| 997 | struct lbs_private *priv = netdev_priv(dev); | 997 | struct lbs_private *priv = dev->ml_priv; |
| 998 | u8 new_rate = 0; | 998 | u8 new_rate = 0; |
| 999 | int ret = -EINVAL; | 999 | int ret = -EINVAL; |
| 1000 | u8 rates[MAX_RATES + 1]; | 1000 | u8 rates[MAX_RATES + 1]; |
| @@ -1054,7 +1054,7 @@ out: | |||
| 1054 | static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, | 1054 | static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, |
| 1055 | struct iw_param *vwrq, char *extra) | 1055 | struct iw_param *vwrq, char *extra) |
| 1056 | { | 1056 | { |
| 1057 | struct lbs_private *priv = netdev_priv(dev); | 1057 | struct lbs_private *priv = dev->ml_priv; |
| 1058 | 1058 | ||
| 1059 | lbs_deb_enter(LBS_DEB_WEXT); | 1059 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1060 | 1060 | ||
| @@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev, | |||
| 1079 | struct iw_request_info *info, u32 * uwrq, char *extra) | 1079 | struct iw_request_info *info, u32 * uwrq, char *extra) |
| 1080 | { | 1080 | { |
| 1081 | int ret = 0; | 1081 | int ret = 0; |
| 1082 | struct lbs_private *priv = netdev_priv(dev); | 1082 | struct lbs_private *priv = dev->ml_priv; |
| 1083 | struct assoc_request * assoc_req; | 1083 | struct assoc_request * assoc_req; |
| 1084 | 1084 | ||
| 1085 | lbs_deb_enter(LBS_DEB_WEXT); | 1085 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev, | |||
| 1124 | struct iw_request_info *info, | 1124 | struct iw_request_info *info, |
| 1125 | struct iw_point *dwrq, u8 * extra) | 1125 | struct iw_point *dwrq, u8 * extra) |
| 1126 | { | 1126 | { |
| 1127 | struct lbs_private *priv = netdev_priv(dev); | 1127 | struct lbs_private *priv = dev->ml_priv; |
| 1128 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; | 1128 | int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; |
| 1129 | 1129 | ||
| 1130 | lbs_deb_enter(LBS_DEB_WEXT); | 1130 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev, | |||
| 1319 | struct iw_point *dwrq, char *extra) | 1319 | struct iw_point *dwrq, char *extra) |
| 1320 | { | 1320 | { |
| 1321 | int ret = 0; | 1321 | int ret = 0; |
| 1322 | struct lbs_private *priv = netdev_priv(dev); | 1322 | struct lbs_private *priv = dev->ml_priv; |
| 1323 | struct assoc_request * assoc_req; | 1323 | struct assoc_request * assoc_req; |
| 1324 | u16 is_default = 0, index = 0, set_tx_key = 0; | 1324 | u16 is_default = 0, index = 0, set_tx_key = 0; |
| 1325 | 1325 | ||
| @@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev, | |||
| 1395 | char *extra) | 1395 | char *extra) |
| 1396 | { | 1396 | { |
| 1397 | int ret = -EINVAL; | 1397 | int ret = -EINVAL; |
| 1398 | struct lbs_private *priv = netdev_priv(dev); | 1398 | struct lbs_private *priv = dev->ml_priv; |
| 1399 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1399 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1400 | int index, max_key_len; | 1400 | int index, max_key_len; |
| 1401 | 1401 | ||
| @@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev, | |||
| 1501 | char *extra) | 1501 | char *extra) |
| 1502 | { | 1502 | { |
| 1503 | int ret = 0; | 1503 | int ret = 0; |
| 1504 | struct lbs_private *priv = netdev_priv(dev); | 1504 | struct lbs_private *priv = dev->ml_priv; |
| 1505 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | 1505 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; |
| 1506 | int alg = ext->alg; | 1506 | int alg = ext->alg; |
| 1507 | struct assoc_request * assoc_req; | 1507 | struct assoc_request * assoc_req; |
| @@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev, | |||
| 1639 | struct iw_point *dwrq, | 1639 | struct iw_point *dwrq, |
| 1640 | char *extra) | 1640 | char *extra) |
| 1641 | { | 1641 | { |
| 1642 | struct lbs_private *priv = netdev_priv(dev); | 1642 | struct lbs_private *priv = dev->ml_priv; |
| 1643 | int ret = 0; | 1643 | int ret = 0; |
| 1644 | struct assoc_request * assoc_req; | 1644 | struct assoc_request * assoc_req; |
| 1645 | 1645 | ||
| @@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev, | |||
| 1685 | char *extra) | 1685 | char *extra) |
| 1686 | { | 1686 | { |
| 1687 | int ret = 0; | 1687 | int ret = 0; |
| 1688 | struct lbs_private *priv = netdev_priv(dev); | 1688 | struct lbs_private *priv = dev->ml_priv; |
| 1689 | 1689 | ||
| 1690 | lbs_deb_enter(LBS_DEB_WEXT); | 1690 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1691 | 1691 | ||
| @@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev, | |||
| 1713 | struct iw_param *dwrq, | 1713 | struct iw_param *dwrq, |
| 1714 | char *extra) | 1714 | char *extra) |
| 1715 | { | 1715 | { |
| 1716 | struct lbs_private *priv = netdev_priv(dev); | 1716 | struct lbs_private *priv = dev->ml_priv; |
| 1717 | struct assoc_request * assoc_req; | 1717 | struct assoc_request * assoc_req; |
| 1718 | int ret = 0; | 1718 | int ret = 0; |
| 1719 | int updated = 0; | 1719 | int updated = 0; |
| @@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev, | |||
| 1816 | char *extra) | 1816 | char *extra) |
| 1817 | { | 1817 | { |
| 1818 | int ret = 0; | 1818 | int ret = 0; |
| 1819 | struct lbs_private *priv = netdev_priv(dev); | 1819 | struct lbs_private *priv = dev->ml_priv; |
| 1820 | 1820 | ||
| 1821 | lbs_deb_enter(LBS_DEB_WEXT); | 1821 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1822 | 1822 | ||
| @@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, | |||
| 1857 | struct iw_param *vwrq, char *extra) | 1857 | struct iw_param *vwrq, char *extra) |
| 1858 | { | 1858 | { |
| 1859 | int ret = 0; | 1859 | int ret = 0; |
| 1860 | struct lbs_private *priv = netdev_priv(dev); | 1860 | struct lbs_private *priv = dev->ml_priv; |
| 1861 | s16 dbm = (s16) vwrq->value; | 1861 | s16 dbm = (s16) vwrq->value; |
| 1862 | 1862 | ||
| 1863 | lbs_deb_enter(LBS_DEB_WEXT); | 1863 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -1936,7 +1936,7 @@ out: | |||
| 1936 | static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | 1936 | static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, |
| 1937 | struct iw_point *dwrq, char *extra) | 1937 | struct iw_point *dwrq, char *extra) |
| 1938 | { | 1938 | { |
| 1939 | struct lbs_private *priv = netdev_priv(dev); | 1939 | struct lbs_private *priv = dev->ml_priv; |
| 1940 | 1940 | ||
| 1941 | lbs_deb_enter(LBS_DEB_WEXT); | 1941 | lbs_deb_enter(LBS_DEB_WEXT); |
| 1942 | 1942 | ||
| @@ -1971,7 +1971,7 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | |||
| 1971 | static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | 1971 | static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, |
| 1972 | struct iw_point *dwrq, char *extra) | 1972 | struct iw_point *dwrq, char *extra) |
| 1973 | { | 1973 | { |
| 1974 | struct lbs_private *priv = netdev_priv(dev); | 1974 | struct lbs_private *priv = dev->ml_priv; |
| 1975 | int ret = 0; | 1975 | int ret = 0; |
| 1976 | u8 ssid[IW_ESSID_MAX_SIZE]; | 1976 | u8 ssid[IW_ESSID_MAX_SIZE]; |
| 1977 | u8 ssid_len = 0; | 1977 | u8 ssid_len = 0; |
| @@ -2040,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev, | |||
| 2040 | struct iw_request_info *info, | 2040 | struct iw_request_info *info, |
| 2041 | struct iw_point *dwrq, char *extra) | 2041 | struct iw_point *dwrq, char *extra) |
| 2042 | { | 2042 | { |
| 2043 | struct lbs_private *priv = netdev_priv(dev); | 2043 | struct lbs_private *priv = dev->ml_priv; |
| 2044 | 2044 | ||
| 2045 | lbs_deb_enter(LBS_DEB_WEXT); | 2045 | lbs_deb_enter(LBS_DEB_WEXT); |
| 2046 | 2046 | ||
| @@ -2058,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
| 2058 | struct iw_request_info *info, | 2058 | struct iw_request_info *info, |
| 2059 | struct iw_point *dwrq, char *extra) | 2059 | struct iw_point *dwrq, char *extra) |
| 2060 | { | 2060 | { |
| 2061 | struct lbs_private *priv = netdev_priv(dev); | 2061 | struct lbs_private *priv = dev->ml_priv; |
| 2062 | int ret = 0; | 2062 | int ret = 0; |
| 2063 | 2063 | ||
| 2064 | lbs_deb_enter(LBS_DEB_WEXT); | 2064 | lbs_deb_enter(LBS_DEB_WEXT); |
| @@ -2102,7 +2102,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
| 2102 | static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, | 2102 | static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, |
| 2103 | struct sockaddr *awrq, char *extra) | 2103 | struct sockaddr *awrq, char *extra) |
| 2104 | { | 2104 | { |
| 2105 | struct lbs_private *priv = netdev_priv(dev); | 2105 | struct lbs_private *priv = dev->ml_priv; |
| 2106 | struct assoc_request * assoc_req; | 2106 | struct assoc_request * assoc_req; |
| 2107 | int ret = 0; | 2107 | int ret = 0; |
| 2108 | 2108 | ||
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index 45a04faa7818..067d1a9c728b 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c | |||
| @@ -3157,8 +3157,20 @@ static int orinoco_pm_notifier(struct notifier_block *notifier, | |||
| 3157 | 3157 | ||
| 3158 | return NOTIFY_DONE; | 3158 | return NOTIFY_DONE; |
| 3159 | } | 3159 | } |
| 3160 | |||
| 3161 | static void orinoco_register_pm_notifier(struct orinoco_private *priv) | ||
| 3162 | { | ||
| 3163 | priv->pm_notifier.notifier_call = orinoco_pm_notifier; | ||
| 3164 | register_pm_notifier(&priv->pm_notifier); | ||
| 3165 | } | ||
| 3166 | |||
| 3167 | static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) | ||
| 3168 | { | ||
| 3169 | unregister_pm_notifier(&priv->pm_notifier); | ||
| 3170 | } | ||
| 3160 | #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ | 3171 | #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ |
| 3161 | #define orinoco_pm_notifier NULL | 3172 | #define orinoco_register_pm_notifier(priv) do { } while(0) |
| 3173 | #define orinoco_unregister_pm_notifier(priv) do { } while(0) | ||
| 3162 | #endif | 3174 | #endif |
| 3163 | 3175 | ||
| 3164 | /********************************************************************/ | 3176 | /********************************************************************/ |
| @@ -3648,8 +3660,7 @@ struct net_device | |||
| 3648 | priv->cached_fw = NULL; | 3660 | priv->cached_fw = NULL; |
| 3649 | 3661 | ||
| 3650 | /* Register PM notifiers */ | 3662 | /* Register PM notifiers */ |
| 3651 | priv->pm_notifier.notifier_call = orinoco_pm_notifier; | 3663 | orinoco_register_pm_notifier(priv); |
| 3652 | register_pm_notifier(&priv->pm_notifier); | ||
| 3653 | 3664 | ||
| 3654 | return dev; | 3665 | return dev; |
| 3655 | } | 3666 | } |
| @@ -3673,7 +3684,7 @@ void free_orinocodev(struct net_device *dev) | |||
| 3673 | kfree(rx_data); | 3684 | kfree(rx_data); |
| 3674 | } | 3685 | } |
| 3675 | 3686 | ||
| 3676 | unregister_pm_notifier(&priv->pm_notifier); | 3687 | orinoco_unregister_pm_notifier(priv); |
| 3677 | orinoco_uncache_fw(priv); | 3688 | orinoco_uncache_fw(priv); |
| 3678 | 3689 | ||
| 3679 | priv->wpa_ie_len = 0; | 3690 | priv->wpa_ie_len = 0; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 22bc07ef2f37..f4747a1134ba 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
| @@ -48,6 +48,10 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 48 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, | 48 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, |
| 49 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, | 49 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, |
| 50 | {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, | 50 | {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, |
| 51 | /* Surecom */ | ||
| 52 | {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, | ||
| 53 | /* Logitech */ | ||
| 54 | {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, | ||
| 51 | /* Netgear */ | 55 | /* Netgear */ |
| 52 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, | 56 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, |
| 53 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, | 57 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, |
| @@ -57,8 +61,16 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 57 | /* Sitecom */ | 61 | /* Sitecom */ |
| 58 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, | 62 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
| 59 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, | 63 | {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, |
| 64 | /* Sphairon Access Systems GmbH */ | ||
| 65 | {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, | ||
| 66 | /* Dick Smith Electronics */ | ||
| 67 | {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, | ||
| 60 | /* Abocom */ | 68 | /* Abocom */ |
| 61 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, | 69 | {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, |
| 70 | /* Qcom */ | ||
| 71 | {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, | ||
| 72 | /* AirLive */ | ||
| 73 | {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, | ||
| 62 | {} | 74 | {} |
| 63 | }; | 75 | }; |
| 64 | 76 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index fde6e4c634e7..a7cf550b9cca 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
| 22 | #include <linux/scatterlist.h> | 22 | #include <linux/scatterlist.h> |
| 23 | #include <linux/skbuff.h> | ||
| 23 | #include <scsi/libiscsi_tcp.h> | 24 | #include <scsi/libiscsi_tcp.h> |
| 24 | 25 | ||
| 25 | /* from cxgb3 LLD */ | 26 | /* from cxgb3 LLD */ |
| @@ -113,6 +114,26 @@ struct cxgb3i_endpoint { | |||
| 113 | struct cxgb3i_conn *cconn; | 114 | struct cxgb3i_conn *cconn; |
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 117 | /** | ||
| 118 | * struct cxgb3i_task_data - private iscsi task data | ||
| 119 | * | ||
| 120 | * @nr_frags: # of coalesced page frags (from scsi sgl) | ||
| 121 | * @frags: coalesced page frags (from scsi sgl) | ||
| 122 | * @skb: tx pdu skb | ||
| 123 | * @offset: data offset for the next pdu | ||
| 124 | * @count: max. possible pdu payload | ||
| 125 | * @sgoffset: offset to the first sg entry for a given offset | ||
| 126 | */ | ||
| 127 | #define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) | ||
| 128 | struct cxgb3i_task_data { | ||
| 129 | unsigned short nr_frags; | ||
| 130 | skb_frag_t frags[MAX_PDU_FRAGS]; | ||
| 131 | struct sk_buff *skb; | ||
| 132 | unsigned int offset; | ||
| 133 | unsigned int count; | ||
| 134 | unsigned int sgoffset; | ||
| 135 | }; | ||
| 136 | |||
| 116 | int cxgb3i_iscsi_init(void); | 137 | int cxgb3i_iscsi_init(void); |
| 117 | void cxgb3i_iscsi_cleanup(void); | 138 | void cxgb3i_iscsi_cleanup(void); |
| 118 | 139 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 08f3a09d9233..a83d36e4926f 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c | |||
| @@ -639,10 +639,11 @@ static int ddp_init(struct t3cdev *tdev) | |||
| 639 | write_unlock(&cxgb3i_ddp_rwlock); | 639 | write_unlock(&cxgb3i_ddp_rwlock); |
| 640 | 640 | ||
| 641 | ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " | 641 | ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x " |
| 642 | "pkt %u,%u.\n", | 642 | "pkt %u/%u, %u/%u.\n", |
| 643 | ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, | 643 | ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits, |
| 644 | ddp->idx_mask, ddp->rsvd_tag_mask, | 644 | ddp->idx_mask, ddp->rsvd_tag_mask, |
| 645 | ddp->max_txsz, ddp->max_rxsz); | 645 | ddp->max_txsz, uinfo.max_txsz, |
| 646 | ddp->max_rxsz, uinfo.max_rxsz); | ||
| 646 | return 0; | 647 | return 0; |
| 647 | 648 | ||
| 648 | free_ddp_map: | 649 | free_ddp_map: |
| @@ -654,8 +655,8 @@ free_ddp_map: | |||
| 654 | * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource | 655 | * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource |
| 655 | * @tdev: t3cdev adapter | 656 | * @tdev: t3cdev adapter |
| 656 | * @tformat: tag format | 657 | * @tformat: tag format |
| 657 | * @txsz: max tx pkt size, filled in by this func. | 658 | * @txsz: max tx pdu payload size, filled in by this func. |
| 658 | * @rxsz: max rx pkt size, filled in by this func. | 659 | * @rxsz: max rx pdu payload size, filled in by this func. |
| 659 | * initialize the ddp pagepod manager for a given adapter if needed and | 660 | * initialize the ddp pagepod manager for a given adapter if needed and |
| 660 | * setup the tag format for a given iscsi entity | 661 | * setup the tag format for a given iscsi entity |
| 661 | */ | 662 | */ |
| @@ -685,10 +686,12 @@ int cxgb3i_adapter_ddp_init(struct t3cdev *tdev, | |||
| 685 | tformat->sw_bits, tformat->rsvd_bits, | 686 | tformat->sw_bits, tformat->rsvd_bits, |
| 686 | tformat->rsvd_shift, tformat->rsvd_mask); | 687 | tformat->rsvd_shift, tformat->rsvd_mask); |
| 687 | 688 | ||
| 688 | *txsz = ddp->max_txsz; | 689 | *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, |
| 689 | *rxsz = ddp->max_rxsz; | 690 | ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN); |
| 690 | ddp_log_info("ddp max pkt size: %u, %u.\n", | 691 | *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, |
| 691 | ddp->max_txsz, ddp->max_rxsz); | 692 | ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN); |
| 693 | ddp_log_info("max payload size: %u/%u, %u/%u.\n", | ||
| 694 | *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz); | ||
| 692 | return 0; | 695 | return 0; |
| 693 | } | 696 | } |
| 694 | EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); | 697 | EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init); |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 5c7c4d95c493..3faae7831c83 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #ifndef __CXGB3I_ULP2_DDP_H__ | 13 | #ifndef __CXGB3I_ULP2_DDP_H__ |
| 14 | #define __CXGB3I_ULP2_DDP_H__ | 14 | #define __CXGB3I_ULP2_DDP_H__ |
| 15 | 15 | ||
| 16 | #include <linux/vmalloc.h> | ||
| 17 | |||
| 16 | /** | 18 | /** |
| 17 | * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity | 19 | * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity |
| 18 | * | 20 | * |
| @@ -85,8 +87,9 @@ struct cxgb3i_ddp_info { | |||
| 85 | struct sk_buff **gl_skb; | 87 | struct sk_buff **gl_skb; |
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| 90 | #define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */ | ||
| 88 | #define ULP2_MAX_PKT_SIZE 16224 | 91 | #define ULP2_MAX_PKT_SIZE 16224 |
| 89 | #define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX) | 92 | #define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN) |
| 90 | #define PPOD_PAGES_MAX 4 | 93 | #define PPOD_PAGES_MAX 4 |
| 91 | #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ | 94 | #define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */ |
| 92 | 95 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c index 091ecb4d9f3d..1ce9f244e46c 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_init.c +++ b/drivers/scsi/cxgb3i/cxgb3i_init.c | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "cxgb3i.h" | 12 | #include "cxgb3i.h" |
| 13 | 13 | ||
| 14 | #define DRV_MODULE_NAME "cxgb3i" | 14 | #define DRV_MODULE_NAME "cxgb3i" |
| 15 | #define DRV_MODULE_VERSION "1.0.0" | 15 | #define DRV_MODULE_VERSION "1.0.1" |
| 16 | #define DRV_MODULE_RELDATE "Jun. 1, 2008" | 16 | #define DRV_MODULE_RELDATE "Jan. 2009" |
| 17 | 17 | ||
| 18 | static char version[] = | 18 | static char version[] = |
| 19 | "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME | 19 | "Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index d83464b9b3f9..fa2a44f37b36 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
| @@ -364,7 +364,8 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, | |||
| 364 | 364 | ||
| 365 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, | 365 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, |
| 366 | cmds_max, | 366 | cmds_max, |
| 367 | sizeof(struct iscsi_tcp_task), | 367 | sizeof(struct iscsi_tcp_task) + |
| 368 | sizeof(struct cxgb3i_task_data), | ||
| 368 | initial_cmdsn, ISCSI_MAX_TARGET); | 369 | initial_cmdsn, ISCSI_MAX_TARGET); |
| 369 | if (!cls_session) | 370 | if (!cls_session) |
| 370 | return NULL; | 371 | return NULL; |
| @@ -402,17 +403,15 @@ static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) | |||
| 402 | { | 403 | { |
| 403 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 404 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 404 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 405 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 405 | unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, | 406 | unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM); |
| 406 | cconn->hba->snic->tx_max_size - | ||
| 407 | ISCSI_PDU_NONPAYLOAD_MAX); | ||
| 408 | 407 | ||
| 408 | max = min(cconn->hba->snic->tx_max_size, max); | ||
| 409 | if (conn->max_xmit_dlength) | 409 | if (conn->max_xmit_dlength) |
| 410 | conn->max_xmit_dlength = min_t(unsigned int, | 410 | conn->max_xmit_dlength = min(conn->max_xmit_dlength, max); |
| 411 | conn->max_xmit_dlength, max); | ||
| 412 | else | 411 | else |
| 413 | conn->max_xmit_dlength = max; | 412 | conn->max_xmit_dlength = max; |
| 414 | align_pdu_size(conn->max_xmit_dlength); | 413 | align_pdu_size(conn->max_xmit_dlength); |
| 415 | cxgb3i_log_info("conn 0x%p, max xmit %u.\n", | 414 | cxgb3i_api_debug("conn 0x%p, max xmit %u.\n", |
| 416 | conn, conn->max_xmit_dlength); | 415 | conn, conn->max_xmit_dlength); |
| 417 | return 0; | 416 | return 0; |
| 418 | } | 417 | } |
| @@ -427,9 +426,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) | |||
| 427 | { | 426 | { |
| 428 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 427 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 429 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 428 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 430 | unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD, | 429 | unsigned int max = cconn->hba->snic->rx_max_size; |
| 431 | cconn->hba->snic->rx_max_size - | ||
| 432 | ISCSI_PDU_NONPAYLOAD_MAX); | ||
| 433 | 430 | ||
| 434 | align_pdu_size(max); | 431 | align_pdu_size(max); |
| 435 | if (conn->max_recv_dlength) { | 432 | if (conn->max_recv_dlength) { |
| @@ -439,8 +436,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) | |||
| 439 | conn->max_recv_dlength, max); | 436 | conn->max_recv_dlength, max); |
| 440 | return -EINVAL; | 437 | return -EINVAL; |
| 441 | } | 438 | } |
| 442 | conn->max_recv_dlength = min_t(unsigned int, | 439 | conn->max_recv_dlength = min(conn->max_recv_dlength, max); |
| 443 | conn->max_recv_dlength, max); | ||
| 444 | align_pdu_size(conn->max_recv_dlength); | 440 | align_pdu_size(conn->max_recv_dlength); |
| 445 | } else | 441 | } else |
| 446 | conn->max_recv_dlength = max; | 442 | conn->max_recv_dlength = max; |
| @@ -844,7 +840,7 @@ static struct scsi_host_template cxgb3i_host_template = { | |||
| 844 | .proc_name = "cxgb3i", | 840 | .proc_name = "cxgb3i", |
| 845 | .queuecommand = iscsi_queuecommand, | 841 | .queuecommand = iscsi_queuecommand, |
| 846 | .change_queue_depth = iscsi_change_queue_depth, | 842 | .change_queue_depth = iscsi_change_queue_depth, |
| 847 | .can_queue = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1), | 843 | .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, |
| 848 | .sg_tablesize = SG_ALL, | 844 | .sg_tablesize = SG_ALL, |
| 849 | .max_sectors = 0xFFFF, | 845 | .max_sectors = 0xFFFF, |
| 850 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, | 846 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index a865f1fefe8b..de3b3b614cca 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c | |||
| @@ -23,19 +23,19 @@ | |||
| 23 | #include "cxgb3i_ddp.h" | 23 | #include "cxgb3i_ddp.h" |
| 24 | 24 | ||
| 25 | #ifdef __DEBUG_C3CN_CONN__ | 25 | #ifdef __DEBUG_C3CN_CONN__ |
| 26 | #define c3cn_conn_debug cxgb3i_log_info | 26 | #define c3cn_conn_debug cxgb3i_log_debug |
| 27 | #else | 27 | #else |
| 28 | #define c3cn_conn_debug(fmt...) | 28 | #define c3cn_conn_debug(fmt...) |
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #ifdef __DEBUG_C3CN_TX__ | 31 | #ifdef __DEBUG_C3CN_TX__ |
| 32 | #define c3cn_tx_debug cxgb3i_log_debug | 32 | #define c3cn_tx_debug cxgb3i_log_debug |
| 33 | #else | 33 | #else |
| 34 | #define c3cn_tx_debug(fmt...) | 34 | #define c3cn_tx_debug(fmt...) |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | #ifdef __DEBUG_C3CN_RX__ | 37 | #ifdef __DEBUG_C3CN_RX__ |
| 38 | #define c3cn_rx_debug cxgb3i_log_debug | 38 | #define c3cn_rx_debug cxgb3i_log_debug |
| 39 | #else | 39 | #else |
| 40 | #define c3cn_rx_debug(fmt...) | 40 | #define c3cn_rx_debug(fmt...) |
| 41 | #endif | 41 | #endif |
| @@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024; | |||
| 47 | module_param(cxgb3_rcv_win, int, 0644); | 47 | module_param(cxgb3_rcv_win, int, 0644); |
| 48 | MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); | 48 | MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)"); |
| 49 | 49 | ||
| 50 | static int cxgb3_snd_win = 64 * 1024; | 50 | static int cxgb3_snd_win = 128 * 1024; |
| 51 | module_param(cxgb3_snd_win, int, 0644); | 51 | module_param(cxgb3_snd_win, int, 0644); |
| 52 | MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)"); | 52 | MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)"); |
| 53 | 53 | ||
| 54 | static int cxgb3_rx_credit_thres = 10 * 1024; | 54 | static int cxgb3_rx_credit_thres = 10 * 1024; |
| 55 | module_param(cxgb3_rx_credit_thres, int, 0644); | 55 | module_param(cxgb3_rx_credit_thres, int, 0644); |
| @@ -301,8 +301,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) | |||
| 301 | static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, | 301 | static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb, |
| 302 | int flags) | 302 | int flags) |
| 303 | { | 303 | { |
| 304 | CXGB3_SKB_CB(skb)->seq = c3cn->write_seq; | 304 | skb_tcp_seq(skb) = c3cn->write_seq; |
| 305 | CXGB3_SKB_CB(skb)->flags = flags; | 305 | skb_flags(skb) = flags; |
| 306 | __skb_queue_tail(&c3cn->write_queue, skb); | 306 | __skb_queue_tail(&c3cn->write_queue, skb); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| @@ -457,12 +457,9 @@ static unsigned int wrlen __read_mostly; | |||
| 457 | * The number of WRs needed for an skb depends on the number of fragments | 457 | * The number of WRs needed for an skb depends on the number of fragments |
| 458 | * in the skb and whether it has any payload in its main body. This maps the | 458 | * in the skb and whether it has any payload in its main body. This maps the |
| 459 | * length of the gather list represented by an skb into the # of necessary WRs. | 459 | * length of the gather list represented by an skb into the # of necessary WRs. |
| 460 | * | 460 | * The extra two fragments are for iscsi bhs and payload padding. |
| 461 | * The max. length of an skb is controlled by the max pdu size which is ~16K. | ||
| 462 | * Also, assume the min. fragment length is the sector size (512), then add | ||
| 463 | * extra fragment counts for iscsi bhs and payload padding. | ||
| 464 | */ | 461 | */ |
| 465 | #define SKB_WR_LIST_SIZE (16384/512 + 3) | 462 | #define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2) |
| 466 | static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; | 463 | static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly; |
| 467 | 464 | ||
| 468 | static void s3_init_wr_tab(unsigned int wr_len) | 465 | static void s3_init_wr_tab(unsigned int wr_len) |
| @@ -485,7 +482,7 @@ static void s3_init_wr_tab(unsigned int wr_len) | |||
| 485 | 482 | ||
| 486 | static inline void reset_wr_list(struct s3_conn *c3cn) | 483 | static inline void reset_wr_list(struct s3_conn *c3cn) |
| 487 | { | 484 | { |
| 488 | c3cn->wr_pending_head = NULL; | 485 | c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL; |
| 489 | } | 486 | } |
| 490 | 487 | ||
| 491 | /* | 488 | /* |
| @@ -496,7 +493,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn) | |||
| 496 | static inline void enqueue_wr(struct s3_conn *c3cn, | 493 | static inline void enqueue_wr(struct s3_conn *c3cn, |
| 497 | struct sk_buff *skb) | 494 | struct sk_buff *skb) |
| 498 | { | 495 | { |
| 499 | skb_wr_data(skb) = NULL; | 496 | skb_tx_wr_next(skb) = NULL; |
| 500 | 497 | ||
| 501 | /* | 498 | /* |
| 502 | * We want to take an extra reference since both us and the driver | 499 | * We want to take an extra reference since both us and the driver |
| @@ -509,10 +506,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn, | |||
| 509 | if (!c3cn->wr_pending_head) | 506 | if (!c3cn->wr_pending_head) |
| 510 | c3cn->wr_pending_head = skb; | 507 | c3cn->wr_pending_head = skb; |
| 511 | else | 508 | else |
| 512 | skb_wr_data(skb) = skb; | 509 | skb_tx_wr_next(c3cn->wr_pending_tail) = skb; |
| 513 | c3cn->wr_pending_tail = skb; | 510 | c3cn->wr_pending_tail = skb; |
| 514 | } | 511 | } |
| 515 | 512 | ||
| 513 | static int count_pending_wrs(struct s3_conn *c3cn) | ||
| 514 | { | ||
| 515 | int n = 0; | ||
| 516 | const struct sk_buff *skb = c3cn->wr_pending_head; | ||
| 517 | |||
| 518 | while (skb) { | ||
| 519 | n += skb->csum; | ||
| 520 | skb = skb_tx_wr_next(skb); | ||
| 521 | } | ||
| 522 | return n; | ||
| 523 | } | ||
| 524 | |||
| 516 | static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) | 525 | static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn) |
| 517 | { | 526 | { |
| 518 | return c3cn->wr_pending_head; | 527 | return c3cn->wr_pending_head; |
| @@ -529,8 +538,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn) | |||
| 529 | 538 | ||
| 530 | if (likely(skb)) { | 539 | if (likely(skb)) { |
| 531 | /* Don't bother clearing the tail */ | 540 | /* Don't bother clearing the tail */ |
| 532 | c3cn->wr_pending_head = skb_wr_data(skb); | 541 | c3cn->wr_pending_head = skb_tx_wr_next(skb); |
| 533 | skb_wr_data(skb) = NULL; | 542 | skb_tx_wr_next(skb) = NULL; |
| 534 | } | 543 | } |
| 535 | return skb; | 544 | return skb; |
| 536 | } | 545 | } |
| @@ -543,13 +552,14 @@ static void purge_wr_queue(struct s3_conn *c3cn) | |||
| 543 | } | 552 | } |
| 544 | 553 | ||
| 545 | static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, | 554 | static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb, |
| 546 | int len) | 555 | int len, int req_completion) |
| 547 | { | 556 | { |
| 548 | struct tx_data_wr *req; | 557 | struct tx_data_wr *req; |
| 549 | 558 | ||
| 550 | skb_reset_transport_header(skb); | 559 | skb_reset_transport_header(skb); |
| 551 | req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); | 560 | req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req)); |
| 552 | req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)); | 561 | req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) | |
| 562 | (req_completion ? F_WR_COMPL : 0)); | ||
| 553 | req->wr_lo = htonl(V_WR_TID(c3cn->tid)); | 563 | req->wr_lo = htonl(V_WR_TID(c3cn->tid)); |
| 554 | req->sndseq = htonl(c3cn->snd_nxt); | 564 | req->sndseq = htonl(c3cn->snd_nxt); |
| 555 | /* len includes the length of any HW ULP additions */ | 565 | /* len includes the length of any HW ULP additions */ |
| @@ -592,7 +602,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 592 | 602 | ||
| 593 | if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || | 603 | if (unlikely(c3cn->state == C3CN_STATE_CONNECTING || |
| 594 | c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || | 604 | c3cn->state == C3CN_STATE_CLOSE_WAIT_1 || |
| 595 | c3cn->state == C3CN_STATE_ABORTING)) { | 605 | c3cn->state >= C3CN_STATE_ABORTING)) { |
| 596 | c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", | 606 | c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n", |
| 597 | c3cn, c3cn->state); | 607 | c3cn, c3cn->state); |
| 598 | return 0; | 608 | return 0; |
| @@ -615,7 +625,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 615 | if (c3cn->wr_avail < wrs_needed) { | 625 | if (c3cn->wr_avail < wrs_needed) { |
| 616 | c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " | 626 | c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, " |
| 617 | "wr %d < %u.\n", | 627 | "wr %d < %u.\n", |
| 618 | c3cn, skb->len, skb->datalen, frags, | 628 | c3cn, skb->len, skb->data_len, frags, |
| 619 | wrs_needed, c3cn->wr_avail); | 629 | wrs_needed, c3cn->wr_avail); |
| 620 | break; | 630 | break; |
| 621 | } | 631 | } |
| @@ -627,20 +637,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion) | |||
| 627 | c3cn->wr_unacked += wrs_needed; | 637 | c3cn->wr_unacked += wrs_needed; |
| 628 | enqueue_wr(c3cn, skb); | 638 | enqueue_wr(c3cn, skb); |
| 629 | 639 | ||
| 630 | if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) { | 640 | c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, " |
| 631 | len += ulp_extra_len(skb); | 641 | "wr %d, left %u, unack %u.\n", |
| 632 | make_tx_data_wr(c3cn, skb, len); | 642 | c3cn, skb->len, skb->data_len, frags, |
| 633 | c3cn->snd_nxt += len; | 643 | wrs_needed, c3cn->wr_avail, c3cn->wr_unacked); |
| 634 | if ((req_completion | 644 | |
| 635 | && c3cn->wr_unacked == wrs_needed) | ||
| 636 | || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL) | ||
| 637 | || c3cn->wr_unacked >= c3cn->wr_max / 2) { | ||
| 638 | struct work_request_hdr *wr = cplhdr(skb); | ||
| 639 | 645 | ||
| 640 | wr->wr_hi |= htonl(F_WR_COMPL); | 646 | if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) { |
| 647 | if ((req_completion && | ||
| 648 | c3cn->wr_unacked == wrs_needed) || | ||
| 649 | (skb_flags(skb) & C3CB_FLAG_COMPL) || | ||
| 650 | c3cn->wr_unacked >= c3cn->wr_max / 2) { | ||
| 651 | req_completion = 1; | ||
| 641 | c3cn->wr_unacked = 0; | 652 | c3cn->wr_unacked = 0; |
| 642 | } | 653 | } |
| 643 | CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR; | 654 | len += ulp_extra_len(skb); |
| 655 | make_tx_data_wr(c3cn, skb, len, req_completion); | ||
| 656 | c3cn->snd_nxt += len; | ||
| 657 | skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR; | ||
| 644 | } | 658 | } |
| 645 | 659 | ||
| 646 | total_size += skb->truesize; | 660 | total_size += skb->truesize; |
| @@ -735,8 +749,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 735 | if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) | 749 | if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED))) |
| 736 | /* upper layer has requested closing */ | 750 | /* upper layer has requested closing */ |
| 737 | send_abort_req(c3cn); | 751 | send_abort_req(c3cn); |
| 738 | else if (c3cn_push_tx_frames(c3cn, 1)) | 752 | else { |
| 753 | if (skb_queue_len(&c3cn->write_queue)) | ||
| 754 | c3cn_push_tx_frames(c3cn, 1); | ||
| 739 | cxgb3i_conn_tx_open(c3cn); | 755 | cxgb3i_conn_tx_open(c3cn); |
| 756 | } | ||
| 740 | } | 757 | } |
| 741 | 758 | ||
| 742 | static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, | 759 | static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, |
| @@ -1082,8 +1099,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1082 | return; | 1099 | return; |
| 1083 | } | 1100 | } |
| 1084 | 1101 | ||
| 1085 | CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq); | 1102 | skb_tcp_seq(skb) = ntohl(hdr_cpl->seq); |
| 1086 | CXGB3_SKB_CB(skb)->flags = 0; | 1103 | skb_flags(skb) = 0; |
| 1087 | 1104 | ||
| 1088 | skb_reset_transport_header(skb); | 1105 | skb_reset_transport_header(skb); |
| 1089 | __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); | 1106 | __skb_pull(skb, sizeof(struct cpl_iscsi_hdr)); |
| @@ -1103,12 +1120,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1103 | goto abort_conn; | 1120 | goto abort_conn; |
| 1104 | 1121 | ||
| 1105 | skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; | 1122 | skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY; |
| 1106 | skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len); | 1123 | skb_rx_pdulen(skb) = ntohs(ddp_cpl.len); |
| 1107 | skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); | 1124 | skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc); |
| 1108 | status = ntohl(ddp_cpl.ddp_status); | 1125 | status = ntohl(ddp_cpl.ddp_status); |
| 1109 | 1126 | ||
| 1110 | c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", | 1127 | c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n", |
| 1111 | skb, skb->len, skb_ulp_pdulen(skb), status); | 1128 | skb, skb->len, skb_rx_pdulen(skb), status); |
| 1112 | 1129 | ||
| 1113 | if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) | 1130 | if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT)) |
| 1114 | skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; | 1131 | skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR; |
| @@ -1126,7 +1143,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1126 | } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) | 1143 | } else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT)) |
| 1127 | skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; | 1144 | skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED; |
| 1128 | 1145 | ||
| 1129 | c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb); | 1146 | c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb); |
| 1130 | __pskb_trim(skb, len); | 1147 | __pskb_trim(skb, len); |
| 1131 | __skb_queue_tail(&c3cn->receive_queue, skb); | 1148 | __skb_queue_tail(&c3cn->receive_queue, skb); |
| 1132 | cxgb3i_conn_pdu_ready(c3cn); | 1149 | cxgb3i_conn_pdu_ready(c3cn); |
| @@ -1151,12 +1168,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx) | |||
| 1151 | * Process an acknowledgment of WR completion. Advance snd_una and send the | 1168 | * Process an acknowledgment of WR completion. Advance snd_una and send the |
| 1152 | * next batch of work requests from the write queue. | 1169 | * next batch of work requests from the write queue. |
| 1153 | */ | 1170 | */ |
| 1171 | static void check_wr_invariants(struct s3_conn *c3cn) | ||
| 1172 | { | ||
| 1173 | int pending = count_pending_wrs(c3cn); | ||
| 1174 | |||
| 1175 | if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max)) | ||
| 1176 | cxgb3i_log_error("TID %u: credit imbalance: avail %u, " | ||
| 1177 | "pending %u, total should be %u\n", | ||
| 1178 | c3cn->tid, c3cn->wr_avail, pending, | ||
| 1179 | c3cn->wr_max); | ||
| 1180 | } | ||
| 1181 | |||
| 1154 | static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | 1182 | static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) |
| 1155 | { | 1183 | { |
| 1156 | struct cpl_wr_ack *hdr = cplhdr(skb); | 1184 | struct cpl_wr_ack *hdr = cplhdr(skb); |
| 1157 | unsigned int credits = ntohs(hdr->credits); | 1185 | unsigned int credits = ntohs(hdr->credits); |
| 1158 | u32 snd_una = ntohl(hdr->snd_una); | 1186 | u32 snd_una = ntohl(hdr->snd_una); |
| 1159 | 1187 | ||
| 1188 | c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n", | ||
| 1189 | credits, c3cn->wr_avail, c3cn->wr_unacked, | ||
| 1190 | c3cn->tid, c3cn->state); | ||
| 1191 | |||
| 1160 | c3cn->wr_avail += credits; | 1192 | c3cn->wr_avail += credits; |
| 1161 | if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) | 1193 | if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail) |
| 1162 | c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; | 1194 | c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail; |
| @@ -1171,6 +1203,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1171 | break; | 1203 | break; |
| 1172 | } | 1204 | } |
| 1173 | if (unlikely(credits < p->csum)) { | 1205 | if (unlikely(credits < p->csum)) { |
| 1206 | struct tx_data_wr *w = cplhdr(p); | ||
| 1207 | cxgb3i_log_error("TID %u got %u WR credits need %u, " | ||
| 1208 | "len %u, main body %u, frags %u, " | ||
| 1209 | "seq # %u, ACK una %u, ACK nxt %u, " | ||
| 1210 | "WR_AVAIL %u, WRs pending %u\n", | ||
| 1211 | c3cn->tid, credits, p->csum, p->len, | ||
| 1212 | p->len - p->data_len, | ||
| 1213 | skb_shinfo(p)->nr_frags, | ||
| 1214 | ntohl(w->sndseq), snd_una, | ||
| 1215 | ntohl(hdr->snd_nxt), c3cn->wr_avail, | ||
| 1216 | count_pending_wrs(c3cn) - credits); | ||
| 1174 | p->csum -= credits; | 1217 | p->csum -= credits; |
| 1175 | break; | 1218 | break; |
| 1176 | } else { | 1219 | } else { |
| @@ -1180,15 +1223,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1180 | } | 1223 | } |
| 1181 | } | 1224 | } |
| 1182 | 1225 | ||
| 1183 | if (unlikely(before(snd_una, c3cn->snd_una))) | 1226 | check_wr_invariants(c3cn); |
| 1227 | |||
| 1228 | if (unlikely(before(snd_una, c3cn->snd_una))) { | ||
| 1229 | cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK " | ||
| 1230 | "snd_una %u\n", | ||
| 1231 | c3cn->tid, snd_una, c3cn->snd_una); | ||
| 1184 | goto out_free; | 1232 | goto out_free; |
| 1233 | } | ||
| 1185 | 1234 | ||
| 1186 | if (c3cn->snd_una != snd_una) { | 1235 | if (c3cn->snd_una != snd_una) { |
| 1187 | c3cn->snd_una = snd_una; | 1236 | c3cn->snd_una = snd_una; |
| 1188 | dst_confirm(c3cn->dst_cache); | 1237 | dst_confirm(c3cn->dst_cache); |
| 1189 | } | 1238 | } |
| 1190 | 1239 | ||
| 1191 | if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0)) | 1240 | if (skb_queue_len(&c3cn->write_queue)) { |
| 1241 | if (c3cn_push_tx_frames(c3cn, 0)) | ||
| 1242 | cxgb3i_conn_tx_open(c3cn); | ||
| 1243 | } else | ||
| 1192 | cxgb3i_conn_tx_open(c3cn); | 1244 | cxgb3i_conn_tx_open(c3cn); |
| 1193 | out_free: | 1245 | out_free: |
| 1194 | __kfree_skb(skb); | 1246 | __kfree_skb(skb); |
| @@ -1452,7 +1504,7 @@ static void init_offload_conn(struct s3_conn *c3cn, | |||
| 1452 | struct dst_entry *dst) | 1504 | struct dst_entry *dst) |
| 1453 | { | 1505 | { |
| 1454 | BUG_ON(c3cn->cdev != cdev); | 1506 | BUG_ON(c3cn->cdev != cdev); |
| 1455 | c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs; | 1507 | c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1; |
| 1456 | c3cn->wr_unacked = 0; | 1508 | c3cn->wr_unacked = 0; |
| 1457 | c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); | 1509 | c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst)); |
| 1458 | 1510 | ||
| @@ -1671,9 +1723,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb) | |||
| 1671 | goto out_err; | 1723 | goto out_err; |
| 1672 | } | 1724 | } |
| 1673 | 1725 | ||
| 1674 | err = -EPIPE; | ||
| 1675 | if (c3cn->err) { | 1726 | if (c3cn->err) { |
| 1676 | c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); | 1727 | c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err); |
| 1728 | err = -EPIPE; | ||
| 1729 | goto out_err; | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) { | ||
| 1733 | c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n", | ||
| 1734 | c3cn, c3cn->write_seq, c3cn->snd_una, | ||
| 1735 | cxgb3_snd_win); | ||
| 1736 | err = -EAGAIN; | ||
| 1677 | goto out_err; | 1737 | goto out_err; |
| 1678 | } | 1738 | } |
| 1679 | 1739 | ||
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index d23156907ffd..6344b9eb2589 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h | |||
| @@ -178,25 +178,33 @@ void cxgb3i_c3cn_release(struct s3_conn *); | |||
| 178 | * @flag: see C3CB_FLAG_* below | 178 | * @flag: see C3CB_FLAG_* below |
| 179 | * @ulp_mode: ULP mode/submode of sk_buff | 179 | * @ulp_mode: ULP mode/submode of sk_buff |
| 180 | * @seq: tcp sequence number | 180 | * @seq: tcp sequence number |
| 181 | * @ddigest: pdu data digest | ||
| 182 | * @pdulen: recovered pdu length | ||
| 183 | * @wr_data: scratch area for tx wr | ||
| 184 | */ | 181 | */ |
| 182 | struct cxgb3_skb_rx_cb { | ||
| 183 | __u32 ddigest; /* data digest */ | ||
| 184 | __u32 pdulen; /* recovered pdu length */ | ||
| 185 | }; | ||
| 186 | |||
| 187 | struct cxgb3_skb_tx_cb { | ||
| 188 | struct sk_buff *wr_next; /* next wr */ | ||
| 189 | }; | ||
| 190 | |||
| 185 | struct cxgb3_skb_cb { | 191 | struct cxgb3_skb_cb { |
| 186 | __u8 flags; | 192 | __u8 flags; |
| 187 | __u8 ulp_mode; | 193 | __u8 ulp_mode; |
| 188 | __u32 seq; | 194 | __u32 seq; |
| 189 | __u32 ddigest; | 195 | union { |
| 190 | __u32 pdulen; | 196 | struct cxgb3_skb_rx_cb rx; |
| 191 | struct sk_buff *wr_data; | 197 | struct cxgb3_skb_tx_cb tx; |
| 198 | }; | ||
| 192 | }; | 199 | }; |
| 193 | 200 | ||
| 194 | #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) | 201 | #define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0])) |
| 195 | 202 | #define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags) | |
| 196 | #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) | 203 | #define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode) |
| 197 | #define skb_ulp_ddigest(skb) (CXGB3_SKB_CB(skb)->ddigest) | 204 | #define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq) |
| 198 | #define skb_ulp_pdulen(skb) (CXGB3_SKB_CB(skb)->pdulen) | 205 | #define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest) |
| 199 | #define skb_wr_data(skb) (CXGB3_SKB_CB(skb)->wr_data) | 206 | #define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen) |
| 207 | #define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next) | ||
| 200 | 208 | ||
| 201 | enum c3cb_flags { | 209 | enum c3cb_flags { |
| 202 | C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ | 210 | C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */ |
| @@ -217,6 +225,7 @@ struct sge_opaque_hdr { | |||
| 217 | /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ | 225 | /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ |
| 218 | #define TX_HEADER_LEN \ | 226 | #define TX_HEADER_LEN \ |
| 219 | (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) | 227 | (sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr)) |
| 228 | #define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN) | ||
| 220 | 229 | ||
| 221 | /* | 230 | /* |
| 222 | * get and set private ip for iscsi traffic | 231 | * get and set private ip for iscsi traffic |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index ce7ce8c6094c..17115c230d65 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c | |||
| @@ -32,6 +32,10 @@ | |||
| 32 | #define cxgb3i_tx_debug(fmt...) | 32 | #define cxgb3i_tx_debug(fmt...) |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | /* always allocate rooms for AHS */ | ||
| 36 | #define SKB_TX_PDU_HEADER_LEN \ | ||
| 37 | (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE) | ||
| 38 | static unsigned int skb_extra_headroom; | ||
| 35 | static struct page *pad_page; | 39 | static struct page *pad_page; |
| 36 | 40 | ||
| 37 | /* | 41 | /* |
| @@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc) | |||
| 146 | 150 | ||
| 147 | void cxgb3i_conn_cleanup_task(struct iscsi_task *task) | 151 | void cxgb3i_conn_cleanup_task(struct iscsi_task *task) |
| 148 | { | 152 | { |
| 149 | struct iscsi_tcp_task *tcp_task = task->dd_data; | 153 | struct cxgb3i_task_data *tdata = task->dd_data + |
| 154 | sizeof(struct iscsi_tcp_task); | ||
| 150 | 155 | ||
| 151 | /* never reached the xmit task callout */ | 156 | /* never reached the xmit task callout */ |
| 152 | if (tcp_task->dd_data) | 157 | if (tdata->skb) |
| 153 | kfree_skb(tcp_task->dd_data); | 158 | __kfree_skb(tdata->skb); |
| 154 | tcp_task->dd_data = NULL; | 159 | memset(tdata, 0, sizeof(struct cxgb3i_task_data)); |
| 155 | 160 | ||
| 156 | /* MNC - Do we need a check in case this is called but | 161 | /* MNC - Do we need a check in case this is called but |
| 157 | * cxgb3i_conn_alloc_pdu has never been called on the task */ | 162 | * cxgb3i_conn_alloc_pdu has never been called on the task */ |
| @@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task) | |||
| 159 | iscsi_tcp_cleanup_task(task); | 164 | iscsi_tcp_cleanup_task(task); |
| 160 | } | 165 | } |
| 161 | 166 | ||
| 162 | /* | 167 | static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, |
| 163 | * We do not support ahs yet | 168 | unsigned int offset, unsigned int *off, |
| 164 | */ | 169 | struct scatterlist **sgp) |
| 170 | { | ||
| 171 | int i; | ||
| 172 | struct scatterlist *sg; | ||
| 173 | |||
| 174 | for_each_sg(sgl, sg, sgcnt, i) { | ||
| 175 | if (offset < sg->length) { | ||
| 176 | *off = offset; | ||
| 177 | *sgp = sg; | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | offset -= sg->length; | ||
| 181 | } | ||
| 182 | return -EFAULT; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, | ||
| 186 | unsigned int dlen, skb_frag_t *frags, | ||
| 187 | int frag_max) | ||
| 188 | { | ||
| 189 | unsigned int datalen = dlen; | ||
| 190 | unsigned int sglen = sg->length - sgoffset; | ||
| 191 | struct page *page = sg_page(sg); | ||
| 192 | int i; | ||
| 193 | |||
| 194 | i = 0; | ||
| 195 | do { | ||
| 196 | unsigned int copy; | ||
| 197 | |||
| 198 | if (!sglen) { | ||
| 199 | sg = sg_next(sg); | ||
| 200 | if (!sg) { | ||
| 201 | cxgb3i_log_error("%s, sg NULL, len %u/%u.\n", | ||
| 202 | __func__, datalen, dlen); | ||
| 203 | return -EINVAL; | ||
| 204 | } | ||
| 205 | sgoffset = 0; | ||
| 206 | sglen = sg->length; | ||
| 207 | page = sg_page(sg); | ||
| 208 | |||
| 209 | } | ||
| 210 | copy = min(datalen, sglen); | ||
| 211 | if (i && page == frags[i - 1].page && | ||
| 212 | sgoffset + sg->offset == | ||
| 213 | frags[i - 1].page_offset + frags[i - 1].size) { | ||
| 214 | frags[i - 1].size += copy; | ||
| 215 | } else { | ||
| 216 | if (i >= frag_max) { | ||
| 217 | cxgb3i_log_error("%s, too many pages %u, " | ||
| 218 | "dlen %u.\n", __func__, | ||
| 219 | frag_max, dlen); | ||
| 220 | return -EINVAL; | ||
| 221 | } | ||
| 222 | |||
| 223 | frags[i].page = page; | ||
| 224 | frags[i].page_offset = sg->offset + sgoffset; | ||
| 225 | frags[i].size = copy; | ||
| 226 | i++; | ||
| 227 | } | ||
| 228 | datalen -= copy; | ||
| 229 | sgoffset += copy; | ||
| 230 | sglen -= copy; | ||
| 231 | } while (datalen); | ||
| 232 | |||
| 233 | return i; | ||
| 234 | } | ||
| 235 | |||
| 165 | int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) | 236 | int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) |
| 166 | { | 237 | { |
| 238 | struct iscsi_conn *conn = task->conn; | ||
| 167 | struct iscsi_tcp_task *tcp_task = task->dd_data; | 239 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
| 168 | struct sk_buff *skb; | 240 | struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task); |
| 241 | struct scsi_cmnd *sc = task->sc; | ||
| 242 | int headroom = SKB_TX_PDU_HEADER_LEN; | ||
| 169 | 243 | ||
| 244 | tcp_task->dd_data = tdata; | ||
| 170 | task->hdr = NULL; | 245 | task->hdr = NULL; |
| 171 | /* always allocate rooms for AHS */ | 246 | |
| 172 | skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + | 247 | /* write command, need to send data pdus */ |
| 173 | TX_HEADER_LEN, GFP_ATOMIC); | 248 | if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT || |
| 174 | if (!skb) | 249 | (opcode == ISCSI_OP_SCSI_CMD && |
| 250 | (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE)))) | ||
| 251 | headroom += min(skb_extra_headroom, conn->max_xmit_dlength); | ||
| 252 | |||
| 253 | tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC); | ||
| 254 | if (!tdata->skb) | ||
| 175 | return -ENOMEM; | 255 | return -ENOMEM; |
| 256 | skb_reserve(tdata->skb, TX_HEADER_LEN); | ||
| 176 | 257 | ||
| 177 | cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", | 258 | cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n", |
| 178 | task, opcode, skb); | 259 | task, opcode, tdata->skb); |
| 179 | 260 | ||
| 180 | tcp_task->dd_data = skb; | 261 | task->hdr = (struct iscsi_hdr *)tdata->skb->data; |
| 181 | skb_reserve(skb, TX_HEADER_LEN); | 262 | task->hdr_max = SKB_TX_PDU_HEADER_LEN; |
| 182 | task->hdr = (struct iscsi_hdr *)skb->data; | ||
| 183 | task->hdr_max = sizeof(struct iscsi_hdr); | ||
| 184 | 263 | ||
| 185 | /* data_out uses scsi_cmd's itt */ | 264 | /* data_out uses scsi_cmd's itt */ |
| 186 | if (opcode != ISCSI_OP_SCSI_DATA_OUT) | 265 | if (opcode != ISCSI_OP_SCSI_DATA_OUT) |
| @@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) | |||
| 192 | int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, | 271 | int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, |
| 193 | unsigned int count) | 272 | unsigned int count) |
| 194 | { | 273 | { |
| 195 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 196 | struct sk_buff *skb = tcp_task->dd_data; | ||
| 197 | struct iscsi_conn *conn = task->conn; | 274 | struct iscsi_conn *conn = task->conn; |
| 198 | struct page *pg; | 275 | struct iscsi_tcp_task *tcp_task = task->dd_data; |
| 276 | struct cxgb3i_task_data *tdata = tcp_task->dd_data; | ||
| 277 | struct sk_buff *skb = tdata->skb; | ||
| 199 | unsigned int datalen = count; | 278 | unsigned int datalen = count; |
| 200 | int i, padlen = iscsi_padding(count); | 279 | int i, padlen = iscsi_padding(count); |
| 201 | skb_frag_t *frag; | 280 | struct page *pg; |
| 202 | 281 | ||
| 203 | cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", | 282 | cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n", |
| 204 | task, task->sc, offset, count, skb); | 283 | task, task->sc, offset, count, skb); |
| @@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset, | |||
| 209 | return 0; | 288 | return 0; |
| 210 | 289 | ||
| 211 | if (task->sc) { | 290 | if (task->sc) { |
| 212 | struct scatterlist *sg; | 291 | struct scsi_data_buffer *sdb = scsi_out(task->sc); |
| 213 | struct scsi_data_buffer *sdb; | 292 | struct scatterlist *sg = NULL; |
| 214 | unsigned int sgoffset = offset; | 293 | int err; |
| 215 | struct page *sgpg; | 294 | |
| 216 | unsigned int sglen; | 295 | tdata->offset = offset; |
| 217 | 296 | tdata->count = count; | |
| 218 | sdb = scsi_out(task->sc); | 297 | err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents, |
| 219 | sg = sdb->table.sgl; | 298 | tdata->offset, &tdata->sgoffset, &sg); |
| 220 | 299 | if (err < 0) { | |
| 221 | for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) { | 300 | cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n", |
| 222 | cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n", | 301 | sdb->table.nents, tdata->offset, |
| 223 | i, sg_page(sg), sg->length, sg->offset); | 302 | sdb->length); |
| 224 | 303 | return err; | |
| 225 | if (sgoffset < sg->length) | ||
| 226 | break; | ||
| 227 | sgoffset -= sg->length; | ||
| 228 | } | 304 | } |
| 229 | sgpg = sg_page(sg); | 305 | err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count, |
| 230 | sglen = sg->length - sgoffset; | 306 | tdata->frags, MAX_PDU_FRAGS); |
| 231 | 307 | if (err < 0) { | |
| 232 | do { | 308 | cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n", |
| 233 | int j = skb_shinfo(skb)->nr_frags; | 309 | sdb->table.nents, tdata->offset, |
| 234 | unsigned int copy; | 310 | tdata->count); |
| 235 | 311 | return err; | |
| 236 | if (!sglen) { | 312 | } |
| 237 | sg = sg_next(sg); | 313 | tdata->nr_frags = err; |
| 238 | sgpg = sg_page(sg); | 314 | |
| 239 | sgoffset = 0; | 315 | if (tdata->nr_frags > MAX_SKB_FRAGS || |
| 240 | sglen = sg->length; | 316 | (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { |
| 241 | ++i; | 317 | char *dst = skb->data + task->hdr_len; |
| 318 | skb_frag_t *frag = tdata->frags; | ||
| 319 | |||
| 320 | /* data fits in the skb's headroom */ | ||
| 321 | for (i = 0; i < tdata->nr_frags; i++, frag++) { | ||
| 322 | char *src = kmap_atomic(frag->page, | ||
| 323 | KM_SOFTIRQ0); | ||
| 324 | |||
| 325 | memcpy(dst, src+frag->page_offset, frag->size); | ||
| 326 | dst += frag->size; | ||
| 327 | kunmap_atomic(src, KM_SOFTIRQ0); | ||
| 242 | } | 328 | } |
| 243 | copy = min(sglen, datalen); | 329 | if (padlen) { |
| 244 | if (j && skb_can_coalesce(skb, j, sgpg, | 330 | memset(dst, 0, padlen); |
| 245 | sg->offset + sgoffset)) { | 331 | padlen = 0; |
| 246 | skb_shinfo(skb)->frags[j - 1].size += copy; | ||
| 247 | } else { | ||
| 248 | get_page(sgpg); | ||
| 249 | skb_fill_page_desc(skb, j, sgpg, | ||
| 250 | sg->offset + sgoffset, copy); | ||
| 251 | } | 332 | } |
| 252 | sgoffset += copy; | 333 | skb_put(skb, count + padlen); |
| 253 | sglen -= copy; | 334 | } else { |
| 254 | datalen -= copy; | 335 | /* data fit into frag_list */ |
| 255 | } while (datalen); | 336 | for (i = 0; i < tdata->nr_frags; i++) |
| 337 | get_page(tdata->frags[i].page); | ||
| 338 | |||
| 339 | memcpy(skb_shinfo(skb)->frags, tdata->frags, | ||
| 340 | sizeof(skb_frag_t) * tdata->nr_frags); | ||
| 341 | skb_shinfo(skb)->nr_frags = tdata->nr_frags; | ||
| 342 | skb->len += count; | ||
| 343 | skb->data_len += count; | ||
| 344 | skb->truesize += count; | ||
| 345 | } | ||
| 346 | |||
| 256 | } else { | 347 | } else { |
| 257 | pg = virt_to_page(task->data); | 348 | pg = virt_to_page(task->data); |
| 258 | 349 | ||
| 259 | while (datalen) { | 350 | get_page(pg); |
| 260 | i = skb_shinfo(skb)->nr_frags; | 351 | skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data), |
| 261 | frag = &skb_shinfo(skb)->frags[i]; | 352 | count); |
| 262 | 353 | skb->len += count; | |
| 263 | get_page(pg); | 354 | skb->data_len += count; |
| 264 | frag->page = pg; | 355 | skb->truesize += count; |
| 265 | frag->page_offset = 0; | ||
| 266 | frag->size = min((unsigned int)PAGE_SIZE, datalen); | ||
| 267 | |||
| 268 | skb_shinfo(skb)->nr_frags++; | ||
| 269 | datalen -= frag->size; | ||
| 270 | pg++; | ||
| 271 | } | ||
| 272 | } | 356 | } |
| 273 | 357 | ||
| 274 | if (padlen) { | 358 | if (padlen) { |
| 275 | i = skb_shinfo(skb)->nr_frags; | 359 | i = skb_shinfo(skb)->nr_frags; |
| 276 | frag = &skb_shinfo(skb)->frags[i]; | 360 | get_page(pad_page); |
| 277 | frag->page = pad_page; | 361 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0, |
| 278 | frag->page_offset = 0; | 362 | padlen); |
| 279 | frag->size = padlen; | 363 | |
| 280 | skb_shinfo(skb)->nr_frags++; | 364 | skb->data_len += padlen; |
| 365 | skb->truesize += padlen; | ||
| 366 | skb->len += padlen; | ||
| 281 | } | 367 | } |
| 282 | 368 | ||
| 283 | datalen = count + padlen; | ||
| 284 | skb->data_len += datalen; | ||
| 285 | skb->truesize += datalen; | ||
| 286 | skb->len += datalen; | ||
| 287 | return 0; | 369 | return 0; |
| 288 | } | 370 | } |
| 289 | 371 | ||
| 290 | int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | 372 | int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) |
| 291 | { | 373 | { |
| 292 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 293 | struct sk_buff *skb = tcp_task->dd_data; | ||
| 294 | struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; | 374 | struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; |
| 295 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; | 375 | struct cxgb3i_conn *cconn = tcp_conn->dd_data; |
| 376 | struct iscsi_tcp_task *tcp_task = task->dd_data; | ||
| 377 | struct cxgb3i_task_data *tdata = tcp_task->dd_data; | ||
| 378 | struct sk_buff *skb = tdata->skb; | ||
| 296 | unsigned int datalen; | 379 | unsigned int datalen; |
| 297 | int err; | 380 | int err; |
| 298 | 381 | ||
| @@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | |||
| 300 | return 0; | 383 | return 0; |
| 301 | 384 | ||
| 302 | datalen = skb->data_len; | 385 | datalen = skb->data_len; |
| 303 | tcp_task->dd_data = NULL; | 386 | tdata->skb = NULL; |
| 304 | err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); | 387 | err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb); |
| 305 | cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", | ||
| 306 | task, skb, skb->len, skb->data_len, err); | ||
| 307 | if (err > 0) { | 388 | if (err > 0) { |
| 308 | int pdulen = err; | 389 | int pdulen = err; |
| 309 | 390 | ||
| 391 | cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n", | ||
| 392 | task, skb, skb->len, skb->data_len, err); | ||
| 393 | |||
| 310 | if (task->conn->hdrdgst_en) | 394 | if (task->conn->hdrdgst_en) |
| 311 | pdulen += ISCSI_DIGEST_SIZE; | 395 | pdulen += ISCSI_DIGEST_SIZE; |
| 312 | if (datalen && task->conn->datadgst_en) | 396 | if (datalen && task->conn->datadgst_en) |
| @@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) | |||
| 325 | return err; | 409 | return err; |
| 326 | } | 410 | } |
| 327 | /* reset skb to send when we are called again */ | 411 | /* reset skb to send when we are called again */ |
| 328 | tcp_task->dd_data = skb; | 412 | tdata->skb = skb; |
| 329 | return -EAGAIN; | 413 | return -EAGAIN; |
| 330 | } | 414 | } |
| 331 | 415 | ||
| 332 | int cxgb3i_pdu_init(void) | 416 | int cxgb3i_pdu_init(void) |
| 333 | { | 417 | { |
| 418 | if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS)) | ||
| 419 | skb_extra_headroom = SKB_TX_HEADROOM; | ||
| 334 | pad_page = alloc_page(GFP_KERNEL); | 420 | pad_page = alloc_page(GFP_KERNEL); |
| 335 | if (!pad_page) | 421 | if (!pad_page) |
| 336 | return -ENOMEM; | 422 | return -ENOMEM; |
| @@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) | |||
| 366 | skb = skb_peek(&c3cn->receive_queue); | 452 | skb = skb_peek(&c3cn->receive_queue); |
| 367 | while (!err && skb) { | 453 | while (!err && skb) { |
| 368 | __skb_unlink(skb, &c3cn->receive_queue); | 454 | __skb_unlink(skb, &c3cn->receive_queue); |
| 369 | read += skb_ulp_pdulen(skb); | 455 | read += skb_rx_pdulen(skb); |
| 456 | cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n", | ||
| 457 | conn, c3cn, skb, skb_rx_pdulen(skb)); | ||
| 370 | err = cxgb3i_conn_read_pdu_skb(conn, skb); | 458 | err = cxgb3i_conn_read_pdu_skb(conn, skb); |
| 371 | __kfree_skb(skb); | 459 | __kfree_skb(skb); |
| 372 | skb = skb_peek(&c3cn->receive_queue); | 460 | skb = skb_peek(&c3cn->receive_queue); |
| @@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn) | |||
| 377 | cxgb3i_c3cn_rx_credits(c3cn, read); | 465 | cxgb3i_c3cn_rx_credits(c3cn, read); |
| 378 | } | 466 | } |
| 379 | conn->rxdata_octets += read; | 467 | conn->rxdata_octets += read; |
| 468 | |||
| 469 | if (err) { | ||
| 470 | cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err); | ||
| 471 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
| 472 | } | ||
| 380 | } | 473 | } |
| 381 | 474 | ||
| 382 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn) | 475 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn) |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h index a3f685cc2362..0770b23d90da 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.h | |||
| @@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss { | |||
| 53 | #define ULP2_FLAG_DCRC_ERROR 0x20 | 53 | #define ULP2_FLAG_DCRC_ERROR 0x20 |
| 54 | #define ULP2_FLAG_PAD_ERROR 0x40 | 54 | #define ULP2_FLAG_PAD_ERROR 0x40 |
| 55 | 55 | ||
| 56 | void cxgb3i_conn_closing(struct s3_conn *); | 56 | void cxgb3i_conn_closing(struct s3_conn *c3cn); |
| 57 | void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); | 57 | void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn); |
| 58 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn); | 58 | void cxgb3i_conn_tx_open(struct s3_conn *c3cn); |
| 59 | #endif | 59 | #endif |
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index a48e4990fe12..34be88d7afa5 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
| @@ -1251,6 +1251,7 @@ static struct pci_device_id hptiop_id_table[] = { | |||
| 1251 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, | 1251 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1252 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, | 1252 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1253 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, | 1253 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1254 | { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, | ||
| 1254 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, | 1255 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1255 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, | 1256 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, |
| 1256 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, | 1257 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 940dc32ff0dc..b82ffd90632e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1040,12 +1040,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 1040 | action = ACTION_FAIL; | 1040 | action = ACTION_FAIL; |
| 1041 | break; | 1041 | break; |
| 1042 | case ABORTED_COMMAND: | 1042 | case ABORTED_COMMAND: |
| 1043 | action = ACTION_FAIL; | ||
| 1043 | if (sshdr.asc == 0x10) { /* DIF */ | 1044 | if (sshdr.asc == 0x10) { /* DIF */ |
| 1044 | description = "Target Data Integrity Failure"; | 1045 | description = "Target Data Integrity Failure"; |
| 1045 | action = ACTION_FAIL; | ||
| 1046 | error = -EILSEQ; | 1046 | error = -EILSEQ; |
| 1047 | } else | 1047 | } |
| 1048 | action = ACTION_RETRY; | ||
| 1049 | break; | 1048 | break; |
| 1050 | case NOT_READY: | 1049 | case NOT_READY: |
| 1051 | /* If the device is in the process of becoming | 1050 | /* If the device is in the process of becoming |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d57566b8be0a..55310dbc10a6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev); | |||
| 107 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); | 107 | static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); |
| 108 | static void sd_print_result(struct scsi_disk *, int); | 108 | static void sd_print_result(struct scsi_disk *, int); |
| 109 | 109 | ||
| 110 | static DEFINE_SPINLOCK(sd_index_lock); | ||
| 110 | static DEFINE_IDA(sd_index_ida); | 111 | static DEFINE_IDA(sd_index_ida); |
| 111 | 112 | ||
| 112 | /* This semaphore is used to mediate the 0->1 reference get in the | 113 | /* This semaphore is used to mediate the 0->1 reference get in the |
| @@ -1914,7 +1915,9 @@ static int sd_probe(struct device *dev) | |||
| 1914 | if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) | 1915 | if (!ida_pre_get(&sd_index_ida, GFP_KERNEL)) |
| 1915 | goto out_put; | 1916 | goto out_put; |
| 1916 | 1917 | ||
| 1918 | spin_lock(&sd_index_lock); | ||
| 1917 | error = ida_get_new(&sd_index_ida, &index); | 1919 | error = ida_get_new(&sd_index_ida, &index); |
| 1920 | spin_unlock(&sd_index_lock); | ||
| 1918 | } while (error == -EAGAIN); | 1921 | } while (error == -EAGAIN); |
| 1919 | 1922 | ||
| 1920 | if (error) | 1923 | if (error) |
| @@ -1936,7 +1939,9 @@ static int sd_probe(struct device *dev) | |||
| 1936 | return 0; | 1939 | return 0; |
| 1937 | 1940 | ||
| 1938 | out_free_index: | 1941 | out_free_index: |
| 1942 | spin_lock(&sd_index_lock); | ||
| 1939 | ida_remove(&sd_index_ida, index); | 1943 | ida_remove(&sd_index_ida, index); |
| 1944 | spin_unlock(&sd_index_lock); | ||
| 1940 | out_put: | 1945 | out_put: |
| 1941 | put_disk(gd); | 1946 | put_disk(gd); |
| 1942 | out_free: | 1947 | out_free: |
| @@ -1986,7 +1991,9 @@ static void scsi_disk_release(struct device *dev) | |||
| 1986 | struct scsi_disk *sdkp = to_scsi_disk(dev); | 1991 | struct scsi_disk *sdkp = to_scsi_disk(dev); |
| 1987 | struct gendisk *disk = sdkp->disk; | 1992 | struct gendisk *disk = sdkp->disk; |
| 1988 | 1993 | ||
| 1994 | spin_lock(&sd_index_lock); | ||
| 1989 | ida_remove(&sd_index_ida, sdkp->index); | 1995 | ida_remove(&sd_index_ida, sdkp->index); |
| 1996 | spin_unlock(&sd_index_lock); | ||
| 1990 | 1997 | ||
| 1991 | disk->private_data = NULL; | 1998 | disk->private_data = NULL; |
| 1992 | put_disk(disk); | 1999 | put_disk(disk); |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 48ff701d3a72..2552b9f325ee 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -2230,7 +2230,7 @@ static int __devexit pxafb_remove(struct platform_device *dev) | |||
| 2230 | 2230 | ||
| 2231 | static struct platform_driver pxafb_driver = { | 2231 | static struct platform_driver pxafb_driver = { |
| 2232 | .probe = pxafb_probe, | 2232 | .probe = pxafb_probe, |
| 2233 | .remove = pxafb_remove, | 2233 | .remove = __devexit_p(pxafb_remove), |
| 2234 | .suspend = pxafb_suspend, | 2234 | .suspend = pxafb_suspend, |
| 2235 | .resume = pxafb_resume, | 2235 | .resume = pxafb_resume, |
| 2236 | .driver = { | 2236 | .driver = { |
diff --git a/fs/Makefile b/fs/Makefile index 38bc735c67ad..dc20db348679 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -69,10 +69,12 @@ obj-$(CONFIG_DLM) += dlm/ | |||
| 69 | # Do not add any filesystems before this line | 69 | # Do not add any filesystems before this line |
| 70 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ | 70 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ |
| 71 | obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 | 71 | obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 |
| 72 | obj-$(CONFIG_EXT4_FS) += ext4/ # Before ext2 so root fs can be ext4 | 72 | obj-$(CONFIG_EXT2_FS) += ext2/ |
| 73 | # We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 | ||
| 74 | # unless explicitly requested by rootfstype | ||
| 75 | obj-$(CONFIG_EXT4_FS) += ext4/ | ||
| 73 | obj-$(CONFIG_JBD) += jbd/ | 76 | obj-$(CONFIG_JBD) += jbd/ |
| 74 | obj-$(CONFIG_JBD2) += jbd2/ | 77 | obj-$(CONFIG_JBD2) += jbd2/ |
| 75 | obj-$(CONFIG_EXT2_FS) += ext2/ | ||
| 76 | obj-$(CONFIG_CRAMFS) += cramfs/ | 78 | obj-$(CONFIG_CRAMFS) += cramfs/ |
| 77 | obj-$(CONFIG_SQUASHFS) += squashfs/ | 79 | obj-$(CONFIG_SQUASHFS) += squashfs/ |
| 78 | obj-y += ramfs/ | 80 | obj-y += ramfs/ |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 9a50b8052dcf..de9459b4cb94 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -609,7 +609,9 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | |||
| 609 | */ | 609 | */ |
| 610 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) | 610 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) |
| 611 | { | 611 | { |
| 612 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3) | 612 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || |
| 613 | (*retries)++ > 3 || | ||
| 614 | !EXT4_SB(sb)->s_journal) | ||
| 613 | return 0; | 615 | return 0; |
| 614 | 616 | ||
| 615 | jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); | 617 | jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 51cdd13e1c31..c7fed5b18745 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -2544,7 +2544,7 @@ retry: | |||
| 2544 | 2544 | ||
| 2545 | ext4_journal_stop(handle); | 2545 | ext4_journal_stop(handle); |
| 2546 | 2546 | ||
| 2547 | if (mpd.retval == -ENOSPC) { | 2547 | if ((mpd.retval == -ENOSPC) && sbi->s_journal) { |
| 2548 | /* commit the transaction which would | 2548 | /* commit the transaction which would |
| 2549 | * free blocks released in the transaction | 2549 | * free blocks released in the transaction |
| 2550 | * and try again | 2550 | * and try again |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a5732c58f676..39d1993cfa13 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -3091,7 +3091,6 @@ static int ext4_freeze(struct super_block *sb) | |||
| 3091 | 3091 | ||
| 3092 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 3092 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
| 3093 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 3093 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 3094 | ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | ||
| 3095 | error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | 3094 | error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); |
| 3096 | if (error) | 3095 | if (error) |
| 3097 | goto out; | 3096 | goto out; |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b97cdc516a8f..106c3ba50844 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
| @@ -52,6 +52,7 @@ header-y += const.h | |||
| 52 | header-y += cgroupstats.h | 52 | header-y += cgroupstats.h |
| 53 | header-y += cramfs_fs.h | 53 | header-y += cramfs_fs.h |
| 54 | header-y += cycx_cfm.h | 54 | header-y += cycx_cfm.h |
| 55 | header-y += dcbnl.h | ||
| 55 | header-y += dlmconstants.h | 56 | header-y += dlmconstants.h |
| 56 | header-y += dlm_device.h | 57 | header-y += dlm_device.h |
| 57 | header-y += dlm_netlink.h | 58 | header-y += dlm_netlink.h |
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 95837bfb5256..455d83219fae 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
| @@ -65,23 +65,20 @@ extern void free_bootmem(unsigned long addr, unsigned long size); | |||
| 65 | #define BOOTMEM_DEFAULT 0 | 65 | #define BOOTMEM_DEFAULT 0 |
| 66 | #define BOOTMEM_EXCLUSIVE (1<<0) | 66 | #define BOOTMEM_EXCLUSIVE (1<<0) |
| 67 | 67 | ||
| 68 | extern int reserve_bootmem(unsigned long addr, | ||
| 69 | unsigned long size, | ||
| 70 | int flags); | ||
| 68 | extern int reserve_bootmem_node(pg_data_t *pgdat, | 71 | extern int reserve_bootmem_node(pg_data_t *pgdat, |
| 69 | unsigned long physaddr, | 72 | unsigned long physaddr, |
| 70 | unsigned long size, | 73 | unsigned long size, |
| 71 | int flags); | 74 | int flags); |
| 72 | #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE | ||
| 73 | extern int reserve_bootmem(unsigned long addr, unsigned long size, int flags); | ||
| 74 | #endif | ||
| 75 | 75 | ||
| 76 | extern void *__alloc_bootmem_nopanic(unsigned long size, | 76 | extern void *__alloc_bootmem(unsigned long size, |
| 77 | unsigned long align, | 77 | unsigned long align, |
| 78 | unsigned long goal); | 78 | unsigned long goal); |
| 79 | extern void *__alloc_bootmem(unsigned long size, | 79 | extern void *__alloc_bootmem_nopanic(unsigned long size, |
| 80 | unsigned long align, | 80 | unsigned long align, |
| 81 | unsigned long goal); | 81 | unsigned long goal); |
| 82 | extern void *__alloc_bootmem_low(unsigned long size, | ||
| 83 | unsigned long align, | ||
| 84 | unsigned long goal); | ||
| 85 | extern void *__alloc_bootmem_node(pg_data_t *pgdat, | 82 | extern void *__alloc_bootmem_node(pg_data_t *pgdat, |
| 86 | unsigned long size, | 83 | unsigned long size, |
| 87 | unsigned long align, | 84 | unsigned long align, |
| @@ -90,30 +87,35 @@ extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat, | |||
| 90 | unsigned long size, | 87 | unsigned long size, |
| 91 | unsigned long align, | 88 | unsigned long align, |
| 92 | unsigned long goal); | 89 | unsigned long goal); |
| 90 | extern void *__alloc_bootmem_low(unsigned long size, | ||
| 91 | unsigned long align, | ||
| 92 | unsigned long goal); | ||
| 93 | extern void *__alloc_bootmem_low_node(pg_data_t *pgdat, | 93 | extern void *__alloc_bootmem_low_node(pg_data_t *pgdat, |
| 94 | unsigned long size, | 94 | unsigned long size, |
| 95 | unsigned long align, | 95 | unsigned long align, |
| 96 | unsigned long goal); | 96 | unsigned long goal); |
| 97 | #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE | 97 | |
| 98 | #define alloc_bootmem(x) \ | 98 | #define alloc_bootmem(x) \ |
| 99 | __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) | 99 | __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) |
| 100 | #define alloc_bootmem_nopanic(x) \ | 100 | #define alloc_bootmem_nopanic(x) \ |
| 101 | __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) | 101 | __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) |
| 102 | #define alloc_bootmem_low(x) \ | ||
| 103 | __alloc_bootmem_low(x, SMP_CACHE_BYTES, 0) | ||
| 104 | #define alloc_bootmem_pages(x) \ | 102 | #define alloc_bootmem_pages(x) \ |
| 105 | __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | 103 | __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) |
| 106 | #define alloc_bootmem_pages_nopanic(x) \ | 104 | #define alloc_bootmem_pages_nopanic(x) \ |
| 107 | __alloc_bootmem_nopanic(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | 105 | __alloc_bootmem_nopanic(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) |
| 108 | #define alloc_bootmem_low_pages(x) \ | ||
| 109 | __alloc_bootmem_low(x, PAGE_SIZE, 0) | ||
| 110 | #define alloc_bootmem_node(pgdat, x) \ | 106 | #define alloc_bootmem_node(pgdat, x) \ |
| 111 | __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) | 107 | __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) |
| 112 | #define alloc_bootmem_pages_node(pgdat, x) \ | 108 | #define alloc_bootmem_pages_node(pgdat, x) \ |
| 113 | __alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | 109 | __alloc_bootmem_node(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) |
| 110 | #define alloc_bootmem_pages_node_nopanic(pgdat, x) \ | ||
| 111 | __alloc_bootmem_node_nopanic(pgdat, x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) | ||
| 112 | |||
| 113 | #define alloc_bootmem_low(x) \ | ||
| 114 | __alloc_bootmem_low(x, SMP_CACHE_BYTES, 0) | ||
| 115 | #define alloc_bootmem_low_pages(x) \ | ||
| 116 | __alloc_bootmem_low(x, PAGE_SIZE, 0) | ||
| 114 | #define alloc_bootmem_low_pages_node(pgdat, x) \ | 117 | #define alloc_bootmem_low_pages_node(pgdat, x) \ |
| 115 | __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0) | 118 | __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0) |
| 116 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ | ||
| 117 | 119 | ||
| 118 | extern int reserve_bootmem_generic(unsigned long addr, unsigned long size, | 120 | extern int reserve_bootmem_generic(unsigned long addr, unsigned long size, |
| 119 | int flags); | 121 | int flags); |
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index b0ef274e0031..7d2e10006188 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
| @@ -20,10 +20,12 @@ | |||
| 20 | #ifndef __LINUX_DCBNL_H__ | 20 | #ifndef __LINUX_DCBNL_H__ |
| 21 | #define __LINUX_DCBNL_H__ | 21 | #define __LINUX_DCBNL_H__ |
| 22 | 22 | ||
| 23 | #include <linux/types.h> | ||
| 24 | |||
| 23 | #define DCB_PROTO_VERSION 1 | 25 | #define DCB_PROTO_VERSION 1 |
| 24 | 26 | ||
| 25 | struct dcbmsg { | 27 | struct dcbmsg { |
| 26 | unsigned char dcb_family; | 28 | __u8 dcb_family; |
| 27 | __u8 cmd; | 29 | __u8 cmd; |
| 28 | __u16 dcb_pad; | 30 | __u16 dcb_pad; |
| 29 | }; | 31 | }; |
diff --git a/include/linux/decompress/bunzip2.h b/include/linux/decompress/bunzip2.h new file mode 100644 index 000000000000..115272137a9c --- /dev/null +++ b/include/linux/decompress/bunzip2.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #ifndef DECOMPRESS_BUNZIP2_H | ||
| 2 | #define DECOMPRESS_BUNZIP2_H | ||
| 3 | |||
| 4 | int bunzip2(unsigned char *inbuf, int len, | ||
| 5 | int(*fill)(void*, unsigned int), | ||
| 6 | int(*flush)(void*, unsigned int), | ||
| 7 | unsigned char *output, | ||
| 8 | int *pos, | ||
| 9 | void(*error)(char *x)); | ||
| 10 | #endif | ||
diff --git a/include/linux/decompress/generic.h b/include/linux/decompress/generic.h new file mode 100644 index 000000000000..6dfb856327bb --- /dev/null +++ b/include/linux/decompress/generic.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #ifndef DECOMPRESS_GENERIC_H | ||
| 2 | #define DECOMPRESS_GENERIC_H | ||
| 3 | |||
| 4 | /* Minimal chunksize to be read. | ||
| 5 | *Bzip2 prefers at least 4096 | ||
| 6 | *Lzma prefers 0x10000 */ | ||
| 7 | #define COMPR_IOBUF_SIZE 4096 | ||
| 8 | |||
| 9 | typedef int (*decompress_fn) (unsigned char *inbuf, int len, | ||
| 10 | int(*fill)(void*, unsigned int), | ||
| 11 | int(*writebb)(void*, unsigned int), | ||
| 12 | unsigned char *output, | ||
| 13 | int *posp, | ||
| 14 | void(*error)(char *x)); | ||
| 15 | |||
| 16 | /* inbuf - input buffer | ||
| 17 | *len - len of pre-read data in inbuf | ||
| 18 | *fill - function to fill inbuf if empty | ||
| 19 | *writebb - function to write out outbug | ||
| 20 | *posp - if non-null, input position (number of bytes read) will be | ||
| 21 | * returned here | ||
| 22 | * | ||
| 23 | *If len != 0, the inbuf is initialized (with as much data), and fill | ||
| 24 | *should not be called | ||
| 25 | *If len = 0, the inbuf is allocated, but empty. Its size is IOBUF_SIZE | ||
| 26 | *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE | ||
| 27 | */ | ||
| 28 | |||
| 29 | /* Utility routine to detect the decompression method */ | ||
| 30 | decompress_fn decompress_method(const unsigned char *inbuf, int len, | ||
| 31 | const char **name); | ||
| 32 | |||
| 33 | #endif | ||
diff --git a/include/linux/decompress/inflate.h b/include/linux/decompress/inflate.h new file mode 100644 index 000000000000..f9b06ccc3e5c --- /dev/null +++ b/include/linux/decompress/inflate.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef INFLATE_H | ||
| 2 | #define INFLATE_H | ||
| 3 | |||
| 4 | /* Other housekeeping constants */ | ||
| 5 | #define INBUFSIZ 4096 | ||
| 6 | |||
| 7 | int gunzip(unsigned char *inbuf, int len, | ||
| 8 | int(*fill)(void*, unsigned int), | ||
| 9 | int(*flush)(void*, unsigned int), | ||
| 10 | unsigned char *output, | ||
| 11 | int *pos, | ||
| 12 | void(*error_fn)(char *x)); | ||
| 13 | #endif | ||
diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h new file mode 100644 index 000000000000..12ff8c3f1d05 --- /dev/null +++ b/include/linux/decompress/mm.h | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* | ||
| 2 | * linux/compr_mm.h | ||
| 3 | * | ||
| 4 | * Memory management for pre-boot and ramdisk uncompressors | ||
| 5 | * | ||
| 6 | * Authors: Alain Knaff <alain@knaff.lu> | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef DECOMPR_MM_H | ||
| 11 | #define DECOMPR_MM_H | ||
| 12 | |||
| 13 | #ifdef STATIC | ||
| 14 | |||
| 15 | /* Code active when included from pre-boot environment: */ | ||
| 16 | |||
| 17 | /* A trivial malloc implementation, adapted from | ||
| 18 | * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 | ||
| 19 | */ | ||
| 20 | static unsigned long malloc_ptr; | ||
| 21 | static int malloc_count; | ||
| 22 | |||
| 23 | static void *malloc(int size) | ||
| 24 | { | ||
| 25 | void *p; | ||
| 26 | |||
| 27 | if (size < 0) | ||
| 28 | error("Malloc error"); | ||
| 29 | if (!malloc_ptr) | ||
| 30 | malloc_ptr = free_mem_ptr; | ||
| 31 | |||
| 32 | malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ | ||
| 33 | |||
| 34 | p = (void *)malloc_ptr; | ||
| 35 | malloc_ptr += size; | ||
| 36 | |||
| 37 | if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) | ||
| 38 | error("Out of memory"); | ||
| 39 | |||
| 40 | malloc_count++; | ||
| 41 | return p; | ||
| 42 | } | ||
| 43 | |||
| 44 | static void free(void *where) | ||
| 45 | { | ||
| 46 | malloc_count--; | ||
| 47 | if (!malloc_count) | ||
| 48 | malloc_ptr = free_mem_ptr; | ||
| 49 | } | ||
| 50 | |||
| 51 | #define large_malloc(a) malloc(a) | ||
| 52 | #define large_free(a) free(a) | ||
| 53 | |||
| 54 | #define set_error_fn(x) | ||
| 55 | |||
| 56 | #define INIT | ||
| 57 | |||
| 58 | #else /* STATIC */ | ||
| 59 | |||
| 60 | /* Code active when compiled standalone for use when loading ramdisk: */ | ||
| 61 | |||
| 62 | #include <linux/kernel.h> | ||
| 63 | #include <linux/fs.h> | ||
| 64 | #include <linux/string.h> | ||
| 65 | #include <linux/vmalloc.h> | ||
| 66 | |||
| 67 | /* Use defines rather than static inline in order to avoid spurious | ||
| 68 | * warnings when not needed (indeed large_malloc / large_free are not | ||
| 69 | * needed by inflate */ | ||
| 70 | |||
| 71 | #define malloc(a) kmalloc(a, GFP_KERNEL) | ||
| 72 | #define free(a) kfree(a) | ||
| 73 | |||
| 74 | #define large_malloc(a) vmalloc(a) | ||
| 75 | #define large_free(a) vfree(a) | ||
| 76 | |||
| 77 | static void(*error)(char *m); | ||
| 78 | #define set_error_fn(x) error = x; | ||
| 79 | |||
| 80 | #define INIT __init | ||
| 81 | #define STATIC | ||
| 82 | |||
| 83 | #include <linux/init.h> | ||
| 84 | |||
| 85 | #endif /* STATIC */ | ||
| 86 | |||
| 87 | #endif /* DECOMPR_MM_H */ | ||
diff --git a/include/linux/decompress/unlzma.h b/include/linux/decompress/unlzma.h new file mode 100644 index 000000000000..7796538f1bf4 --- /dev/null +++ b/include/linux/decompress/unlzma.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #ifndef DECOMPRESS_UNLZMA_H | ||
| 2 | #define DECOMPRESS_UNLZMA_H | ||
| 3 | |||
| 4 | int unlzma(unsigned char *, int, | ||
| 5 | int(*fill)(void*, unsigned int), | ||
| 6 | int(*flush)(void*, unsigned int), | ||
| 7 | unsigned char *output, | ||
| 8 | int *posp, | ||
| 9 | void(*error)(char *x) | ||
| 10 | ); | ||
| 11 | |||
| 12 | #endif | ||
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index cbc2f0cd631b..0adb0f91568c 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h | |||
| @@ -91,8 +91,11 @@ io_mapping_unmap_atomic(void *vaddr) | |||
| 91 | static inline void * | 91 | static inline void * |
| 92 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) | 92 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) |
| 93 | { | 93 | { |
| 94 | resource_size_t phys_addr; | ||
| 95 | |||
| 94 | BUG_ON(offset >= mapping->size); | 96 | BUG_ON(offset >= mapping->size); |
| 95 | resource_size_t phys_addr = mapping->base + offset; | 97 | phys_addr = mapping->base + offset; |
| 98 | |||
| 96 | return ioremap_wc(phys_addr, PAGE_SIZE); | 99 | return ioremap_wc(phys_addr, PAGE_SIZE); |
| 97 | } | 100 | } |
| 98 | 101 | ||
diff --git a/include/linux/netfilter/xt_NFLOG.h b/include/linux/netfilter/xt_NFLOG.h index cdcd0ed58f7a..4b36aeb46a10 100644 --- a/include/linux/netfilter/xt_NFLOG.h +++ b/include/linux/netfilter/xt_NFLOG.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #define _XT_NFLOG_TARGET | 2 | #define _XT_NFLOG_TARGET |
| 3 | 3 | ||
| 4 | #define XT_NFLOG_DEFAULT_GROUP 0x1 | 4 | #define XT_NFLOG_DEFAULT_GROUP 0x1 |
| 5 | #define XT_NFLOG_DEFAULT_THRESHOLD 1 | 5 | #define XT_NFLOG_DEFAULT_THRESHOLD 0 |
| 6 | 6 | ||
| 7 | #define XT_NFLOG_MASK 0x0 | 7 | #define XT_NFLOG_MASK 0x0 |
| 8 | 8 | ||
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 3577ffd90d45..545b068bcb70 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
| @@ -76,52 +76,98 @@ | |||
| 76 | 76 | ||
| 77 | #ifdef CONFIG_SMP | 77 | #ifdef CONFIG_SMP |
| 78 | 78 | ||
| 79 | #ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
| 80 | |||
| 81 | /* minimum unit size, also is the maximum supported allocation size */ | ||
| 82 | #define PCPU_MIN_UNIT_SIZE (16UL << PAGE_SHIFT) | ||
| 83 | |||
| 84 | /* | ||
| 85 | * PERCPU_DYNAMIC_RESERVE indicates the amount of free area to piggy | ||
| 86 | * back on the first chunk if arch is manually allocating and mapping | ||
| 87 | * it for faster access (as a part of large page mapping for example). | ||
| 88 | * Note that dynamic percpu allocator covers both static and dynamic | ||
| 89 | * areas, so these values are bigger than PERCPU_MODULE_RESERVE. | ||
| 90 | * | ||
| 91 | * On typical configuration with modules, the following values leave | ||
| 92 | * about 8k of free space on the first chunk after boot on both x86_32 | ||
| 93 | * and 64 when module support is enabled. When module support is | ||
| 94 | * disabled, it's much tighter. | ||
| 95 | */ | ||
| 96 | #ifndef PERCPU_DYNAMIC_RESERVE | ||
| 97 | # if BITS_PER_LONG > 32 | ||
| 98 | # ifdef CONFIG_MODULES | ||
| 99 | # define PERCPU_DYNAMIC_RESERVE (6 << PAGE_SHIFT) | ||
| 100 | # else | ||
| 101 | # define PERCPU_DYNAMIC_RESERVE (4 << PAGE_SHIFT) | ||
| 102 | # endif | ||
| 103 | # else | ||
| 104 | # ifdef CONFIG_MODULES | ||
| 105 | # define PERCPU_DYNAMIC_RESERVE (4 << PAGE_SHIFT) | ||
| 106 | # else | ||
| 107 | # define PERCPU_DYNAMIC_RESERVE (2 << PAGE_SHIFT) | ||
| 108 | # endif | ||
| 109 | # endif | ||
| 110 | #endif /* PERCPU_DYNAMIC_RESERVE */ | ||
| 111 | |||
| 112 | extern void *pcpu_base_addr; | ||
| 113 | |||
| 114 | typedef struct page * (*pcpu_get_page_fn_t)(unsigned int cpu, int pageno); | ||
| 115 | typedef void (*pcpu_populate_pte_fn_t)(unsigned long addr); | ||
| 116 | |||
| 117 | extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | ||
| 118 | size_t static_size, size_t unit_size, | ||
| 119 | size_t free_size, void *base_addr, | ||
| 120 | pcpu_populate_pte_fn_t populate_pte_fn); | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Use this to get to a cpu's version of the per-cpu object | ||
| 124 | * dynamically allocated. Non-atomic access to the current CPU's | ||
| 125 | * version should probably be combined with get_cpu()/put_cpu(). | ||
| 126 | */ | ||
| 127 | #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) | ||
| 128 | |||
| 129 | #else /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
| 130 | |||
| 79 | struct percpu_data { | 131 | struct percpu_data { |
| 80 | void *ptrs[1]; | 132 | void *ptrs[1]; |
| 81 | }; | 133 | }; |
| 82 | 134 | ||
| 83 | #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) | 135 | #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) |
| 84 | /* | 136 | |
| 85 | * Use this to get to a cpu's version of the per-cpu object dynamically | 137 | #define per_cpu_ptr(ptr, cpu) \ |
| 86 | * allocated. Non-atomic access to the current CPU's version should | 138 | ({ \ |
| 87 | * probably be combined with get_cpu()/put_cpu(). | 139 | struct percpu_data *__p = __percpu_disguise(ptr); \ |
| 88 | */ | 140 | (__typeof__(ptr))__p->ptrs[(cpu)]; \ |
| 89 | #define percpu_ptr(ptr, cpu) \ | ||
| 90 | ({ \ | ||
| 91 | struct percpu_data *__p = __percpu_disguise(ptr); \ | ||
| 92 | (__typeof__(ptr))__p->ptrs[(cpu)]; \ | ||
| 93 | }) | 141 | }) |
| 94 | 142 | ||
| 95 | extern void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask); | 143 | #endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ |
| 96 | extern void percpu_free(void *__pdata); | 144 | |
| 145 | extern void *__alloc_percpu(size_t size, size_t align); | ||
| 146 | extern void free_percpu(void *__pdata); | ||
| 97 | 147 | ||
| 98 | #else /* CONFIG_SMP */ | 148 | #else /* CONFIG_SMP */ |
| 99 | 149 | ||
| 100 | #define percpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) | 150 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
| 101 | 151 | ||
| 102 | static __always_inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask) | 152 | static inline void *__alloc_percpu(size_t size, size_t align) |
| 103 | { | 153 | { |
| 104 | return kzalloc(size, gfp); | 154 | /* |
| 155 | * Can't easily make larger alignment work with kmalloc. WARN | ||
| 156 | * on it. Larger alignment should only be used for module | ||
| 157 | * percpu sections on SMP for which this path isn't used. | ||
| 158 | */ | ||
| 159 | WARN_ON_ONCE(align > SMP_CACHE_BYTES); | ||
| 160 | return kzalloc(size, GFP_KERNEL); | ||
| 105 | } | 161 | } |
| 106 | 162 | ||
| 107 | static inline void percpu_free(void *__pdata) | 163 | static inline void free_percpu(void *p) |
| 108 | { | 164 | { |
| 109 | kfree(__pdata); | 165 | kfree(p); |
| 110 | } | 166 | } |
| 111 | 167 | ||
| 112 | #endif /* CONFIG_SMP */ | 168 | #endif /* CONFIG_SMP */ |
| 113 | 169 | ||
| 114 | #define percpu_alloc_mask(size, gfp, mask) \ | 170 | #define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type), \ |
| 115 | __percpu_alloc_mask((size), (gfp), &(mask)) | 171 | __alignof__(type)) |
| 116 | |||
| 117 | #define percpu_alloc(size, gfp) percpu_alloc_mask((size), (gfp), cpu_online_map) | ||
| 118 | |||
| 119 | /* (legacy) interface for use without CPU hotplug handling */ | ||
| 120 | |||
| 121 | #define __alloc_percpu(size) percpu_alloc_mask((size), GFP_KERNEL, \ | ||
| 122 | cpu_possible_map) | ||
| 123 | #define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type)) | ||
| 124 | #define free_percpu(ptr) percpu_free((ptr)) | ||
| 125 | #define per_cpu_ptr(ptr, cpu) percpu_ptr((ptr), (cpu)) | ||
| 126 | 172 | ||
| 127 | #endif /* __LINUX_PERCPU_H */ | 173 | #endif /* __LINUX_PERCPU_H */ |
diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h index f3f697df1d71..80044a4f3ab9 100644 --- a/include/linux/rcuclassic.h +++ b/include/linux/rcuclassic.h | |||
| @@ -181,4 +181,10 @@ extern long rcu_batches_completed_bh(void); | |||
| 181 | #define rcu_enter_nohz() do { } while (0) | 181 | #define rcu_enter_nohz() do { } while (0) |
| 182 | #define rcu_exit_nohz() do { } while (0) | 182 | #define rcu_exit_nohz() do { } while (0) |
| 183 | 183 | ||
| 184 | /* A context switch is a grace period for rcuclassic. */ | ||
| 185 | static inline int rcu_blocking_is_gp(void) | ||
| 186 | { | ||
| 187 | return num_online_cpus() == 1; | ||
| 188 | } | ||
| 189 | |||
| 184 | #endif /* __LINUX_RCUCLASSIC_H */ | 190 | #endif /* __LINUX_RCUCLASSIC_H */ |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 921340a7b71c..528343e6da51 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -52,6 +52,9 @@ struct rcu_head { | |||
| 52 | void (*func)(struct rcu_head *head); | 52 | void (*func)(struct rcu_head *head); |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* Internal to kernel, but needed by rcupreempt.h. */ | ||
| 56 | extern int rcu_scheduler_active; | ||
| 57 | |||
| 55 | #if defined(CONFIG_CLASSIC_RCU) | 58 | #if defined(CONFIG_CLASSIC_RCU) |
| 56 | #include <linux/rcuclassic.h> | 59 | #include <linux/rcuclassic.h> |
| 57 | #elif defined(CONFIG_TREE_RCU) | 60 | #elif defined(CONFIG_TREE_RCU) |
| @@ -265,6 +268,7 @@ extern void rcu_barrier_sched(void); | |||
| 265 | 268 | ||
| 266 | /* Internal to kernel */ | 269 | /* Internal to kernel */ |
| 267 | extern void rcu_init(void); | 270 | extern void rcu_init(void); |
| 271 | extern void rcu_scheduler_starting(void); | ||
| 268 | extern int rcu_needs_cpu(int cpu); | 272 | extern int rcu_needs_cpu(int cpu); |
| 269 | 273 | ||
| 270 | #endif /* __LINUX_RCUPDATE_H */ | 274 | #endif /* __LINUX_RCUPDATE_H */ |
diff --git a/include/linux/rcupreempt.h b/include/linux/rcupreempt.h index 3e05c09b54a2..74304b4538d8 100644 --- a/include/linux/rcupreempt.h +++ b/include/linux/rcupreempt.h | |||
| @@ -142,4 +142,19 @@ static inline void rcu_exit_nohz(void) | |||
| 142 | #define rcu_exit_nohz() do { } while (0) | 142 | #define rcu_exit_nohz() do { } while (0) |
| 143 | #endif /* CONFIG_NO_HZ */ | 143 | #endif /* CONFIG_NO_HZ */ |
| 144 | 144 | ||
| 145 | /* | ||
| 146 | * A context switch is a grace period for rcupreempt synchronize_rcu() | ||
| 147 | * only during early boot, before the scheduler has been initialized. | ||
| 148 | * So, how the heck do we get a context switch? Well, if the caller | ||
| 149 | * invokes synchronize_rcu(), they are willing to accept a context | ||
| 150 | * switch, so we simply pretend that one happened. | ||
| 151 | * | ||
| 152 | * After boot, there might be a blocked or preempted task in an RCU | ||
| 153 | * read-side critical section, so we cannot then take the fastpath. | ||
| 154 | */ | ||
| 155 | static inline int rcu_blocking_is_gp(void) | ||
| 156 | { | ||
| 157 | return num_online_cpus() == 1 && !rcu_scheduler_active; | ||
| 158 | } | ||
| 159 | |||
| 145 | #endif /* __LINUX_RCUPREEMPT_H */ | 160 | #endif /* __LINUX_RCUPREEMPT_H */ |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index d4368b7975c3..a722fb67bb2d 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
| @@ -326,4 +326,10 @@ static inline void rcu_exit_nohz(void) | |||
| 326 | } | 326 | } |
| 327 | #endif /* CONFIG_NO_HZ */ | 327 | #endif /* CONFIG_NO_HZ */ |
| 328 | 328 | ||
| 329 | /* A context switch is a grace period for rcutree. */ | ||
| 330 | static inline int rcu_blocking_is_gp(void) | ||
| 331 | { | ||
| 332 | return num_online_cpus() == 1; | ||
| 333 | } | ||
| 334 | |||
| 329 | #endif /* __LINUX_RCUTREE_H */ | 335 | #endif /* __LINUX_RCUTREE_H */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index f0a50b20e8a0..a7c7698583bb 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -2303,9 +2303,13 @@ extern long sched_group_rt_runtime(struct task_group *tg); | |||
| 2303 | extern int sched_group_set_rt_period(struct task_group *tg, | 2303 | extern int sched_group_set_rt_period(struct task_group *tg, |
| 2304 | long rt_period_us); | 2304 | long rt_period_us); |
| 2305 | extern long sched_group_rt_period(struct task_group *tg); | 2305 | extern long sched_group_rt_period(struct task_group *tg); |
| 2306 | extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); | ||
| 2306 | #endif | 2307 | #endif |
| 2307 | #endif | 2308 | #endif |
| 2308 | 2309 | ||
| 2310 | extern int task_can_switch_user(struct user_struct *up, | ||
| 2311 | struct task_struct *tsk); | ||
| 2312 | |||
| 2309 | #ifdef CONFIG_TASK_XACCT | 2313 | #ifdef CONFIG_TASK_XACCT |
| 2310 | static inline void add_rchar(struct task_struct *tsk, ssize_t amt) | 2314 | static inline void add_rchar(struct task_struct *tsk, ssize_t amt) |
| 2311 | { | 2315 | { |
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 6f3c603b0d67..6b58367d145e 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h | |||
| @@ -41,13 +41,13 @@ static inline void pagefault_enable(void) | |||
| 41 | #ifndef ARCH_HAS_NOCACHE_UACCESS | 41 | #ifndef ARCH_HAS_NOCACHE_UACCESS |
| 42 | 42 | ||
| 43 | static inline unsigned long __copy_from_user_inatomic_nocache(void *to, | 43 | static inline unsigned long __copy_from_user_inatomic_nocache(void *to, |
| 44 | const void __user *from, unsigned long n, unsigned long total) | 44 | const void __user *from, unsigned long n) |
| 45 | { | 45 | { |
| 46 | return __copy_from_user_inatomic(to, from, n); | 46 | return __copy_from_user_inatomic(to, from, n); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static inline unsigned long __copy_from_user_nocache(void *to, | 49 | static inline unsigned long __copy_from_user_nocache(void *to, |
| 50 | const void __user *from, unsigned long n, unsigned long total) | 50 | const void __user *from, unsigned long n) |
| 51 | { | 51 | { |
| 52 | return __copy_from_user(to, from, n); | 52 | return __copy_from_user(to, from, n); |
| 53 | } | 53 | } |
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 9c0890c7a06a..a43ebec3a7b9 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h | |||
| @@ -95,6 +95,9 @@ extern struct vm_struct *remove_vm_area(const void *addr); | |||
| 95 | 95 | ||
| 96 | extern int map_vm_area(struct vm_struct *area, pgprot_t prot, | 96 | extern int map_vm_area(struct vm_struct *area, pgprot_t prot, |
| 97 | struct page ***pages); | 97 | struct page ***pages); |
| 98 | extern int map_kernel_range_noflush(unsigned long start, unsigned long size, | ||
| 99 | pgprot_t prot, struct page **pages); | ||
| 100 | extern void unmap_kernel_range_noflush(unsigned long addr, unsigned long size); | ||
| 98 | extern void unmap_kernel_range(unsigned long addr, unsigned long size); | 101 | extern void unmap_kernel_range(unsigned long addr, unsigned long size); |
| 99 | 102 | ||
| 100 | /* Allocate/destroy a 'vmalloc' VM area. */ | 103 | /* Allocate/destroy a 'vmalloc' VM area. */ |
| @@ -110,5 +113,6 @@ extern long vwrite(char *buf, char *addr, unsigned long count); | |||
| 110 | */ | 113 | */ |
| 111 | extern rwlock_t vmlist_lock; | 114 | extern rwlock_t vmlist_lock; |
| 112 | extern struct vm_struct *vmlist; | 115 | extern struct vm_struct *vmlist; |
| 116 | extern __init void vm_area_register_early(struct vm_struct *vm, size_t align); | ||
| 113 | 117 | ||
| 114 | #endif /* _LINUX_VMALLOC_H */ | 118 | #endif /* _LINUX_VMALLOC_H */ |
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index e78afe7f28e3..c25068e38516 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h | |||
| @@ -59,7 +59,7 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb) | |||
| 59 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; | 59 | struct nf_conn *ct = (struct nf_conn *)skb->nfct; |
| 60 | int ret = NF_ACCEPT; | 60 | int ret = NF_ACCEPT; |
| 61 | 61 | ||
| 62 | if (ct) { | 62 | if (ct && ct != &nf_conntrack_untracked) { |
| 63 | if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) | 63 | if (!nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) |
| 64 | ret = __nf_conntrack_confirm(skb); | 64 | ret = __nf_conntrack_confirm(skb); |
| 65 | nf_ct_deliver_cached_events(ct); | 65 | nf_ct_deliver_cached_events(ct); |
diff --git a/init/Kconfig b/init/Kconfig index f068071fcc5d..95a66131403a 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -101,6 +101,66 @@ config LOCALVERSION_AUTO | |||
| 101 | 101 | ||
| 102 | which is done within the script "scripts/setlocalversion".) | 102 | which is done within the script "scripts/setlocalversion".) |
| 103 | 103 | ||
| 104 | config HAVE_KERNEL_GZIP | ||
| 105 | bool | ||
| 106 | |||
| 107 | config HAVE_KERNEL_BZIP2 | ||
| 108 | bool | ||
| 109 | |||
| 110 | config HAVE_KERNEL_LZMA | ||
| 111 | bool | ||
| 112 | |||
| 113 | choice | ||
| 114 | prompt "Kernel compression mode" | ||
| 115 | default KERNEL_GZIP | ||
| 116 | depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA | ||
| 117 | help | ||
| 118 | The linux kernel is a kind of self-extracting executable. | ||
| 119 | Several compression algorithms are available, which differ | ||
| 120 | in efficiency, compression and decompression speed. | ||
| 121 | Compression speed is only relevant when building a kernel. | ||
| 122 | Decompression speed is relevant at each boot. | ||
| 123 | |||
| 124 | If you have any problems with bzip2 or lzma compressed | ||
| 125 | kernels, mail me (Alain Knaff) <alain@knaff.lu>. (An older | ||
| 126 | version of this functionality (bzip2 only), for 2.4, was | ||
| 127 | supplied by Christian Ludwig) | ||
| 128 | |||
| 129 | High compression options are mostly useful for users, who | ||
| 130 | are low on disk space (embedded systems), but for whom ram | ||
| 131 | size matters less. | ||
| 132 | |||
| 133 | If in doubt, select 'gzip' | ||
| 134 | |||
| 135 | config KERNEL_GZIP | ||
| 136 | bool "Gzip" | ||
| 137 | depends on HAVE_KERNEL_GZIP | ||
| 138 | help | ||
| 139 | The old and tried gzip compression. Its compression ratio is | ||
| 140 | the poorest among the 3 choices; however its speed (both | ||
| 141 | compression and decompression) is the fastest. | ||
| 142 | |||
| 143 | config KERNEL_BZIP2 | ||
| 144 | bool "Bzip2" | ||
| 145 | depends on HAVE_KERNEL_BZIP2 | ||
| 146 | help | ||
| 147 | Its compression ratio and speed is intermediate. | ||
| 148 | Decompression speed is slowest among the three. The kernel | ||
| 149 | size is about 10% smaller with bzip2, in comparison to gzip. | ||
| 150 | Bzip2 uses a large amount of memory. For modern kernels you | ||
| 151 | will need at least 8MB RAM or more for booting. | ||
| 152 | |||
| 153 | config KERNEL_LZMA | ||
| 154 | bool "LZMA" | ||
| 155 | depends on HAVE_KERNEL_LZMA | ||
| 156 | help | ||
| 157 | The most recent compression algorithm. | ||
| 158 | Its ratio is best, decompression speed is between the other | ||
| 159 | two. Compression is slowest. The kernel size is about 33% | ||
| 160 | smaller with LZMA in comparison to gzip. | ||
| 161 | |||
| 162 | endchoice | ||
| 163 | |||
| 104 | config SWAP | 164 | config SWAP |
| 105 | bool "Support for paging of anonymous memory (swap)" | 165 | bool "Support for paging of anonymous memory (swap)" |
| 106 | depends on MMU && BLOCK | 166 | depends on MMU && BLOCK |
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 0f0f0cf3ba9a..027a402708de 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | #include "do_mounts.h" | 11 | #include "do_mounts.h" |
| 12 | #include "../fs/squashfs/squashfs_fs.h" | 12 | #include "../fs/squashfs/squashfs_fs.h" |
| 13 | 13 | ||
| 14 | #include <linux/decompress/generic.h> | ||
| 15 | |||
| 16 | |||
| 14 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ | 17 | int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ |
| 15 | 18 | ||
| 16 | static int __init prompt_ramdisk(char *str) | 19 | static int __init prompt_ramdisk(char *str) |
| @@ -29,7 +32,7 @@ static int __init ramdisk_start_setup(char *str) | |||
| 29 | } | 32 | } |
| 30 | __setup("ramdisk_start=", ramdisk_start_setup); | 33 | __setup("ramdisk_start=", ramdisk_start_setup); |
| 31 | 34 | ||
| 32 | static int __init crd_load(int in_fd, int out_fd); | 35 | static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); |
| 33 | 36 | ||
| 34 | /* | 37 | /* |
| 35 | * This routine tries to find a RAM disk image to load, and returns the | 38 | * This routine tries to find a RAM disk image to load, and returns the |
| @@ -38,15 +41,15 @@ static int __init crd_load(int in_fd, int out_fd); | |||
| 38 | * numbers could not be found. | 41 | * numbers could not be found. |
| 39 | * | 42 | * |
| 40 | * We currently check for the following magic numbers: | 43 | * We currently check for the following magic numbers: |
| 41 | * minix | 44 | * minix |
| 42 | * ext2 | 45 | * ext2 |
| 43 | * romfs | 46 | * romfs |
| 44 | * cramfs | 47 | * cramfs |
| 45 | * squashfs | 48 | * squashfs |
| 46 | * gzip | 49 | * gzip |
| 47 | */ | 50 | */ |
| 48 | static int __init | 51 | static int __init |
| 49 | identify_ramdisk_image(int fd, int start_block) | 52 | identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) |
| 50 | { | 53 | { |
| 51 | const int size = 512; | 54 | const int size = 512; |
| 52 | struct minix_super_block *minixsb; | 55 | struct minix_super_block *minixsb; |
| @@ -56,6 +59,7 @@ identify_ramdisk_image(int fd, int start_block) | |||
| 56 | struct squashfs_super_block *squashfsb; | 59 | struct squashfs_super_block *squashfsb; |
| 57 | int nblocks = -1; | 60 | int nblocks = -1; |
| 58 | unsigned char *buf; | 61 | unsigned char *buf; |
| 62 | const char *compress_name; | ||
| 59 | 63 | ||
| 60 | buf = kmalloc(size, GFP_KERNEL); | 64 | buf = kmalloc(size, GFP_KERNEL); |
| 61 | if (!buf) | 65 | if (!buf) |
| @@ -69,18 +73,19 @@ identify_ramdisk_image(int fd, int start_block) | |||
| 69 | memset(buf, 0xe5, size); | 73 | memset(buf, 0xe5, size); |
| 70 | 74 | ||
| 71 | /* | 75 | /* |
| 72 | * Read block 0 to test for gzipped kernel | 76 | * Read block 0 to test for compressed kernel |
| 73 | */ | 77 | */ |
| 74 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); | 78 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); |
| 75 | sys_read(fd, buf, size); | 79 | sys_read(fd, buf, size); |
| 76 | 80 | ||
| 77 | /* | 81 | *decompressor = decompress_method(buf, size, &compress_name); |
| 78 | * If it matches the gzip magic numbers, return 0 | 82 | if (compress_name) { |
| 79 | */ | 83 | printk(KERN_NOTICE "RAMDISK: %s image found at block %d\n", |
| 80 | if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { | 84 | compress_name, start_block); |
| 81 | printk(KERN_NOTICE | 85 | if (!*decompressor) |
| 82 | "RAMDISK: Compressed image found at block %d\n", | 86 | printk(KERN_EMERG |
| 83 | start_block); | 87 | "RAMDISK: %s decompressor not configured!\n", |
| 88 | compress_name); | ||
| 84 | nblocks = 0; | 89 | nblocks = 0; |
| 85 | goto done; | 90 | goto done; |
| 86 | } | 91 | } |
| @@ -142,7 +147,7 @@ identify_ramdisk_image(int fd, int start_block) | |||
| 142 | printk(KERN_NOTICE | 147 | printk(KERN_NOTICE |
| 143 | "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", | 148 | "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", |
| 144 | start_block); | 149 | start_block); |
| 145 | 150 | ||
| 146 | done: | 151 | done: |
| 147 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); | 152 | sys_lseek(fd, start_block * BLOCK_SIZE, 0); |
| 148 | kfree(buf); | 153 | kfree(buf); |
| @@ -157,6 +162,7 @@ int __init rd_load_image(char *from) | |||
| 157 | int nblocks, i, disk; | 162 | int nblocks, i, disk; |
| 158 | char *buf = NULL; | 163 | char *buf = NULL; |
| 159 | unsigned short rotate = 0; | 164 | unsigned short rotate = 0; |
| 165 | decompress_fn decompressor = NULL; | ||
| 160 | #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) | 166 | #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) |
| 161 | char rotator[4] = { '|' , '/' , '-' , '\\' }; | 167 | char rotator[4] = { '|' , '/' , '-' , '\\' }; |
| 162 | #endif | 168 | #endif |
| @@ -169,12 +175,12 @@ int __init rd_load_image(char *from) | |||
| 169 | if (in_fd < 0) | 175 | if (in_fd < 0) |
| 170 | goto noclose_input; | 176 | goto noclose_input; |
| 171 | 177 | ||
| 172 | nblocks = identify_ramdisk_image(in_fd, rd_image_start); | 178 | nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); |
| 173 | if (nblocks < 0) | 179 | if (nblocks < 0) |
| 174 | goto done; | 180 | goto done; |
| 175 | 181 | ||
| 176 | if (nblocks == 0) { | 182 | if (nblocks == 0) { |
| 177 | if (crd_load(in_fd, out_fd) == 0) | 183 | if (crd_load(in_fd, out_fd, decompressor) == 0) |
| 178 | goto successful_load; | 184 | goto successful_load; |
| 179 | goto done; | 185 | goto done; |
| 180 | } | 186 | } |
| @@ -200,7 +206,7 @@ int __init rd_load_image(char *from) | |||
| 200 | nblocks, rd_blocks); | 206 | nblocks, rd_blocks); |
| 201 | goto done; | 207 | goto done; |
| 202 | } | 208 | } |
| 203 | 209 | ||
| 204 | /* | 210 | /* |
| 205 | * OK, time to copy in the data | 211 | * OK, time to copy in the data |
| 206 | */ | 212 | */ |
| @@ -273,138 +279,48 @@ int __init rd_load_disk(int n) | |||
| 273 | return rd_load_image("/dev/root"); | 279 | return rd_load_image("/dev/root"); |
| 274 | } | 280 | } |
| 275 | 281 | ||
| 276 | /* | ||
| 277 | * gzip declarations | ||
| 278 | */ | ||
| 279 | |||
| 280 | #define OF(args) args | ||
| 281 | |||
| 282 | #ifndef memzero | ||
| 283 | #define memzero(s, n) memset ((s), 0, (n)) | ||
| 284 | #endif | ||
| 285 | |||
| 286 | typedef unsigned char uch; | ||
| 287 | typedef unsigned short ush; | ||
| 288 | typedef unsigned long ulg; | ||
| 289 | |||
| 290 | #define INBUFSIZ 4096 | ||
| 291 | #define WSIZE 0x8000 /* window size--must be a power of two, and */ | ||
| 292 | /* at least 32K for zip's deflate method */ | ||
| 293 | |||
| 294 | static uch *inbuf; | ||
| 295 | static uch *window; | ||
| 296 | |||
| 297 | static unsigned insize; /* valid bytes in inbuf */ | ||
| 298 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
| 299 | static unsigned outcnt; /* bytes in output buffer */ | ||
| 300 | static int exit_code; | 282 | static int exit_code; |
| 301 | static int unzip_error; | 283 | static int decompress_error; |
| 302 | static long bytes_out; | ||
| 303 | static int crd_infd, crd_outfd; | 284 | static int crd_infd, crd_outfd; |
| 304 | 285 | ||
| 305 | #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) | 286 | static int __init compr_fill(void *buf, unsigned int len) |
| 306 | |||
| 307 | /* Diagnostic functions (stubbed out) */ | ||
| 308 | #define Assert(cond,msg) | ||
| 309 | #define Trace(x) | ||
| 310 | #define Tracev(x) | ||
| 311 | #define Tracevv(x) | ||
| 312 | #define Tracec(c,x) | ||
| 313 | #define Tracecv(c,x) | ||
| 314 | |||
| 315 | #define STATIC static | ||
| 316 | #define INIT __init | ||
| 317 | |||
| 318 | static int __init fill_inbuf(void); | ||
| 319 | static void __init flush_window(void); | ||
| 320 | static void __init error(char *m); | ||
| 321 | |||
| 322 | #define NO_INFLATE_MALLOC | ||
| 323 | |||
| 324 | #include "../lib/inflate.c" | ||
| 325 | |||
| 326 | /* =========================================================================== | ||
| 327 | * Fill the input buffer. This is called only when the buffer is empty | ||
| 328 | * and at least one byte is really needed. | ||
| 329 | * Returning -1 does not guarantee that gunzip() will ever return. | ||
| 330 | */ | ||
| 331 | static int __init fill_inbuf(void) | ||
| 332 | { | 287 | { |
| 333 | if (exit_code) return -1; | 288 | int r = sys_read(crd_infd, buf, len); |
| 334 | 289 | if (r < 0) | |
| 335 | insize = sys_read(crd_infd, inbuf, INBUFSIZ); | 290 | printk(KERN_ERR "RAMDISK: error while reading compressed data"); |
| 336 | if (insize == 0) { | 291 | else if (r == 0) |
| 337 | error("RAMDISK: ran out of compressed data"); | 292 | printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); |
| 338 | return -1; | 293 | return r; |
| 339 | } | ||
| 340 | |||
| 341 | inptr = 1; | ||
| 342 | |||
| 343 | return inbuf[0]; | ||
| 344 | } | 294 | } |
| 345 | 295 | ||
| 346 | /* =========================================================================== | 296 | static int __init compr_flush(void *window, unsigned int outcnt) |
| 347 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
| 348 | * (Used for the decompressed data only.) | ||
| 349 | */ | ||
| 350 | static void __init flush_window(void) | ||
| 351 | { | 297 | { |
| 352 | ulg c = crc; /* temporary variable */ | 298 | int written = sys_write(crd_outfd, window, outcnt); |
| 353 | unsigned n, written; | 299 | if (written != outcnt) { |
| 354 | uch *in, ch; | 300 | if (decompress_error == 0) |
| 355 | 301 | printk(KERN_ERR | |
| 356 | written = sys_write(crd_outfd, window, outcnt); | 302 | "RAMDISK: incomplete write (%d != %d)\n", |
| 357 | if (written != outcnt && unzip_error == 0) { | 303 | written, outcnt); |
| 358 | printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", | 304 | decompress_error = 1; |
| 359 | written, outcnt, bytes_out); | 305 | return -1; |
| 360 | unzip_error = 1; | 306 | } |
| 361 | } | 307 | return outcnt; |
| 362 | in = window; | ||
| 363 | for (n = 0; n < outcnt; n++) { | ||
| 364 | ch = *in++; | ||
| 365 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
| 366 | } | ||
| 367 | crc = c; | ||
| 368 | bytes_out += (ulg)outcnt; | ||
| 369 | outcnt = 0; | ||
| 370 | } | 308 | } |
| 371 | 309 | ||
| 372 | static void __init error(char *x) | 310 | static void __init error(char *x) |
| 373 | { | 311 | { |
| 374 | printk(KERN_ERR "%s\n", x); | 312 | printk(KERN_ERR "%s\n", x); |
| 375 | exit_code = 1; | 313 | exit_code = 1; |
| 376 | unzip_error = 1; | 314 | decompress_error = 1; |
| 377 | } | 315 | } |
| 378 | 316 | ||
| 379 | static int __init crd_load(int in_fd, int out_fd) | 317 | static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) |
| 380 | { | 318 | { |
| 381 | int result; | 319 | int result; |
| 382 | |||
| 383 | insize = 0; /* valid bytes in inbuf */ | ||
| 384 | inptr = 0; /* index of next byte to be processed in inbuf */ | ||
| 385 | outcnt = 0; /* bytes in output buffer */ | ||
| 386 | exit_code = 0; | ||
| 387 | bytes_out = 0; | ||
| 388 | crc = (ulg)0xffffffffL; /* shift register contents */ | ||
| 389 | |||
| 390 | crd_infd = in_fd; | 320 | crd_infd = in_fd; |
| 391 | crd_outfd = out_fd; | 321 | crd_outfd = out_fd; |
| 392 | inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); | 322 | result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); |
| 393 | if (!inbuf) { | 323 | if (decompress_error) |
| 394 | printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); | ||
| 395 | return -1; | ||
| 396 | } | ||
| 397 | window = kmalloc(WSIZE, GFP_KERNEL); | ||
| 398 | if (!window) { | ||
| 399 | printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); | ||
| 400 | kfree(inbuf); | ||
| 401 | return -1; | ||
| 402 | } | ||
| 403 | makecrc(); | ||
| 404 | result = gunzip(); | ||
| 405 | if (unzip_error) | ||
| 406 | result = 1; | 324 | result = 1; |
| 407 | kfree(inbuf); | ||
| 408 | kfree(window); | ||
| 409 | return result; | 325 | return result; |
| 410 | } | 326 | } |
diff --git a/init/initramfs.c b/init/initramfs.c index d9c941c0c3ca..7dcde7ea6603 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
| @@ -390,11 +390,13 @@ static int __init write_buffer(char *buf, unsigned len) | |||
| 390 | return len - count; | 390 | return len - count; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static void __init flush_buffer(char *buf, unsigned len) | 393 | static int __init flush_buffer(void *bufv, unsigned len) |
| 394 | { | 394 | { |
| 395 | char *buf = (char *) bufv; | ||
| 395 | int written; | 396 | int written; |
| 397 | int origLen = len; | ||
| 396 | if (message) | 398 | if (message) |
| 397 | return; | 399 | return -1; |
| 398 | while ((written = write_buffer(buf, len)) < len && !message) { | 400 | while ((written = write_buffer(buf, len)) < len && !message) { |
| 399 | char c = buf[written]; | 401 | char c = buf[written]; |
| 400 | if (c == '0') { | 402 | if (c == '0') { |
| @@ -408,84 +410,28 @@ static void __init flush_buffer(char *buf, unsigned len) | |||
| 408 | } else | 410 | } else |
| 409 | error("junk in compressed archive"); | 411 | error("junk in compressed archive"); |
| 410 | } | 412 | } |
| 413 | return origLen; | ||
| 411 | } | 414 | } |
| 412 | 415 | ||
| 413 | /* | 416 | static unsigned my_inptr; /* index of next byte to be processed in inbuf */ |
| 414 | * gzip declarations | ||
| 415 | */ | ||
| 416 | 417 | ||
| 417 | #define OF(args) args | 418 | #include <linux/decompress/generic.h> |
| 418 | |||
| 419 | #ifndef memzero | ||
| 420 | #define memzero(s, n) memset ((s), 0, (n)) | ||
| 421 | #endif | ||
| 422 | |||
| 423 | typedef unsigned char uch; | ||
| 424 | typedef unsigned short ush; | ||
| 425 | typedef unsigned long ulg; | ||
| 426 | |||
| 427 | #define WSIZE 0x8000 /* window size--must be a power of two, and */ | ||
| 428 | /* at least 32K for zip's deflate method */ | ||
| 429 | |||
| 430 | static uch *inbuf; | ||
| 431 | static uch *window; | ||
| 432 | |||
| 433 | static unsigned insize; /* valid bytes in inbuf */ | ||
| 434 | static unsigned inptr; /* index of next byte to be processed in inbuf */ | ||
| 435 | static unsigned outcnt; /* bytes in output buffer */ | ||
| 436 | static long bytes_out; | ||
| 437 | |||
| 438 | #define get_byte() (inptr < insize ? inbuf[inptr++] : -1) | ||
| 439 | |||
| 440 | /* Diagnostic functions (stubbed out) */ | ||
| 441 | #define Assert(cond,msg) | ||
| 442 | #define Trace(x) | ||
| 443 | #define Tracev(x) | ||
| 444 | #define Tracevv(x) | ||
| 445 | #define Tracec(c,x) | ||
| 446 | #define Tracecv(c,x) | ||
| 447 | |||
| 448 | #define STATIC static | ||
| 449 | #define INIT __init | ||
| 450 | |||
| 451 | static void __init flush_window(void); | ||
| 452 | static void __init error(char *m); | ||
| 453 | |||
| 454 | #define NO_INFLATE_MALLOC | ||
| 455 | |||
| 456 | #include "../lib/inflate.c" | ||
| 457 | |||
| 458 | /* =========================================================================== | ||
| 459 | * Write the output window window[0..outcnt-1] and update crc and bytes_out. | ||
| 460 | * (Used for the decompressed data only.) | ||
| 461 | */ | ||
| 462 | static void __init flush_window(void) | ||
| 463 | { | ||
| 464 | ulg c = crc; /* temporary variable */ | ||
| 465 | unsigned n; | ||
| 466 | uch *in, ch; | ||
| 467 | |||
| 468 | flush_buffer(window, outcnt); | ||
| 469 | in = window; | ||
| 470 | for (n = 0; n < outcnt; n++) { | ||
| 471 | ch = *in++; | ||
| 472 | c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); | ||
| 473 | } | ||
| 474 | crc = c; | ||
| 475 | bytes_out += (ulg)outcnt; | ||
| 476 | outcnt = 0; | ||
| 477 | } | ||
| 478 | 419 | ||
| 479 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | 420 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) |
| 480 | { | 421 | { |
| 481 | int written; | 422 | int written; |
| 423 | decompress_fn decompress; | ||
| 424 | const char *compress_name; | ||
| 425 | static __initdata char msg_buf[64]; | ||
| 426 | |||
| 482 | dry_run = check_only; | 427 | dry_run = check_only; |
| 483 | header_buf = kmalloc(110, GFP_KERNEL); | 428 | header_buf = kmalloc(110, GFP_KERNEL); |
| 484 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); | 429 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); |
| 485 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); | 430 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); |
| 486 | window = kmalloc(WSIZE, GFP_KERNEL); | 431 | |
| 487 | if (!window || !header_buf || !symlink_buf || !name_buf) | 432 | if (!header_buf || !symlink_buf || !name_buf) |
| 488 | panic("can't allocate buffers"); | 433 | panic("can't allocate buffers"); |
| 434 | |||
| 489 | state = Start; | 435 | state = Start; |
| 490 | this_header = 0; | 436 | this_header = 0; |
| 491 | message = NULL; | 437 | message = NULL; |
| @@ -505,22 +451,25 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | |||
| 505 | continue; | 451 | continue; |
| 506 | } | 452 | } |
| 507 | this_header = 0; | 453 | this_header = 0; |
| 508 | insize = len; | 454 | decompress = decompress_method(buf, len, &compress_name); |
| 509 | inbuf = buf; | 455 | if (decompress) |
| 510 | inptr = 0; | 456 | decompress(buf, len, NULL, flush_buffer, NULL, |
| 511 | outcnt = 0; /* bytes in output buffer */ | 457 | &my_inptr, error); |
| 512 | bytes_out = 0; | 458 | else if (compress_name) { |
| 513 | crc = (ulg)0xffffffffL; /* shift register contents */ | 459 | if (!message) { |
| 514 | makecrc(); | 460 | snprintf(msg_buf, sizeof msg_buf, |
| 515 | gunzip(); | 461 | "compression method %s not configured", |
| 462 | compress_name); | ||
| 463 | message = msg_buf; | ||
| 464 | } | ||
| 465 | } | ||
| 516 | if (state != Reset) | 466 | if (state != Reset) |
| 517 | error("junk in gzipped archive"); | 467 | error("junk in compressed archive"); |
| 518 | this_header = saved_offset + inptr; | 468 | this_header = saved_offset + my_inptr; |
| 519 | buf += inptr; | 469 | buf += my_inptr; |
| 520 | len -= inptr; | 470 | len -= my_inptr; |
| 521 | } | 471 | } |
| 522 | dir_utime(); | 472 | dir_utime(); |
| 523 | kfree(window); | ||
| 524 | kfree(name_buf); | 473 | kfree(name_buf); |
| 525 | kfree(symlink_buf); | 474 | kfree(symlink_buf); |
| 526 | kfree(header_buf); | 475 | kfree(header_buf); |
| @@ -579,7 +528,7 @@ static int __init populate_rootfs(void) | |||
| 579 | char *err = unpack_to_rootfs(__initramfs_start, | 528 | char *err = unpack_to_rootfs(__initramfs_start, |
| 580 | __initramfs_end - __initramfs_start, 0); | 529 | __initramfs_end - __initramfs_start, 0); |
| 581 | if (err) | 530 | if (err) |
| 582 | panic(err); | 531 | panic(err); /* Failed to decompress INTERNAL initramfs */ |
| 583 | if (initrd_start) { | 532 | if (initrd_start) { |
| 584 | #ifdef CONFIG_BLK_DEV_RAM | 533 | #ifdef CONFIG_BLK_DEV_RAM |
| 585 | int fd; | 534 | int fd; |
| @@ -605,9 +554,12 @@ static int __init populate_rootfs(void) | |||
| 605 | printk(KERN_INFO "Unpacking initramfs..."); | 554 | printk(KERN_INFO "Unpacking initramfs..."); |
| 606 | err = unpack_to_rootfs((char *)initrd_start, | 555 | err = unpack_to_rootfs((char *)initrd_start, |
| 607 | initrd_end - initrd_start, 0); | 556 | initrd_end - initrd_start, 0); |
| 608 | if (err) | 557 | if (err) { |
| 609 | panic(err); | 558 | printk(" failed!\n"); |
| 610 | printk(" done\n"); | 559 | printk(KERN_EMERG "%s\n", err); |
| 560 | } else { | ||
| 561 | printk(" done\n"); | ||
| 562 | } | ||
| 611 | free_initrd(); | 563 | free_initrd(); |
| 612 | #endif | 564 | #endif |
| 613 | } | 565 | } |
diff --git a/init/main.c b/init/main.c index 6441083f8273..6bf83afd654d 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -98,7 +98,7 @@ static inline void mark_rodata_ro(void) { } | |||
| 98 | extern void tc_init(void); | 98 | extern void tc_init(void); |
| 99 | #endif | 99 | #endif |
| 100 | 100 | ||
| 101 | enum system_states system_state; | 101 | enum system_states system_state __read_mostly; |
| 102 | EXPORT_SYMBOL(system_state); | 102 | EXPORT_SYMBOL(system_state); |
| 103 | 103 | ||
| 104 | /* | 104 | /* |
| @@ -464,6 +464,7 @@ static noinline void __init_refok rest_init(void) | |||
| 464 | * at least once to get things moving: | 464 | * at least once to get things moving: |
| 465 | */ | 465 | */ |
| 466 | init_idle_bootup_task(current); | 466 | init_idle_bootup_task(current); |
| 467 | rcu_scheduler_starting(); | ||
| 467 | preempt_enable_no_resched(); | 468 | preempt_enable_no_resched(); |
| 468 | schedule(); | 469 | schedule(); |
| 469 | preempt_disable(); | 470 | preempt_disable(); |
diff --git a/kernel/module.c b/kernel/module.c index ba22484a987e..1f0657ae555b 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include <linux/tracepoint.h> | 51 | #include <linux/tracepoint.h> |
| 52 | #include <linux/ftrace.h> | 52 | #include <linux/ftrace.h> |
| 53 | #include <linux/async.h> | 53 | #include <linux/async.h> |
| 54 | #include <linux/percpu.h> | ||
| 54 | 55 | ||
| 55 | #if 0 | 56 | #if 0 |
| 56 | #define DEBUGP printk | 57 | #define DEBUGP printk |
| @@ -366,6 +367,34 @@ static struct module *find_module(const char *name) | |||
| 366 | } | 367 | } |
| 367 | 368 | ||
| 368 | #ifdef CONFIG_SMP | 369 | #ifdef CONFIG_SMP |
| 370 | |||
| 371 | #ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
| 372 | |||
| 373 | static void *percpu_modalloc(unsigned long size, unsigned long align, | ||
| 374 | const char *name) | ||
| 375 | { | ||
| 376 | void *ptr; | ||
| 377 | |||
| 378 | if (align > PAGE_SIZE) { | ||
| 379 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", | ||
| 380 | name, align, PAGE_SIZE); | ||
| 381 | align = PAGE_SIZE; | ||
| 382 | } | ||
| 383 | |||
| 384 | ptr = __alloc_percpu(size, align); | ||
| 385 | if (!ptr) | ||
| 386 | printk(KERN_WARNING | ||
| 387 | "Could not allocate %lu bytes percpu data\n", size); | ||
| 388 | return ptr; | ||
| 389 | } | ||
| 390 | |||
| 391 | static void percpu_modfree(void *freeme) | ||
| 392 | { | ||
| 393 | free_percpu(freeme); | ||
| 394 | } | ||
| 395 | |||
| 396 | #else /* ... !CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
| 397 | |||
| 369 | /* Number of blocks used and allocated. */ | 398 | /* Number of blocks used and allocated. */ |
| 370 | static unsigned int pcpu_num_used, pcpu_num_allocated; | 399 | static unsigned int pcpu_num_used, pcpu_num_allocated; |
| 371 | /* Size of each block. -ve means used. */ | 400 | /* Size of each block. -ve means used. */ |
| @@ -480,21 +509,6 @@ static void percpu_modfree(void *freeme) | |||
| 480 | } | 509 | } |
| 481 | } | 510 | } |
| 482 | 511 | ||
| 483 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, | ||
| 484 | Elf_Shdr *sechdrs, | ||
| 485 | const char *secstrings) | ||
| 486 | { | ||
| 487 | return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); | ||
| 488 | } | ||
| 489 | |||
| 490 | static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) | ||
| 491 | { | ||
| 492 | int cpu; | ||
| 493 | |||
| 494 | for_each_possible_cpu(cpu) | ||
| 495 | memcpy(pcpudest + per_cpu_offset(cpu), from, size); | ||
| 496 | } | ||
| 497 | |||
| 498 | static int percpu_modinit(void) | 512 | static int percpu_modinit(void) |
| 499 | { | 513 | { |
| 500 | pcpu_num_used = 2; | 514 | pcpu_num_used = 2; |
| @@ -513,7 +527,26 @@ static int percpu_modinit(void) | |||
| 513 | return 0; | 527 | return 0; |
| 514 | } | 528 | } |
| 515 | __initcall(percpu_modinit); | 529 | __initcall(percpu_modinit); |
| 530 | |||
| 531 | #endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
| 532 | |||
| 533 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, | ||
| 534 | Elf_Shdr *sechdrs, | ||
| 535 | const char *secstrings) | ||
| 536 | { | ||
| 537 | return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); | ||
| 538 | } | ||
| 539 | |||
| 540 | static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) | ||
| 541 | { | ||
| 542 | int cpu; | ||
| 543 | |||
| 544 | for_each_possible_cpu(cpu) | ||
| 545 | memcpy(pcpudest + per_cpu_offset(cpu), from, size); | ||
| 546 | } | ||
| 547 | |||
| 516 | #else /* ... !CONFIG_SMP */ | 548 | #else /* ... !CONFIG_SMP */ |
| 549 | |||
| 517 | static inline void *percpu_modalloc(unsigned long size, unsigned long align, | 550 | static inline void *percpu_modalloc(unsigned long size, unsigned long align, |
| 518 | const char *name) | 551 | const char *name) |
| 519 | { | 552 | { |
| @@ -535,6 +568,7 @@ static inline void percpu_modcopy(void *pcpudst, const void *src, | |||
| 535 | /* pcpusec should be 0, and size of that section should be 0. */ | 568 | /* pcpusec should be 0, and size of that section should be 0. */ |
| 536 | BUG_ON(size != 0); | 569 | BUG_ON(size != 0); |
| 537 | } | 570 | } |
| 571 | |||
| 538 | #endif /* CONFIG_SMP */ | 572 | #endif /* CONFIG_SMP */ |
| 539 | 573 | ||
| 540 | #define MODINFO_ATTR(field) \ | 574 | #define MODINFO_ATTR(field) \ |
diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index bd5a9003497c..654c640a6b9c 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c | |||
| @@ -679,8 +679,8 @@ int rcu_needs_cpu(int cpu) | |||
| 679 | void rcu_check_callbacks(int cpu, int user) | 679 | void rcu_check_callbacks(int cpu, int user) |
| 680 | { | 680 | { |
| 681 | if (user || | 681 | if (user || |
| 682 | (idle_cpu(cpu) && !in_softirq() && | 682 | (idle_cpu(cpu) && rcu_scheduler_active && |
| 683 | hardirq_count() <= (1 << HARDIRQ_SHIFT))) { | 683 | !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) { |
| 684 | 684 | ||
| 685 | /* | 685 | /* |
| 686 | * Get here if this CPU took its interrupt from user | 686 | * Get here if this CPU took its interrupt from user |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index d92a76a881aa..cae8a059cf47 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/cpu.h> | 44 | #include <linux/cpu.h> |
| 45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
| 46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
| 47 | #include <linux/kernel_stat.h> | ||
| 47 | 48 | ||
| 48 | enum rcu_barrier { | 49 | enum rcu_barrier { |
| 49 | RCU_BARRIER_STD, | 50 | RCU_BARRIER_STD, |
| @@ -55,6 +56,7 @@ static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL}; | |||
| 55 | static atomic_t rcu_barrier_cpu_count; | 56 | static atomic_t rcu_barrier_cpu_count; |
| 56 | static DEFINE_MUTEX(rcu_barrier_mutex); | 57 | static DEFINE_MUTEX(rcu_barrier_mutex); |
| 57 | static struct completion rcu_barrier_completion; | 58 | static struct completion rcu_barrier_completion; |
| 59 | int rcu_scheduler_active __read_mostly; | ||
| 58 | 60 | ||
| 59 | /* | 61 | /* |
| 60 | * Awaken the corresponding synchronize_rcu() instance now that a | 62 | * Awaken the corresponding synchronize_rcu() instance now that a |
| @@ -80,6 +82,10 @@ void wakeme_after_rcu(struct rcu_head *head) | |||
| 80 | void synchronize_rcu(void) | 82 | void synchronize_rcu(void) |
| 81 | { | 83 | { |
| 82 | struct rcu_synchronize rcu; | 84 | struct rcu_synchronize rcu; |
| 85 | |||
| 86 | if (rcu_blocking_is_gp()) | ||
| 87 | return; | ||
| 88 | |||
| 83 | init_completion(&rcu.completion); | 89 | init_completion(&rcu.completion); |
| 84 | /* Will wake me after RCU finished. */ | 90 | /* Will wake me after RCU finished. */ |
| 85 | call_rcu(&rcu.head, wakeme_after_rcu); | 91 | call_rcu(&rcu.head, wakeme_after_rcu); |
| @@ -175,3 +181,9 @@ void __init rcu_init(void) | |||
| 175 | __rcu_init(); | 181 | __rcu_init(); |
| 176 | } | 182 | } |
| 177 | 183 | ||
| 184 | void rcu_scheduler_starting(void) | ||
| 185 | { | ||
| 186 | WARN_ON(num_online_cpus() != 1); | ||
| 187 | WARN_ON(nr_context_switches() > 0); | ||
| 188 | rcu_scheduler_active = 1; | ||
| 189 | } | ||
diff --git a/kernel/rcupreempt.c b/kernel/rcupreempt.c index 33cfc50781f9..5d59e850fb71 100644 --- a/kernel/rcupreempt.c +++ b/kernel/rcupreempt.c | |||
| @@ -1181,6 +1181,9 @@ void __synchronize_sched(void) | |||
| 1181 | { | 1181 | { |
| 1182 | struct rcu_synchronize rcu; | 1182 | struct rcu_synchronize rcu; |
| 1183 | 1183 | ||
| 1184 | if (num_online_cpus() == 1) | ||
| 1185 | return; /* blocking is gp if only one CPU! */ | ||
| 1186 | |||
| 1184 | init_completion(&rcu.completion); | 1187 | init_completion(&rcu.completion); |
| 1185 | /* Will wake me after RCU finished. */ | 1188 | /* Will wake me after RCU finished. */ |
| 1186 | call_rcu_sched(&rcu.head, wakeme_after_rcu); | 1189 | call_rcu_sched(&rcu.head, wakeme_after_rcu); |
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index b2fd602a6f6f..97ce31579ec0 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
| @@ -948,8 +948,8 @@ static void rcu_do_batch(struct rcu_data *rdp) | |||
| 948 | void rcu_check_callbacks(int cpu, int user) | 948 | void rcu_check_callbacks(int cpu, int user) |
| 949 | { | 949 | { |
| 950 | if (user || | 950 | if (user || |
| 951 | (idle_cpu(cpu) && !in_softirq() && | 951 | (idle_cpu(cpu) && rcu_scheduler_active && |
| 952 | hardirq_count() <= (1 << HARDIRQ_SHIFT))) { | 952 | !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) { |
| 953 | 953 | ||
| 954 | /* | 954 | /* |
| 955 | * Get here if this CPU took its interrupt from user | 955 | * Get here if this CPU took its interrupt from user |
diff --git a/kernel/sched.c b/kernel/sched.c index 7d97ff7c4478..0a76d0b6f215 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -223,7 +223,7 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b) | |||
| 223 | { | 223 | { |
| 224 | ktime_t now; | 224 | ktime_t now; |
| 225 | 225 | ||
| 226 | if (rt_bandwidth_enabled() && rt_b->rt_runtime == RUNTIME_INF) | 226 | if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) |
| 227 | return; | 227 | return; |
| 228 | 228 | ||
| 229 | if (hrtimer_active(&rt_b->rt_period_timer)) | 229 | if (hrtimer_active(&rt_b->rt_period_timer)) |
| @@ -9219,6 +9219,16 @@ static int sched_rt_global_constraints(void) | |||
| 9219 | 9219 | ||
| 9220 | return ret; | 9220 | return ret; |
| 9221 | } | 9221 | } |
| 9222 | |||
| 9223 | int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk) | ||
| 9224 | { | ||
| 9225 | /* Don't accept realtime tasks when there is no way for them to run */ | ||
| 9226 | if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0) | ||
| 9227 | return 0; | ||
| 9228 | |||
| 9229 | return 1; | ||
| 9230 | } | ||
| 9231 | |||
| 9222 | #else /* !CONFIG_RT_GROUP_SCHED */ | 9232 | #else /* !CONFIG_RT_GROUP_SCHED */ |
| 9223 | static int sched_rt_global_constraints(void) | 9233 | static int sched_rt_global_constraints(void) |
| 9224 | { | 9234 | { |
| @@ -9312,8 +9322,7 @@ cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, | |||
| 9312 | struct task_struct *tsk) | 9322 | struct task_struct *tsk) |
| 9313 | { | 9323 | { |
| 9314 | #ifdef CONFIG_RT_GROUP_SCHED | 9324 | #ifdef CONFIG_RT_GROUP_SCHED |
| 9315 | /* Don't accept realtime tasks when there is no way for them to run */ | 9325 | if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk)) |
| 9316 | if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0) | ||
| 9317 | return -EINVAL; | 9326 | return -EINVAL; |
| 9318 | #else | 9327 | #else |
| 9319 | /* We don't support RT-tasks being in separate groups */ | 9328 | /* We don't support RT-tasks being in separate groups */ |
| @@ -9476,7 +9485,7 @@ cpuacct_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp) | |||
| 9476 | 9485 | ||
| 9477 | static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) | 9486 | static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) |
| 9478 | { | 9487 | { |
| 9479 | u64 *cpuusage = percpu_ptr(ca->cpuusage, cpu); | 9488 | u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); |
| 9480 | u64 data; | 9489 | u64 data; |
| 9481 | 9490 | ||
| 9482 | #ifndef CONFIG_64BIT | 9491 | #ifndef CONFIG_64BIT |
| @@ -9495,7 +9504,7 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu) | |||
| 9495 | 9504 | ||
| 9496 | static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) | 9505 | static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) |
| 9497 | { | 9506 | { |
| 9498 | u64 *cpuusage = percpu_ptr(ca->cpuusage, cpu); | 9507 | u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); |
| 9499 | 9508 | ||
| 9500 | #ifndef CONFIG_64BIT | 9509 | #ifndef CONFIG_64BIT |
| 9501 | /* | 9510 | /* |
| @@ -9591,7 +9600,7 @@ static void cpuacct_charge(struct task_struct *tsk, u64 cputime) | |||
| 9591 | ca = task_ca(tsk); | 9600 | ca = task_ca(tsk); |
| 9592 | 9601 | ||
| 9593 | for (; ca; ca = ca->parent) { | 9602 | for (; ca; ca = ca->parent) { |
| 9594 | u64 *cpuusage = percpu_ptr(ca->cpuusage, cpu); | 9603 | u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); |
| 9595 | *cpuusage += cputime; | 9604 | *cpuusage += cputime; |
| 9596 | } | 9605 | } |
| 9597 | } | 9606 | } |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index ad64fcb731f2..57d4b13b631d 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <linux/seccomp.h> | 9 | #include <linux/seccomp.h> |
| 10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
| 11 | #include <linux/compat.h> | ||
| 11 | 12 | ||
| 12 | /* #define SECCOMP_DEBUG 1 */ | 13 | /* #define SECCOMP_DEBUG 1 */ |
| 13 | #define NR_SECCOMP_MODES 1 | 14 | #define NR_SECCOMP_MODES 1 |
| @@ -22,7 +23,7 @@ static int mode1_syscalls[] = { | |||
| 22 | 0, /* null terminated */ | 23 | 0, /* null terminated */ |
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | #ifdef TIF_32BIT | 26 | #ifdef CONFIG_COMPAT |
| 26 | static int mode1_syscalls_32[] = { | 27 | static int mode1_syscalls_32[] = { |
| 27 | __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32, | 28 | __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32, |
| 28 | 0, /* null terminated */ | 29 | 0, /* null terminated */ |
| @@ -37,8 +38,8 @@ void __secure_computing(int this_syscall) | |||
| 37 | switch (mode) { | 38 | switch (mode) { |
| 38 | case 1: | 39 | case 1: |
| 39 | syscall = mode1_syscalls; | 40 | syscall = mode1_syscalls; |
| 40 | #ifdef TIF_32BIT | 41 | #ifdef CONFIG_COMPAT |
| 41 | if (test_thread_flag(TIF_32BIT)) | 42 | if (is_compat_task()) |
| 42 | syscall = mode1_syscalls_32; | 43 | syscall = mode1_syscalls_32; |
| 43 | #endif | 44 | #endif |
| 44 | do { | 45 | do { |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 0cd415ee62a2..74541ca49536 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
| @@ -170,7 +170,7 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) | |||
| 170 | * doesn't hit this CPU until we're ready. */ | 170 | * doesn't hit this CPU until we're ready. */ |
| 171 | get_cpu(); | 171 | get_cpu(); |
| 172 | for_each_online_cpu(i) { | 172 | for_each_online_cpu(i) { |
| 173 | sm_work = percpu_ptr(stop_machine_work, i); | 173 | sm_work = per_cpu_ptr(stop_machine_work, i); |
| 174 | INIT_WORK(sm_work, stop_cpu); | 174 | INIT_WORK(sm_work, stop_cpu); |
| 175 | queue_work_on(i, stop_machine_wq, sm_work); | 175 | queue_work_on(i, stop_machine_wq, sm_work); |
| 176 | } | 176 | } |
diff --git a/kernel/sys.c b/kernel/sys.c index f145c415bc16..37f458e6882a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -559,7 +559,7 @@ error: | |||
| 559 | abort_creds(new); | 559 | abort_creds(new); |
| 560 | return retval; | 560 | return retval; |
| 561 | } | 561 | } |
| 562 | 562 | ||
| 563 | /* | 563 | /* |
| 564 | * change the user struct in a credentials set to match the new UID | 564 | * change the user struct in a credentials set to match the new UID |
| 565 | */ | 565 | */ |
| @@ -571,6 +571,11 @@ static int set_user(struct cred *new) | |||
| 571 | if (!new_user) | 571 | if (!new_user) |
| 572 | return -EAGAIN; | 572 | return -EAGAIN; |
| 573 | 573 | ||
| 574 | if (!task_can_switch_user(new_user, current)) { | ||
| 575 | free_uid(new_user); | ||
| 576 | return -EINVAL; | ||
| 577 | } | ||
| 578 | |||
| 574 | if (atomic_read(&new_user->processes) >= | 579 | if (atomic_read(&new_user->processes) >= |
| 575 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && | 580 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && |
| 576 | new_user != INIT_USER) { | 581 | new_user != INIT_USER) { |
| @@ -631,10 +636,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
| 631 | goto error; | 636 | goto error; |
| 632 | } | 637 | } |
| 633 | 638 | ||
| 634 | retval = -EAGAIN; | 639 | if (new->uid != old->uid) { |
| 635 | if (new->uid != old->uid && set_user(new) < 0) | 640 | retval = set_user(new); |
| 636 | goto error; | 641 | if (retval < 0) |
| 637 | 642 | goto error; | |
| 643 | } | ||
| 638 | if (ruid != (uid_t) -1 || | 644 | if (ruid != (uid_t) -1 || |
| 639 | (euid != (uid_t) -1 && euid != old->uid)) | 645 | (euid != (uid_t) -1 && euid != old->uid)) |
| 640 | new->suid = new->euid; | 646 | new->suid = new->euid; |
| @@ -680,9 +686,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
| 680 | retval = -EPERM; | 686 | retval = -EPERM; |
| 681 | if (capable(CAP_SETUID)) { | 687 | if (capable(CAP_SETUID)) { |
| 682 | new->suid = new->uid = uid; | 688 | new->suid = new->uid = uid; |
| 683 | if (uid != old->uid && set_user(new) < 0) { | 689 | if (uid != old->uid) { |
| 684 | retval = -EAGAIN; | 690 | retval = set_user(new); |
| 685 | goto error; | 691 | if (retval < 0) |
| 692 | goto error; | ||
| 686 | } | 693 | } |
| 687 | } else if (uid != old->uid && uid != new->suid) { | 694 | } else if (uid != old->uid && uid != new->suid) { |
| 688 | goto error; | 695 | goto error; |
| @@ -734,11 +741,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
| 734 | goto error; | 741 | goto error; |
| 735 | } | 742 | } |
| 736 | 743 | ||
| 737 | retval = -EAGAIN; | ||
| 738 | if (ruid != (uid_t) -1) { | 744 | if (ruid != (uid_t) -1) { |
| 739 | new->uid = ruid; | 745 | new->uid = ruid; |
| 740 | if (ruid != old->uid && set_user(new) < 0) | 746 | if (ruid != old->uid) { |
| 741 | goto error; | 747 | retval = set_user(new); |
| 748 | if (retval < 0) | ||
| 749 | goto error; | ||
| 750 | } | ||
| 742 | } | 751 | } |
| 743 | if (euid != (uid_t) -1) | 752 | if (euid != (uid_t) -1) |
| 744 | new->euid = euid; | 753 | new->euid = euid; |
diff --git a/kernel/user.c b/kernel/user.c index 3551ac742395..6a9b696128c8 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -362,6 +362,24 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 362 | 362 | ||
| 363 | #endif | 363 | #endif |
| 364 | 364 | ||
| 365 | #if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED) | ||
| 366 | /* | ||
| 367 | * We need to check if a setuid can take place. This function should be called | ||
| 368 | * before successfully completing the setuid. | ||
| 369 | */ | ||
| 370 | int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) | ||
| 371 | { | ||
| 372 | |||
| 373 | return sched_rt_can_attach(up->tg, tsk); | ||
| 374 | |||
| 375 | } | ||
| 376 | #else | ||
| 377 | int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) | ||
| 378 | { | ||
| 379 | return 1; | ||
| 380 | } | ||
| 381 | #endif | ||
| 382 | |||
| 365 | /* | 383 | /* |
| 366 | * Locate the user_struct for the passed UID. If found, take a ref on it. The | 384 | * Locate the user_struct for the passed UID. If found, take a ref on it. The |
| 367 | * caller must undo that ref with free_uid(). | 385 | * caller must undo that ref with free_uid(). |
diff --git a/lib/Kconfig b/lib/Kconfig index 03c2c24b9083..daa481824d9c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
| @@ -98,6 +98,20 @@ config LZO_DECOMPRESS | |||
| 98 | tristate | 98 | tristate |
| 99 | 99 | ||
| 100 | # | 100 | # |
| 101 | # These all provide a common interface (hence the apparent duplication with | ||
| 102 | # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.) | ||
| 103 | # | ||
| 104 | config DECOMPRESS_GZIP | ||
| 105 | select ZLIB_INFLATE | ||
| 106 | tristate | ||
| 107 | |||
| 108 | config DECOMPRESS_BZIP2 | ||
| 109 | tristate | ||
| 110 | |||
| 111 | config DECOMPRESS_LZMA | ||
| 112 | tristate | ||
| 113 | |||
| 114 | # | ||
| 101 | # Generic allocator support is selected if needed | 115 | # Generic allocator support is selected if needed |
| 102 | # | 116 | # |
| 103 | config GENERIC_ALLOCATOR | 117 | config GENERIC_ALLOCATOR |
diff --git a/lib/Makefile b/lib/Makefile index 32b0e64ded27..790de7c25d0d 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ | |||
| 11 | rbtree.o radix-tree.o dump_stack.o \ | 11 | rbtree.o radix-tree.o dump_stack.o \ |
| 12 | idr.o int_sqrt.o extable.o prio_tree.o \ | 12 | idr.o int_sqrt.o extable.o prio_tree.o \ |
| 13 | sha1.o irq_regs.o reciprocal_div.o argv_split.o \ | 13 | sha1.o irq_regs.o reciprocal_div.o argv_split.o \ |
| 14 | proportions.o prio_heap.o ratelimit.o show_mem.o is_single_threaded.o | 14 | proportions.o prio_heap.o ratelimit.o show_mem.o \ |
| 15 | is_single_threaded.o decompress.o | ||
| 15 | 16 | ||
| 16 | lib-$(CONFIG_MMU) += ioremap.o | 17 | lib-$(CONFIG_MMU) += ioremap.o |
| 17 | lib-$(CONFIG_SMP) += cpumask.o | 18 | lib-$(CONFIG_SMP) += cpumask.o |
| @@ -65,6 +66,10 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ | |||
| 65 | obj-$(CONFIG_LZO_COMPRESS) += lzo/ | 66 | obj-$(CONFIG_LZO_COMPRESS) += lzo/ |
| 66 | obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ | 67 | obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ |
| 67 | 68 | ||
| 69 | lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o | ||
| 70 | lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o | ||
| 71 | lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o | ||
| 72 | |||
| 68 | obj-$(CONFIG_TEXTSEARCH) += textsearch.o | 73 | obj-$(CONFIG_TEXTSEARCH) += textsearch.o |
| 69 | obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o | 74 | obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o |
| 70 | obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o | 75 | obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o |
diff --git a/lib/decompress.c b/lib/decompress.c new file mode 100644 index 000000000000..d2842f571674 --- /dev/null +++ b/lib/decompress.c | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* | ||
| 2 | * decompress.c | ||
| 3 | * | ||
| 4 | * Detect the decompression method based on magic number | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/decompress/generic.h> | ||
| 8 | |||
| 9 | #include <linux/decompress/bunzip2.h> | ||
| 10 | #include <linux/decompress/unlzma.h> | ||
| 11 | #include <linux/decompress/inflate.h> | ||
| 12 | |||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/string.h> | ||
| 15 | |||
| 16 | #ifndef CONFIG_DECOMPRESS_GZIP | ||
| 17 | # define gunzip NULL | ||
| 18 | #endif | ||
| 19 | #ifndef CONFIG_DECOMPRESS_BZIP2 | ||
| 20 | # define bunzip2 NULL | ||
| 21 | #endif | ||
| 22 | #ifndef CONFIG_DECOMPRESS_LZMA | ||
| 23 | # define unlzma NULL | ||
| 24 | #endif | ||
| 25 | |||
| 26 | static const struct compress_format { | ||
| 27 | unsigned char magic[2]; | ||
| 28 | const char *name; | ||
| 29 | decompress_fn decompressor; | ||
| 30 | } compressed_formats[] = { | ||
| 31 | { {037, 0213}, "gzip", gunzip }, | ||
| 32 | { {037, 0236}, "gzip", gunzip }, | ||
| 33 | { {0x42, 0x5a}, "bzip2", bunzip2 }, | ||
| 34 | { {0x5d, 0x00}, "lzma", unlzma }, | ||
| 35 | { {0, 0}, NULL, NULL } | ||
| 36 | }; | ||
| 37 | |||
| 38 | decompress_fn decompress_method(const unsigned char *inbuf, int len, | ||
| 39 | const char **name) | ||
| 40 | { | ||
| 41 | const struct compress_format *cf; | ||
| 42 | |||
| 43 | if (len < 2) | ||
| 44 | return NULL; /* Need at least this much... */ | ||
| 45 | |||
| 46 | for (cf = compressed_formats; cf->name; cf++) { | ||
| 47 | if (!memcmp(inbuf, cf->magic, 2)) | ||
| 48 | break; | ||
| 49 | |||
| 50 | } | ||
| 51 | if (name) | ||
| 52 | *name = cf->name; | ||
| 53 | return cf->decompressor; | ||
| 54 | } | ||
diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c new file mode 100644 index 000000000000..5d3ddb5fcfd9 --- /dev/null +++ b/lib/decompress_bunzip2.c | |||
| @@ -0,0 +1,735 @@ | |||
| 1 | /* vi: set sw = 4 ts = 4: */ | ||
| 2 | /* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net). | ||
| 3 | |||
| 4 | Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), | ||
| 5 | which also acknowledges contributions by Mike Burrows, David Wheeler, | ||
| 6 | Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, | ||
| 7 | Robert Sedgewick, and Jon L. Bentley. | ||
| 8 | |||
| 9 | This code is licensed under the LGPLv2: | ||
| 10 | LGPL (http://www.gnu.org/copyleft/lgpl.html | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* | ||
| 14 | Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org). | ||
| 15 | |||
| 16 | More efficient reading of Huffman codes, a streamlined read_bunzip() | ||
| 17 | function, and various other tweaks. In (limited) tests, approximately | ||
| 18 | 20% faster than bzcat on x86 and about 10% faster on arm. | ||
| 19 | |||
| 20 | Note that about 2/3 of the time is spent in read_unzip() reversing | ||
| 21 | the Burrows-Wheeler transformation. Much of that time is delay | ||
| 22 | resulting from cache misses. | ||
| 23 | |||
| 24 | I would ask that anyone benefiting from this work, especially those | ||
| 25 | using it in commercial products, consider making a donation to my local | ||
| 26 | non-profit hospice organization in the name of the woman I loved, who | ||
| 27 | passed away Feb. 12, 2003. | ||
| 28 | |||
| 29 | In memory of Toni W. Hagan | ||
| 30 | |||
| 31 | Hospice of Acadiana, Inc. | ||
| 32 | 2600 Johnston St., Suite 200 | ||
| 33 | Lafayette, LA 70503-3240 | ||
| 34 | |||
| 35 | Phone (337) 232-1234 or 1-800-738-2226 | ||
| 36 | Fax (337) 232-1297 | ||
| 37 | |||
| 38 | http://www.hospiceacadiana.com/ | ||
| 39 | |||
| 40 | Manuel | ||
| 41 | */ | ||
| 42 | |||
| 43 | /* | ||
| 44 | Made it fit for running in Linux Kernel by Alain Knaff (alain@knaff.lu) | ||
| 45 | */ | ||
| 46 | |||
| 47 | |||
| 48 | #ifndef STATIC | ||
| 49 | #include <linux/decompress/bunzip2.h> | ||
| 50 | #endif /* !STATIC */ | ||
| 51 | |||
| 52 | #include <linux/decompress/mm.h> | ||
| 53 | |||
| 54 | #ifndef INT_MAX | ||
| 55 | #define INT_MAX 0x7fffffff | ||
| 56 | #endif | ||
| 57 | |||
| 58 | /* Constants for Huffman coding */ | ||
| 59 | #define MAX_GROUPS 6 | ||
| 60 | #define GROUP_SIZE 50 /* 64 would have been more efficient */ | ||
| 61 | #define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */ | ||
| 62 | #define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ | ||
| 63 | #define SYMBOL_RUNA 0 | ||
| 64 | #define SYMBOL_RUNB 1 | ||
| 65 | |||
| 66 | /* Status return values */ | ||
| 67 | #define RETVAL_OK 0 | ||
| 68 | #define RETVAL_LAST_BLOCK (-1) | ||
| 69 | #define RETVAL_NOT_BZIP_DATA (-2) | ||
| 70 | #define RETVAL_UNEXPECTED_INPUT_EOF (-3) | ||
| 71 | #define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) | ||
| 72 | #define RETVAL_DATA_ERROR (-5) | ||
| 73 | #define RETVAL_OUT_OF_MEMORY (-6) | ||
| 74 | #define RETVAL_OBSOLETE_INPUT (-7) | ||
| 75 | |||
| 76 | /* Other housekeeping constants */ | ||
| 77 | #define BZIP2_IOBUF_SIZE 4096 | ||
| 78 | |||
| 79 | /* This is what we know about each Huffman coding group */ | ||
| 80 | struct group_data { | ||
| 81 | /* We have an extra slot at the end of limit[] for a sentinal value. */ | ||
| 82 | int limit[MAX_HUFCODE_BITS+1]; | ||
| 83 | int base[MAX_HUFCODE_BITS]; | ||
| 84 | int permute[MAX_SYMBOLS]; | ||
| 85 | int minLen, maxLen; | ||
| 86 | }; | ||
| 87 | |||
| 88 | /* Structure holding all the housekeeping data, including IO buffers and | ||
| 89 | memory that persists between calls to bunzip */ | ||
| 90 | struct bunzip_data { | ||
| 91 | /* State for interrupting output loop */ | ||
| 92 | int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; | ||
| 93 | /* I/O tracking data (file handles, buffers, positions, etc.) */ | ||
| 94 | int (*fill)(void*, unsigned int); | ||
| 95 | int inbufCount, inbufPos /*, outbufPos*/; | ||
| 96 | unsigned char *inbuf /*,*outbuf*/; | ||
| 97 | unsigned int inbufBitCount, inbufBits; | ||
| 98 | /* The CRC values stored in the block header and calculated from the | ||
| 99 | data */ | ||
| 100 | unsigned int crc32Table[256], headerCRC, totalCRC, writeCRC; | ||
| 101 | /* Intermediate buffer and its size (in bytes) */ | ||
| 102 | unsigned int *dbuf, dbufSize; | ||
| 103 | /* These things are a bit too big to go on the stack */ | ||
| 104 | unsigned char selectors[32768]; /* nSelectors = 15 bits */ | ||
| 105 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ | ||
| 106 | int io_error; /* non-zero if we have IO error */ | ||
| 107 | }; | ||
| 108 | |||
| 109 | |||
| 110 | /* Return the next nnn bits of input. All reads from the compressed input | ||
| 111 | are done through this function. All reads are big endian */ | ||
| 112 | static unsigned int INIT get_bits(struct bunzip_data *bd, char bits_wanted) | ||
| 113 | { | ||
| 114 | unsigned int bits = 0; | ||
| 115 | |||
| 116 | /* If we need to get more data from the byte buffer, do so. | ||
| 117 | (Loop getting one byte at a time to enforce endianness and avoid | ||
| 118 | unaligned access.) */ | ||
| 119 | while (bd->inbufBitCount < bits_wanted) { | ||
| 120 | /* If we need to read more data from file into byte buffer, do | ||
| 121 | so */ | ||
| 122 | if (bd->inbufPos == bd->inbufCount) { | ||
| 123 | if (bd->io_error) | ||
| 124 | return 0; | ||
| 125 | bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE); | ||
| 126 | if (bd->inbufCount <= 0) { | ||
| 127 | bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF; | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | bd->inbufPos = 0; | ||
| 131 | } | ||
| 132 | /* Avoid 32-bit overflow (dump bit buffer to top of output) */ | ||
| 133 | if (bd->inbufBitCount >= 24) { | ||
| 134 | bits = bd->inbufBits&((1 << bd->inbufBitCount)-1); | ||
| 135 | bits_wanted -= bd->inbufBitCount; | ||
| 136 | bits <<= bits_wanted; | ||
| 137 | bd->inbufBitCount = 0; | ||
| 138 | } | ||
| 139 | /* Grab next 8 bits of input from buffer. */ | ||
| 140 | bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; | ||
| 141 | bd->inbufBitCount += 8; | ||
| 142 | } | ||
| 143 | /* Calculate result */ | ||
| 144 | bd->inbufBitCount -= bits_wanted; | ||
| 145 | bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1); | ||
| 146 | |||
| 147 | return bits; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Unpacks the next block and sets up for the inverse burrows-wheeler step. */ | ||
| 151 | |||
| 152 | static int INIT get_next_block(struct bunzip_data *bd) | ||
| 153 | { | ||
| 154 | struct group_data *hufGroup = NULL; | ||
| 155 | int *base = NULL; | ||
| 156 | int *limit = NULL; | ||
| 157 | int dbufCount, nextSym, dbufSize, groupCount, selector, | ||
| 158 | i, j, k, t, runPos, symCount, symTotal, nSelectors, | ||
| 159 | byteCount[256]; | ||
| 160 | unsigned char uc, symToByte[256], mtfSymbol[256], *selectors; | ||
| 161 | unsigned int *dbuf, origPtr; | ||
| 162 | |||
| 163 | dbuf = bd->dbuf; | ||
| 164 | dbufSize = bd->dbufSize; | ||
| 165 | selectors = bd->selectors; | ||
| 166 | |||
| 167 | /* Read in header signature and CRC, then validate signature. | ||
| 168 | (last block signature means CRC is for whole file, return now) */ | ||
| 169 | i = get_bits(bd, 24); | ||
| 170 | j = get_bits(bd, 24); | ||
| 171 | bd->headerCRC = get_bits(bd, 32); | ||
| 172 | if ((i == 0x177245) && (j == 0x385090)) | ||
| 173 | return RETVAL_LAST_BLOCK; | ||
| 174 | if ((i != 0x314159) || (j != 0x265359)) | ||
| 175 | return RETVAL_NOT_BZIP_DATA; | ||
| 176 | /* We can add support for blockRandomised if anybody complains. | ||
| 177 | There was some code for this in busybox 1.0.0-pre3, but nobody ever | ||
| 178 | noticed that it didn't actually work. */ | ||
| 179 | if (get_bits(bd, 1)) | ||
| 180 | return RETVAL_OBSOLETE_INPUT; | ||
| 181 | origPtr = get_bits(bd, 24); | ||
| 182 | if (origPtr > dbufSize) | ||
| 183 | return RETVAL_DATA_ERROR; | ||
| 184 | /* mapping table: if some byte values are never used (encoding things | ||
| 185 | like ascii text), the compression code removes the gaps to have fewer | ||
| 186 | symbols to deal with, and writes a sparse bitfield indicating which | ||
| 187 | values were present. We make a translation table to convert the | ||
| 188 | symbols back to the corresponding bytes. */ | ||
| 189 | t = get_bits(bd, 16); | ||
| 190 | symTotal = 0; | ||
| 191 | for (i = 0; i < 16; i++) { | ||
| 192 | if (t&(1 << (15-i))) { | ||
| 193 | k = get_bits(bd, 16); | ||
| 194 | for (j = 0; j < 16; j++) | ||
| 195 | if (k&(1 << (15-j))) | ||
| 196 | symToByte[symTotal++] = (16*i)+j; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | /* How many different Huffman coding groups does this block use? */ | ||
| 200 | groupCount = get_bits(bd, 3); | ||
| 201 | if (groupCount < 2 || groupCount > MAX_GROUPS) | ||
| 202 | return RETVAL_DATA_ERROR; | ||
| 203 | /* nSelectors: Every GROUP_SIZE many symbols we select a new | ||
| 204 | Huffman coding group. Read in the group selector list, | ||
| 205 | which is stored as MTF encoded bit runs. (MTF = Move To | ||
| 206 | Front, as each value is used it's moved to the start of the | ||
| 207 | list.) */ | ||
| 208 | nSelectors = get_bits(bd, 15); | ||
| 209 | if (!nSelectors) | ||
| 210 | return RETVAL_DATA_ERROR; | ||
| 211 | for (i = 0; i < groupCount; i++) | ||
| 212 | mtfSymbol[i] = i; | ||
| 213 | for (i = 0; i < nSelectors; i++) { | ||
| 214 | /* Get next value */ | ||
| 215 | for (j = 0; get_bits(bd, 1); j++) | ||
| 216 | if (j >= groupCount) | ||
| 217 | return RETVAL_DATA_ERROR; | ||
| 218 | /* Decode MTF to get the next selector */ | ||
| 219 | uc = mtfSymbol[j]; | ||
| 220 | for (; j; j--) | ||
| 221 | mtfSymbol[j] = mtfSymbol[j-1]; | ||
| 222 | mtfSymbol[0] = selectors[i] = uc; | ||
| 223 | } | ||
| 224 | /* Read the Huffman coding tables for each group, which code | ||
| 225 | for symTotal literal symbols, plus two run symbols (RUNA, | ||
| 226 | RUNB) */ | ||
| 227 | symCount = symTotal+2; | ||
| 228 | for (j = 0; j < groupCount; j++) { | ||
| 229 | unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1]; | ||
| 230 | int minLen, maxLen, pp; | ||
| 231 | /* Read Huffman code lengths for each symbol. They're | ||
| 232 | stored in a way similar to mtf; record a starting | ||
| 233 | value for the first symbol, and an offset from the | ||
| 234 | previous value for everys symbol after that. | ||
| 235 | (Subtracting 1 before the loop and then adding it | ||
| 236 | back at the end is an optimization that makes the | ||
| 237 | test inside the loop simpler: symbol length 0 | ||
| 238 | becomes negative, so an unsigned inequality catches | ||
| 239 | it.) */ | ||
| 240 | t = get_bits(bd, 5)-1; | ||
| 241 | for (i = 0; i < symCount; i++) { | ||
| 242 | for (;;) { | ||
| 243 | if (((unsigned)t) > (MAX_HUFCODE_BITS-1)) | ||
| 244 | return RETVAL_DATA_ERROR; | ||
| 245 | |||
| 246 | /* If first bit is 0, stop. Else | ||
| 247 | second bit indicates whether to | ||
| 248 | increment or decrement the value. | ||
| 249 | Optimization: grab 2 bits and unget | ||
| 250 | the second if the first was 0. */ | ||
| 251 | |||
| 252 | k = get_bits(bd, 2); | ||
| 253 | if (k < 2) { | ||
| 254 | bd->inbufBitCount++; | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | /* Add one if second bit 1, else | ||
| 258 | * subtract 1. Avoids if/else */ | ||
| 259 | t += (((k+1)&2)-1); | ||
| 260 | } | ||
| 261 | /* Correct for the initial -1, to get the | ||
| 262 | * final symbol length */ | ||
| 263 | length[i] = t+1; | ||
| 264 | } | ||
| 265 | /* Find largest and smallest lengths in this group */ | ||
| 266 | minLen = maxLen = length[0]; | ||
| 267 | |||
| 268 | for (i = 1; i < symCount; i++) { | ||
| 269 | if (length[i] > maxLen) | ||
| 270 | maxLen = length[i]; | ||
| 271 | else if (length[i] < minLen) | ||
| 272 | minLen = length[i]; | ||
| 273 | } | ||
| 274 | |||
| 275 | /* Calculate permute[], base[], and limit[] tables from | ||
| 276 | * length[]. | ||
| 277 | * | ||
| 278 | * permute[] is the lookup table for converting | ||
| 279 | * Huffman coded symbols into decoded symbols. base[] | ||
| 280 | * is the amount to subtract from the value of a | ||
| 281 | * Huffman symbol of a given length when using | ||
| 282 | * permute[]. | ||
| 283 | * | ||
| 284 | * limit[] indicates the largest numerical value a | ||
| 285 | * symbol with a given number of bits can have. This | ||
| 286 | * is how the Huffman codes can vary in length: each | ||
| 287 | * code with a value > limit[length] needs another | ||
| 288 | * bit. | ||
| 289 | */ | ||
| 290 | hufGroup = bd->groups+j; | ||
| 291 | hufGroup->minLen = minLen; | ||
| 292 | hufGroup->maxLen = maxLen; | ||
| 293 | /* Note that minLen can't be smaller than 1, so we | ||
| 294 | adjust the base and limit array pointers so we're | ||
| 295 | not always wasting the first entry. We do this | ||
| 296 | again when using them (during symbol decoding).*/ | ||
| 297 | base = hufGroup->base-1; | ||
| 298 | limit = hufGroup->limit-1; | ||
| 299 | /* Calculate permute[]. Concurently, initialize | ||
| 300 | * temp[] and limit[]. */ | ||
| 301 | pp = 0; | ||
| 302 | for (i = minLen; i <= maxLen; i++) { | ||
| 303 | temp[i] = limit[i] = 0; | ||
| 304 | for (t = 0; t < symCount; t++) | ||
| 305 | if (length[t] == i) | ||
| 306 | hufGroup->permute[pp++] = t; | ||
| 307 | } | ||
| 308 | /* Count symbols coded for at each bit length */ | ||
| 309 | for (i = 0; i < symCount; i++) | ||
| 310 | temp[length[i]]++; | ||
| 311 | /* Calculate limit[] (the largest symbol-coding value | ||
| 312 | *at each bit length, which is (previous limit << | ||
| 313 | *1)+symbols at this level), and base[] (number of | ||
| 314 | *symbols to ignore at each bit length, which is limit | ||
| 315 | *minus the cumulative count of symbols coded for | ||
| 316 | *already). */ | ||
| 317 | pp = t = 0; | ||
| 318 | for (i = minLen; i < maxLen; i++) { | ||
| 319 | pp += temp[i]; | ||
| 320 | /* We read the largest possible symbol size | ||
| 321 | and then unget bits after determining how | ||
| 322 | many we need, and those extra bits could be | ||
| 323 | set to anything. (They're noise from | ||
| 324 | future symbols.) At each level we're | ||
| 325 | really only interested in the first few | ||
| 326 | bits, so here we set all the trailing | ||
| 327 | to-be-ignored bits to 1 so they don't | ||
| 328 | affect the value > limit[length] | ||
| 329 | comparison. */ | ||
| 330 | limit[i] = (pp << (maxLen - i)) - 1; | ||
| 331 | pp <<= 1; | ||
| 332 | base[i+1] = pp-(t += temp[i]); | ||
| 333 | } | ||
| 334 | limit[maxLen+1] = INT_MAX; /* Sentinal value for | ||
| 335 | * reading next sym. */ | ||
| 336 | limit[maxLen] = pp+temp[maxLen]-1; | ||
| 337 | base[minLen] = 0; | ||
| 338 | } | ||
| 339 | /* We've finished reading and digesting the block header. Now | ||
| 340 | read this block's Huffman coded symbols from the file and | ||
| 341 | undo the Huffman coding and run length encoding, saving the | ||
| 342 | result into dbuf[dbufCount++] = uc */ | ||
| 343 | |||
| 344 | /* Initialize symbol occurrence counters and symbol Move To | ||
| 345 | * Front table */ | ||
| 346 | for (i = 0; i < 256; i++) { | ||
| 347 | byteCount[i] = 0; | ||
| 348 | mtfSymbol[i] = (unsigned char)i; | ||
| 349 | } | ||
| 350 | /* Loop through compressed symbols. */ | ||
| 351 | runPos = dbufCount = symCount = selector = 0; | ||
| 352 | for (;;) { | ||
| 353 | /* Determine which Huffman coding group to use. */ | ||
| 354 | if (!(symCount--)) { | ||
| 355 | symCount = GROUP_SIZE-1; | ||
| 356 | if (selector >= nSelectors) | ||
| 357 | return RETVAL_DATA_ERROR; | ||
| 358 | hufGroup = bd->groups+selectors[selector++]; | ||
| 359 | base = hufGroup->base-1; | ||
| 360 | limit = hufGroup->limit-1; | ||
| 361 | } | ||
| 362 | /* Read next Huffman-coded symbol. */ | ||
| 363 | /* Note: It is far cheaper to read maxLen bits and | ||
| 364 | back up than it is to read minLen bits and then an | ||
| 365 | additional bit at a time, testing as we go. | ||
| 366 | Because there is a trailing last block (with file | ||
| 367 | CRC), there is no danger of the overread causing an | ||
| 368 | unexpected EOF for a valid compressed file. As a | ||
| 369 | further optimization, we do the read inline | ||
| 370 | (falling back to a call to get_bits if the buffer | ||
| 371 | runs dry). The following (up to got_huff_bits:) is | ||
| 372 | equivalent to j = get_bits(bd, hufGroup->maxLen); | ||
| 373 | */ | ||
| 374 | while (bd->inbufBitCount < hufGroup->maxLen) { | ||
| 375 | if (bd->inbufPos == bd->inbufCount) { | ||
| 376 | j = get_bits(bd, hufGroup->maxLen); | ||
| 377 | goto got_huff_bits; | ||
| 378 | } | ||
| 379 | bd->inbufBits = | ||
| 380 | (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; | ||
| 381 | bd->inbufBitCount += 8; | ||
| 382 | }; | ||
| 383 | bd->inbufBitCount -= hufGroup->maxLen; | ||
| 384 | j = (bd->inbufBits >> bd->inbufBitCount)& | ||
| 385 | ((1 << hufGroup->maxLen)-1); | ||
| 386 | got_huff_bits: | ||
| 387 | /* Figure how how many bits are in next symbol and | ||
| 388 | * unget extras */ | ||
| 389 | i = hufGroup->minLen; | ||
| 390 | while (j > limit[i]) | ||
| 391 | ++i; | ||
| 392 | bd->inbufBitCount += (hufGroup->maxLen - i); | ||
| 393 | /* Huffman decode value to get nextSym (with bounds checking) */ | ||
| 394 | if ((i > hufGroup->maxLen) | ||
| 395 | || (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i])) | ||
| 396 | >= MAX_SYMBOLS)) | ||
| 397 | return RETVAL_DATA_ERROR; | ||
| 398 | nextSym = hufGroup->permute[j]; | ||
| 399 | /* We have now decoded the symbol, which indicates | ||
| 400 | either a new literal byte, or a repeated run of the | ||
| 401 | most recent literal byte. First, check if nextSym | ||
| 402 | indicates a repeated run, and if so loop collecting | ||
| 403 | how many times to repeat the last literal. */ | ||
| 404 | if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */ | ||
| 405 | /* If this is the start of a new run, zero out | ||
| 406 | * counter */ | ||
| 407 | if (!runPos) { | ||
| 408 | runPos = 1; | ||
| 409 | t = 0; | ||
| 410 | } | ||
| 411 | /* Neat trick that saves 1 symbol: instead of | ||
| 412 | or-ing 0 or 1 at each bit position, add 1 | ||
| 413 | or 2 instead. For example, 1011 is 1 << 0 | ||
| 414 | + 1 << 1 + 2 << 2. 1010 is 2 << 0 + 2 << 1 | ||
| 415 | + 1 << 2. You can make any bit pattern | ||
| 416 | that way using 1 less symbol than the basic | ||
| 417 | or 0/1 method (except all bits 0, which | ||
| 418 | would use no symbols, but a run of length 0 | ||
| 419 | doesn't mean anything in this context). | ||
| 420 | Thus space is saved. */ | ||
| 421 | t += (runPos << nextSym); | ||
| 422 | /* +runPos if RUNA; +2*runPos if RUNB */ | ||
| 423 | |||
| 424 | runPos <<= 1; | ||
| 425 | continue; | ||
| 426 | } | ||
| 427 | /* When we hit the first non-run symbol after a run, | ||
| 428 | we now know how many times to repeat the last | ||
| 429 | literal, so append that many copies to our buffer | ||
| 430 | of decoded symbols (dbuf) now. (The last literal | ||
| 431 | used is the one at the head of the mtfSymbol | ||
| 432 | array.) */ | ||
| 433 | if (runPos) { | ||
| 434 | runPos = 0; | ||
| 435 | if (dbufCount+t >= dbufSize) | ||
| 436 | return RETVAL_DATA_ERROR; | ||
| 437 | |||
| 438 | uc = symToByte[mtfSymbol[0]]; | ||
| 439 | byteCount[uc] += t; | ||
| 440 | while (t--) | ||
| 441 | dbuf[dbufCount++] = uc; | ||
| 442 | } | ||
| 443 | /* Is this the terminating symbol? */ | ||
| 444 | if (nextSym > symTotal) | ||
| 445 | break; | ||
| 446 | /* At this point, nextSym indicates a new literal | ||
| 447 | character. Subtract one to get the position in the | ||
| 448 | MTF array at which this literal is currently to be | ||
| 449 | found. (Note that the result can't be -1 or 0, | ||
| 450 | because 0 and 1 are RUNA and RUNB. But another | ||
| 451 | instance of the first symbol in the mtf array, | ||
| 452 | position 0, would have been handled as part of a | ||
| 453 | run above. Therefore 1 unused mtf position minus 2 | ||
| 454 | non-literal nextSym values equals -1.) */ | ||
| 455 | if (dbufCount >= dbufSize) | ||
| 456 | return RETVAL_DATA_ERROR; | ||
| 457 | i = nextSym - 1; | ||
| 458 | uc = mtfSymbol[i]; | ||
| 459 | /* Adjust the MTF array. Since we typically expect to | ||
| 460 | *move only a small number of symbols, and are bound | ||
| 461 | *by 256 in any case, using memmove here would | ||
| 462 | *typically be bigger and slower due to function call | ||
| 463 | *overhead and other assorted setup costs. */ | ||
| 464 | do { | ||
| 465 | mtfSymbol[i] = mtfSymbol[i-1]; | ||
| 466 | } while (--i); | ||
| 467 | mtfSymbol[0] = uc; | ||
| 468 | uc = symToByte[uc]; | ||
| 469 | /* We have our literal byte. Save it into dbuf. */ | ||
| 470 | byteCount[uc]++; | ||
| 471 | dbuf[dbufCount++] = (unsigned int)uc; | ||
| 472 | } | ||
| 473 | /* At this point, we've read all the Huffman-coded symbols | ||
| 474 | (and repeated runs) for this block from the input stream, | ||
| 475 | and decoded them into the intermediate buffer. There are | ||
| 476 | dbufCount many decoded bytes in dbuf[]. Now undo the | ||
| 477 | Burrows-Wheeler transform on dbuf. See | ||
| 478 | http://dogma.net/markn/articles/bwt/bwt.htm | ||
| 479 | */ | ||
| 480 | /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ | ||
| 481 | j = 0; | ||
| 482 | for (i = 0; i < 256; i++) { | ||
| 483 | k = j+byteCount[i]; | ||
| 484 | byteCount[i] = j; | ||
| 485 | j = k; | ||
| 486 | } | ||
| 487 | /* Figure out what order dbuf would be in if we sorted it. */ | ||
| 488 | for (i = 0; i < dbufCount; i++) { | ||
| 489 | uc = (unsigned char)(dbuf[i] & 0xff); | ||
| 490 | dbuf[byteCount[uc]] |= (i << 8); | ||
| 491 | byteCount[uc]++; | ||
| 492 | } | ||
| 493 | /* Decode first byte by hand to initialize "previous" byte. | ||
| 494 | Note that it doesn't get output, and if the first three | ||
| 495 | characters are identical it doesn't qualify as a run (hence | ||
| 496 | writeRunCountdown = 5). */ | ||
| 497 | if (dbufCount) { | ||
| 498 | if (origPtr >= dbufCount) | ||
| 499 | return RETVAL_DATA_ERROR; | ||
| 500 | bd->writePos = dbuf[origPtr]; | ||
| 501 | bd->writeCurrent = (unsigned char)(bd->writePos&0xff); | ||
| 502 | bd->writePos >>= 8; | ||
| 503 | bd->writeRunCountdown = 5; | ||
| 504 | } | ||
| 505 | bd->writeCount = dbufCount; | ||
| 506 | |||
| 507 | return RETVAL_OK; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* Undo burrows-wheeler transform on intermediate buffer to produce output. | ||
| 511 | If start_bunzip was initialized with out_fd =-1, then up to len bytes of | ||
| 512 | data are written to outbuf. Return value is number of bytes written or | ||
| 513 | error (all errors are negative numbers). If out_fd!=-1, outbuf and len | ||
| 514 | are ignored, data is written to out_fd and return is RETVAL_OK or error. | ||
| 515 | */ | ||
| 516 | |||
| 517 | static int INIT read_bunzip(struct bunzip_data *bd, char *outbuf, int len) | ||
| 518 | { | ||
| 519 | const unsigned int *dbuf; | ||
| 520 | int pos, xcurrent, previous, gotcount; | ||
| 521 | |||
| 522 | /* If last read was short due to end of file, return last block now */ | ||
| 523 | if (bd->writeCount < 0) | ||
| 524 | return bd->writeCount; | ||
| 525 | |||
| 526 | gotcount = 0; | ||
| 527 | dbuf = bd->dbuf; | ||
| 528 | pos = bd->writePos; | ||
| 529 | xcurrent = bd->writeCurrent; | ||
| 530 | |||
| 531 | /* We will always have pending decoded data to write into the output | ||
| 532 | buffer unless this is the very first call (in which case we haven't | ||
| 533 | Huffman-decoded a block into the intermediate buffer yet). */ | ||
| 534 | |||
| 535 | if (bd->writeCopies) { | ||
| 536 | /* Inside the loop, writeCopies means extra copies (beyond 1) */ | ||
| 537 | --bd->writeCopies; | ||
| 538 | /* Loop outputting bytes */ | ||
| 539 | for (;;) { | ||
| 540 | /* If the output buffer is full, snapshot | ||
| 541 | * state and return */ | ||
| 542 | if (gotcount >= len) { | ||
| 543 | bd->writePos = pos; | ||
| 544 | bd->writeCurrent = xcurrent; | ||
| 545 | bd->writeCopies++; | ||
| 546 | return len; | ||
| 547 | } | ||
| 548 | /* Write next byte into output buffer, updating CRC */ | ||
| 549 | outbuf[gotcount++] = xcurrent; | ||
| 550 | bd->writeCRC = (((bd->writeCRC) << 8) | ||
| 551 | ^bd->crc32Table[((bd->writeCRC) >> 24) | ||
| 552 | ^xcurrent]); | ||
| 553 | /* Loop now if we're outputting multiple | ||
| 554 | * copies of this byte */ | ||
| 555 | if (bd->writeCopies) { | ||
| 556 | --bd->writeCopies; | ||
| 557 | continue; | ||
| 558 | } | ||
| 559 | decode_next_byte: | ||
| 560 | if (!bd->writeCount--) | ||
| 561 | break; | ||
| 562 | /* Follow sequence vector to undo | ||
| 563 | * Burrows-Wheeler transform */ | ||
| 564 | previous = xcurrent; | ||
| 565 | pos = dbuf[pos]; | ||
| 566 | xcurrent = pos&0xff; | ||
| 567 | pos >>= 8; | ||
| 568 | /* After 3 consecutive copies of the same | ||
| 569 | byte, the 4th is a repeat count. We count | ||
| 570 | down from 4 instead *of counting up because | ||
| 571 | testing for non-zero is faster */ | ||
| 572 | if (--bd->writeRunCountdown) { | ||
| 573 | if (xcurrent != previous) | ||
| 574 | bd->writeRunCountdown = 4; | ||
| 575 | } else { | ||
| 576 | /* We have a repeated run, this byte | ||
| 577 | * indicates the count */ | ||
| 578 | bd->writeCopies = xcurrent; | ||
| 579 | xcurrent = previous; | ||
| 580 | bd->writeRunCountdown = 5; | ||
| 581 | /* Sometimes there are just 3 bytes | ||
| 582 | * (run length 0) */ | ||
| 583 | if (!bd->writeCopies) | ||
| 584 | goto decode_next_byte; | ||
| 585 | /* Subtract the 1 copy we'd output | ||
| 586 | * anyway to get extras */ | ||
| 587 | --bd->writeCopies; | ||
| 588 | } | ||
| 589 | } | ||
| 590 | /* Decompression of this block completed successfully */ | ||
| 591 | bd->writeCRC = ~bd->writeCRC; | ||
| 592 | bd->totalCRC = ((bd->totalCRC << 1) | | ||
| 593 | (bd->totalCRC >> 31)) ^ bd->writeCRC; | ||
| 594 | /* If this block had a CRC error, force file level CRC error. */ | ||
| 595 | if (bd->writeCRC != bd->headerCRC) { | ||
| 596 | bd->totalCRC = bd->headerCRC+1; | ||
| 597 | return RETVAL_LAST_BLOCK; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | /* Refill the intermediate buffer by Huffman-decoding next | ||
| 602 | * block of input */ | ||
| 603 | /* (previous is just a convenient unused temp variable here) */ | ||
| 604 | previous = get_next_block(bd); | ||
| 605 | if (previous) { | ||
| 606 | bd->writeCount = previous; | ||
| 607 | return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount; | ||
| 608 | } | ||
| 609 | bd->writeCRC = 0xffffffffUL; | ||
| 610 | pos = bd->writePos; | ||
| 611 | xcurrent = bd->writeCurrent; | ||
| 612 | goto decode_next_byte; | ||
| 613 | } | ||
| 614 | |||
| 615 | static int INIT nofill(void *buf, unsigned int len) | ||
| 616 | { | ||
| 617 | return -1; | ||
| 618 | } | ||
| 619 | |||
| 620 | /* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain | ||
| 621 | a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are | ||
| 622 | ignored, and data is read from file handle into temporary buffer. */ | ||
| 623 | static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, | ||
| 624 | int (*fill)(void*, unsigned int)) | ||
| 625 | { | ||
| 626 | struct bunzip_data *bd; | ||
| 627 | unsigned int i, j, c; | ||
| 628 | const unsigned int BZh0 = | ||
| 629 | (((unsigned int)'B') << 24)+(((unsigned int)'Z') << 16) | ||
| 630 | +(((unsigned int)'h') << 8)+(unsigned int)'0'; | ||
| 631 | |||
| 632 | /* Figure out how much data to allocate */ | ||
| 633 | i = sizeof(struct bunzip_data); | ||
| 634 | |||
| 635 | /* Allocate bunzip_data. Most fields initialize to zero. */ | ||
| 636 | bd = *bdp = malloc(i); | ||
| 637 | memset(bd, 0, sizeof(struct bunzip_data)); | ||
| 638 | /* Setup input buffer */ | ||
| 639 | bd->inbuf = inbuf; | ||
| 640 | bd->inbufCount = len; | ||
| 641 | if (fill != NULL) | ||
| 642 | bd->fill = fill; | ||
| 643 | else | ||
| 644 | bd->fill = nofill; | ||
| 645 | |||
| 646 | /* Init the CRC32 table (big endian) */ | ||
| 647 | for (i = 0; i < 256; i++) { | ||
| 648 | c = i << 24; | ||
| 649 | for (j = 8; j; j--) | ||
| 650 | c = c&0x80000000 ? (c << 1)^0x04c11db7 : (c << 1); | ||
| 651 | bd->crc32Table[i] = c; | ||
| 652 | } | ||
| 653 | |||
| 654 | /* Ensure that file starts with "BZh['1'-'9']." */ | ||
| 655 | i = get_bits(bd, 32); | ||
| 656 | if (((unsigned int)(i-BZh0-1)) >= 9) | ||
| 657 | return RETVAL_NOT_BZIP_DATA; | ||
| 658 | |||
| 659 | /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of | ||
| 660 | uncompressed data. Allocate intermediate buffer for block. */ | ||
| 661 | bd->dbufSize = 100000*(i-BZh0); | ||
| 662 | |||
| 663 | bd->dbuf = large_malloc(bd->dbufSize * sizeof(int)); | ||
| 664 | return RETVAL_OK; | ||
| 665 | } | ||
| 666 | |||
| 667 | /* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, | ||
| 668 | not end of file.) */ | ||
| 669 | STATIC int INIT bunzip2(unsigned char *buf, int len, | ||
| 670 | int(*fill)(void*, unsigned int), | ||
| 671 | int(*flush)(void*, unsigned int), | ||
| 672 | unsigned char *outbuf, | ||
| 673 | int *pos, | ||
| 674 | void(*error_fn)(char *x)) | ||
| 675 | { | ||
| 676 | struct bunzip_data *bd; | ||
| 677 | int i = -1; | ||
| 678 | unsigned char *inbuf; | ||
| 679 | |||
| 680 | set_error_fn(error_fn); | ||
| 681 | if (flush) | ||
| 682 | outbuf = malloc(BZIP2_IOBUF_SIZE); | ||
| 683 | else | ||
| 684 | len -= 4; /* Uncompressed size hack active in pre-boot | ||
| 685 | environment */ | ||
| 686 | if (!outbuf) { | ||
| 687 | error("Could not allocate output bufer"); | ||
| 688 | return -1; | ||
| 689 | } | ||
| 690 | if (buf) | ||
| 691 | inbuf = buf; | ||
| 692 | else | ||
| 693 | inbuf = malloc(BZIP2_IOBUF_SIZE); | ||
| 694 | if (!inbuf) { | ||
| 695 | error("Could not allocate input bufer"); | ||
| 696 | goto exit_0; | ||
| 697 | } | ||
| 698 | i = start_bunzip(&bd, inbuf, len, fill); | ||
| 699 | if (!i) { | ||
| 700 | for (;;) { | ||
| 701 | i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE); | ||
| 702 | if (i <= 0) | ||
| 703 | break; | ||
| 704 | if (!flush) | ||
| 705 | outbuf += i; | ||
| 706 | else | ||
| 707 | if (i != flush(outbuf, i)) { | ||
| 708 | i = RETVAL_UNEXPECTED_OUTPUT_EOF; | ||
| 709 | break; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | } | ||
| 713 | /* Check CRC and release memory */ | ||
| 714 | if (i == RETVAL_LAST_BLOCK) { | ||
| 715 | if (bd->headerCRC != bd->totalCRC) | ||
| 716 | error("Data integrity error when decompressing."); | ||
| 717 | else | ||
| 718 | i = RETVAL_OK; | ||
| 719 | } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) { | ||
| 720 | error("Compressed file ends unexpectedly"); | ||
| 721 | } | ||
| 722 | if (bd->dbuf) | ||
| 723 | large_free(bd->dbuf); | ||
| 724 | if (pos) | ||
| 725 | *pos = bd->inbufPos; | ||
| 726 | free(bd); | ||
| 727 | if (!buf) | ||
| 728 | free(inbuf); | ||
| 729 | exit_0: | ||
| 730 | if (flush) | ||
| 731 | free(outbuf); | ||
| 732 | return i; | ||
| 733 | } | ||
| 734 | |||
| 735 | #define decompress bunzip2 | ||
diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c new file mode 100644 index 000000000000..839a329b4fc4 --- /dev/null +++ b/lib/decompress_inflate.c | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | #ifdef STATIC | ||
| 2 | /* Pre-boot environment: included */ | ||
| 3 | |||
| 4 | /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots | ||
| 5 | * errors about console_printk etc... on ARM */ | ||
| 6 | #define _LINUX_KERNEL_H | ||
| 7 | |||
| 8 | #include "zlib_inflate/inftrees.c" | ||
| 9 | #include "zlib_inflate/inffast.c" | ||
| 10 | #include "zlib_inflate/inflate.c" | ||
| 11 | |||
| 12 | #else /* STATIC */ | ||
| 13 | /* initramfs et al: linked */ | ||
| 14 | |||
| 15 | #include <linux/zutil.h> | ||
| 16 | |||
| 17 | #include "zlib_inflate/inftrees.h" | ||
| 18 | #include "zlib_inflate/inffast.h" | ||
| 19 | #include "zlib_inflate/inflate.h" | ||
| 20 | |||
| 21 | #include "zlib_inflate/infutil.h" | ||
| 22 | |||
| 23 | #endif /* STATIC */ | ||
| 24 | |||
| 25 | #include <linux/decompress/mm.h> | ||
| 26 | |||
| 27 | #define INBUF_LEN (16*1024) | ||
| 28 | |||
| 29 | /* Included from initramfs et al code */ | ||
| 30 | STATIC int INIT gunzip(unsigned char *buf, int len, | ||
| 31 | int(*fill)(void*, unsigned int), | ||
| 32 | int(*flush)(void*, unsigned int), | ||
| 33 | unsigned char *out_buf, | ||
| 34 | int *pos, | ||
| 35 | void(*error_fn)(char *x)) { | ||
| 36 | u8 *zbuf; | ||
| 37 | struct z_stream_s *strm; | ||
| 38 | int rc; | ||
| 39 | size_t out_len; | ||
| 40 | |||
| 41 | set_error_fn(error_fn); | ||
| 42 | rc = -1; | ||
| 43 | if (flush) { | ||
| 44 | out_len = 0x8000; /* 32 K */ | ||
| 45 | out_buf = malloc(out_len); | ||
| 46 | } else { | ||
| 47 | out_len = 0x7fffffff; /* no limit */ | ||
| 48 | } | ||
| 49 | if (!out_buf) { | ||
| 50 | error("Out of memory while allocating output buffer"); | ||
| 51 | goto gunzip_nomem1; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (buf) | ||
| 55 | zbuf = buf; | ||
| 56 | else { | ||
| 57 | zbuf = malloc(INBUF_LEN); | ||
| 58 | len = 0; | ||
| 59 | } | ||
| 60 | if (!zbuf) { | ||
| 61 | error("Out of memory while allocating input buffer"); | ||
| 62 | goto gunzip_nomem2; | ||
| 63 | } | ||
| 64 | |||
| 65 | strm = malloc(sizeof(*strm)); | ||
| 66 | if (strm == NULL) { | ||
| 67 | error("Out of memory while allocating z_stream"); | ||
| 68 | goto gunzip_nomem3; | ||
| 69 | } | ||
| 70 | |||
| 71 | strm->workspace = malloc(flush ? zlib_inflate_workspacesize() : | ||
| 72 | sizeof(struct inflate_state)); | ||
| 73 | if (strm->workspace == NULL) { | ||
| 74 | error("Out of memory while allocating workspace"); | ||
| 75 | goto gunzip_nomem4; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (len == 0) | ||
| 79 | len = fill(zbuf, INBUF_LEN); | ||
| 80 | |||
| 81 | /* verify the gzip header */ | ||
| 82 | if (len < 10 || | ||
| 83 | zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) { | ||
| 84 | if (pos) | ||
| 85 | *pos = 0; | ||
| 86 | error("Not a gzip file"); | ||
| 87 | goto gunzip_5; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* skip over gzip header (1f,8b,08... 10 bytes total + | ||
| 91 | * possible asciz filename) | ||
| 92 | */ | ||
| 93 | strm->next_in = zbuf + 10; | ||
| 94 | /* skip over asciz filename */ | ||
| 95 | if (zbuf[3] & 0x8) { | ||
| 96 | while (strm->next_in[0]) | ||
| 97 | strm->next_in++; | ||
| 98 | strm->next_in++; | ||
| 99 | } | ||
| 100 | strm->avail_in = len - (strm->next_in - zbuf); | ||
| 101 | |||
| 102 | strm->next_out = out_buf; | ||
| 103 | strm->avail_out = out_len; | ||
| 104 | |||
| 105 | rc = zlib_inflateInit2(strm, -MAX_WBITS); | ||
| 106 | |||
| 107 | if (!flush) { | ||
| 108 | WS(strm)->inflate_state.wsize = 0; | ||
| 109 | WS(strm)->inflate_state.window = NULL; | ||
| 110 | } | ||
| 111 | |||
| 112 | while (rc == Z_OK) { | ||
| 113 | if (strm->avail_in == 0) { | ||
| 114 | /* TODO: handle case where both pos and fill are set */ | ||
| 115 | len = fill(zbuf, INBUF_LEN); | ||
| 116 | if (len < 0) { | ||
| 117 | rc = -1; | ||
| 118 | error("read error"); | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | strm->next_in = zbuf; | ||
| 122 | strm->avail_in = len; | ||
| 123 | } | ||
| 124 | rc = zlib_inflate(strm, 0); | ||
| 125 | |||
| 126 | /* Write any data generated */ | ||
| 127 | if (flush && strm->next_out > out_buf) { | ||
| 128 | int l = strm->next_out - out_buf; | ||
| 129 | if (l != flush(out_buf, l)) { | ||
| 130 | rc = -1; | ||
| 131 | error("write error"); | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | strm->next_out = out_buf; | ||
| 135 | strm->avail_out = out_len; | ||
| 136 | } | ||
| 137 | |||
| 138 | /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ | ||
| 139 | if (rc == Z_STREAM_END) { | ||
| 140 | rc = 0; | ||
| 141 | break; | ||
| 142 | } else if (rc != Z_OK) { | ||
| 143 | error("uncompression error"); | ||
| 144 | rc = -1; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | zlib_inflateEnd(strm); | ||
| 149 | if (pos) | ||
| 150 | /* add + 8 to skip over trailer */ | ||
| 151 | *pos = strm->next_in - zbuf+8; | ||
| 152 | |||
| 153 | gunzip_5: | ||
| 154 | free(strm->workspace); | ||
| 155 | gunzip_nomem4: | ||
| 156 | free(strm); | ||
| 157 | gunzip_nomem3: | ||
| 158 | if (!buf) | ||
| 159 | free(zbuf); | ||
| 160 | gunzip_nomem2: | ||
| 161 | if (flush) | ||
| 162 | free(out_buf); | ||
| 163 | gunzip_nomem1: | ||
| 164 | return rc; /* returns Z_OK (0) if successful */ | ||
| 165 | } | ||
| 166 | |||
| 167 | #define decompress gunzip | ||
diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c new file mode 100644 index 000000000000..546f2f4c157e --- /dev/null +++ b/lib/decompress_unlzma.c | |||
| @@ -0,0 +1,647 @@ | |||
| 1 | /* Lzma decompressor for Linux kernel. Shamelessly snarfed | ||
| 2 | *from busybox 1.1.1 | ||
| 3 | * | ||
| 4 | *Linux kernel adaptation | ||
| 5 | *Copyright (C) 2006 Alain < alain@knaff.lu > | ||
| 6 | * | ||
| 7 | *Based on small lzma deflate implementation/Small range coder | ||
| 8 | *implementation for lzma. | ||
| 9 | *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > | ||
| 10 | * | ||
| 11 | *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) | ||
| 12 | *Copyright (C) 1999-2005 Igor Pavlov | ||
| 13 | * | ||
| 14 | *Copyrights of the parts, see headers below. | ||
| 15 | * | ||
| 16 | * | ||
| 17 | *This program is free software; you can redistribute it and/or | ||
| 18 | *modify it under the terms of the GNU Lesser General Public | ||
| 19 | *License as published by the Free Software Foundation; either | ||
| 20 | *version 2.1 of the License, or (at your option) any later version. | ||
| 21 | * | ||
| 22 | *This program is distributed in the hope that it will be useful, | ||
| 23 | *but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 24 | *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 25 | *Lesser General Public License for more details. | ||
| 26 | * | ||
| 27 | *You should have received a copy of the GNU Lesser General Public | ||
| 28 | *License along with this library; if not, write to the Free Software | ||
| 29 | *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 30 | */ | ||
| 31 | |||
| 32 | #ifndef STATIC | ||
| 33 | #include <linux/decompress/unlzma.h> | ||
| 34 | #endif /* STATIC */ | ||
| 35 | |||
| 36 | #include <linux/decompress/mm.h> | ||
| 37 | |||
| 38 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | ||
| 39 | |||
| 40 | static long long INIT read_int(unsigned char *ptr, int size) | ||
| 41 | { | ||
| 42 | int i; | ||
| 43 | long long ret = 0; | ||
| 44 | |||
| 45 | for (i = 0; i < size; i++) | ||
| 46 | ret = (ret << 8) | ptr[size-i-1]; | ||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | #define ENDIAN_CONVERT(x) \ | ||
| 51 | x = (typeof(x))read_int((unsigned char *)&x, sizeof(x)) | ||
| 52 | |||
| 53 | |||
| 54 | /* Small range coder implementation for lzma. | ||
| 55 | *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > | ||
| 56 | * | ||
| 57 | *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) | ||
| 58 | *Copyright (c) 1999-2005 Igor Pavlov | ||
| 59 | */ | ||
| 60 | |||
| 61 | #include <linux/compiler.h> | ||
| 62 | |||
| 63 | #define LZMA_IOBUF_SIZE 0x10000 | ||
| 64 | |||
| 65 | struct rc { | ||
| 66 | int (*fill)(void*, unsigned int); | ||
| 67 | uint8_t *ptr; | ||
| 68 | uint8_t *buffer; | ||
| 69 | uint8_t *buffer_end; | ||
| 70 | int buffer_size; | ||
| 71 | uint32_t code; | ||
| 72 | uint32_t range; | ||
| 73 | uint32_t bound; | ||
| 74 | }; | ||
| 75 | |||
| 76 | |||
| 77 | #define RC_TOP_BITS 24 | ||
| 78 | #define RC_MOVE_BITS 5 | ||
| 79 | #define RC_MODEL_TOTAL_BITS 11 | ||
| 80 | |||
| 81 | |||
| 82 | /* Called twice: once at startup and once in rc_normalize() */ | ||
| 83 | static void INIT rc_read(struct rc *rc) | ||
| 84 | { | ||
| 85 | rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); | ||
| 86 | if (rc->buffer_size <= 0) | ||
| 87 | error("unexpected EOF"); | ||
| 88 | rc->ptr = rc->buffer; | ||
| 89 | rc->buffer_end = rc->buffer + rc->buffer_size; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Called once */ | ||
| 93 | static inline void INIT rc_init(struct rc *rc, | ||
| 94 | int (*fill)(void*, unsigned int), | ||
| 95 | char *buffer, int buffer_size) | ||
| 96 | { | ||
| 97 | rc->fill = fill; | ||
| 98 | rc->buffer = (uint8_t *)buffer; | ||
| 99 | rc->buffer_size = buffer_size; | ||
| 100 | rc->buffer_end = rc->buffer + rc->buffer_size; | ||
| 101 | rc->ptr = rc->buffer; | ||
| 102 | |||
| 103 | rc->code = 0; | ||
| 104 | rc->range = 0xFFFFFFFF; | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void INIT rc_init_code(struct rc *rc) | ||
| 108 | { | ||
| 109 | int i; | ||
| 110 | |||
| 111 | for (i = 0; i < 5; i++) { | ||
| 112 | if (rc->ptr >= rc->buffer_end) | ||
| 113 | rc_read(rc); | ||
| 114 | rc->code = (rc->code << 8) | *rc->ptr++; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | |||
| 119 | /* Called once. TODO: bb_maybe_free() */ | ||
| 120 | static inline void INIT rc_free(struct rc *rc) | ||
| 121 | { | ||
| 122 | free(rc->buffer); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ | ||
| 126 | static void INIT rc_do_normalize(struct rc *rc) | ||
| 127 | { | ||
| 128 | if (rc->ptr >= rc->buffer_end) | ||
| 129 | rc_read(rc); | ||
| 130 | rc->range <<= 8; | ||
| 131 | rc->code = (rc->code << 8) | *rc->ptr++; | ||
| 132 | } | ||
| 133 | static inline void INIT rc_normalize(struct rc *rc) | ||
| 134 | { | ||
| 135 | if (rc->range < (1 << RC_TOP_BITS)) | ||
| 136 | rc_do_normalize(rc); | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Called 9 times */ | ||
| 140 | /* Why rc_is_bit_0_helper exists? | ||
| 141 | *Because we want to always expose (rc->code < rc->bound) to optimizer | ||
| 142 | */ | ||
| 143 | static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p) | ||
| 144 | { | ||
| 145 | rc_normalize(rc); | ||
| 146 | rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); | ||
| 147 | return rc->bound; | ||
| 148 | } | ||
| 149 | static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p) | ||
| 150 | { | ||
| 151 | uint32_t t = rc_is_bit_0_helper(rc, p); | ||
| 152 | return rc->code < t; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* Called ~10 times, but very small, thus inlined */ | ||
| 156 | static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p) | ||
| 157 | { | ||
| 158 | rc->range = rc->bound; | ||
| 159 | *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; | ||
| 160 | } | ||
| 161 | static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) | ||
| 162 | { | ||
| 163 | rc->range -= rc->bound; | ||
| 164 | rc->code -= rc->bound; | ||
| 165 | *p -= *p >> RC_MOVE_BITS; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* Called 4 times in unlzma loop */ | ||
| 169 | static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) | ||
| 170 | { | ||
| 171 | if (rc_is_bit_0(rc, p)) { | ||
| 172 | rc_update_bit_0(rc, p); | ||
| 173 | *symbol *= 2; | ||
| 174 | return 0; | ||
| 175 | } else { | ||
| 176 | rc_update_bit_1(rc, p); | ||
| 177 | *symbol = *symbol * 2 + 1; | ||
| 178 | return 1; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | /* Called once */ | ||
| 183 | static inline int INIT rc_direct_bit(struct rc *rc) | ||
| 184 | { | ||
| 185 | rc_normalize(rc); | ||
| 186 | rc->range >>= 1; | ||
| 187 | if (rc->code >= rc->range) { | ||
| 188 | rc->code -= rc->range; | ||
| 189 | return 1; | ||
| 190 | } | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Called twice */ | ||
| 195 | static inline void INIT | ||
| 196 | rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol) | ||
| 197 | { | ||
| 198 | int i = num_levels; | ||
| 199 | |||
| 200 | *symbol = 1; | ||
| 201 | while (i--) | ||
| 202 | rc_get_bit(rc, p + *symbol, symbol); | ||
| 203 | *symbol -= 1 << num_levels; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | /* | ||
| 208 | * Small lzma deflate implementation. | ||
| 209 | * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > | ||
| 210 | * | ||
| 211 | * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) | ||
| 212 | * Copyright (C) 1999-2005 Igor Pavlov | ||
| 213 | */ | ||
| 214 | |||
| 215 | |||
| 216 | struct lzma_header { | ||
| 217 | uint8_t pos; | ||
| 218 | uint32_t dict_size; | ||
| 219 | uint64_t dst_size; | ||
| 220 | } __attribute__ ((packed)) ; | ||
| 221 | |||
| 222 | |||
| 223 | #define LZMA_BASE_SIZE 1846 | ||
| 224 | #define LZMA_LIT_SIZE 768 | ||
| 225 | |||
| 226 | #define LZMA_NUM_POS_BITS_MAX 4 | ||
| 227 | |||
| 228 | #define LZMA_LEN_NUM_LOW_BITS 3 | ||
| 229 | #define LZMA_LEN_NUM_MID_BITS 3 | ||
| 230 | #define LZMA_LEN_NUM_HIGH_BITS 8 | ||
| 231 | |||
| 232 | #define LZMA_LEN_CHOICE 0 | ||
| 233 | #define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) | ||
| 234 | #define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) | ||
| 235 | #define LZMA_LEN_MID (LZMA_LEN_LOW \ | ||
| 236 | + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) | ||
| 237 | #define LZMA_LEN_HIGH (LZMA_LEN_MID \ | ||
| 238 | +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) | ||
| 239 | #define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) | ||
| 240 | |||
| 241 | #define LZMA_NUM_STATES 12 | ||
| 242 | #define LZMA_NUM_LIT_STATES 7 | ||
| 243 | |||
| 244 | #define LZMA_START_POS_MODEL_INDEX 4 | ||
| 245 | #define LZMA_END_POS_MODEL_INDEX 14 | ||
| 246 | #define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) | ||
| 247 | |||
| 248 | #define LZMA_NUM_POS_SLOT_BITS 6 | ||
| 249 | #define LZMA_NUM_LEN_TO_POS_STATES 4 | ||
| 250 | |||
| 251 | #define LZMA_NUM_ALIGN_BITS 4 | ||
| 252 | |||
| 253 | #define LZMA_MATCH_MIN_LEN 2 | ||
| 254 | |||
| 255 | #define LZMA_IS_MATCH 0 | ||
| 256 | #define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) | ||
| 257 | #define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) | ||
| 258 | #define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) | ||
| 259 | #define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) | ||
| 260 | #define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) | ||
| 261 | #define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ | ||
| 262 | + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) | ||
| 263 | #define LZMA_SPEC_POS (LZMA_POS_SLOT \ | ||
| 264 | +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) | ||
| 265 | #define LZMA_ALIGN (LZMA_SPEC_POS \ | ||
| 266 | + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) | ||
| 267 | #define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) | ||
| 268 | #define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) | ||
| 269 | #define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) | ||
| 270 | |||
| 271 | |||
| 272 | struct writer { | ||
| 273 | uint8_t *buffer; | ||
| 274 | uint8_t previous_byte; | ||
| 275 | size_t buffer_pos; | ||
| 276 | int bufsize; | ||
| 277 | size_t global_pos; | ||
| 278 | int(*flush)(void*, unsigned int); | ||
| 279 | struct lzma_header *header; | ||
| 280 | }; | ||
| 281 | |||
| 282 | struct cstate { | ||
| 283 | int state; | ||
| 284 | uint32_t rep0, rep1, rep2, rep3; | ||
| 285 | }; | ||
| 286 | |||
| 287 | static inline size_t INIT get_pos(struct writer *wr) | ||
| 288 | { | ||
| 289 | return | ||
| 290 | wr->global_pos + wr->buffer_pos; | ||
| 291 | } | ||
| 292 | |||
| 293 | static inline uint8_t INIT peek_old_byte(struct writer *wr, | ||
| 294 | uint32_t offs) | ||
| 295 | { | ||
| 296 | if (!wr->flush) { | ||
| 297 | int32_t pos; | ||
| 298 | while (offs > wr->header->dict_size) | ||
| 299 | offs -= wr->header->dict_size; | ||
| 300 | pos = wr->buffer_pos - offs; | ||
| 301 | return wr->buffer[pos]; | ||
| 302 | } else { | ||
| 303 | uint32_t pos = wr->buffer_pos - offs; | ||
| 304 | while (pos >= wr->header->dict_size) | ||
| 305 | pos += wr->header->dict_size; | ||
| 306 | return wr->buffer[pos]; | ||
| 307 | } | ||
| 308 | |||
| 309 | } | ||
| 310 | |||
| 311 | static inline void INIT write_byte(struct writer *wr, uint8_t byte) | ||
| 312 | { | ||
| 313 | wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; | ||
| 314 | if (wr->flush && wr->buffer_pos == wr->header->dict_size) { | ||
| 315 | wr->buffer_pos = 0; | ||
| 316 | wr->global_pos += wr->header->dict_size; | ||
| 317 | wr->flush((char *)wr->buffer, wr->header->dict_size); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | static inline void INIT copy_byte(struct writer *wr, uint32_t offs) | ||
| 323 | { | ||
| 324 | write_byte(wr, peek_old_byte(wr, offs)); | ||
| 325 | } | ||
| 326 | |||
| 327 | static inline void INIT copy_bytes(struct writer *wr, | ||
| 328 | uint32_t rep0, int len) | ||
| 329 | { | ||
| 330 | do { | ||
| 331 | copy_byte(wr, rep0); | ||
| 332 | len--; | ||
| 333 | } while (len != 0 && wr->buffer_pos < wr->header->dst_size); | ||
| 334 | } | ||
| 335 | |||
| 336 | static inline void INIT process_bit0(struct writer *wr, struct rc *rc, | ||
| 337 | struct cstate *cst, uint16_t *p, | ||
| 338 | int pos_state, uint16_t *prob, | ||
| 339 | int lc, uint32_t literal_pos_mask) { | ||
| 340 | int mi = 1; | ||
| 341 | rc_update_bit_0(rc, prob); | ||
| 342 | prob = (p + LZMA_LITERAL + | ||
| 343 | (LZMA_LIT_SIZE | ||
| 344 | * (((get_pos(wr) & literal_pos_mask) << lc) | ||
| 345 | + (wr->previous_byte >> (8 - lc)))) | ||
| 346 | ); | ||
| 347 | |||
| 348 | if (cst->state >= LZMA_NUM_LIT_STATES) { | ||
| 349 | int match_byte = peek_old_byte(wr, cst->rep0); | ||
| 350 | do { | ||
| 351 | int bit; | ||
| 352 | uint16_t *prob_lit; | ||
| 353 | |||
| 354 | match_byte <<= 1; | ||
| 355 | bit = match_byte & 0x100; | ||
| 356 | prob_lit = prob + 0x100 + bit + mi; | ||
| 357 | if (rc_get_bit(rc, prob_lit, &mi)) { | ||
| 358 | if (!bit) | ||
| 359 | break; | ||
| 360 | } else { | ||
| 361 | if (bit) | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | } while (mi < 0x100); | ||
| 365 | } | ||
| 366 | while (mi < 0x100) { | ||
| 367 | uint16_t *prob_lit = prob + mi; | ||
| 368 | rc_get_bit(rc, prob_lit, &mi); | ||
| 369 | } | ||
| 370 | write_byte(wr, mi); | ||
| 371 | if (cst->state < 4) | ||
| 372 | cst->state = 0; | ||
| 373 | else if (cst->state < 10) | ||
| 374 | cst->state -= 3; | ||
| 375 | else | ||
| 376 | cst->state -= 6; | ||
| 377 | } | ||
| 378 | |||
| 379 | static inline void INIT process_bit1(struct writer *wr, struct rc *rc, | ||
| 380 | struct cstate *cst, uint16_t *p, | ||
| 381 | int pos_state, uint16_t *prob) { | ||
| 382 | int offset; | ||
| 383 | uint16_t *prob_len; | ||
| 384 | int num_bits; | ||
| 385 | int len; | ||
| 386 | |||
| 387 | rc_update_bit_1(rc, prob); | ||
| 388 | prob = p + LZMA_IS_REP + cst->state; | ||
| 389 | if (rc_is_bit_0(rc, prob)) { | ||
| 390 | rc_update_bit_0(rc, prob); | ||
| 391 | cst->rep3 = cst->rep2; | ||
| 392 | cst->rep2 = cst->rep1; | ||
| 393 | cst->rep1 = cst->rep0; | ||
| 394 | cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3; | ||
| 395 | prob = p + LZMA_LEN_CODER; | ||
| 396 | } else { | ||
| 397 | rc_update_bit_1(rc, prob); | ||
| 398 | prob = p + LZMA_IS_REP_G0 + cst->state; | ||
| 399 | if (rc_is_bit_0(rc, prob)) { | ||
| 400 | rc_update_bit_0(rc, prob); | ||
| 401 | prob = (p + LZMA_IS_REP_0_LONG | ||
| 402 | + (cst->state << | ||
| 403 | LZMA_NUM_POS_BITS_MAX) + | ||
| 404 | pos_state); | ||
| 405 | if (rc_is_bit_0(rc, prob)) { | ||
| 406 | rc_update_bit_0(rc, prob); | ||
| 407 | |||
| 408 | cst->state = cst->state < LZMA_NUM_LIT_STATES ? | ||
| 409 | 9 : 11; | ||
| 410 | copy_byte(wr, cst->rep0); | ||
| 411 | return; | ||
| 412 | } else { | ||
| 413 | rc_update_bit_1(rc, prob); | ||
| 414 | } | ||
| 415 | } else { | ||
| 416 | uint32_t distance; | ||
| 417 | |||
| 418 | rc_update_bit_1(rc, prob); | ||
| 419 | prob = p + LZMA_IS_REP_G1 + cst->state; | ||
| 420 | if (rc_is_bit_0(rc, prob)) { | ||
| 421 | rc_update_bit_0(rc, prob); | ||
| 422 | distance = cst->rep1; | ||
| 423 | } else { | ||
| 424 | rc_update_bit_1(rc, prob); | ||
| 425 | prob = p + LZMA_IS_REP_G2 + cst->state; | ||
| 426 | if (rc_is_bit_0(rc, prob)) { | ||
| 427 | rc_update_bit_0(rc, prob); | ||
| 428 | distance = cst->rep2; | ||
| 429 | } else { | ||
| 430 | rc_update_bit_1(rc, prob); | ||
| 431 | distance = cst->rep3; | ||
| 432 | cst->rep3 = cst->rep2; | ||
| 433 | } | ||
| 434 | cst->rep2 = cst->rep1; | ||
| 435 | } | ||
| 436 | cst->rep1 = cst->rep0; | ||
| 437 | cst->rep0 = distance; | ||
| 438 | } | ||
| 439 | cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11; | ||
| 440 | prob = p + LZMA_REP_LEN_CODER; | ||
| 441 | } | ||
| 442 | |||
| 443 | prob_len = prob + LZMA_LEN_CHOICE; | ||
| 444 | if (rc_is_bit_0(rc, prob_len)) { | ||
| 445 | rc_update_bit_0(rc, prob_len); | ||
| 446 | prob_len = (prob + LZMA_LEN_LOW | ||
| 447 | + (pos_state << | ||
| 448 | LZMA_LEN_NUM_LOW_BITS)); | ||
| 449 | offset = 0; | ||
| 450 | num_bits = LZMA_LEN_NUM_LOW_BITS; | ||
| 451 | } else { | ||
| 452 | rc_update_bit_1(rc, prob_len); | ||
| 453 | prob_len = prob + LZMA_LEN_CHOICE_2; | ||
| 454 | if (rc_is_bit_0(rc, prob_len)) { | ||
| 455 | rc_update_bit_0(rc, prob_len); | ||
| 456 | prob_len = (prob + LZMA_LEN_MID | ||
| 457 | + (pos_state << | ||
| 458 | LZMA_LEN_NUM_MID_BITS)); | ||
| 459 | offset = 1 << LZMA_LEN_NUM_LOW_BITS; | ||
| 460 | num_bits = LZMA_LEN_NUM_MID_BITS; | ||
| 461 | } else { | ||
| 462 | rc_update_bit_1(rc, prob_len); | ||
| 463 | prob_len = prob + LZMA_LEN_HIGH; | ||
| 464 | offset = ((1 << LZMA_LEN_NUM_LOW_BITS) | ||
| 465 | + (1 << LZMA_LEN_NUM_MID_BITS)); | ||
| 466 | num_bits = LZMA_LEN_NUM_HIGH_BITS; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | rc_bit_tree_decode(rc, prob_len, num_bits, &len); | ||
| 471 | len += offset; | ||
| 472 | |||
| 473 | if (cst->state < 4) { | ||
| 474 | int pos_slot; | ||
| 475 | |||
| 476 | cst->state += LZMA_NUM_LIT_STATES; | ||
| 477 | prob = | ||
| 478 | p + LZMA_POS_SLOT + | ||
| 479 | ((len < | ||
| 480 | LZMA_NUM_LEN_TO_POS_STATES ? len : | ||
| 481 | LZMA_NUM_LEN_TO_POS_STATES - 1) | ||
| 482 | << LZMA_NUM_POS_SLOT_BITS); | ||
| 483 | rc_bit_tree_decode(rc, prob, | ||
| 484 | LZMA_NUM_POS_SLOT_BITS, | ||
| 485 | &pos_slot); | ||
| 486 | if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { | ||
| 487 | int i, mi; | ||
| 488 | num_bits = (pos_slot >> 1) - 1; | ||
| 489 | cst->rep0 = 2 | (pos_slot & 1); | ||
| 490 | if (pos_slot < LZMA_END_POS_MODEL_INDEX) { | ||
| 491 | cst->rep0 <<= num_bits; | ||
| 492 | prob = p + LZMA_SPEC_POS + | ||
| 493 | cst->rep0 - pos_slot - 1; | ||
| 494 | } else { | ||
| 495 | num_bits -= LZMA_NUM_ALIGN_BITS; | ||
| 496 | while (num_bits--) | ||
| 497 | cst->rep0 = (cst->rep0 << 1) | | ||
| 498 | rc_direct_bit(rc); | ||
| 499 | prob = p + LZMA_ALIGN; | ||
| 500 | cst->rep0 <<= LZMA_NUM_ALIGN_BITS; | ||
| 501 | num_bits = LZMA_NUM_ALIGN_BITS; | ||
| 502 | } | ||
| 503 | i = 1; | ||
| 504 | mi = 1; | ||
| 505 | while (num_bits--) { | ||
| 506 | if (rc_get_bit(rc, prob + mi, &mi)) | ||
| 507 | cst->rep0 |= i; | ||
| 508 | i <<= 1; | ||
| 509 | } | ||
| 510 | } else | ||
| 511 | cst->rep0 = pos_slot; | ||
| 512 | if (++(cst->rep0) == 0) | ||
| 513 | return; | ||
| 514 | } | ||
| 515 | |||
| 516 | len += LZMA_MATCH_MIN_LEN; | ||
| 517 | |||
| 518 | copy_bytes(wr, cst->rep0, len); | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | |||
| 523 | STATIC inline int INIT unlzma(unsigned char *buf, int in_len, | ||
| 524 | int(*fill)(void*, unsigned int), | ||
| 525 | int(*flush)(void*, unsigned int), | ||
| 526 | unsigned char *output, | ||
| 527 | int *posp, | ||
| 528 | void(*error_fn)(char *x) | ||
| 529 | ) | ||
| 530 | { | ||
| 531 | struct lzma_header header; | ||
| 532 | int lc, pb, lp; | ||
| 533 | uint32_t pos_state_mask; | ||
| 534 | uint32_t literal_pos_mask; | ||
| 535 | uint16_t *p; | ||
| 536 | int num_probs; | ||
| 537 | struct rc rc; | ||
| 538 | int i, mi; | ||
| 539 | struct writer wr; | ||
| 540 | struct cstate cst; | ||
| 541 | unsigned char *inbuf; | ||
| 542 | int ret = -1; | ||
| 543 | |||
| 544 | set_error_fn(error_fn); | ||
| 545 | if (!flush) | ||
| 546 | in_len -= 4; /* Uncompressed size hack active in pre-boot | ||
| 547 | environment */ | ||
| 548 | if (buf) | ||
| 549 | inbuf = buf; | ||
| 550 | else | ||
| 551 | inbuf = malloc(LZMA_IOBUF_SIZE); | ||
| 552 | if (!inbuf) { | ||
| 553 | error("Could not allocate input bufer"); | ||
| 554 | goto exit_0; | ||
| 555 | } | ||
| 556 | |||
| 557 | cst.state = 0; | ||
| 558 | cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1; | ||
| 559 | |||
| 560 | wr.header = &header; | ||
| 561 | wr.flush = flush; | ||
| 562 | wr.global_pos = 0; | ||
| 563 | wr.previous_byte = 0; | ||
| 564 | wr.buffer_pos = 0; | ||
| 565 | |||
| 566 | rc_init(&rc, fill, inbuf, in_len); | ||
| 567 | |||
| 568 | for (i = 0; i < sizeof(header); i++) { | ||
| 569 | if (rc.ptr >= rc.buffer_end) | ||
| 570 | rc_read(&rc); | ||
| 571 | ((unsigned char *)&header)[i] = *rc.ptr++; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (header.pos >= (9 * 5 * 5)) | ||
| 575 | error("bad header"); | ||
| 576 | |||
| 577 | mi = 0; | ||
| 578 | lc = header.pos; | ||
| 579 | while (lc >= 9) { | ||
| 580 | mi++; | ||
| 581 | lc -= 9; | ||
| 582 | } | ||
| 583 | pb = 0; | ||
| 584 | lp = mi; | ||
| 585 | while (lp >= 5) { | ||
| 586 | pb++; | ||
| 587 | lp -= 5; | ||
| 588 | } | ||
| 589 | pos_state_mask = (1 << pb) - 1; | ||
| 590 | literal_pos_mask = (1 << lp) - 1; | ||
| 591 | |||
| 592 | ENDIAN_CONVERT(header.dict_size); | ||
| 593 | ENDIAN_CONVERT(header.dst_size); | ||
| 594 | |||
| 595 | if (header.dict_size == 0) | ||
| 596 | header.dict_size = 1; | ||
| 597 | |||
| 598 | if (output) | ||
| 599 | wr.buffer = output; | ||
| 600 | else { | ||
| 601 | wr.bufsize = MIN(header.dst_size, header.dict_size); | ||
| 602 | wr.buffer = large_malloc(wr.bufsize); | ||
| 603 | } | ||
| 604 | if (wr.buffer == NULL) | ||
| 605 | goto exit_1; | ||
| 606 | |||
| 607 | num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); | ||
| 608 | p = (uint16_t *) large_malloc(num_probs * sizeof(*p)); | ||
| 609 | if (p == 0) | ||
| 610 | goto exit_2; | ||
| 611 | num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); | ||
| 612 | for (i = 0; i < num_probs; i++) | ||
| 613 | p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; | ||
| 614 | |||
| 615 | rc_init_code(&rc); | ||
| 616 | |||
| 617 | while (get_pos(&wr) < header.dst_size) { | ||
| 618 | int pos_state = get_pos(&wr) & pos_state_mask; | ||
| 619 | uint16_t *prob = p + LZMA_IS_MATCH + | ||
| 620 | (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; | ||
| 621 | if (rc_is_bit_0(&rc, prob)) | ||
| 622 | process_bit0(&wr, &rc, &cst, p, pos_state, prob, | ||
| 623 | lc, literal_pos_mask); | ||
| 624 | else { | ||
| 625 | process_bit1(&wr, &rc, &cst, p, pos_state, prob); | ||
| 626 | if (cst.rep0 == 0) | ||
| 627 | break; | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | if (posp) | ||
| 632 | *posp = rc.ptr-rc.buffer; | ||
| 633 | if (wr.flush) | ||
| 634 | wr.flush(wr.buffer, wr.buffer_pos); | ||
| 635 | ret = 0; | ||
| 636 | large_free(p); | ||
| 637 | exit_2: | ||
| 638 | if (!output) | ||
| 639 | large_free(wr.buffer); | ||
| 640 | exit_1: | ||
| 641 | if (!buf) | ||
| 642 | free(inbuf); | ||
| 643 | exit_0: | ||
| 644 | return ret; | ||
| 645 | } | ||
| 646 | |||
| 647 | #define decompress unlzma | ||
diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h index df8a6c92052d..3d17b3d1b21f 100644 --- a/lib/zlib_inflate/inflate.h +++ b/lib/zlib_inflate/inflate.h | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | #ifndef INFLATE_H | ||
| 2 | #define INFLATE_H | ||
| 3 | |||
| 1 | /* inflate.h -- internal inflate state definition | 4 | /* inflate.h -- internal inflate state definition |
| 2 | * Copyright (C) 1995-2004 Mark Adler | 5 | * Copyright (C) 1995-2004 Mark Adler |
| 3 | * For conditions of distribution and use, see copyright notice in zlib.h | 6 | * For conditions of distribution and use, see copyright notice in zlib.h |
| @@ -105,3 +108,4 @@ struct inflate_state { | |||
| 105 | unsigned short work[288]; /* work area for code table building */ | 108 | unsigned short work[288]; /* work area for code table building */ |
| 106 | code codes[ENOUGH]; /* space for code tables */ | 109 | code codes[ENOUGH]; /* space for code tables */ |
| 107 | }; | 110 | }; |
| 111 | #endif | ||
diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h index 5f5219b1240e..b70b4731ac7a 100644 --- a/lib/zlib_inflate/inftrees.h +++ b/lib/zlib_inflate/inftrees.h | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | #ifndef INFTREES_H | ||
| 2 | #define INFTREES_H | ||
| 3 | |||
| 1 | /* inftrees.h -- header to use inftrees.c | 4 | /* inftrees.h -- header to use inftrees.c |
| 2 | * Copyright (C) 1995-2005 Mark Adler | 5 | * Copyright (C) 1995-2005 Mark Adler |
| 3 | * For conditions of distribution and use, see copyright notice in zlib.h | 6 | * For conditions of distribution and use, see copyright notice in zlib.h |
| @@ -53,3 +56,4 @@ typedef enum { | |||
| 53 | extern int zlib_inflate_table (codetype type, unsigned short *lens, | 56 | extern int zlib_inflate_table (codetype type, unsigned short *lens, |
| 54 | unsigned codes, code **table, | 57 | unsigned codes, code **table, |
| 55 | unsigned *bits, unsigned short *work); | 58 | unsigned *bits, unsigned short *work); |
| 59 | #endif | ||
diff --git a/mm/Makefile b/mm/Makefile index 72255be57f89..818569b68f46 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
| @@ -30,6 +30,10 @@ obj-$(CONFIG_FAILSLAB) += failslab.o | |||
| 30 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o | 30 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o |
| 31 | obj-$(CONFIG_FS_XIP) += filemap_xip.o | 31 | obj-$(CONFIG_FS_XIP) += filemap_xip.o |
| 32 | obj-$(CONFIG_MIGRATION) += migrate.o | 32 | obj-$(CONFIG_MIGRATION) += migrate.o |
| 33 | ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
| 34 | obj-$(CONFIG_SMP) += percpu.o | ||
| 35 | else | ||
| 33 | obj-$(CONFIG_SMP) += allocpercpu.o | 36 | obj-$(CONFIG_SMP) += allocpercpu.o |
| 37 | endif | ||
| 34 | obj-$(CONFIG_QUICKLIST) += quicklist.o | 38 | obj-$(CONFIG_QUICKLIST) += quicklist.o |
| 35 | obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o | 39 | obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o |
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c index 4297bc41bfd2..3653c570232b 100644 --- a/mm/allocpercpu.c +++ b/mm/allocpercpu.c | |||
| @@ -99,45 +99,51 @@ static int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp, | |||
| 99 | __percpu_populate_mask((__pdata), (size), (gfp), &(mask)) | 99 | __percpu_populate_mask((__pdata), (size), (gfp), &(mask)) |
| 100 | 100 | ||
| 101 | /** | 101 | /** |
| 102 | * percpu_alloc_mask - initial setup of per-cpu data | 102 | * alloc_percpu - initial setup of per-cpu data |
| 103 | * @size: size of per-cpu object | 103 | * @size: size of per-cpu object |
| 104 | * @gfp: may sleep or not etc. | 104 | * @align: alignment |
| 105 | * @mask: populate per-data for cpu's selected through mask bits | ||
| 106 | * | 105 | * |
| 107 | * Populating per-cpu data for all online cpu's would be a typical use case, | 106 | * Allocate dynamic percpu area. Percpu objects are populated with |
| 108 | * which is simplified by the percpu_alloc() wrapper. | 107 | * zeroed buffers. |
| 109 | * Per-cpu objects are populated with zeroed buffers. | ||
| 110 | */ | 108 | */ |
| 111 | void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask) | 109 | void *__alloc_percpu(size_t size, size_t align) |
| 112 | { | 110 | { |
| 113 | /* | 111 | /* |
| 114 | * We allocate whole cache lines to avoid false sharing | 112 | * We allocate whole cache lines to avoid false sharing |
| 115 | */ | 113 | */ |
| 116 | size_t sz = roundup(nr_cpu_ids * sizeof(void *), cache_line_size()); | 114 | size_t sz = roundup(nr_cpu_ids * sizeof(void *), cache_line_size()); |
| 117 | void *pdata = kzalloc(sz, gfp); | 115 | void *pdata = kzalloc(sz, GFP_KERNEL); |
| 118 | void *__pdata = __percpu_disguise(pdata); | 116 | void *__pdata = __percpu_disguise(pdata); |
| 119 | 117 | ||
| 118 | /* | ||
| 119 | * Can't easily make larger alignment work with kmalloc. WARN | ||
| 120 | * on it. Larger alignment should only be used for module | ||
| 121 | * percpu sections on SMP for which this path isn't used. | ||
| 122 | */ | ||
| 123 | WARN_ON_ONCE(align > __alignof__(unsigned long long)); | ||
| 124 | |||
| 120 | if (unlikely(!pdata)) | 125 | if (unlikely(!pdata)) |
| 121 | return NULL; | 126 | return NULL; |
| 122 | if (likely(!__percpu_populate_mask(__pdata, size, gfp, mask))) | 127 | if (likely(!__percpu_populate_mask(__pdata, size, GFP_KERNEL, |
| 128 | &cpu_possible_map))) | ||
| 123 | return __pdata; | 129 | return __pdata; |
| 124 | kfree(pdata); | 130 | kfree(pdata); |
| 125 | return NULL; | 131 | return NULL; |
| 126 | } | 132 | } |
| 127 | EXPORT_SYMBOL_GPL(__percpu_alloc_mask); | 133 | EXPORT_SYMBOL_GPL(__alloc_percpu); |
| 128 | 134 | ||
| 129 | /** | 135 | /** |
| 130 | * percpu_free - final cleanup of per-cpu data | 136 | * free_percpu - final cleanup of per-cpu data |
| 131 | * @__pdata: object to clean up | 137 | * @__pdata: object to clean up |
| 132 | * | 138 | * |
| 133 | * We simply clean up any per-cpu object left. No need for the client to | 139 | * We simply clean up any per-cpu object left. No need for the client to |
| 134 | * track and specify through a bis mask which per-cpu objects are to free. | 140 | * track and specify through a bis mask which per-cpu objects are to free. |
| 135 | */ | 141 | */ |
| 136 | void percpu_free(void *__pdata) | 142 | void free_percpu(void *__pdata) |
| 137 | { | 143 | { |
| 138 | if (unlikely(!__pdata)) | 144 | if (unlikely(!__pdata)) |
| 139 | return; | 145 | return; |
| 140 | __percpu_depopulate_mask(__pdata, &cpu_possible_map); | 146 | __percpu_depopulate_mask(__pdata, &cpu_possible_map); |
| 141 | kfree(__percpu_disguise(__pdata)); | 147 | kfree(__percpu_disguise(__pdata)); |
| 142 | } | 148 | } |
| 143 | EXPORT_SYMBOL_GPL(percpu_free); | 149 | EXPORT_SYMBOL_GPL(free_percpu); |
diff --git a/mm/bootmem.c b/mm/bootmem.c index 51a0ccf61e0e..daf92713f7de 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
| @@ -382,7 +382,6 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, | |||
| 382 | return mark_bootmem_node(pgdat->bdata, start, end, 1, flags); | 382 | return mark_bootmem_node(pgdat->bdata, start, end, 1, flags); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE | ||
| 386 | /** | 385 | /** |
| 387 | * reserve_bootmem - mark a page range as usable | 386 | * reserve_bootmem - mark a page range as usable |
| 388 | * @addr: starting address of the range | 387 | * @addr: starting address of the range |
| @@ -403,7 +402,6 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, | |||
| 403 | 402 | ||
| 404 | return mark_bootmem(start, end, 1, flags); | 403 | return mark_bootmem(start, end, 1, flags); |
| 405 | } | 404 | } |
| 406 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ | ||
| 407 | 405 | ||
| 408 | static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | 406 | static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, |
| 409 | unsigned long step) | 407 | unsigned long step) |
| @@ -429,8 +427,8 @@ static unsigned long align_off(struct bootmem_data *bdata, unsigned long off, | |||
| 429 | } | 427 | } |
| 430 | 428 | ||
| 431 | static void * __init alloc_bootmem_core(struct bootmem_data *bdata, | 429 | static void * __init alloc_bootmem_core(struct bootmem_data *bdata, |
| 432 | unsigned long size, unsigned long align, | 430 | unsigned long size, unsigned long align, |
| 433 | unsigned long goal, unsigned long limit) | 431 | unsigned long goal, unsigned long limit) |
| 434 | { | 432 | { |
| 435 | unsigned long fallback = 0; | 433 | unsigned long fallback = 0; |
| 436 | unsigned long min, max, start, sidx, midx, step; | 434 | unsigned long min, max, start, sidx, midx, step; |
| @@ -530,17 +528,34 @@ find_block: | |||
| 530 | return NULL; | 528 | return NULL; |
| 531 | } | 529 | } |
| 532 | 530 | ||
| 531 | static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata, | ||
| 532 | unsigned long size, unsigned long align, | ||
| 533 | unsigned long goal, unsigned long limit) | ||
| 534 | { | ||
| 535 | #ifdef CONFIG_HAVE_ARCH_BOOTMEM | ||
| 536 | bootmem_data_t *p_bdata; | ||
| 537 | |||
| 538 | p_bdata = bootmem_arch_preferred_node(bdata, size, align, goal, limit); | ||
| 539 | if (p_bdata) | ||
| 540 | return alloc_bootmem_core(p_bdata, size, align, goal, limit); | ||
| 541 | #endif | ||
| 542 | return NULL; | ||
| 543 | } | ||
| 544 | |||
| 533 | static void * __init ___alloc_bootmem_nopanic(unsigned long size, | 545 | static void * __init ___alloc_bootmem_nopanic(unsigned long size, |
| 534 | unsigned long align, | 546 | unsigned long align, |
| 535 | unsigned long goal, | 547 | unsigned long goal, |
| 536 | unsigned long limit) | 548 | unsigned long limit) |
| 537 | { | 549 | { |
| 538 | bootmem_data_t *bdata; | 550 | bootmem_data_t *bdata; |
| 551 | void *region; | ||
| 539 | 552 | ||
| 540 | restart: | 553 | restart: |
| 541 | list_for_each_entry(bdata, &bdata_list, list) { | 554 | region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit); |
| 542 | void *region; | 555 | if (region) |
| 556 | return region; | ||
| 543 | 557 | ||
| 558 | list_for_each_entry(bdata, &bdata_list, list) { | ||
| 544 | if (goal && bdata->node_low_pfn <= PFN_DOWN(goal)) | 559 | if (goal && bdata->node_low_pfn <= PFN_DOWN(goal)) |
| 545 | continue; | 560 | continue; |
| 546 | if (limit && bdata->node_min_pfn >= PFN_DOWN(limit)) | 561 | if (limit && bdata->node_min_pfn >= PFN_DOWN(limit)) |
| @@ -618,6 +633,10 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata, | |||
| 618 | { | 633 | { |
| 619 | void *ptr; | 634 | void *ptr; |
| 620 | 635 | ||
| 636 | ptr = alloc_arch_preferred_bootmem(bdata, size, align, goal, limit); | ||
| 637 | if (ptr) | ||
| 638 | return ptr; | ||
| 639 | |||
| 621 | ptr = alloc_bootmem_core(bdata, size, align, goal, limit); | 640 | ptr = alloc_bootmem_core(bdata, size, align, goal, limit); |
| 622 | if (ptr) | 641 | if (ptr) |
| 623 | return ptr; | 642 | return ptr; |
| @@ -674,6 +693,10 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, | |||
| 674 | { | 693 | { |
| 675 | void *ptr; | 694 | void *ptr; |
| 676 | 695 | ||
| 696 | ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0); | ||
| 697 | if (ptr) | ||
| 698 | return ptr; | ||
| 699 | |||
| 677 | ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0); | 700 | ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0); |
| 678 | if (ptr) | 701 | if (ptr) |
| 679 | return ptr; | 702 | return ptr; |
diff --git a/mm/filemap.c b/mm/filemap.c index 60fd56772cc6..126d3973b3d1 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1816,14 +1816,14 @@ EXPORT_SYMBOL(file_remove_suid); | |||
| 1816 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, | 1816 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, |
| 1817 | const struct iovec *iov, size_t base, size_t bytes) | 1817 | const struct iovec *iov, size_t base, size_t bytes) |
| 1818 | { | 1818 | { |
| 1819 | size_t copied = 0, left = 0, total = bytes; | 1819 | size_t copied = 0, left = 0; |
| 1820 | 1820 | ||
| 1821 | while (bytes) { | 1821 | while (bytes) { |
| 1822 | char __user *buf = iov->iov_base + base; | 1822 | char __user *buf = iov->iov_base + base; |
| 1823 | int copy = min(bytes, iov->iov_len - base); | 1823 | int copy = min(bytes, iov->iov_len - base); |
| 1824 | 1824 | ||
| 1825 | base = 0; | 1825 | base = 0; |
| 1826 | left = __copy_from_user_inatomic_nocache(vaddr, buf, copy, total); | 1826 | left = __copy_from_user_inatomic(vaddr, buf, copy); |
| 1827 | copied += copy; | 1827 | copied += copy; |
| 1828 | bytes -= copy; | 1828 | bytes -= copy; |
| 1829 | vaddr += copy; | 1829 | vaddr += copy; |
| @@ -1851,9 +1851,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
| 1851 | if (likely(i->nr_segs == 1)) { | 1851 | if (likely(i->nr_segs == 1)) { |
| 1852 | int left; | 1852 | int left; |
| 1853 | char __user *buf = i->iov->iov_base + i->iov_offset; | 1853 | char __user *buf = i->iov->iov_base + i->iov_offset; |
| 1854 | 1854 | left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); | |
| 1855 | left = __copy_from_user_inatomic_nocache(kaddr + offset, | ||
| 1856 | buf, bytes, bytes); | ||
| 1857 | copied = bytes - left; | 1855 | copied = bytes - left; |
| 1858 | } else { | 1856 | } else { |
| 1859 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, | 1857 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, |
| @@ -1881,8 +1879,7 @@ size_t iov_iter_copy_from_user(struct page *page, | |||
| 1881 | if (likely(i->nr_segs == 1)) { | 1879 | if (likely(i->nr_segs == 1)) { |
| 1882 | int left; | 1880 | int left; |
| 1883 | char __user *buf = i->iov->iov_base + i->iov_offset; | 1881 | char __user *buf = i->iov->iov_base + i->iov_offset; |
| 1884 | 1882 | left = __copy_from_user(kaddr + offset, buf, bytes); | |
| 1885 | left = __copy_from_user_nocache(kaddr + offset, buf, bytes, bytes); | ||
| 1886 | copied = bytes - left; | 1883 | copied = bytes - left; |
| 1887 | } else { | 1884 | } else { |
| 1888 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, | 1885 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, |
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index bf54f8a2cf1d..0c04615651b7 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
| @@ -354,7 +354,7 @@ __xip_file_write(struct file *filp, const char __user *buf, | |||
| 354 | break; | 354 | break; |
| 355 | 355 | ||
| 356 | copied = bytes - | 356 | copied = bytes - |
| 357 | __copy_from_user_nocache(xip_mem + offset, buf, bytes, bytes); | 357 | __copy_from_user_nocache(xip_mem + offset, buf, bytes); |
| 358 | 358 | ||
| 359 | if (likely(copied > 0)) { | 359 | if (likely(copied > 0)) { |
| 360 | status = copied; | 360 | status = copied; |
diff --git a/mm/percpu.c b/mm/percpu.c new file mode 100644 index 000000000000..3d0f5456827c --- /dev/null +++ b/mm/percpu.c | |||
| @@ -0,0 +1,979 @@ | |||
| 1 | /* | ||
| 2 | * linux/mm/percpu.c - percpu memory allocator | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 SUSE Linux Products GmbH | ||
| 5 | * Copyright (C) 2009 Tejun Heo <tj@kernel.org> | ||
| 6 | * | ||
| 7 | * This file is released under the GPLv2. | ||
| 8 | * | ||
| 9 | * This is percpu allocator which can handle both static and dynamic | ||
| 10 | * areas. Percpu areas are allocated in chunks in vmalloc area. Each | ||
| 11 | * chunk is consisted of num_possible_cpus() units and the first chunk | ||
| 12 | * is used for static percpu variables in the kernel image (special | ||
| 13 | * boot time alloc/init handling necessary as these areas need to be | ||
| 14 | * brought up before allocation services are running). Unit grows as | ||
| 15 | * necessary and all units grow or shrink in unison. When a chunk is | ||
| 16 | * filled up, another chunk is allocated. ie. in vmalloc area | ||
| 17 | * | ||
| 18 | * c0 c1 c2 | ||
| 19 | * ------------------- ------------------- ------------ | ||
| 20 | * | u0 | u1 | u2 | u3 | | u0 | u1 | u2 | u3 | | u0 | u1 | u | ||
| 21 | * ------------------- ...... ------------------- .... ------------ | ||
| 22 | * | ||
| 23 | * Allocation is done in offset-size areas of single unit space. Ie, | ||
| 24 | * an area of 512 bytes at 6k in c1 occupies 512 bytes at 6k of c1:u0, | ||
| 25 | * c1:u1, c1:u2 and c1:u3. Percpu access can be done by configuring | ||
| 26 | * percpu base registers UNIT_SIZE apart. | ||
| 27 | * | ||
| 28 | * There are usually many small percpu allocations many of them as | ||
| 29 | * small as 4 bytes. The allocator organizes chunks into lists | ||
| 30 | * according to free size and tries to allocate from the fullest one. | ||
| 31 | * Each chunk keeps the maximum contiguous area size hint which is | ||
| 32 | * guaranteed to be eqaul to or larger than the maximum contiguous | ||
| 33 | * area in the chunk. This helps the allocator not to iterate the | ||
| 34 | * chunk maps unnecessarily. | ||
| 35 | * | ||
| 36 | * Allocation state in each chunk is kept using an array of integers | ||
| 37 | * on chunk->map. A positive value in the map represents a free | ||
| 38 | * region and negative allocated. Allocation inside a chunk is done | ||
| 39 | * by scanning this map sequentially and serving the first matching | ||
| 40 | * entry. This is mostly copied from the percpu_modalloc() allocator. | ||
| 41 | * Chunks are also linked into a rb tree to ease address to chunk | ||
| 42 | * mapping during free. | ||
| 43 | * | ||
| 44 | * To use this allocator, arch code should do the followings. | ||
| 45 | * | ||
| 46 | * - define CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
| 47 | * | ||
| 48 | * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate | ||
| 49 | * regular address to percpu pointer and back | ||
| 50 | * | ||
| 51 | * - use pcpu_setup_first_chunk() during percpu area initialization to | ||
| 52 | * setup the first chunk containing the kernel static percpu area | ||
| 53 | */ | ||
| 54 | |||
| 55 | #include <linux/bitmap.h> | ||
| 56 | #include <linux/bootmem.h> | ||
| 57 | #include <linux/list.h> | ||
| 58 | #include <linux/mm.h> | ||
| 59 | #include <linux/module.h> | ||
| 60 | #include <linux/mutex.h> | ||
| 61 | #include <linux/percpu.h> | ||
| 62 | #include <linux/pfn.h> | ||
| 63 | #include <linux/rbtree.h> | ||
| 64 | #include <linux/slab.h> | ||
| 65 | #include <linux/vmalloc.h> | ||
| 66 | |||
| 67 | #include <asm/cacheflush.h> | ||
| 68 | #include <asm/tlbflush.h> | ||
| 69 | |||
| 70 | #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ | ||
| 71 | #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ | ||
| 72 | |||
| 73 | struct pcpu_chunk { | ||
| 74 | struct list_head list; /* linked to pcpu_slot lists */ | ||
| 75 | struct rb_node rb_node; /* key is chunk->vm->addr */ | ||
| 76 | int free_size; /* free bytes in the chunk */ | ||
| 77 | int contig_hint; /* max contiguous size hint */ | ||
| 78 | struct vm_struct *vm; /* mapped vmalloc region */ | ||
| 79 | int map_used; /* # of map entries used */ | ||
| 80 | int map_alloc; /* # of map entries allocated */ | ||
| 81 | int *map; /* allocation map */ | ||
| 82 | bool immutable; /* no [de]population allowed */ | ||
| 83 | struct page *page[]; /* #cpus * UNIT_PAGES */ | ||
| 84 | }; | ||
| 85 | |||
| 86 | static int pcpu_unit_pages __read_mostly; | ||
| 87 | static int pcpu_unit_size __read_mostly; | ||
| 88 | static int pcpu_chunk_size __read_mostly; | ||
| 89 | static int pcpu_nr_slots __read_mostly; | ||
| 90 | static size_t pcpu_chunk_struct_size __read_mostly; | ||
| 91 | |||
| 92 | /* the address of the first chunk which starts with the kernel static area */ | ||
| 93 | void *pcpu_base_addr __read_mostly; | ||
| 94 | EXPORT_SYMBOL_GPL(pcpu_base_addr); | ||
| 95 | |||
| 96 | /* the size of kernel static area */ | ||
| 97 | static int pcpu_static_size __read_mostly; | ||
| 98 | |||
| 99 | /* | ||
| 100 | * One mutex to rule them all. | ||
| 101 | * | ||
| 102 | * The following mutex is grabbed in the outermost public alloc/free | ||
| 103 | * interface functions and released only when the operation is | ||
| 104 | * complete. As such, every function in this file other than the | ||
| 105 | * outermost functions are called under pcpu_mutex. | ||
| 106 | * | ||
| 107 | * It can easily be switched to use spinlock such that only the area | ||
| 108 | * allocation and page population commit are protected with it doing | ||
| 109 | * actual [de]allocation without holding any lock. However, given | ||
| 110 | * what this allocator does, I think it's better to let them run | ||
| 111 | * sequentially. | ||
| 112 | */ | ||
| 113 | static DEFINE_MUTEX(pcpu_mutex); | ||
| 114 | |||
| 115 | static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ | ||
| 116 | static struct rb_root pcpu_addr_root = RB_ROOT; /* chunks by address */ | ||
| 117 | |||
| 118 | static int __pcpu_size_to_slot(int size) | ||
| 119 | { | ||
| 120 | int highbit = fls(size); /* size is in bytes */ | ||
| 121 | return max(highbit - PCPU_SLOT_BASE_SHIFT + 2, 1); | ||
| 122 | } | ||
| 123 | |||
| 124 | static int pcpu_size_to_slot(int size) | ||
| 125 | { | ||
| 126 | if (size == pcpu_unit_size) | ||
| 127 | return pcpu_nr_slots - 1; | ||
| 128 | return __pcpu_size_to_slot(size); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int pcpu_chunk_slot(const struct pcpu_chunk *chunk) | ||
| 132 | { | ||
| 133 | if (chunk->free_size < sizeof(int) || chunk->contig_hint < sizeof(int)) | ||
| 134 | return 0; | ||
| 135 | |||
| 136 | return pcpu_size_to_slot(chunk->free_size); | ||
| 137 | } | ||
| 138 | |||
| 139 | static int pcpu_page_idx(unsigned int cpu, int page_idx) | ||
| 140 | { | ||
| 141 | return cpu * pcpu_unit_pages + page_idx; | ||
| 142 | } | ||
| 143 | |||
| 144 | static struct page **pcpu_chunk_pagep(struct pcpu_chunk *chunk, | ||
| 145 | unsigned int cpu, int page_idx) | ||
| 146 | { | ||
| 147 | return &chunk->page[pcpu_page_idx(cpu, page_idx)]; | ||
| 148 | } | ||
| 149 | |||
| 150 | static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, | ||
| 151 | unsigned int cpu, int page_idx) | ||
| 152 | { | ||
| 153 | return (unsigned long)chunk->vm->addr + | ||
| 154 | (pcpu_page_idx(cpu, page_idx) << PAGE_SHIFT); | ||
| 155 | } | ||
| 156 | |||
| 157 | static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk, | ||
| 158 | int page_idx) | ||
| 159 | { | ||
| 160 | return *pcpu_chunk_pagep(chunk, 0, page_idx) != NULL; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * pcpu_realloc - versatile realloc | ||
| 165 | * @p: the current pointer (can be NULL for new allocations) | ||
| 166 | * @size: the current size in bytes (can be 0 for new allocations) | ||
| 167 | * @new_size: the wanted new size in bytes (can be 0 for free) | ||
| 168 | * | ||
| 169 | * More robust realloc which can be used to allocate, resize or free a | ||
| 170 | * memory area of arbitrary size. If the needed size goes over | ||
| 171 | * PAGE_SIZE, kernel VM is used. | ||
| 172 | * | ||
| 173 | * RETURNS: | ||
| 174 | * The new pointer on success, NULL on failure. | ||
| 175 | */ | ||
| 176 | static void *pcpu_realloc(void *p, size_t size, size_t new_size) | ||
| 177 | { | ||
| 178 | void *new; | ||
| 179 | |||
| 180 | if (new_size <= PAGE_SIZE) | ||
| 181 | new = kmalloc(new_size, GFP_KERNEL); | ||
| 182 | else | ||
| 183 | new = vmalloc(new_size); | ||
| 184 | if (new_size && !new) | ||
| 185 | return NULL; | ||
| 186 | |||
| 187 | memcpy(new, p, min(size, new_size)); | ||
| 188 | if (new_size > size) | ||
| 189 | memset(new + size, 0, new_size - size); | ||
| 190 | |||
| 191 | if (size <= PAGE_SIZE) | ||
| 192 | kfree(p); | ||
| 193 | else | ||
| 194 | vfree(p); | ||
| 195 | |||
| 196 | return new; | ||
| 197 | } | ||
| 198 | |||
| 199 | /** | ||
| 200 | * pcpu_chunk_relocate - put chunk in the appropriate chunk slot | ||
| 201 | * @chunk: chunk of interest | ||
| 202 | * @oslot: the previous slot it was on | ||
| 203 | * | ||
| 204 | * This function is called after an allocation or free changed @chunk. | ||
| 205 | * New slot according to the changed state is determined and @chunk is | ||
| 206 | * moved to the slot. | ||
| 207 | */ | ||
| 208 | static void pcpu_chunk_relocate(struct pcpu_chunk *chunk, int oslot) | ||
| 209 | { | ||
| 210 | int nslot = pcpu_chunk_slot(chunk); | ||
| 211 | |||
| 212 | if (oslot != nslot) { | ||
| 213 | if (oslot < nslot) | ||
| 214 | list_move(&chunk->list, &pcpu_slot[nslot]); | ||
| 215 | else | ||
| 216 | list_move_tail(&chunk->list, &pcpu_slot[nslot]); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | static struct rb_node **pcpu_chunk_rb_search(void *addr, | ||
| 221 | struct rb_node **parentp) | ||
| 222 | { | ||
| 223 | struct rb_node **p = &pcpu_addr_root.rb_node; | ||
| 224 | struct rb_node *parent = NULL; | ||
| 225 | struct pcpu_chunk *chunk; | ||
| 226 | |||
| 227 | while (*p) { | ||
| 228 | parent = *p; | ||
| 229 | chunk = rb_entry(parent, struct pcpu_chunk, rb_node); | ||
| 230 | |||
| 231 | if (addr < chunk->vm->addr) | ||
| 232 | p = &(*p)->rb_left; | ||
| 233 | else if (addr > chunk->vm->addr) | ||
| 234 | p = &(*p)->rb_right; | ||
| 235 | else | ||
| 236 | break; | ||
| 237 | } | ||
| 238 | |||
| 239 | if (parentp) | ||
| 240 | *parentp = parent; | ||
| 241 | return p; | ||
| 242 | } | ||
| 243 | |||
| 244 | /** | ||
| 245 | * pcpu_chunk_addr_search - search for chunk containing specified address | ||
| 246 | * @addr: address to search for | ||
| 247 | * | ||
| 248 | * Look for chunk which might contain @addr. More specifically, it | ||
| 249 | * searchs for the chunk with the highest start address which isn't | ||
| 250 | * beyond @addr. | ||
| 251 | * | ||
| 252 | * RETURNS: | ||
| 253 | * The address of the found chunk. | ||
| 254 | */ | ||
| 255 | static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr) | ||
| 256 | { | ||
| 257 | struct rb_node *n, *parent; | ||
| 258 | struct pcpu_chunk *chunk; | ||
| 259 | |||
| 260 | n = *pcpu_chunk_rb_search(addr, &parent); | ||
| 261 | if (!n) { | ||
| 262 | /* no exactly matching chunk, the parent is the closest */ | ||
| 263 | n = parent; | ||
| 264 | BUG_ON(!n); | ||
| 265 | } | ||
| 266 | chunk = rb_entry(n, struct pcpu_chunk, rb_node); | ||
| 267 | |||
| 268 | if (addr < chunk->vm->addr) { | ||
| 269 | /* the parent was the next one, look for the previous one */ | ||
| 270 | n = rb_prev(n); | ||
| 271 | BUG_ON(!n); | ||
| 272 | chunk = rb_entry(n, struct pcpu_chunk, rb_node); | ||
| 273 | } | ||
| 274 | |||
| 275 | return chunk; | ||
| 276 | } | ||
| 277 | |||
| 278 | /** | ||
| 279 | * pcpu_chunk_addr_insert - insert chunk into address rb tree | ||
| 280 | * @new: chunk to insert | ||
| 281 | * | ||
| 282 | * Insert @new into address rb tree. | ||
| 283 | */ | ||
| 284 | static void pcpu_chunk_addr_insert(struct pcpu_chunk *new) | ||
| 285 | { | ||
| 286 | struct rb_node **p, *parent; | ||
| 287 | |||
| 288 | p = pcpu_chunk_rb_search(new->vm->addr, &parent); | ||
| 289 | BUG_ON(*p); | ||
| 290 | rb_link_node(&new->rb_node, parent, p); | ||
| 291 | rb_insert_color(&new->rb_node, &pcpu_addr_root); | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * pcpu_split_block - split a map block | ||
| 296 | * @chunk: chunk of interest | ||
| 297 | * @i: index of map block to split | ||
| 298 | * @head: head size in bytes (can be 0) | ||
| 299 | * @tail: tail size in bytes (can be 0) | ||
| 300 | * | ||
| 301 | * Split the @i'th map block into two or three blocks. If @head is | ||
| 302 | * non-zero, @head bytes block is inserted before block @i moving it | ||
| 303 | * to @i+1 and reducing its size by @head bytes. | ||
| 304 | * | ||
| 305 | * If @tail is non-zero, the target block, which can be @i or @i+1 | ||
| 306 | * depending on @head, is reduced by @tail bytes and @tail byte block | ||
| 307 | * is inserted after the target block. | ||
| 308 | * | ||
| 309 | * RETURNS: | ||
| 310 | * 0 on success, -errno on failure. | ||
| 311 | */ | ||
| 312 | static int pcpu_split_block(struct pcpu_chunk *chunk, int i, int head, int tail) | ||
| 313 | { | ||
| 314 | int nr_extra = !!head + !!tail; | ||
| 315 | int target = chunk->map_used + nr_extra; | ||
| 316 | |||
| 317 | /* reallocation required? */ | ||
| 318 | if (chunk->map_alloc < target) { | ||
| 319 | int new_alloc = chunk->map_alloc; | ||
| 320 | int *new; | ||
| 321 | |||
| 322 | while (new_alloc < target) | ||
| 323 | new_alloc *= 2; | ||
| 324 | |||
| 325 | new = pcpu_realloc(chunk->map, | ||
| 326 | chunk->map_alloc * sizeof(new[0]), | ||
| 327 | new_alloc * sizeof(new[0])); | ||
| 328 | if (!new) | ||
| 329 | return -ENOMEM; | ||
| 330 | |||
| 331 | chunk->map_alloc = new_alloc; | ||
| 332 | chunk->map = new; | ||
| 333 | } | ||
| 334 | |||
| 335 | /* insert a new subblock */ | ||
| 336 | memmove(&chunk->map[i + nr_extra], &chunk->map[i], | ||
| 337 | sizeof(chunk->map[0]) * (chunk->map_used - i)); | ||
| 338 | chunk->map_used += nr_extra; | ||
| 339 | |||
| 340 | if (head) { | ||
| 341 | chunk->map[i + 1] = chunk->map[i] - head; | ||
| 342 | chunk->map[i++] = head; | ||
| 343 | } | ||
| 344 | if (tail) { | ||
| 345 | chunk->map[i++] -= tail; | ||
| 346 | chunk->map[i] = tail; | ||
| 347 | } | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | /** | ||
| 352 | * pcpu_alloc_area - allocate area from a pcpu_chunk | ||
| 353 | * @chunk: chunk of interest | ||
| 354 | * @size: wanted size in bytes | ||
| 355 | * @align: wanted align | ||
| 356 | * | ||
| 357 | * Try to allocate @size bytes area aligned at @align from @chunk. | ||
| 358 | * Note that this function only allocates the offset. It doesn't | ||
| 359 | * populate or map the area. | ||
| 360 | * | ||
| 361 | * RETURNS: | ||
| 362 | * Allocated offset in @chunk on success, -errno on failure. | ||
| 363 | */ | ||
| 364 | static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align) | ||
| 365 | { | ||
| 366 | int oslot = pcpu_chunk_slot(chunk); | ||
| 367 | int max_contig = 0; | ||
| 368 | int i, off; | ||
| 369 | |||
| 370 | /* | ||
| 371 | * The static chunk initially doesn't have map attached | ||
| 372 | * because kmalloc wasn't available during init. Give it one. | ||
| 373 | */ | ||
| 374 | if (unlikely(!chunk->map)) { | ||
| 375 | chunk->map = pcpu_realloc(NULL, 0, | ||
| 376 | PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); | ||
| 377 | if (!chunk->map) | ||
| 378 | return -ENOMEM; | ||
| 379 | |||
| 380 | chunk->map_alloc = PCPU_DFL_MAP_ALLOC; | ||
| 381 | chunk->map[chunk->map_used++] = -pcpu_static_size; | ||
| 382 | if (chunk->free_size) | ||
| 383 | chunk->map[chunk->map_used++] = chunk->free_size; | ||
| 384 | } | ||
| 385 | |||
| 386 | for (i = 0, off = 0; i < chunk->map_used; off += abs(chunk->map[i++])) { | ||
| 387 | bool is_last = i + 1 == chunk->map_used; | ||
| 388 | int head, tail; | ||
| 389 | |||
| 390 | /* extra for alignment requirement */ | ||
| 391 | head = ALIGN(off, align) - off; | ||
| 392 | BUG_ON(i == 0 && head != 0); | ||
| 393 | |||
| 394 | if (chunk->map[i] < 0) | ||
| 395 | continue; | ||
| 396 | if (chunk->map[i] < head + size) { | ||
| 397 | max_contig = max(chunk->map[i], max_contig); | ||
| 398 | continue; | ||
| 399 | } | ||
| 400 | |||
| 401 | /* | ||
| 402 | * If head is small or the previous block is free, | ||
| 403 | * merge'em. Note that 'small' is defined as smaller | ||
| 404 | * than sizeof(int), which is very small but isn't too | ||
| 405 | * uncommon for percpu allocations. | ||
| 406 | */ | ||
| 407 | if (head && (head < sizeof(int) || chunk->map[i - 1] > 0)) { | ||
| 408 | if (chunk->map[i - 1] > 0) | ||
| 409 | chunk->map[i - 1] += head; | ||
| 410 | else { | ||
| 411 | chunk->map[i - 1] -= head; | ||
| 412 | chunk->free_size -= head; | ||
| 413 | } | ||
| 414 | chunk->map[i] -= head; | ||
| 415 | off += head; | ||
| 416 | head = 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | /* if tail is small, just keep it around */ | ||
| 420 | tail = chunk->map[i] - head - size; | ||
| 421 | if (tail < sizeof(int)) | ||
| 422 | tail = 0; | ||
| 423 | |||
| 424 | /* split if warranted */ | ||
| 425 | if (head || tail) { | ||
| 426 | if (pcpu_split_block(chunk, i, head, tail)) | ||
| 427 | return -ENOMEM; | ||
| 428 | if (head) { | ||
| 429 | i++; | ||
| 430 | off += head; | ||
| 431 | max_contig = max(chunk->map[i - 1], max_contig); | ||
| 432 | } | ||
| 433 | if (tail) | ||
| 434 | max_contig = max(chunk->map[i + 1], max_contig); | ||
| 435 | } | ||
| 436 | |||
| 437 | /* update hint and mark allocated */ | ||
| 438 | if (is_last) | ||
| 439 | chunk->contig_hint = max_contig; /* fully scanned */ | ||
| 440 | else | ||
| 441 | chunk->contig_hint = max(chunk->contig_hint, | ||
| 442 | max_contig); | ||
| 443 | |||
| 444 | chunk->free_size -= chunk->map[i]; | ||
| 445 | chunk->map[i] = -chunk->map[i]; | ||
| 446 | |||
| 447 | pcpu_chunk_relocate(chunk, oslot); | ||
| 448 | return off; | ||
| 449 | } | ||
| 450 | |||
| 451 | chunk->contig_hint = max_contig; /* fully scanned */ | ||
| 452 | pcpu_chunk_relocate(chunk, oslot); | ||
| 453 | |||
| 454 | /* | ||
| 455 | * Tell the upper layer that this chunk has no area left. | ||
| 456 | * Note that this is not an error condition but a notification | ||
| 457 | * to upper layer that it needs to look at other chunks. | ||
| 458 | * -ENOSPC is chosen as it isn't used in memory subsystem and | ||
| 459 | * matches the meaning in a way. | ||
| 460 | */ | ||
| 461 | return -ENOSPC; | ||
| 462 | } | ||
| 463 | |||
| 464 | /** | ||
| 465 | * pcpu_free_area - free area to a pcpu_chunk | ||
| 466 | * @chunk: chunk of interest | ||
| 467 | * @freeme: offset of area to free | ||
| 468 | * | ||
| 469 | * Free area starting from @freeme to @chunk. Note that this function | ||
| 470 | * only modifies the allocation map. It doesn't depopulate or unmap | ||
| 471 | * the area. | ||
| 472 | */ | ||
| 473 | static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) | ||
| 474 | { | ||
| 475 | int oslot = pcpu_chunk_slot(chunk); | ||
| 476 | int i, off; | ||
| 477 | |||
| 478 | for (i = 0, off = 0; i < chunk->map_used; off += abs(chunk->map[i++])) | ||
| 479 | if (off == freeme) | ||
| 480 | break; | ||
| 481 | BUG_ON(off != freeme); | ||
| 482 | BUG_ON(chunk->map[i] > 0); | ||
| 483 | |||
| 484 | chunk->map[i] = -chunk->map[i]; | ||
| 485 | chunk->free_size += chunk->map[i]; | ||
| 486 | |||
| 487 | /* merge with previous? */ | ||
| 488 | if (i > 0 && chunk->map[i - 1] >= 0) { | ||
| 489 | chunk->map[i - 1] += chunk->map[i]; | ||
| 490 | chunk->map_used--; | ||
| 491 | memmove(&chunk->map[i], &chunk->map[i + 1], | ||
| 492 | (chunk->map_used - i) * sizeof(chunk->map[0])); | ||
| 493 | i--; | ||
| 494 | } | ||
| 495 | /* merge with next? */ | ||
| 496 | if (i + 1 < chunk->map_used && chunk->map[i + 1] >= 0) { | ||
| 497 | chunk->map[i] += chunk->map[i + 1]; | ||
| 498 | chunk->map_used--; | ||
| 499 | memmove(&chunk->map[i + 1], &chunk->map[i + 2], | ||
| 500 | (chunk->map_used - (i + 1)) * sizeof(chunk->map[0])); | ||
| 501 | } | ||
| 502 | |||
| 503 | chunk->contig_hint = max(chunk->map[i], chunk->contig_hint); | ||
| 504 | pcpu_chunk_relocate(chunk, oslot); | ||
| 505 | } | ||
| 506 | |||
| 507 | /** | ||
| 508 | * pcpu_unmap - unmap pages out of a pcpu_chunk | ||
| 509 | * @chunk: chunk of interest | ||
| 510 | * @page_start: page index of the first page to unmap | ||
| 511 | * @page_end: page index of the last page to unmap + 1 | ||
| 512 | * @flush: whether to flush cache and tlb or not | ||
| 513 | * | ||
| 514 | * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. | ||
| 515 | * If @flush is true, vcache is flushed before unmapping and tlb | ||
| 516 | * after. | ||
| 517 | */ | ||
| 518 | static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | ||
| 519 | bool flush) | ||
| 520 | { | ||
| 521 | unsigned int last = num_possible_cpus() - 1; | ||
| 522 | unsigned int cpu; | ||
| 523 | |||
| 524 | /* unmap must not be done on immutable chunk */ | ||
| 525 | WARN_ON(chunk->immutable); | ||
| 526 | |||
| 527 | /* | ||
| 528 | * Each flushing trial can be very expensive, issue flush on | ||
| 529 | * the whole region at once rather than doing it for each cpu. | ||
| 530 | * This could be an overkill but is more scalable. | ||
| 531 | */ | ||
| 532 | if (flush) | ||
| 533 | flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), | ||
| 534 | pcpu_chunk_addr(chunk, last, page_end)); | ||
| 535 | |||
| 536 | for_each_possible_cpu(cpu) | ||
| 537 | unmap_kernel_range_noflush( | ||
| 538 | pcpu_chunk_addr(chunk, cpu, page_start), | ||
| 539 | (page_end - page_start) << PAGE_SHIFT); | ||
| 540 | |||
| 541 | /* ditto as flush_cache_vunmap() */ | ||
| 542 | if (flush) | ||
| 543 | flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), | ||
| 544 | pcpu_chunk_addr(chunk, last, page_end)); | ||
| 545 | } | ||
| 546 | |||
| 547 | /** | ||
| 548 | * pcpu_depopulate_chunk - depopulate and unmap an area of a pcpu_chunk | ||
| 549 | * @chunk: chunk to depopulate | ||
| 550 | * @off: offset to the area to depopulate | ||
| 551 | * @size: size of the area to depopulate in bytes | ||
| 552 | * @flush: whether to flush cache and tlb or not | ||
| 553 | * | ||
| 554 | * For each cpu, depopulate and unmap pages [@page_start,@page_end) | ||
| 555 | * from @chunk. If @flush is true, vcache is flushed before unmapping | ||
| 556 | * and tlb after. | ||
| 557 | */ | ||
| 558 | static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size, | ||
| 559 | bool flush) | ||
| 560 | { | ||
| 561 | int page_start = PFN_DOWN(off); | ||
| 562 | int page_end = PFN_UP(off + size); | ||
| 563 | int unmap_start = -1; | ||
| 564 | int uninitialized_var(unmap_end); | ||
| 565 | unsigned int cpu; | ||
| 566 | int i; | ||
| 567 | |||
| 568 | for (i = page_start; i < page_end; i++) { | ||
| 569 | for_each_possible_cpu(cpu) { | ||
| 570 | struct page **pagep = pcpu_chunk_pagep(chunk, cpu, i); | ||
| 571 | |||
| 572 | if (!*pagep) | ||
| 573 | continue; | ||
| 574 | |||
| 575 | __free_page(*pagep); | ||
| 576 | |||
| 577 | /* | ||
| 578 | * If it's partial depopulation, it might get | ||
| 579 | * populated or depopulated again. Mark the | ||
| 580 | * page gone. | ||
| 581 | */ | ||
| 582 | *pagep = NULL; | ||
| 583 | |||
| 584 | unmap_start = unmap_start < 0 ? i : unmap_start; | ||
| 585 | unmap_end = i + 1; | ||
| 586 | } | ||
| 587 | } | ||
| 588 | |||
| 589 | if (unmap_start >= 0) | ||
| 590 | pcpu_unmap(chunk, unmap_start, unmap_end, flush); | ||
| 591 | } | ||
| 592 | |||
| 593 | /** | ||
| 594 | * pcpu_map - map pages into a pcpu_chunk | ||
| 595 | * @chunk: chunk of interest | ||
| 596 | * @page_start: page index of the first page to map | ||
| 597 | * @page_end: page index of the last page to map + 1 | ||
| 598 | * | ||
| 599 | * For each cpu, map pages [@page_start,@page_end) into @chunk. | ||
| 600 | * vcache is flushed afterwards. | ||
| 601 | */ | ||
| 602 | static int pcpu_map(struct pcpu_chunk *chunk, int page_start, int page_end) | ||
| 603 | { | ||
| 604 | unsigned int last = num_possible_cpus() - 1; | ||
| 605 | unsigned int cpu; | ||
| 606 | int err; | ||
| 607 | |||
| 608 | /* map must not be done on immutable chunk */ | ||
| 609 | WARN_ON(chunk->immutable); | ||
| 610 | |||
| 611 | for_each_possible_cpu(cpu) { | ||
| 612 | err = map_kernel_range_noflush( | ||
| 613 | pcpu_chunk_addr(chunk, cpu, page_start), | ||
| 614 | (page_end - page_start) << PAGE_SHIFT, | ||
| 615 | PAGE_KERNEL, | ||
| 616 | pcpu_chunk_pagep(chunk, cpu, page_start)); | ||
| 617 | if (err < 0) | ||
| 618 | return err; | ||
| 619 | } | ||
| 620 | |||
| 621 | /* flush at once, please read comments in pcpu_unmap() */ | ||
| 622 | flush_cache_vmap(pcpu_chunk_addr(chunk, 0, page_start), | ||
| 623 | pcpu_chunk_addr(chunk, last, page_end)); | ||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | |||
| 627 | /** | ||
| 628 | * pcpu_populate_chunk - populate and map an area of a pcpu_chunk | ||
| 629 | * @chunk: chunk of interest | ||
| 630 | * @off: offset to the area to populate | ||
| 631 | * @size: size of the area to populate in bytes | ||
| 632 | * | ||
| 633 | * For each cpu, populate and map pages [@page_start,@page_end) into | ||
| 634 | * @chunk. The area is cleared on return. | ||
| 635 | */ | ||
| 636 | static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) | ||
| 637 | { | ||
| 638 | const gfp_t alloc_mask = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; | ||
| 639 | int page_start = PFN_DOWN(off); | ||
| 640 | int page_end = PFN_UP(off + size); | ||
| 641 | int map_start = -1; | ||
| 642 | int uninitialized_var(map_end); | ||
| 643 | unsigned int cpu; | ||
| 644 | int i; | ||
| 645 | |||
| 646 | for (i = page_start; i < page_end; i++) { | ||
| 647 | if (pcpu_chunk_page_occupied(chunk, i)) { | ||
| 648 | if (map_start >= 0) { | ||
| 649 | if (pcpu_map(chunk, map_start, map_end)) | ||
| 650 | goto err; | ||
| 651 | map_start = -1; | ||
| 652 | } | ||
| 653 | continue; | ||
| 654 | } | ||
| 655 | |||
| 656 | map_start = map_start < 0 ? i : map_start; | ||
| 657 | map_end = i + 1; | ||
| 658 | |||
| 659 | for_each_possible_cpu(cpu) { | ||
| 660 | struct page **pagep = pcpu_chunk_pagep(chunk, cpu, i); | ||
| 661 | |||
| 662 | *pagep = alloc_pages_node(cpu_to_node(cpu), | ||
| 663 | alloc_mask, 0); | ||
| 664 | if (!*pagep) | ||
| 665 | goto err; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | |||
| 669 | if (map_start >= 0 && pcpu_map(chunk, map_start, map_end)) | ||
| 670 | goto err; | ||
| 671 | |||
| 672 | for_each_possible_cpu(cpu) | ||
| 673 | memset(chunk->vm->addr + cpu * pcpu_unit_size + off, 0, | ||
| 674 | size); | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | err: | ||
| 678 | /* likely under heavy memory pressure, give memory back */ | ||
| 679 | pcpu_depopulate_chunk(chunk, off, size, true); | ||
| 680 | return -ENOMEM; | ||
| 681 | } | ||
| 682 | |||
| 683 | static void free_pcpu_chunk(struct pcpu_chunk *chunk) | ||
| 684 | { | ||
| 685 | if (!chunk) | ||
| 686 | return; | ||
| 687 | if (chunk->vm) | ||
| 688 | free_vm_area(chunk->vm); | ||
| 689 | pcpu_realloc(chunk->map, chunk->map_alloc * sizeof(chunk->map[0]), 0); | ||
| 690 | kfree(chunk); | ||
| 691 | } | ||
| 692 | |||
| 693 | static struct pcpu_chunk *alloc_pcpu_chunk(void) | ||
| 694 | { | ||
| 695 | struct pcpu_chunk *chunk; | ||
| 696 | |||
| 697 | chunk = kzalloc(pcpu_chunk_struct_size, GFP_KERNEL); | ||
| 698 | if (!chunk) | ||
| 699 | return NULL; | ||
| 700 | |||
| 701 | chunk->map = pcpu_realloc(NULL, 0, | ||
| 702 | PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0])); | ||
| 703 | chunk->map_alloc = PCPU_DFL_MAP_ALLOC; | ||
| 704 | chunk->map[chunk->map_used++] = pcpu_unit_size; | ||
| 705 | |||
| 706 | chunk->vm = get_vm_area(pcpu_chunk_size, GFP_KERNEL); | ||
| 707 | if (!chunk->vm) { | ||
| 708 | free_pcpu_chunk(chunk); | ||
| 709 | return NULL; | ||
| 710 | } | ||
| 711 | |||
| 712 | INIT_LIST_HEAD(&chunk->list); | ||
| 713 | chunk->free_size = pcpu_unit_size; | ||
| 714 | chunk->contig_hint = pcpu_unit_size; | ||
| 715 | |||
| 716 | return chunk; | ||
| 717 | } | ||
| 718 | |||
| 719 | /** | ||
| 720 | * __alloc_percpu - allocate percpu area | ||
| 721 | * @size: size of area to allocate in bytes | ||
| 722 | * @align: alignment of area (max PAGE_SIZE) | ||
| 723 | * | ||
| 724 | * Allocate percpu area of @size bytes aligned at @align. Might | ||
| 725 | * sleep. Might trigger writeouts. | ||
| 726 | * | ||
| 727 | * RETURNS: | ||
| 728 | * Percpu pointer to the allocated area on success, NULL on failure. | ||
| 729 | */ | ||
| 730 | void *__alloc_percpu(size_t size, size_t align) | ||
| 731 | { | ||
| 732 | void *ptr = NULL; | ||
| 733 | struct pcpu_chunk *chunk; | ||
| 734 | int slot, off; | ||
| 735 | |||
| 736 | if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) { | ||
| 737 | WARN(true, "illegal size (%zu) or align (%zu) for " | ||
| 738 | "percpu allocation\n", size, align); | ||
| 739 | return NULL; | ||
| 740 | } | ||
| 741 | |||
| 742 | mutex_lock(&pcpu_mutex); | ||
| 743 | |||
| 744 | /* allocate area */ | ||
| 745 | for (slot = pcpu_size_to_slot(size); slot < pcpu_nr_slots; slot++) { | ||
| 746 | list_for_each_entry(chunk, &pcpu_slot[slot], list) { | ||
| 747 | if (size > chunk->contig_hint) | ||
| 748 | continue; | ||
| 749 | off = pcpu_alloc_area(chunk, size, align); | ||
| 750 | if (off >= 0) | ||
| 751 | goto area_found; | ||
| 752 | if (off != -ENOSPC) | ||
| 753 | goto out_unlock; | ||
| 754 | } | ||
| 755 | } | ||
| 756 | |||
| 757 | /* hmmm... no space left, create a new chunk */ | ||
| 758 | chunk = alloc_pcpu_chunk(); | ||
| 759 | if (!chunk) | ||
| 760 | goto out_unlock; | ||
| 761 | pcpu_chunk_relocate(chunk, -1); | ||
| 762 | pcpu_chunk_addr_insert(chunk); | ||
| 763 | |||
| 764 | off = pcpu_alloc_area(chunk, size, align); | ||
| 765 | if (off < 0) | ||
| 766 | goto out_unlock; | ||
| 767 | |||
| 768 | area_found: | ||
| 769 | /* populate, map and clear the area */ | ||
| 770 | if (pcpu_populate_chunk(chunk, off, size)) { | ||
| 771 | pcpu_free_area(chunk, off); | ||
| 772 | goto out_unlock; | ||
| 773 | } | ||
| 774 | |||
| 775 | ptr = __addr_to_pcpu_ptr(chunk->vm->addr + off); | ||
| 776 | out_unlock: | ||
| 777 | mutex_unlock(&pcpu_mutex); | ||
| 778 | return ptr; | ||
| 779 | } | ||
| 780 | EXPORT_SYMBOL_GPL(__alloc_percpu); | ||
| 781 | |||
| 782 | static void pcpu_kill_chunk(struct pcpu_chunk *chunk) | ||
| 783 | { | ||
| 784 | WARN_ON(chunk->immutable); | ||
| 785 | pcpu_depopulate_chunk(chunk, 0, pcpu_unit_size, false); | ||
| 786 | list_del(&chunk->list); | ||
| 787 | rb_erase(&chunk->rb_node, &pcpu_addr_root); | ||
| 788 | free_pcpu_chunk(chunk); | ||
| 789 | } | ||
| 790 | |||
| 791 | /** | ||
| 792 | * free_percpu - free percpu area | ||
| 793 | * @ptr: pointer to area to free | ||
| 794 | * | ||
| 795 | * Free percpu area @ptr. Might sleep. | ||
| 796 | */ | ||
| 797 | void free_percpu(void *ptr) | ||
| 798 | { | ||
| 799 | void *addr = __pcpu_ptr_to_addr(ptr); | ||
| 800 | struct pcpu_chunk *chunk; | ||
| 801 | int off; | ||
| 802 | |||
| 803 | if (!ptr) | ||
| 804 | return; | ||
| 805 | |||
| 806 | mutex_lock(&pcpu_mutex); | ||
| 807 | |||
| 808 | chunk = pcpu_chunk_addr_search(addr); | ||
| 809 | off = addr - chunk->vm->addr; | ||
| 810 | |||
| 811 | pcpu_free_area(chunk, off); | ||
| 812 | |||
| 813 | /* the chunk became fully free, kill one if there are other free ones */ | ||
| 814 | if (chunk->free_size == pcpu_unit_size) { | ||
| 815 | struct pcpu_chunk *pos; | ||
| 816 | |||
| 817 | list_for_each_entry(pos, | ||
| 818 | &pcpu_slot[pcpu_chunk_slot(chunk)], list) | ||
| 819 | if (pos != chunk) { | ||
| 820 | pcpu_kill_chunk(pos); | ||
| 821 | break; | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 825 | mutex_unlock(&pcpu_mutex); | ||
| 826 | } | ||
| 827 | EXPORT_SYMBOL_GPL(free_percpu); | ||
| 828 | |||
| 829 | /** | ||
| 830 | * pcpu_setup_first_chunk - initialize the first percpu chunk | ||
| 831 | * @get_page_fn: callback to fetch page pointer | ||
| 832 | * @static_size: the size of static percpu area in bytes | ||
| 833 | * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, 0 for auto | ||
| 834 | * @free_size: free size in bytes, 0 for auto | ||
| 835 | * @base_addr: mapped address, NULL for auto | ||
| 836 | * @populate_pte_fn: callback to allocate pagetable, NULL if unnecessary | ||
| 837 | * | ||
| 838 | * Initialize the first percpu chunk which contains the kernel static | ||
| 839 | * perpcu area. This function is to be called from arch percpu area | ||
| 840 | * setup path. The first two parameters are mandatory. The rest are | ||
| 841 | * optional. | ||
| 842 | * | ||
| 843 | * @get_page_fn() should return pointer to percpu page given cpu | ||
| 844 | * number and page number. It should at least return enough pages to | ||
| 845 | * cover the static area. The returned pages for static area should | ||
| 846 | * have been initialized with valid data. If @unit_size is specified, | ||
| 847 | * it can also return pages after the static area. NULL return | ||
| 848 | * indicates end of pages for the cpu. Note that @get_page_fn() must | ||
| 849 | * return the same number of pages for all cpus. | ||
| 850 | * | ||
| 851 | * @unit_size, if non-zero, determines unit size and must be aligned | ||
| 852 | * to PAGE_SIZE and equal to or larger than @static_size + @free_size. | ||
| 853 | * | ||
| 854 | * @free_size determines the number of free bytes after the static | ||
| 855 | * area in the first chunk. If zero, whatever left is available. | ||
| 856 | * Specifying non-zero value make percpu leave the area after | ||
| 857 | * @static_size + @free_size alone. | ||
| 858 | * | ||
| 859 | * Non-null @base_addr means that the caller already allocated virtual | ||
| 860 | * region for the first chunk and mapped it. percpu must not mess | ||
| 861 | * with the chunk. Note that @base_addr with 0 @unit_size or non-NULL | ||
| 862 | * @populate_pte_fn doesn't make any sense. | ||
| 863 | * | ||
| 864 | * @populate_pte_fn is used to populate the pagetable. NULL means the | ||
| 865 | * caller already populated the pagetable. | ||
| 866 | * | ||
| 867 | * RETURNS: | ||
| 868 | * The determined pcpu_unit_size which can be used to initialize | ||
| 869 | * percpu access. | ||
| 870 | */ | ||
| 871 | size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | ||
| 872 | size_t static_size, size_t unit_size, | ||
| 873 | size_t free_size, void *base_addr, | ||
| 874 | pcpu_populate_pte_fn_t populate_pte_fn) | ||
| 875 | { | ||
| 876 | static struct vm_struct static_vm; | ||
| 877 | struct pcpu_chunk *static_chunk; | ||
| 878 | unsigned int cpu; | ||
| 879 | int nr_pages; | ||
| 880 | int err, i; | ||
| 881 | |||
| 882 | /* santiy checks */ | ||
| 883 | BUG_ON(!static_size); | ||
| 884 | BUG_ON(!unit_size && free_size); | ||
| 885 | BUG_ON(unit_size && unit_size < static_size + free_size); | ||
| 886 | BUG_ON(unit_size & ~PAGE_MASK); | ||
| 887 | BUG_ON(base_addr && !unit_size); | ||
| 888 | BUG_ON(base_addr && populate_pte_fn); | ||
| 889 | |||
| 890 | if (unit_size) | ||
| 891 | pcpu_unit_pages = unit_size >> PAGE_SHIFT; | ||
| 892 | else | ||
| 893 | pcpu_unit_pages = max_t(int, PCPU_MIN_UNIT_SIZE >> PAGE_SHIFT, | ||
| 894 | PFN_UP(static_size)); | ||
| 895 | |||
| 896 | pcpu_static_size = static_size; | ||
| 897 | pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT; | ||
| 898 | pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size; | ||
| 899 | pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) | ||
| 900 | + num_possible_cpus() * pcpu_unit_pages * sizeof(struct page *); | ||
| 901 | |||
| 902 | /* | ||
| 903 | * Allocate chunk slots. The additional last slot is for | ||
| 904 | * empty chunks. | ||
| 905 | */ | ||
| 906 | pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2; | ||
| 907 | pcpu_slot = alloc_bootmem(pcpu_nr_slots * sizeof(pcpu_slot[0])); | ||
| 908 | for (i = 0; i < pcpu_nr_slots; i++) | ||
| 909 | INIT_LIST_HEAD(&pcpu_slot[i]); | ||
| 910 | |||
| 911 | /* init static_chunk */ | ||
| 912 | static_chunk = alloc_bootmem(pcpu_chunk_struct_size); | ||
| 913 | INIT_LIST_HEAD(&static_chunk->list); | ||
| 914 | static_chunk->vm = &static_vm; | ||
| 915 | |||
| 916 | if (free_size) | ||
| 917 | static_chunk->free_size = free_size; | ||
| 918 | else | ||
| 919 | static_chunk->free_size = pcpu_unit_size - pcpu_static_size; | ||
| 920 | |||
| 921 | static_chunk->contig_hint = static_chunk->free_size; | ||
| 922 | |||
| 923 | /* allocate vm address */ | ||
| 924 | static_vm.flags = VM_ALLOC; | ||
| 925 | static_vm.size = pcpu_chunk_size; | ||
| 926 | |||
| 927 | if (!base_addr) | ||
| 928 | vm_area_register_early(&static_vm, PAGE_SIZE); | ||
| 929 | else { | ||
| 930 | /* | ||
| 931 | * Pages already mapped. No need to remap into | ||
| 932 | * vmalloc area. In this case the static chunk can't | ||
| 933 | * be mapped or unmapped by percpu and is marked | ||
| 934 | * immutable. | ||
| 935 | */ | ||
| 936 | static_vm.addr = base_addr; | ||
| 937 | static_chunk->immutable = true; | ||
| 938 | } | ||
| 939 | |||
| 940 | /* assign pages */ | ||
| 941 | nr_pages = -1; | ||
| 942 | for_each_possible_cpu(cpu) { | ||
| 943 | for (i = 0; i < pcpu_unit_pages; i++) { | ||
| 944 | struct page *page = get_page_fn(cpu, i); | ||
| 945 | |||
| 946 | if (!page) | ||
| 947 | break; | ||
| 948 | *pcpu_chunk_pagep(static_chunk, cpu, i) = page; | ||
| 949 | } | ||
| 950 | |||
| 951 | BUG_ON(i < PFN_UP(pcpu_static_size)); | ||
| 952 | |||
| 953 | if (nr_pages < 0) | ||
| 954 | nr_pages = i; | ||
| 955 | else | ||
| 956 | BUG_ON(nr_pages != i); | ||
| 957 | } | ||
| 958 | |||
| 959 | /* map them */ | ||
| 960 | if (populate_pte_fn) { | ||
| 961 | for_each_possible_cpu(cpu) | ||
| 962 | for (i = 0; i < nr_pages; i++) | ||
| 963 | populate_pte_fn(pcpu_chunk_addr(static_chunk, | ||
| 964 | cpu, i)); | ||
| 965 | |||
| 966 | err = pcpu_map(static_chunk, 0, nr_pages); | ||
| 967 | if (err) | ||
| 968 | panic("failed to setup static percpu area, err=%d\n", | ||
| 969 | err); | ||
| 970 | } | ||
| 971 | |||
| 972 | /* link static_chunk in */ | ||
| 973 | pcpu_chunk_relocate(static_chunk, -1); | ||
| 974 | pcpu_chunk_addr_insert(static_chunk); | ||
| 975 | |||
| 976 | /* we're done */ | ||
| 977 | pcpu_base_addr = (void *)pcpu_chunk_addr(static_chunk, 0, 0); | ||
| 978 | return pcpu_unit_size; | ||
| 979 | } | ||
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 11a929872ebd..af58324c361a 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/radix-tree.h> | 24 | #include <linux/radix-tree.h> |
| 25 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
| 26 | #include <linux/bootmem.h> | 26 | #include <linux/bootmem.h> |
| 27 | #include <linux/pfn.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
| 29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
| @@ -152,8 +153,8 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr, | |||
| 152 | * | 153 | * |
| 153 | * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N] | 154 | * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N] |
| 154 | */ | 155 | */ |
| 155 | static int vmap_page_range(unsigned long start, unsigned long end, | 156 | static int vmap_page_range_noflush(unsigned long start, unsigned long end, |
| 156 | pgprot_t prot, struct page **pages) | 157 | pgprot_t prot, struct page **pages) |
| 157 | { | 158 | { |
| 158 | pgd_t *pgd; | 159 | pgd_t *pgd; |
| 159 | unsigned long next; | 160 | unsigned long next; |
| @@ -169,13 +170,22 @@ static int vmap_page_range(unsigned long start, unsigned long end, | |||
| 169 | if (err) | 170 | if (err) |
| 170 | break; | 171 | break; |
| 171 | } while (pgd++, addr = next, addr != end); | 172 | } while (pgd++, addr = next, addr != end); |
| 172 | flush_cache_vmap(start, end); | ||
| 173 | 173 | ||
| 174 | if (unlikely(err)) | 174 | if (unlikely(err)) |
| 175 | return err; | 175 | return err; |
| 176 | return nr; | 176 | return nr; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static int vmap_page_range(unsigned long start, unsigned long end, | ||
| 180 | pgprot_t prot, struct page **pages) | ||
| 181 | { | ||
| 182 | int ret; | ||
| 183 | |||
| 184 | ret = vmap_page_range_noflush(start, end, prot, pages); | ||
| 185 | flush_cache_vmap(start, end); | ||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 179 | static inline int is_vmalloc_or_module_addr(const void *x) | 189 | static inline int is_vmalloc_or_module_addr(const void *x) |
| 180 | { | 190 | { |
| 181 | /* | 191 | /* |
| @@ -990,6 +1000,32 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro | |||
| 990 | } | 1000 | } |
| 991 | EXPORT_SYMBOL(vm_map_ram); | 1001 | EXPORT_SYMBOL(vm_map_ram); |
| 992 | 1002 | ||
| 1003 | /** | ||
| 1004 | * vm_area_register_early - register vmap area early during boot | ||
| 1005 | * @vm: vm_struct to register | ||
| 1006 | * @align: requested alignment | ||
| 1007 | * | ||
| 1008 | * This function is used to register kernel vm area before | ||
| 1009 | * vmalloc_init() is called. @vm->size and @vm->flags should contain | ||
| 1010 | * proper values on entry and other fields should be zero. On return, | ||
| 1011 | * vm->addr contains the allocated address. | ||
| 1012 | * | ||
| 1013 | * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING. | ||
| 1014 | */ | ||
| 1015 | void __init vm_area_register_early(struct vm_struct *vm, size_t align) | ||
| 1016 | { | ||
| 1017 | static size_t vm_init_off __initdata; | ||
| 1018 | unsigned long addr; | ||
| 1019 | |||
| 1020 | addr = ALIGN(VMALLOC_START + vm_init_off, align); | ||
| 1021 | vm_init_off = PFN_ALIGN(addr + vm->size) - VMALLOC_START; | ||
| 1022 | |||
| 1023 | vm->addr = (void *)addr; | ||
| 1024 | |||
| 1025 | vm->next = vmlist; | ||
| 1026 | vmlist = vm; | ||
| 1027 | } | ||
| 1028 | |||
| 993 | void __init vmalloc_init(void) | 1029 | void __init vmalloc_init(void) |
| 994 | { | 1030 | { |
| 995 | struct vmap_area *va; | 1031 | struct vmap_area *va; |
| @@ -1017,6 +1053,58 @@ void __init vmalloc_init(void) | |||
| 1017 | vmap_initialized = true; | 1053 | vmap_initialized = true; |
| 1018 | } | 1054 | } |
| 1019 | 1055 | ||
| 1056 | /** | ||
| 1057 | * map_kernel_range_noflush - map kernel VM area with the specified pages | ||
| 1058 | * @addr: start of the VM area to map | ||
| 1059 | * @size: size of the VM area to map | ||
| 1060 | * @prot: page protection flags to use | ||
| 1061 | * @pages: pages to map | ||
| 1062 | * | ||
| 1063 | * Map PFN_UP(@size) pages at @addr. The VM area @addr and @size | ||
| 1064 | * specify should have been allocated using get_vm_area() and its | ||
| 1065 | * friends. | ||
| 1066 | * | ||
| 1067 | * NOTE: | ||
| 1068 | * This function does NOT do any cache flushing. The caller is | ||
| 1069 | * responsible for calling flush_cache_vmap() on to-be-mapped areas | ||
| 1070 | * before calling this function. | ||
| 1071 | * | ||
| 1072 | * RETURNS: | ||
| 1073 | * The number of pages mapped on success, -errno on failure. | ||
| 1074 | */ | ||
| 1075 | int map_kernel_range_noflush(unsigned long addr, unsigned long size, | ||
| 1076 | pgprot_t prot, struct page **pages) | ||
| 1077 | { | ||
| 1078 | return vmap_page_range_noflush(addr, addr + size, prot, pages); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /** | ||
| 1082 | * unmap_kernel_range_noflush - unmap kernel VM area | ||
| 1083 | * @addr: start of the VM area to unmap | ||
| 1084 | * @size: size of the VM area to unmap | ||
| 1085 | * | ||
| 1086 | * Unmap PFN_UP(@size) pages at @addr. The VM area @addr and @size | ||
| 1087 | * specify should have been allocated using get_vm_area() and its | ||
| 1088 | * friends. | ||
| 1089 | * | ||
| 1090 | * NOTE: | ||
| 1091 | * This function does NOT do any cache flushing. The caller is | ||
| 1092 | * responsible for calling flush_cache_vunmap() on to-be-mapped areas | ||
| 1093 | * before calling this function and flush_tlb_kernel_range() after. | ||
| 1094 | */ | ||
| 1095 | void unmap_kernel_range_noflush(unsigned long addr, unsigned long size) | ||
| 1096 | { | ||
| 1097 | vunmap_page_range(addr, addr + size); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /** | ||
| 1101 | * unmap_kernel_range - unmap kernel VM area and flush cache and TLB | ||
| 1102 | * @addr: start of the VM area to unmap | ||
| 1103 | * @size: size of the VM area to unmap | ||
| 1104 | * | ||
| 1105 | * Similar to unmap_kernel_range_noflush() but flushes vcache before | ||
| 1106 | * the unmapping and tlb after. | ||
| 1107 | */ | ||
| 1020 | void unmap_kernel_range(unsigned long addr, unsigned long size) | 1108 | void unmap_kernel_range(unsigned long addr, unsigned long size) |
| 1021 | { | 1109 | { |
| 1022 | unsigned long end = addr + size; | 1110 | unsigned long end = addr + size; |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index e9db889d6222..2886d2fb9ab5 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
| @@ -1,12 +1,16 @@ | |||
| 1 | #include <linux/skbuff.h> | 1 | #include <linux/skbuff.h> |
| 2 | #include <linux/netdevice.h> | 2 | #include <linux/netdevice.h> |
| 3 | #include <linux/if_vlan.h> | 3 | #include <linux/if_vlan.h> |
| 4 | #include <linux/netpoll.h> | ||
| 4 | #include "vlan.h" | 5 | #include "vlan.h" |
| 5 | 6 | ||
| 6 | /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ | 7 | /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ |
| 7 | int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, | 8 | int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, |
| 8 | u16 vlan_tci, int polling) | 9 | u16 vlan_tci, int polling) |
| 9 | { | 10 | { |
| 11 | if (netpoll_rx(skb)) | ||
| 12 | return NET_RX_DROP; | ||
| 13 | |||
| 10 | if (skb_bond_should_drop(skb)) | 14 | if (skb_bond_should_drop(skb)) |
| 11 | goto drop; | 15 | goto drop; |
| 12 | 16 | ||
| @@ -100,6 +104,9 @@ int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, | |||
| 100 | { | 104 | { |
| 101 | int err = NET_RX_SUCCESS; | 105 | int err = NET_RX_SUCCESS; |
| 102 | 106 | ||
| 107 | if (netpoll_receive_skb(skb)) | ||
| 108 | return NET_RX_DROP; | ||
| 109 | |||
| 103 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { | 110 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { |
| 104 | case -1: | 111 | case -1: |
| 105 | return netif_receive_skb(skb); | 112 | return netif_receive_skb(skb); |
| @@ -126,6 +133,9 @@ int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, | |||
| 126 | if (!skb) | 133 | if (!skb) |
| 127 | goto out; | 134 | goto out; |
| 128 | 135 | ||
| 136 | if (netpoll_receive_skb(skb)) | ||
| 137 | goto out; | ||
| 138 | |||
| 129 | err = NET_RX_SUCCESS; | 139 | err = NET_RX_SUCCESS; |
| 130 | 140 | ||
| 131 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { | 141 | switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { |
diff --git a/net/core/dev.c b/net/core/dev.c index a17e00662363..72b0d26fd46d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2488,6 +2488,9 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
| 2488 | 2488 | ||
| 2489 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 2489 | int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
| 2490 | { | 2490 | { |
| 2491 | if (netpoll_receive_skb(skb)) | ||
| 2492 | return NET_RX_DROP; | ||
| 2493 | |||
| 2491 | switch (__napi_gro_receive(napi, skb)) { | 2494 | switch (__napi_gro_receive(napi, skb)) { |
| 2492 | case -1: | 2495 | case -1: |
| 2493 | return netif_receive_skb(skb); | 2496 | return netif_receive_skb(skb); |
| @@ -2558,6 +2561,9 @@ int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) | |||
| 2558 | if (!skb) | 2561 | if (!skb) |
| 2559 | goto out; | 2562 | goto out; |
| 2560 | 2563 | ||
| 2564 | if (netpoll_receive_skb(skb)) | ||
| 2565 | goto out; | ||
| 2566 | |||
| 2561 | err = NET_RX_SUCCESS; | 2567 | err = NET_RX_SUCCESS; |
| 2562 | 2568 | ||
| 2563 | switch (__napi_gro_receive(napi, skb)) { | 2569 | switch (__napi_gro_receive(napi, skb)) { |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 743f5542d65a..3a3dad801354 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -1375,10 +1375,10 @@ EXPORT_SYMBOL_GPL(snmp_fold_field); | |||
| 1375 | int snmp_mib_init(void *ptr[2], size_t mibsize) | 1375 | int snmp_mib_init(void *ptr[2], size_t mibsize) |
| 1376 | { | 1376 | { |
| 1377 | BUG_ON(ptr == NULL); | 1377 | BUG_ON(ptr == NULL); |
| 1378 | ptr[0] = __alloc_percpu(mibsize); | 1378 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); |
| 1379 | if (!ptr[0]) | 1379 | if (!ptr[0]) |
| 1380 | goto err0; | 1380 | goto err0; |
| 1381 | ptr[1] = __alloc_percpu(mibsize); | 1381 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); |
| 1382 | if (!ptr[1]) | 1382 | if (!ptr[1]) |
| 1383 | goto err1; | 1383 | goto err1; |
| 1384 | return 0; | 1384 | return 0; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 97f71153584f..bf895401218f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -3376,7 +3376,7 @@ int __init ip_rt_init(void) | |||
| 3376 | int rc = 0; | 3376 | int rc = 0; |
| 3377 | 3377 | ||
| 3378 | #ifdef CONFIG_NET_CLS_ROUTE | 3378 | #ifdef CONFIG_NET_CLS_ROUTE |
| 3379 | ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct)); | 3379 | ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct)); |
| 3380 | if (!ip_rt_acct) | 3380 | if (!ip_rt_acct) |
| 3381 | panic("IP: failed to allocate ip_rt_acct\n"); | 3381 | panic("IP: failed to allocate ip_rt_acct\n"); |
| 3382 | #endif | 3382 | #endif |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a6961d75c7ea..c28976a7e596 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -1374,7 +1374,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk, | |||
| 1374 | 1374 | ||
| 1375 | static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | 1375 | static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, |
| 1376 | struct tcp_sacktag_state *state, | 1376 | struct tcp_sacktag_state *state, |
| 1377 | unsigned int pcount, int shifted, int mss) | 1377 | unsigned int pcount, int shifted, int mss, |
| 1378 | int dup_sack) | ||
| 1378 | { | 1379 | { |
| 1379 | struct tcp_sock *tp = tcp_sk(sk); | 1380 | struct tcp_sock *tp = tcp_sk(sk); |
| 1380 | struct sk_buff *prev = tcp_write_queue_prev(sk, skb); | 1381 | struct sk_buff *prev = tcp_write_queue_prev(sk, skb); |
| @@ -1410,7 +1411,7 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | |||
| 1410 | } | 1411 | } |
| 1411 | 1412 | ||
| 1412 | /* We discard results */ | 1413 | /* We discard results */ |
| 1413 | tcp_sacktag_one(skb, sk, state, 0, pcount); | 1414 | tcp_sacktag_one(skb, sk, state, dup_sack, pcount); |
| 1414 | 1415 | ||
| 1415 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ | 1416 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ |
| 1416 | TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); | 1417 | TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); |
| @@ -1561,7 +1562,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, | |||
| 1561 | 1562 | ||
| 1562 | if (!skb_shift(prev, skb, len)) | 1563 | if (!skb_shift(prev, skb, len)) |
| 1563 | goto fallback; | 1564 | goto fallback; |
| 1564 | if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss)) | 1565 | if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) |
| 1565 | goto out; | 1566 | goto out; |
| 1566 | 1567 | ||
| 1567 | /* Hole filled allows collapsing with the next as well, this is very | 1568 | /* Hole filled allows collapsing with the next as well, this is very |
| @@ -1580,7 +1581,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, | |||
| 1580 | len = skb->len; | 1581 | len = skb->len; |
| 1581 | if (skb_shift(prev, skb, len)) { | 1582 | if (skb_shift(prev, skb, len)) { |
| 1582 | pcount += tcp_skb_pcount(skb); | 1583 | pcount += tcp_skb_pcount(skb); |
| 1583 | tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss); | 1584 | tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0); |
| 1584 | } | 1585 | } |
| 1585 | 1586 | ||
| 1586 | out: | 1587 | out: |
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 2747ec7bfb63..4660b088a8ce 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Tom Kelly's Scalable TCP | 1 | /* Tom Kelly's Scalable TCP |
| 2 | * | 2 | * |
| 3 | * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/ | 3 | * See http://www.deneholme.net/tom/scalable/ |
| 4 | * | 4 | * |
| 5 | * John Heffner <jheffner@sc.edu> | 5 | * John Heffner <jheffner@sc.edu> |
| 6 | */ | 6 | */ |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 8fe267feb81e..1bcc3431859e 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
| @@ -258,11 +258,11 @@ unique: | |||
| 258 | 258 | ||
| 259 | if (twp != NULL) { | 259 | if (twp != NULL) { |
| 260 | *twp = tw; | 260 | *twp = tw; |
| 261 | NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED); | 261 | NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); |
| 262 | } else if (tw != NULL) { | 262 | } else if (tw != NULL) { |
| 263 | /* Silly. Should hash-dance instead... */ | 263 | /* Silly. Should hash-dance instead... */ |
| 264 | inet_twsk_deschedule(tw, death_row); | 264 | inet_twsk_deschedule(tw, death_row); |
| 265 | NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED); | 265 | NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED); |
| 266 | 266 | ||
| 267 | inet_twsk_put(tw); | 267 | inet_twsk_put(tw); |
| 268 | } | 268 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c323643ffcf9..72dbb6d1a6b3 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
| @@ -201,8 +201,9 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | |||
| 201 | 201 | ||
| 202 | if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | 202 | if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && |
| 203 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { | 203 | nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { |
| 204 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, | 204 | if (LOG_INVALID(net, IPPROTO_ICMPV6)) |
| 205 | "nf_ct_icmpv6: ICMPv6 checksum failed\n"); | 205 | nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, |
| 206 | "nf_ct_icmpv6: ICMPv6 checksum failed "); | ||
| 206 | return -NF_ACCEPT; | 207 | return -NF_ACCEPT; |
| 207 | } | 208 | } |
| 208 | 209 | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index fa49dc7fe100..c712e9fc6bba 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE | 41 | #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE |
| 42 | #define NFULNL_TIMEOUT_DEFAULT HZ /* every second */ | 42 | #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ |
| 43 | #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ | 43 | #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ |
| 44 | #define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ | 44 | #define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ |
| 45 | 45 | ||
| @@ -590,8 +590,10 @@ nfulnl_log_packet(u_int8_t pf, | |||
| 590 | 590 | ||
| 591 | qthreshold = inst->qthreshold; | 591 | qthreshold = inst->qthreshold; |
| 592 | /* per-rule qthreshold overrides per-instance */ | 592 | /* per-rule qthreshold overrides per-instance */ |
| 593 | if (qthreshold > li->u.ulog.qthreshold) | 593 | if (li->u.ulog.qthreshold) |
| 594 | qthreshold = li->u.ulog.qthreshold; | 594 | if (qthreshold > li->u.ulog.qthreshold) |
| 595 | qthreshold = li->u.ulog.qthreshold; | ||
| 596 | |||
| 595 | 597 | ||
| 596 | switch (inst->copy_mode) { | 598 | switch (inst->copy_mode) { |
| 597 | case NFULNL_COPY_META: | 599 | case NFULNL_COPY_META: |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index bfbf521f6ea5..5baccfa5a0de 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
| @@ -827,59 +827,143 @@ static const struct file_operations xt_table_ops = { | |||
| 827 | .release = seq_release_net, | 827 | .release = seq_release_net, |
| 828 | }; | 828 | }; |
| 829 | 829 | ||
| 830 | static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) | 830 | /* |
| 831 | * Traverse state for ip{,6}_{tables,matches} for helping crossing | ||
| 832 | * the multi-AF mutexes. | ||
| 833 | */ | ||
| 834 | struct nf_mttg_trav { | ||
| 835 | struct list_head *head, *curr; | ||
| 836 | uint8_t class, nfproto; | ||
| 837 | }; | ||
| 838 | |||
| 839 | enum { | ||
| 840 | MTTG_TRAV_INIT, | ||
| 841 | MTTG_TRAV_NFP_UNSPEC, | ||
| 842 | MTTG_TRAV_NFP_SPEC, | ||
| 843 | MTTG_TRAV_DONE, | ||
| 844 | }; | ||
| 845 | |||
| 846 | static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, | ||
| 847 | bool is_target) | ||
| 831 | { | 848 | { |
| 832 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 849 | static const uint8_t next_class[] = { |
| 833 | u_int16_t af = (unsigned long)pde->data; | 850 | [MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC, |
| 851 | [MTTG_TRAV_NFP_SPEC] = MTTG_TRAV_DONE, | ||
| 852 | }; | ||
| 853 | struct nf_mttg_trav *trav = seq->private; | ||
| 854 | |||
| 855 | switch (trav->class) { | ||
| 856 | case MTTG_TRAV_INIT: | ||
| 857 | trav->class = MTTG_TRAV_NFP_UNSPEC; | ||
| 858 | mutex_lock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 859 | trav->head = trav->curr = is_target ? | ||
| 860 | &xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match; | ||
| 861 | break; | ||
| 862 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 863 | trav->curr = trav->curr->next; | ||
| 864 | if (trav->curr != trav->head) | ||
| 865 | break; | ||
| 866 | mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 867 | mutex_lock(&xt[trav->nfproto].mutex); | ||
| 868 | trav->head = trav->curr = is_target ? | ||
| 869 | &xt[trav->nfproto].target : &xt[trav->nfproto].match; | ||
| 870 | trav->class = next_class[trav->class]; | ||
| 871 | break; | ||
| 872 | case MTTG_TRAV_NFP_SPEC: | ||
| 873 | trav->curr = trav->curr->next; | ||
| 874 | if (trav->curr != trav->head) | ||
| 875 | break; | ||
| 876 | /* fallthru, _stop will unlock */ | ||
| 877 | default: | ||
| 878 | return NULL; | ||
| 879 | } | ||
| 834 | 880 | ||
| 835 | mutex_lock(&xt[af].mutex); | 881 | if (ppos != NULL) |
| 836 | return seq_list_start(&xt[af].match, *pos); | 882 | ++*ppos; |
| 883 | return trav; | ||
| 837 | } | 884 | } |
| 838 | 885 | ||
| 839 | static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 886 | static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos, |
| 887 | bool is_target) | ||
| 840 | { | 888 | { |
| 841 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 889 | struct nf_mttg_trav *trav = seq->private; |
| 842 | u_int16_t af = (unsigned long)pde->data; | 890 | unsigned int j; |
| 843 | 891 | ||
| 844 | return seq_list_next(v, &xt[af].match, pos); | 892 | trav->class = MTTG_TRAV_INIT; |
| 893 | for (j = 0; j < *pos; ++j) | ||
| 894 | if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL) | ||
| 895 | return NULL; | ||
| 896 | return trav; | ||
| 845 | } | 897 | } |
| 846 | 898 | ||
| 847 | static void xt_match_seq_stop(struct seq_file *seq, void *v) | 899 | static void xt_mttg_seq_stop(struct seq_file *seq, void *v) |
| 848 | { | 900 | { |
| 849 | struct proc_dir_entry *pde = seq->private; | 901 | struct nf_mttg_trav *trav = seq->private; |
| 850 | u_int16_t af = (unsigned long)pde->data; | 902 | |
| 903 | switch (trav->class) { | ||
| 904 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 905 | mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 906 | break; | ||
| 907 | case MTTG_TRAV_NFP_SPEC: | ||
| 908 | mutex_unlock(&xt[trav->nfproto].mutex); | ||
| 909 | break; | ||
| 910 | } | ||
| 911 | } | ||
| 851 | 912 | ||
| 852 | mutex_unlock(&xt[af].mutex); | 913 | static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) |
| 914 | { | ||
| 915 | return xt_mttg_seq_start(seq, pos, false); | ||
| 853 | } | 916 | } |
| 854 | 917 | ||
| 855 | static int xt_match_seq_show(struct seq_file *seq, void *v) | 918 | static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) |
| 856 | { | 919 | { |
| 857 | struct xt_match *match = list_entry(v, struct xt_match, list); | 920 | return xt_mttg_seq_next(seq, v, ppos, false); |
| 921 | } | ||
| 858 | 922 | ||
| 859 | if (strlen(match->name)) | 923 | static int xt_match_seq_show(struct seq_file *seq, void *v) |
| 860 | return seq_printf(seq, "%s\n", match->name); | 924 | { |
| 861 | else | 925 | const struct nf_mttg_trav *trav = seq->private; |
| 862 | return 0; | 926 | const struct xt_match *match; |
| 927 | |||
| 928 | switch (trav->class) { | ||
| 929 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 930 | case MTTG_TRAV_NFP_SPEC: | ||
| 931 | if (trav->curr == trav->head) | ||
| 932 | return 0; | ||
| 933 | match = list_entry(trav->curr, struct xt_match, list); | ||
| 934 | return (*match->name == '\0') ? 0 : | ||
| 935 | seq_printf(seq, "%s\n", match->name); | ||
| 936 | } | ||
| 937 | return 0; | ||
| 863 | } | 938 | } |
| 864 | 939 | ||
| 865 | static const struct seq_operations xt_match_seq_ops = { | 940 | static const struct seq_operations xt_match_seq_ops = { |
| 866 | .start = xt_match_seq_start, | 941 | .start = xt_match_seq_start, |
| 867 | .next = xt_match_seq_next, | 942 | .next = xt_match_seq_next, |
| 868 | .stop = xt_match_seq_stop, | 943 | .stop = xt_mttg_seq_stop, |
| 869 | .show = xt_match_seq_show, | 944 | .show = xt_match_seq_show, |
| 870 | }; | 945 | }; |
| 871 | 946 | ||
| 872 | static int xt_match_open(struct inode *inode, struct file *file) | 947 | static int xt_match_open(struct inode *inode, struct file *file) |
| 873 | { | 948 | { |
| 949 | struct seq_file *seq; | ||
| 950 | struct nf_mttg_trav *trav; | ||
| 874 | int ret; | 951 | int ret; |
| 875 | 952 | ||
| 876 | ret = seq_open(file, &xt_match_seq_ops); | 953 | trav = kmalloc(sizeof(*trav), GFP_KERNEL); |
| 877 | if (!ret) { | 954 | if (trav == NULL) |
| 878 | struct seq_file *seq = file->private_data; | 955 | return -ENOMEM; |
| 879 | 956 | ||
| 880 | seq->private = PDE(inode); | 957 | ret = seq_open(file, &xt_match_seq_ops); |
| 958 | if (ret < 0) { | ||
| 959 | kfree(trav); | ||
| 960 | return ret; | ||
| 881 | } | 961 | } |
| 882 | return ret; | 962 | |
| 963 | seq = file->private_data; | ||
| 964 | seq->private = trav; | ||
| 965 | trav->nfproto = (unsigned long)PDE(inode)->data; | ||
| 966 | return 0; | ||
| 883 | } | 967 | } |
| 884 | 968 | ||
| 885 | static const struct file_operations xt_match_ops = { | 969 | static const struct file_operations xt_match_ops = { |
| @@ -887,62 +971,63 @@ static const struct file_operations xt_match_ops = { | |||
| 887 | .open = xt_match_open, | 971 | .open = xt_match_open, |
| 888 | .read = seq_read, | 972 | .read = seq_read, |
| 889 | .llseek = seq_lseek, | 973 | .llseek = seq_lseek, |
| 890 | .release = seq_release, | 974 | .release = seq_release_private, |
| 891 | }; | 975 | }; |
| 892 | 976 | ||
| 893 | static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) | 977 | static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) |
| 894 | { | 978 | { |
| 895 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 979 | return xt_mttg_seq_start(seq, pos, true); |
| 896 | u_int16_t af = (unsigned long)pde->data; | ||
| 897 | |||
| 898 | mutex_lock(&xt[af].mutex); | ||
| 899 | return seq_list_start(&xt[af].target, *pos); | ||
| 900 | } | 980 | } |
| 901 | 981 | ||
| 902 | static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 982 | static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos) |
| 903 | { | 983 | { |
| 904 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 984 | return xt_mttg_seq_next(seq, v, ppos, true); |
| 905 | u_int16_t af = (unsigned long)pde->data; | ||
| 906 | |||
| 907 | return seq_list_next(v, &xt[af].target, pos); | ||
| 908 | } | ||
| 909 | |||
| 910 | static void xt_target_seq_stop(struct seq_file *seq, void *v) | ||
| 911 | { | ||
| 912 | struct proc_dir_entry *pde = seq->private; | ||
| 913 | u_int16_t af = (unsigned long)pde->data; | ||
| 914 | |||
| 915 | mutex_unlock(&xt[af].mutex); | ||
| 916 | } | 985 | } |
| 917 | 986 | ||
| 918 | static int xt_target_seq_show(struct seq_file *seq, void *v) | 987 | static int xt_target_seq_show(struct seq_file *seq, void *v) |
| 919 | { | 988 | { |
| 920 | struct xt_target *target = list_entry(v, struct xt_target, list); | 989 | const struct nf_mttg_trav *trav = seq->private; |
| 921 | 990 | const struct xt_target *target; | |
| 922 | if (strlen(target->name)) | 991 | |
| 923 | return seq_printf(seq, "%s\n", target->name); | 992 | switch (trav->class) { |
| 924 | else | 993 | case MTTG_TRAV_NFP_UNSPEC: |
| 925 | return 0; | 994 | case MTTG_TRAV_NFP_SPEC: |
| 995 | if (trav->curr == trav->head) | ||
| 996 | return 0; | ||
| 997 | target = list_entry(trav->curr, struct xt_target, list); | ||
| 998 | return (*target->name == '\0') ? 0 : | ||
| 999 | seq_printf(seq, "%s\n", target->name); | ||
| 1000 | } | ||
| 1001 | return 0; | ||
| 926 | } | 1002 | } |
| 927 | 1003 | ||
| 928 | static const struct seq_operations xt_target_seq_ops = { | 1004 | static const struct seq_operations xt_target_seq_ops = { |
| 929 | .start = xt_target_seq_start, | 1005 | .start = xt_target_seq_start, |
| 930 | .next = xt_target_seq_next, | 1006 | .next = xt_target_seq_next, |
| 931 | .stop = xt_target_seq_stop, | 1007 | .stop = xt_mttg_seq_stop, |
| 932 | .show = xt_target_seq_show, | 1008 | .show = xt_target_seq_show, |
| 933 | }; | 1009 | }; |
| 934 | 1010 | ||
| 935 | static int xt_target_open(struct inode *inode, struct file *file) | 1011 | static int xt_target_open(struct inode *inode, struct file *file) |
| 936 | { | 1012 | { |
| 1013 | struct seq_file *seq; | ||
| 1014 | struct nf_mttg_trav *trav; | ||
| 937 | int ret; | 1015 | int ret; |
| 938 | 1016 | ||
| 939 | ret = seq_open(file, &xt_target_seq_ops); | 1017 | trav = kmalloc(sizeof(*trav), GFP_KERNEL); |
| 940 | if (!ret) { | 1018 | if (trav == NULL) |
| 941 | struct seq_file *seq = file->private_data; | 1019 | return -ENOMEM; |
| 942 | 1020 | ||
| 943 | seq->private = PDE(inode); | 1021 | ret = seq_open(file, &xt_target_seq_ops); |
| 1022 | if (ret < 0) { | ||
| 1023 | kfree(trav); | ||
| 1024 | return ret; | ||
| 944 | } | 1025 | } |
| 945 | return ret; | 1026 | |
| 1027 | seq = file->private_data; | ||
| 1028 | seq->private = trav; | ||
| 1029 | trav->nfproto = (unsigned long)PDE(inode)->data; | ||
| 1030 | return 0; | ||
| 946 | } | 1031 | } |
| 947 | 1032 | ||
| 948 | static const struct file_operations xt_target_ops = { | 1033 | static const struct file_operations xt_target_ops = { |
| @@ -950,7 +1035,7 @@ static const struct file_operations xt_target_ops = { | |||
| 950 | .open = xt_target_open, | 1035 | .open = xt_target_open, |
| 951 | .read = seq_read, | 1036 | .read = seq_read, |
| 952 | .llseek = seq_lseek, | 1037 | .llseek = seq_lseek, |
| 953 | .release = seq_release, | 1038 | .release = seq_release_private, |
| 954 | }; | 1039 | }; |
| 955 | 1040 | ||
| 956 | #define FORMAT_TABLES "_tables_names" | 1041 | #define FORMAT_TABLES "_tables_names" |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index fe80b614a400..791e030ea903 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
| @@ -542,7 +542,7 @@ recent_mt_proc_write(struct file *file, const char __user *input, | |||
| 542 | struct recent_entry *e; | 542 | struct recent_entry *e; |
| 543 | char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")]; | 543 | char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")]; |
| 544 | const char *c = buf; | 544 | const char *c = buf; |
| 545 | union nf_inet_addr addr; | 545 | union nf_inet_addr addr = {}; |
| 546 | u_int16_t family; | 546 | u_int16_t family; |
| 547 | bool add, succ; | 547 | bool add, succ; |
| 548 | 548 | ||
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index f6b4fa97df70..e36e94ab4e10 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
| @@ -66,11 +66,15 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
| 66 | { | 66 | { |
| 67 | struct drr_sched *q = qdisc_priv(sch); | 67 | struct drr_sched *q = qdisc_priv(sch); |
| 68 | struct drr_class *cl = (struct drr_class *)*arg; | 68 | struct drr_class *cl = (struct drr_class *)*arg; |
| 69 | struct nlattr *opt = tca[TCA_OPTIONS]; | ||
| 69 | struct nlattr *tb[TCA_DRR_MAX + 1]; | 70 | struct nlattr *tb[TCA_DRR_MAX + 1]; |
| 70 | u32 quantum; | 71 | u32 quantum; |
| 71 | int err; | 72 | int err; |
| 72 | 73 | ||
| 73 | err = nla_parse_nested(tb, TCA_DRR_MAX, tca[TCA_OPTIONS], drr_policy); | 74 | if (!opt) |
| 75 | return -EINVAL; | ||
| 76 | |||
| 77 | err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy); | ||
| 74 | if (err < 0) | 78 | if (err < 0) |
| 75 | return err; | 79 | return err; |
| 76 | 80 | ||
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index e06365775bdf..3b949a354470 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib | |||
| @@ -186,3 +186,17 @@ quiet_cmd_gzip = GZIP $@ | |||
| 186 | cmd_gzip = gzip -f -9 < $< > $@ | 186 | cmd_gzip = gzip -f -9 < $< > $@ |
| 187 | 187 | ||
| 188 | 188 | ||
| 189 | # Bzip2 | ||
| 190 | # --------------------------------------------------------------------------- | ||
| 191 | |||
| 192 | # Bzip2 does not include size in file... so we have to fake that | ||
| 193 | size_append=$(CONFIG_SHELL) $(srctree)/scripts/bin_size | ||
| 194 | |||
| 195 | quiet_cmd_bzip2 = BZIP2 $@ | ||
| 196 | cmd_bzip2 = (bzip2 -9 < $< && $(size_append) $<) > $@ || (rm -f $@ ; false) | ||
| 197 | |||
| 198 | # Lzma | ||
| 199 | # --------------------------------------------------------------------------- | ||
| 200 | |||
| 201 | quiet_cmd_lzma = LZMA $@ | ||
| 202 | cmd_lzma = (lzma -9 -c $< && $(size_append) $<) >$@ || (rm -f $@ ; false) | ||
diff --git a/scripts/bin_size b/scripts/bin_size new file mode 100644 index 000000000000..43e1b360cee6 --- /dev/null +++ b/scripts/bin_size | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | if [ $# = 0 ] ; then | ||
| 4 | echo Usage: $0 file | ||
| 5 | fi | ||
| 6 | |||
| 7 | size_dec=`stat -c "%s" $1` | ||
| 8 | size_hex_echo_string=`printf "%08x" $size_dec | | ||
| 9 | sed 's/\(..\)\(..\)\(..\)\(..\)/\\\\x\4\\\\x\3\\\\x\2\\\\x\1/g'` | ||
| 10 | /bin/echo -ne $size_hex_echo_string | ||
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 5f3415f28736..3eea8f15131b 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | # Released under the terms of the GNU GPL | 5 | # Released under the terms of the GNU GPL |
| 6 | # | 6 | # |
| 7 | # Generate a cpio packed initramfs. It uses gen_init_cpio to generate | 7 | # Generate a cpio packed initramfs. It uses gen_init_cpio to generate |
| 8 | # the cpio archive, and gzip to pack it. | 8 | # the cpio archive, and then compresses it. |
| 9 | # The script may also be used to generate the inputfile used for gen_init_cpio | 9 | # The script may also be used to generate the inputfile used for gen_init_cpio |
| 10 | # This script assumes that gen_init_cpio is located in usr/ directory | 10 | # This script assumes that gen_init_cpio is located in usr/ directory |
| 11 | 11 | ||
| @@ -16,8 +16,8 @@ usage() { | |||
| 16 | cat << EOF | 16 | cat << EOF |
| 17 | Usage: | 17 | Usage: |
| 18 | $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ... | 18 | $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ... |
| 19 | -o <file> Create gzipped initramfs file named <file> using | 19 | -o <file> Create compressed initramfs file named <file> using |
| 20 | gen_init_cpio and gzip | 20 | gen_init_cpio and compressor depending on the extension |
| 21 | -u <uid> User ID to map to user ID 0 (root). | 21 | -u <uid> User ID to map to user ID 0 (root). |
| 22 | <uid> is only meaningful if <cpio_source> is a | 22 | <uid> is only meaningful if <cpio_source> is a |
| 23 | directory. "squash" forces all files to uid 0. | 23 | directory. "squash" forces all files to uid 0. |
| @@ -225,6 +225,7 @@ cpio_list= | |||
| 225 | output="/dev/stdout" | 225 | output="/dev/stdout" |
| 226 | output_file="" | 226 | output_file="" |
| 227 | is_cpio_compressed= | 227 | is_cpio_compressed= |
| 228 | compr="gzip -9 -f" | ||
| 228 | 229 | ||
| 229 | arg="$1" | 230 | arg="$1" |
| 230 | case "$arg" in | 231 | case "$arg" in |
| @@ -233,11 +234,15 @@ case "$arg" in | |||
| 233 | echo "deps_initramfs := \\" | 234 | echo "deps_initramfs := \\" |
| 234 | shift | 235 | shift |
| 235 | ;; | 236 | ;; |
| 236 | "-o") # generate gzipped cpio image named $1 | 237 | "-o") # generate compressed cpio image named $1 |
| 237 | shift | 238 | shift |
| 238 | output_file="$1" | 239 | output_file="$1" |
| 239 | cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)" | 240 | cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)" |
| 240 | output=${cpio_list} | 241 | output=${cpio_list} |
| 242 | echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f" | ||
| 243 | echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f" | ||
| 244 | echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f" | ||
| 245 | echo "$output_file" | grep -q "\.cpio$" && compr="cat" | ||
| 241 | shift | 246 | shift |
| 242 | ;; | 247 | ;; |
| 243 | esac | 248 | esac |
| @@ -274,7 +279,7 @@ while [ $# -gt 0 ]; do | |||
| 274 | esac | 279 | esac |
| 275 | done | 280 | done |
| 276 | 281 | ||
| 277 | # If output_file is set we will generate cpio archive and gzip it | 282 | # If output_file is set we will generate cpio archive and compress it |
| 278 | # we are carefull to delete tmp files | 283 | # we are carefull to delete tmp files |
| 279 | if [ ! -z ${output_file} ]; then | 284 | if [ ! -z ${output_file} ]; then |
| 280 | if [ -z ${cpio_file} ]; then | 285 | if [ -z ${cpio_file} ]; then |
| @@ -287,7 +292,8 @@ if [ ! -z ${output_file} ]; then | |||
| 287 | if [ "${is_cpio_compressed}" = "compressed" ]; then | 292 | if [ "${is_cpio_compressed}" = "compressed" ]; then |
| 288 | cat ${cpio_tfile} > ${output_file} | 293 | cat ${cpio_tfile} > ${output_file} |
| 289 | else | 294 | else |
| 290 | cat ${cpio_tfile} | gzip -f -9 - > ${output_file} | 295 | (cat ${cpio_tfile} | ${compr} - > ${output_file}) \ |
| 296 | || (rm -f ${output_file} ; false) | ||
| 291 | fi | 297 | fi |
| 292 | [ -z ${cpio_file} ] && rm ${cpio_tfile} | 298 | [ -z ${cpio_file} ] && rm ${cpio_tfile} |
| 293 | fi | 299 | fi |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 3f4b26647386..350794ab9b42 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -386,11 +386,12 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) | |||
| 386 | if (!S_ISSOCK(inode->i_mode) || | 386 | if (!S_ISSOCK(inode->i_mode) || |
| 387 | ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) | 387 | ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) |
| 388 | return 0; | 388 | return 0; |
| 389 | |||
| 390 | sock = SOCKET_I(inode); | 389 | sock = SOCKET_I(inode); |
| 391 | sk = sock->sk; | 390 | sk = sock->sk; |
| 391 | if (sk == NULL) | ||
| 392 | return 0; | ||
| 392 | sksec = sk->sk_security; | 393 | sksec = sk->sk_security; |
| 393 | if (sksec->nlbl_state != NLBL_REQUIRE) | 394 | if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE) |
| 394 | return 0; | 395 | return 0; |
| 395 | 396 | ||
| 396 | local_bh_disable(); | 397 | local_bh_disable(); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c8d9178f47e5..5e909e0da04b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -2095,6 +2095,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | |||
| 2095 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), | 2095 | SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), |
| 2096 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ | 2096 | /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ |
| 2097 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), | 2097 | SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), |
| 2098 | /* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */ | ||
| 2099 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03), | ||
| 2098 | {} | 2100 | {} |
| 2099 | }; | 2101 | }; |
| 2100 | 2102 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a680be0d4534..6c26afcb8262 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -10557,6 +10557,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
| 10557 | SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), | 10557 | SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC), |
| 10558 | SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), | 10558 | SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC), |
| 10559 | SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), | 10559 | SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC), |
| 10560 | SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC), | ||
| 10560 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10561 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), |
| 10561 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), | 10562 | SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF), |
| 10562 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), | 10563 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8027edf3c8f2..3bc427645da8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -4989,7 +4989,7 @@ again: | |||
| 4989 | case STAC_DELL_M4_3: | 4989 | case STAC_DELL_M4_3: |
| 4990 | spec->num_dmics = 1; | 4990 | spec->num_dmics = 1; |
| 4991 | spec->num_smuxes = 0; | 4991 | spec->num_smuxes = 0; |
| 4992 | spec->num_dmuxes = 0; | 4992 | spec->num_dmuxes = 1; |
| 4993 | break; | 4993 | break; |
| 4994 | default: | 4994 | default: |
| 4995 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | 4995 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; |
diff --git a/usr/Kconfig b/usr/Kconfig index 86cecb59dd07..43a3a0fe8f29 100644 --- a/usr/Kconfig +++ b/usr/Kconfig | |||
| @@ -44,3 +44,92 @@ config INITRAMFS_ROOT_GID | |||
| 44 | owned by group root in the initial ramdisk image. | 44 | owned by group root in the initial ramdisk image. |
| 45 | 45 | ||
| 46 | If you are not sure, leave it set to "0". | 46 | If you are not sure, leave it set to "0". |
| 47 | |||
| 48 | config RD_GZIP | ||
| 49 | bool "Initial ramdisk compressed using gzip" | ||
| 50 | default y | ||
| 51 | depends on BLK_DEV_INITRD=y | ||
| 52 | select DECOMPRESS_GZIP | ||
| 53 | help | ||
| 54 | Support loading of a gzip encoded initial ramdisk or cpio buffer. | ||
| 55 | If unsure, say Y. | ||
| 56 | |||
| 57 | config RD_BZIP2 | ||
| 58 | bool "Initial ramdisk compressed using bzip2" | ||
| 59 | default n | ||
| 60 | depends on BLK_DEV_INITRD=y | ||
| 61 | select DECOMPRESS_BZIP2 | ||
| 62 | help | ||
| 63 | Support loading of a bzip2 encoded initial ramdisk or cpio buffer | ||
| 64 | If unsure, say N. | ||
| 65 | |||
| 66 | config RD_LZMA | ||
| 67 | bool "Initial ramdisk compressed using lzma" | ||
| 68 | default n | ||
| 69 | depends on BLK_DEV_INITRD=y | ||
| 70 | select DECOMPRESS_LZMA | ||
| 71 | help | ||
| 72 | Support loading of a lzma encoded initial ramdisk or cpio buffer | ||
| 73 | If unsure, say N. | ||
| 74 | |||
| 75 | choice | ||
| 76 | prompt "Built-in initramfs compression mode" | ||
| 77 | help | ||
| 78 | This setting is only meaningful if the INITRAMFS_SOURCE is | ||
| 79 | set. It decides by which algorithm the INITRAMFS_SOURCE will | ||
| 80 | be compressed. | ||
| 81 | Several compression algorithms are available, which differ | ||
| 82 | in efficiency, compression and decompression speed. | ||
| 83 | Compression speed is only relevant when building a kernel. | ||
| 84 | Decompression speed is relevant at each boot. | ||
| 85 | |||
| 86 | If you have any problems with bzip2 or lzma compressed | ||
| 87 | initramfs, mail me (Alain Knaff) <alain@knaff.lu>. | ||
| 88 | |||
| 89 | High compression options are mostly useful for users who | ||
| 90 | are low on disk space (embedded systems), but for whom ram | ||
| 91 | size matters less. | ||
| 92 | |||
| 93 | If in doubt, select 'gzip' | ||
| 94 | |||
| 95 | config INITRAMFS_COMPRESSION_NONE | ||
| 96 | bool "None" | ||
| 97 | help | ||
| 98 | Do not compress the built-in initramfs at all. This may | ||
| 99 | sound wasteful in space, but, you should be aware that the | ||
| 100 | built-in initramfs will be compressed at a later stage | ||
| 101 | anyways along with the rest of the kernel, on those | ||
| 102 | architectures that support this. | ||
| 103 | However, not compressing the initramfs may lead to slightly | ||
| 104 | higher memory consumption during a short time at boot, while | ||
| 105 | both the cpio image and the unpacked filesystem image will | ||
| 106 | be present in memory simultaneously | ||
| 107 | |||
| 108 | config INITRAMFS_COMPRESSION_GZIP | ||
| 109 | bool "Gzip" | ||
| 110 | depends on RD_GZIP | ||
| 111 | help | ||
| 112 | The old and tried gzip compression. Its compression ratio is | ||
| 113 | the poorest among the 3 choices; however its speed (both | ||
| 114 | compression and decompression) is the fastest. | ||
| 115 | |||
| 116 | config INITRAMFS_COMPRESSION_BZIP2 | ||
| 117 | bool "Bzip2" | ||
| 118 | depends on RD_BZIP2 | ||
| 119 | help | ||
| 120 | Its compression ratio and speed is intermediate. | ||
| 121 | Decompression speed is slowest among the three. The initramfs | ||
| 122 | size is about 10% smaller with bzip2, in comparison to gzip. | ||
| 123 | Bzip2 uses a large amount of memory. For modern kernels you | ||
| 124 | will need at least 8MB RAM or more for booting. | ||
| 125 | |||
| 126 | config INITRAMFS_COMPRESSION_LZMA | ||
| 127 | bool "LZMA" | ||
| 128 | depends on RD_LZMA | ||
| 129 | help | ||
| 130 | The most recent compression algorithm. | ||
| 131 | Its ratio is best, decompression speed is between the other | ||
| 132 | two. Compression is slowest. The initramfs size is about 33% | ||
| 133 | smaller with LZMA in comparison to gzip. | ||
| 134 | |||
| 135 | endchoice | ||
diff --git a/usr/Makefile b/usr/Makefile index 201f27f8cbaf..b84894b3929d 100644 --- a/usr/Makefile +++ b/usr/Makefile | |||
| @@ -6,13 +6,25 @@ klibcdirs:; | |||
| 6 | PHONY += klibcdirs | 6 | PHONY += klibcdirs |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | # No compression | ||
| 10 | suffix_$(CONFIG_INITRAMFS_COMPRESSION_NONE) = | ||
| 11 | |||
| 12 | # Gzip, but no bzip2 | ||
| 13 | suffix_$(CONFIG_INITRAMFS_COMPRESSION_GZIP) = .gz | ||
| 14 | |||
| 15 | # Bzip2 | ||
| 16 | suffix_$(CONFIG_INITRAMFS_COMPRESSION_BZIP2) = .bz2 | ||
| 17 | |||
| 18 | # Lzma | ||
| 19 | suffix_$(CONFIG_INITRAMFS_COMPRESSION_LZMA) = .lzma | ||
| 20 | |||
| 9 | # Generate builtin.o based on initramfs_data.o | 21 | # Generate builtin.o based on initramfs_data.o |
| 10 | obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o | 22 | obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data$(suffix_y).o |
| 11 | 23 | ||
| 12 | # initramfs_data.o contains the initramfs_data.cpio.gz image. | 24 | # initramfs_data.o contains the compressed initramfs_data.cpio image. |
| 13 | # The image is included using .incbin, a dependency which is not | 25 | # The image is included using .incbin, a dependency which is not |
| 14 | # tracked automatically. | 26 | # tracked automatically. |
| 15 | $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE | 27 | $(obj)/initramfs_data$(suffix_y).o: $(obj)/initramfs_data.cpio$(suffix_y) FORCE |
| 16 | 28 | ||
| 17 | ##### | 29 | ##### |
| 18 | # Generate the initramfs cpio archive | 30 | # Generate the initramfs cpio archive |
| @@ -25,28 +37,28 @@ ramfs-args := \ | |||
| 25 | $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ | 37 | $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ |
| 26 | $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) | 38 | $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) |
| 27 | 39 | ||
| 28 | # .initramfs_data.cpio.gz.d is used to identify all files included | 40 | # .initramfs_data.cpio.d is used to identify all files included |
| 29 | # in initramfs and to detect if any files are added/removed. | 41 | # in initramfs and to detect if any files are added/removed. |
| 30 | # Removed files are identified by directory timestamp being updated | 42 | # Removed files are identified by directory timestamp being updated |
| 31 | # The dependency list is generated by gen_initramfs.sh -l | 43 | # The dependency list is generated by gen_initramfs.sh -l |
| 32 | ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),) | 44 | ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),) |
| 33 | include $(obj)/.initramfs_data.cpio.gz.d | 45 | include $(obj)/.initramfs_data.cpio.d |
| 34 | endif | 46 | endif |
| 35 | 47 | ||
| 36 | quiet_cmd_initfs = GEN $@ | 48 | quiet_cmd_initfs = GEN $@ |
| 37 | cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) | 49 | cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) |
| 38 | 50 | ||
| 39 | targets := initramfs_data.cpio.gz | 51 | targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio |
| 40 | # do not try to update files included in initramfs | 52 | # do not try to update files included in initramfs |
| 41 | $(deps_initramfs): ; | 53 | $(deps_initramfs): ; |
| 42 | 54 | ||
| 43 | $(deps_initramfs): klibcdirs | 55 | $(deps_initramfs): klibcdirs |
| 44 | # We rebuild initramfs_data.cpio.gz if: | 56 | # We rebuild initramfs_data.cpio if: |
| 45 | # 1) Any included file is newer then initramfs_data.cpio.gz | 57 | # 1) Any included file is newer then initramfs_data.cpio |
| 46 | # 2) There are changes in which files are included (added or deleted) | 58 | # 2) There are changes in which files are included (added or deleted) |
| 47 | # 3) If gen_init_cpio are newer than initramfs_data.cpio.gz | 59 | # 3) If gen_init_cpio are newer than initramfs_data.cpio |
| 48 | # 4) arguments to gen_initramfs.sh changes | 60 | # 4) arguments to gen_initramfs.sh changes |
| 49 | $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs | 61 | $(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs |
| 50 | $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d | 62 | $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d |
| 51 | $(call if_changed,initfs) | 63 | $(call if_changed,initfs) |
| 52 | 64 | ||
diff --git a/usr/initramfs_data.S b/usr/initramfs_data.S index c2e1ad424f4a..7c6973d8d829 100644 --- a/usr/initramfs_data.S +++ b/usr/initramfs_data.S | |||
| @@ -26,5 +26,5 @@ SECTIONS | |||
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | .section .init.ramfs,"a" | 28 | .section .init.ramfs,"a" |
| 29 | .incbin "usr/initramfs_data.cpio.gz" | 29 | .incbin "usr/initramfs_data.cpio" |
| 30 | 30 | ||
diff --git a/usr/initramfs_data.bz2.S b/usr/initramfs_data.bz2.S new file mode 100644 index 000000000000..bc54d090365c --- /dev/null +++ b/usr/initramfs_data.bz2.S | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | initramfs_data includes the compressed binary that is the | ||
| 3 | filesystem used for early user space. | ||
| 4 | Note: Older versions of "as" (prior to binutils 2.11.90.0.23 | ||
| 5 | released on 2001-07-14) dit not support .incbin. | ||
| 6 | If you are forced to use older binutils than that then the | ||
| 7 | following trick can be applied to create the resulting binary: | ||
| 8 | |||
| 9 | |||
| 10 | ld -m elf_i386 --format binary --oformat elf32-i386 -r \ | ||
| 11 | -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o | ||
| 12 | ld -m elf_i386 -r -o built-in.o initramfs_data.o | ||
| 13 | |||
| 14 | initramfs_data.scr looks like this: | ||
| 15 | SECTIONS | ||
| 16 | { | ||
| 17 | .init.ramfs : { *(.data) } | ||
| 18 | } | ||
| 19 | |||
| 20 | The above example is for i386 - the parameters vary from architectures. | ||
| 21 | Eventually look up LDFLAGS_BLOB in an older version of the | ||
| 22 | arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. | ||
| 23 | |||
| 24 | Using .incbin has the advantage over ld that the correct flags are set | ||
| 25 | in the ELF header, as required by certain architectures. | ||
| 26 | */ | ||
| 27 | |||
| 28 | .section .init.ramfs,"a" | ||
| 29 | .incbin "usr/initramfs_data.cpio.bz2" | ||
diff --git a/usr/initramfs_data.gz.S b/usr/initramfs_data.gz.S new file mode 100644 index 000000000000..890c8dd1d6bd --- /dev/null +++ b/usr/initramfs_data.gz.S | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | initramfs_data includes the compressed binary that is the | ||
| 3 | filesystem used for early user space. | ||
| 4 | Note: Older versions of "as" (prior to binutils 2.11.90.0.23 | ||
| 5 | released on 2001-07-14) dit not support .incbin. | ||
| 6 | If you are forced to use older binutils than that then the | ||
| 7 | following trick can be applied to create the resulting binary: | ||
| 8 | |||
| 9 | |||
| 10 | ld -m elf_i386 --format binary --oformat elf32-i386 -r \ | ||
| 11 | -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o | ||
| 12 | ld -m elf_i386 -r -o built-in.o initramfs_data.o | ||
| 13 | |||
| 14 | initramfs_data.scr looks like this: | ||
| 15 | SECTIONS | ||
| 16 | { | ||
| 17 | .init.ramfs : { *(.data) } | ||
| 18 | } | ||
| 19 | |||
| 20 | The above example is for i386 - the parameters vary from architectures. | ||
| 21 | Eventually look up LDFLAGS_BLOB in an older version of the | ||
| 22 | arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. | ||
| 23 | |||
| 24 | Using .incbin has the advantage over ld that the correct flags are set | ||
| 25 | in the ELF header, as required by certain architectures. | ||
| 26 | */ | ||
| 27 | |||
| 28 | .section .init.ramfs,"a" | ||
| 29 | .incbin "usr/initramfs_data.cpio.gz" | ||
diff --git a/usr/initramfs_data.lzma.S b/usr/initramfs_data.lzma.S new file mode 100644 index 000000000000..e11469e48562 --- /dev/null +++ b/usr/initramfs_data.lzma.S | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | initramfs_data includes the compressed binary that is the | ||
| 3 | filesystem used for early user space. | ||
| 4 | Note: Older versions of "as" (prior to binutils 2.11.90.0.23 | ||
| 5 | released on 2001-07-14) dit not support .incbin. | ||
| 6 | If you are forced to use older binutils than that then the | ||
| 7 | following trick can be applied to create the resulting binary: | ||
| 8 | |||
| 9 | |||
| 10 | ld -m elf_i386 --format binary --oformat elf32-i386 -r \ | ||
| 11 | -T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o | ||
| 12 | ld -m elf_i386 -r -o built-in.o initramfs_data.o | ||
| 13 | |||
| 14 | initramfs_data.scr looks like this: | ||
| 15 | SECTIONS | ||
| 16 | { | ||
| 17 | .init.ramfs : { *(.data) } | ||
| 18 | } | ||
| 19 | |||
| 20 | The above example is for i386 - the parameters vary from architectures. | ||
| 21 | Eventually look up LDFLAGS_BLOB in an older version of the | ||
| 22 | arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced. | ||
| 23 | |||
| 24 | Using .incbin has the advantage over ld that the correct flags are set | ||
| 25 | in the ELF header, as required by certain architectures. | ||
| 26 | */ | ||
| 27 | |||
| 28 | .section .init.ramfs,"a" | ||
| 29 | .incbin "usr/initramfs_data.cpio.lzma" | ||
