diff options
40 files changed, 178 insertions, 109 deletions
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 13 | 2 | PATCHLEVEL = 13 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc7 | 4 | EXTRAVERSION = -rc8 |
| 5 | NAME = One Giant Leap for Frogkind | 5 | NAME = One Giant Leap for Frogkind |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 739c3dfc1da2..34d5fd585bbb 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c | |||
| @@ -171,7 +171,7 @@ void __init arm_dt_init_cpu_maps(void) | |||
| 171 | 171 | ||
| 172 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | 172 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) |
| 173 | { | 173 | { |
| 174 | return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu); | 174 | return phys_id == cpu_logical_map(cpu); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static const void * __init arch_get_next_mach(const char *const **match) | 177 | static const void * __init arch_get_next_mach(const char *const **match) |
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index d85055cd24ba..20d553c9f5e2 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c | |||
| @@ -254,7 +254,7 @@ static int probe_current_pmu(struct arm_pmu *pmu) | |||
| 254 | static int cpu_pmu_device_probe(struct platform_device *pdev) | 254 | static int cpu_pmu_device_probe(struct platform_device *pdev) |
| 255 | { | 255 | { |
| 256 | const struct of_device_id *of_id; | 256 | const struct of_device_id *of_id; |
| 257 | int (*init_fn)(struct arm_pmu *); | 257 | const int (*init_fn)(struct arm_pmu *); |
| 258 | struct device_node *node = pdev->dev.of_node; | 258 | struct device_node *node = pdev->dev.of_node; |
| 259 | struct arm_pmu *pmu; | 259 | struct arm_pmu *pmu; |
| 260 | int ret = -ENODEV; | 260 | int ret = -ENODEV; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 6eda3bf85c52..4636d56af2db 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
| @@ -431,9 +431,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
| 431 | instr2 = __mem_to_opcode_thumb16(instr2); | 431 | instr2 = __mem_to_opcode_thumb16(instr2); |
| 432 | instr = __opcode_thumb32_compose(instr, instr2); | 432 | instr = __opcode_thumb32_compose(instr, instr2); |
| 433 | } | 433 | } |
| 434 | } else if (get_user(instr, (u32 __user *)pc)) { | 434 | } else { |
| 435 | if (get_user(instr, (u32 __user *)pc)) | ||
| 436 | goto die_sig; | ||
| 435 | instr = __mem_to_opcode_arm(instr); | 437 | instr = __mem_to_opcode_arm(instr); |
| 436 | goto die_sig; | ||
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | if (call_undef_hook(regs, instr) == 0) | 440 | if (call_undef_hook(regs, instr) == 0) |
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index bd3bf66ce344..c7de89b263dd 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c | |||
| @@ -53,6 +53,7 @@ static void __init highbank_scu_map_io(void) | |||
| 53 | 53 | ||
| 54 | static void highbank_l2x0_disable(void) | 54 | static void highbank_l2x0_disable(void) |
| 55 | { | 55 | { |
| 56 | outer_flush_all(); | ||
| 56 | /* Disable PL310 L2 Cache controller */ | 57 | /* Disable PL310 L2 Cache controller */ |
| 57 | highbank_smc1(0x102, 0x0); | 58 | highbank_smc1(0x102, 0x0); |
| 58 | } | 59 | } |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index b39efd46abf9..c0ab9b26be3d 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
| @@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void) | |||
| 162 | 162 | ||
| 163 | static void omap4_l2x0_disable(void) | 163 | static void omap4_l2x0_disable(void) |
| 164 | { | 164 | { |
| 165 | outer_flush_all(); | ||
| 165 | /* Disable PL310 L2 Cache controller */ | 166 | /* Disable PL310 L2 Cache controller */ |
| 166 | omap_smc1(0x102, 0x0); | 167 | omap_smc1(0x102, 0x0); |
| 167 | } | 168 | } |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1f7b19a47060..3e8f106ee5fe 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
| @@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc) | |||
| 229 | #ifdef CONFIG_ZONE_DMA | 229 | #ifdef CONFIG_ZONE_DMA |
| 230 | if (mdesc->dma_zone_size) { | 230 | if (mdesc->dma_zone_size) { |
| 231 | arm_dma_zone_size = mdesc->dma_zone_size; | 231 | arm_dma_zone_size = mdesc->dma_zone_size; |
| 232 | arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1; | 232 | arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1; |
| 233 | } else | 233 | } else |
| 234 | arm_dma_limit = 0xffffffff; | 234 | arm_dma_limit = 0xffffffff; |
| 235 | arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT; | 235 | arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT; |
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h index c75025f27c20..06b9bc7ea14b 100644 --- a/arch/mips/include/asm/cacheops.h +++ b/arch/mips/include/asm/cacheops.h | |||
| @@ -83,6 +83,6 @@ | |||
| 83 | /* | 83 | /* |
| 84 | * Loongson2-specific cacheops | 84 | * Loongson2-specific cacheops |
| 85 | */ | 85 | */ |
| 86 | #define Hit_Invalidate_I_Loongson23 0x00 | 86 | #define Hit_Invalidate_I_Loongson2 0x00 |
| 87 | 87 | ||
| 88 | #endif /* __ASM_CACHEOPS_H */ | 88 | #endif /* __ASM_CACHEOPS_H */ |
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index 34d1a1917125..c84caddb8bde 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h | |||
| @@ -165,7 +165,7 @@ static inline void flush_icache_line(unsigned long addr) | |||
| 165 | __iflush_prologue | 165 | __iflush_prologue |
| 166 | switch (boot_cpu_type()) { | 166 | switch (boot_cpu_type()) { |
| 167 | case CPU_LOONGSON2: | 167 | case CPU_LOONGSON2: |
| 168 | cache_op(Hit_Invalidate_I_Loongson23, addr); | 168 | cache_op(Hit_Invalidate_I_Loongson2, addr); |
| 169 | break; | 169 | break; |
| 170 | 170 | ||
| 171 | default: | 171 | default: |
| @@ -219,7 +219,7 @@ static inline void protected_flush_icache_line(unsigned long addr) | |||
| 219 | { | 219 | { |
| 220 | switch (boot_cpu_type()) { | 220 | switch (boot_cpu_type()) { |
| 221 | case CPU_LOONGSON2: | 221 | case CPU_LOONGSON2: |
| 222 | protected_cache_op(Hit_Invalidate_I_Loongson23, addr); | 222 | protected_cache_op(Hit_Invalidate_I_Loongson2, addr); |
| 223 | break; | 223 | break; |
| 224 | 224 | ||
| 225 | default: | 225 | default: |
| @@ -357,8 +357,8 @@ static inline void invalidate_tcache_page(unsigned long addr) | |||
| 357 | "i" (op)); | 357 | "i" (op)); |
| 358 | 358 | ||
| 359 | /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ | 359 | /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ |
| 360 | #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \ | 360 | #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ |
| 361 | static inline void blast_##pfx##cache##lsize(void) \ | 361 | static inline void extra##blast_##pfx##cache##lsize(void) \ |
| 362 | { \ | 362 | { \ |
| 363 | unsigned long start = INDEX_BASE; \ | 363 | unsigned long start = INDEX_BASE; \ |
| 364 | unsigned long end = start + current_cpu_data.desc.waysize; \ | 364 | unsigned long end = start + current_cpu_data.desc.waysize; \ |
| @@ -376,7 +376,7 @@ static inline void blast_##pfx##cache##lsize(void) \ | |||
| 376 | __##pfx##flush_epilogue \ | 376 | __##pfx##flush_epilogue \ |
| 377 | } \ | 377 | } \ |
| 378 | \ | 378 | \ |
| 379 | static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ | 379 | static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \ |
| 380 | { \ | 380 | { \ |
| 381 | unsigned long start = page; \ | 381 | unsigned long start = page; \ |
| 382 | unsigned long end = page + PAGE_SIZE; \ | 382 | unsigned long end = page + PAGE_SIZE; \ |
| @@ -391,7 +391,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \ | |||
| 391 | __##pfx##flush_epilogue \ | 391 | __##pfx##flush_epilogue \ |
| 392 | } \ | 392 | } \ |
| 393 | \ | 393 | \ |
| 394 | static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ | 394 | static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \ |
| 395 | { \ | 395 | { \ |
| 396 | unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ | 396 | unsigned long indexmask = current_cpu_data.desc.waysize - 1; \ |
| 397 | unsigned long start = INDEX_BASE + (page & indexmask); \ | 397 | unsigned long start = INDEX_BASE + (page & indexmask); \ |
| @@ -410,23 +410,24 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) | |||
| 410 | __##pfx##flush_epilogue \ | 410 | __##pfx##flush_epilogue \ |
| 411 | } | 411 | } |
| 412 | 412 | ||
| 413 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16) | 413 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) |
| 414 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16) | 414 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) |
| 415 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) | 415 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) |
| 416 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) | 416 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) |
| 417 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) | 417 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) |
| 418 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) | 418 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) |
| 419 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64) | 419 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) |
| 420 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) | 420 | __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) |
| 421 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) | 421 | __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) |
| 422 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) | 422 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) |
| 423 | 423 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) | |
| 424 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16) | 424 | |
| 425 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32) | 425 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) |
| 426 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16) | 426 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) |
| 427 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32) | 427 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) |
| 428 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64) | 428 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) |
| 429 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128) | 429 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) |
| 430 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) | ||
| 430 | 431 | ||
| 431 | /* build blast_xxx_range, protected_blast_xxx_range */ | 432 | /* build blast_xxx_range, protected_blast_xxx_range */ |
| 432 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ | 433 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ |
| @@ -452,8 +453,8 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, | |||
| 452 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) | 453 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) |
| 453 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) | 454 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) |
| 454 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) | 455 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) |
| 455 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \ | 456 | __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ |
| 456 | protected_, loongson23_) | 457 | protected_, loongson2_) |
| 457 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) | 458 | __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) |
| 458 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) | 459 | __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) |
| 459 | /* blast_inv_dcache_range */ | 460 | /* blast_inv_dcache_range */ |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 62ffd20ea869..49e572d879e1 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
| @@ -237,6 +237,8 @@ static void r4k_blast_icache_page_setup(void) | |||
| 237 | r4k_blast_icache_page = (void *)cache_noop; | 237 | r4k_blast_icache_page = (void *)cache_noop; |
| 238 | else if (ic_lsize == 16) | 238 | else if (ic_lsize == 16) |
| 239 | r4k_blast_icache_page = blast_icache16_page; | 239 | r4k_blast_icache_page = blast_icache16_page; |
| 240 | else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2) | ||
| 241 | r4k_blast_icache_page = loongson2_blast_icache32_page; | ||
| 240 | else if (ic_lsize == 32) | 242 | else if (ic_lsize == 32) |
| 241 | r4k_blast_icache_page = blast_icache32_page; | 243 | r4k_blast_icache_page = blast_icache32_page; |
| 242 | else if (ic_lsize == 64) | 244 | else if (ic_lsize == 64) |
| @@ -261,6 +263,9 @@ static void r4k_blast_icache_page_indexed_setup(void) | |||
| 261 | else if (TX49XX_ICACHE_INDEX_INV_WAR) | 263 | else if (TX49XX_ICACHE_INDEX_INV_WAR) |
| 262 | r4k_blast_icache_page_indexed = | 264 | r4k_blast_icache_page_indexed = |
| 263 | tx49_blast_icache32_page_indexed; | 265 | tx49_blast_icache32_page_indexed; |
| 266 | else if (current_cpu_type() == CPU_LOONGSON2) | ||
| 267 | r4k_blast_icache_page_indexed = | ||
| 268 | loongson2_blast_icache32_page_indexed; | ||
| 264 | else | 269 | else |
| 265 | r4k_blast_icache_page_indexed = | 270 | r4k_blast_icache_page_indexed = |
| 266 | blast_icache32_page_indexed; | 271 | blast_icache32_page_indexed; |
| @@ -284,6 +289,8 @@ static void r4k_blast_icache_setup(void) | |||
| 284 | r4k_blast_icache = blast_r4600_v1_icache32; | 289 | r4k_blast_icache = blast_r4600_v1_icache32; |
| 285 | else if (TX49XX_ICACHE_INDEX_INV_WAR) | 290 | else if (TX49XX_ICACHE_INDEX_INV_WAR) |
| 286 | r4k_blast_icache = tx49_blast_icache32; | 291 | r4k_blast_icache = tx49_blast_icache32; |
| 292 | else if (current_cpu_type() == CPU_LOONGSON2) | ||
| 293 | r4k_blast_icache = loongson2_blast_icache32; | ||
| 287 | else | 294 | else |
| 288 | r4k_blast_icache = blast_icache32; | 295 | r4k_blast_icache = blast_icache32; |
| 289 | } else if (ic_lsize == 64) | 296 | } else if (ic_lsize == 64) |
| @@ -580,11 +587,11 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo | |||
| 580 | else { | 587 | else { |
| 581 | switch (boot_cpu_type()) { | 588 | switch (boot_cpu_type()) { |
| 582 | case CPU_LOONGSON2: | 589 | case CPU_LOONGSON2: |
| 583 | protected_blast_icache_range(start, end); | 590 | protected_loongson2_blast_icache_range(start, end); |
| 584 | break; | 591 | break; |
| 585 | 592 | ||
| 586 | default: | 593 | default: |
| 587 | protected_loongson23_blast_icache_range(start, end); | 594 | protected_blast_icache_range(start, end); |
| 588 | break; | 595 | break; |
| 589 | } | 596 | } |
| 590 | } | 597 | } |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index cb64a6e1dc51..078145acf7fb 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -1986,19 +1986,23 @@ static void __init prom_init_stdout(void) | |||
| 1986 | /* Get the full OF pathname of the stdout device */ | 1986 | /* Get the full OF pathname of the stdout device */ |
| 1987 | memset(path, 0, 256); | 1987 | memset(path, 0, 256); |
| 1988 | call_prom("instance-to-path", 3, 1, prom.stdout, path, 255); | 1988 | call_prom("instance-to-path", 3, 1, prom.stdout, path, 255); |
| 1989 | stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout); | ||
| 1990 | val = cpu_to_be32(stdout_node); | ||
| 1991 | prom_setprop(prom.chosen, "/chosen", "linux,stdout-package", | ||
| 1992 | &val, sizeof(val)); | ||
| 1993 | prom_printf("OF stdout device is: %s\n", of_stdout_device); | 1989 | prom_printf("OF stdout device is: %s\n", of_stdout_device); |
| 1994 | prom_setprop(prom.chosen, "/chosen", "linux,stdout-path", | 1990 | prom_setprop(prom.chosen, "/chosen", "linux,stdout-path", |
| 1995 | path, strlen(path) + 1); | 1991 | path, strlen(path) + 1); |
| 1996 | 1992 | ||
| 1997 | /* If it's a display, note it */ | 1993 | /* instance-to-package fails on PA-Semi */ |
| 1998 | memset(type, 0, sizeof(type)); | 1994 | stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout); |
| 1999 | prom_getprop(stdout_node, "device_type", type, sizeof(type)); | 1995 | if (stdout_node != PROM_ERROR) { |
| 2000 | if (strcmp(type, "display") == 0) | 1996 | val = cpu_to_be32(stdout_node); |
| 2001 | prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0); | 1997 | prom_setprop(prom.chosen, "/chosen", "linux,stdout-package", |
| 1998 | &val, sizeof(val)); | ||
| 1999 | |||
| 2000 | /* If it's a display, note it */ | ||
| 2001 | memset(type, 0, sizeof(type)); | ||
| 2002 | prom_getprop(stdout_node, "device_type", type, sizeof(type)); | ||
| 2003 | if (strcmp(type, "display") == 0) | ||
| 2004 | prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0); | ||
| 2005 | } | ||
| 2002 | } | 2006 | } |
| 2003 | 2007 | ||
| 2004 | static int __init prom_find_machine_type(void) | 2008 | static int __init prom_find_machine_type(void) |
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index c49a613c6452..cea1c76d49bf 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h | |||
| @@ -293,12 +293,13 @@ static inline int restore_fpu_checking(struct task_struct *tsk) | |||
| 293 | /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception | 293 | /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception |
| 294 | is pending. Clear the x87 state here by setting it to fixed | 294 | is pending. Clear the x87 state here by setting it to fixed |
| 295 | values. "m" is a random variable that should be in L1 */ | 295 | values. "m" is a random variable that should be in L1 */ |
| 296 | alternative_input( | 296 | if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) { |
| 297 | ASM_NOP8 ASM_NOP2, | 297 | asm volatile( |
| 298 | "emms\n\t" /* clear stack tags */ | 298 | "fnclex\n\t" |
| 299 | "fildl %P[addr]", /* set F?P to defined value */ | 299 | "emms\n\t" |
| 300 | X86_FEATURE_FXSAVE_LEAK, | 300 | "fildl %P[addr]" /* set F?P to defined value */ |
| 301 | [addr] "m" (tsk->thread.fpu.has_fpu)); | 301 | : : [addr] "m" (tsk->thread.fpu.has_fpu)); |
| 302 | } | ||
| 302 | 303 | ||
| 303 | return fpu_restore_checking(&tsk->thread.fpu); | 304 | return fpu_restore_checking(&tsk->thread.fpu); |
| 304 | } | 305 | } |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 51e2988c5728..a2a4f4697889 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -1082,7 +1082,7 @@ ENTRY(ftrace_caller) | |||
| 1082 | pushl $0 /* Pass NULL as regs pointer */ | 1082 | pushl $0 /* Pass NULL as regs pointer */ |
| 1083 | movl 4*4(%esp), %eax | 1083 | movl 4*4(%esp), %eax |
| 1084 | movl 0x4(%ebp), %edx | 1084 | movl 0x4(%ebp), %edx |
| 1085 | leal function_trace_op, %ecx | 1085 | movl function_trace_op, %ecx |
| 1086 | subl $MCOUNT_INSN_SIZE, %eax | 1086 | subl $MCOUNT_INSN_SIZE, %eax |
| 1087 | 1087 | ||
| 1088 | .globl ftrace_call | 1088 | .globl ftrace_call |
| @@ -1140,7 +1140,7 @@ ENTRY(ftrace_regs_caller) | |||
| 1140 | movl 12*4(%esp), %eax /* Load ip (1st parameter) */ | 1140 | movl 12*4(%esp), %eax /* Load ip (1st parameter) */ |
| 1141 | subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ | 1141 | subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ |
| 1142 | movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ | 1142 | movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ |
| 1143 | leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ | 1143 | movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ |
| 1144 | pushl %esp /* Save pt_regs as 4th parameter */ | 1144 | pushl %esp /* Save pt_regs as 4th parameter */ |
| 1145 | 1145 | ||
| 1146 | GLOBAL(ftrace_regs_call) | 1146 | GLOBAL(ftrace_regs_call) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index e21b0785a85b..1e96c3628bf2 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -88,7 +88,7 @@ END(function_hook) | |||
| 88 | MCOUNT_SAVE_FRAME \skip | 88 | MCOUNT_SAVE_FRAME \skip |
| 89 | 89 | ||
| 90 | /* Load the ftrace_ops into the 3rd parameter */ | 90 | /* Load the ftrace_ops into the 3rd parameter */ |
| 91 | leaq function_trace_op, %rdx | 91 | movq function_trace_op(%rip), %rdx |
| 92 | 92 | ||
| 93 | /* Load ip into the first parameter */ | 93 | /* Load ip into the first parameter */ |
| 94 | movq RIP(%rsp), %rdi | 94 | movq RIP(%rsp), %rdi |
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index a2e69d26266d..83a598ebb65a 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c | |||
| @@ -425,10 +425,7 @@ static void null_del_dev(struct nullb *nullb) | |||
| 425 | list_del_init(&nullb->list); | 425 | list_del_init(&nullb->list); |
| 426 | 426 | ||
| 427 | del_gendisk(nullb->disk); | 427 | del_gendisk(nullb->disk); |
| 428 | if (queue_mode == NULL_Q_MQ) | 428 | blk_cleanup_queue(nullb->q); |
| 429 | blk_mq_free_queue(nullb->q); | ||
| 430 | else | ||
| 431 | blk_cleanup_queue(nullb->q); | ||
| 432 | put_disk(nullb->disk); | 429 | put_disk(nullb->disk); |
| 433 | kfree(nullb); | 430 | kfree(nullb); |
| 434 | } | 431 | } |
| @@ -578,10 +575,7 @@ static int null_add_dev(void) | |||
| 578 | disk = nullb->disk = alloc_disk_node(1, home_node); | 575 | disk = nullb->disk = alloc_disk_node(1, home_node); |
| 579 | if (!disk) { | 576 | if (!disk) { |
| 580 | queue_fail: | 577 | queue_fail: |
| 581 | if (queue_mode == NULL_Q_MQ) | 578 | blk_cleanup_queue(nullb->q); |
| 582 | blk_mq_free_queue(nullb->q); | ||
| 583 | else | ||
| 584 | blk_cleanup_queue(nullb->q); | ||
| 585 | cleanup_queues(nullb); | 579 | cleanup_queues(nullb); |
| 586 | err: | 580 | err: |
| 587 | kfree(nullb); | 581 | kfree(nullb); |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 85071a1c4547..b0733153dfd2 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
| @@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector) | |||
| 1041 | /* if equal delete the probed mode */ | 1041 | /* if equal delete the probed mode */ |
| 1042 | mode->status = pmode->status; | 1042 | mode->status = pmode->status; |
| 1043 | /* Merge type bits together */ | 1043 | /* Merge type bits together */ |
| 1044 | mode->type = pmode->type; | 1044 | mode->type |= pmode->type; |
| 1045 | list_del(&pmode->head); | 1045 | list_del(&pmode->head); |
| 1046 | drm_mode_destroy(connector->dev, pmode); | 1046 | drm_mode_destroy(connector->dev, pmode); |
| 1047 | break; | 1047 | break; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d1dedc02f15..f13d5edc39d5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -2713,6 +2713,8 @@ static void gen8_irq_preinstall(struct drm_device *dev) | |||
| 2713 | #undef GEN8_IRQ_INIT_NDX | 2713 | #undef GEN8_IRQ_INIT_NDX |
| 2714 | 2714 | ||
| 2715 | POSTING_READ(GEN8_PCU_IIR); | 2715 | POSTING_READ(GEN8_PCU_IIR); |
| 2716 | |||
| 2717 | ibx_irq_preinstall(dev); | ||
| 2716 | } | 2718 | } |
| 2717 | 2719 | ||
| 2718 | static void ibx_hpd_irq_setup(struct drm_device *dev) | 2720 | static void ibx_hpd_irq_setup(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 526c8ded16b0..b69dc3e66c16 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
| @@ -1057,12 +1057,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev) | |||
| 1057 | enum pipe pipe; | 1057 | enum pipe pipe; |
| 1058 | struct intel_crtc *intel_crtc; | 1058 | struct intel_crtc *intel_crtc; |
| 1059 | 1059 | ||
| 1060 | dev_priv->ddi_plls.spll_refcount = 0; | ||
| 1061 | dev_priv->ddi_plls.wrpll1_refcount = 0; | ||
| 1062 | dev_priv->ddi_plls.wrpll2_refcount = 0; | ||
| 1063 | |||
| 1060 | for_each_pipe(pipe) { | 1064 | for_each_pipe(pipe) { |
| 1061 | intel_crtc = | 1065 | intel_crtc = |
| 1062 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); | 1066 | to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
| 1063 | 1067 | ||
| 1064 | if (!intel_crtc->active) | 1068 | if (!intel_crtc->active) { |
| 1069 | intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE; | ||
| 1065 | continue; | 1070 | continue; |
| 1071 | } | ||
| 1066 | 1072 | ||
| 1067 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, | 1073 | intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv, |
| 1068 | pipe); | 1074 | pipe); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 769b864465a9..2bde35d34eb9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -11053,10 +11053,10 @@ void intel_modeset_gem_init(struct drm_device *dev) | |||
| 11053 | 11053 | ||
| 11054 | intel_setup_overlay(dev); | 11054 | intel_setup_overlay(dev); |
| 11055 | 11055 | ||
| 11056 | drm_modeset_lock_all(dev); | 11056 | mutex_lock(&dev->mode_config.mutex); |
| 11057 | drm_mode_config_reset(dev); | 11057 | drm_mode_config_reset(dev); |
| 11058 | intel_modeset_setup_hw_state(dev, false); | 11058 | intel_modeset_setup_hw_state(dev, false); |
| 11059 | drm_modeset_unlock_all(dev); | 11059 | mutex_unlock(&dev->mode_config.mutex); |
| 11060 | } | 11060 | } |
| 11061 | 11061 | ||
| 11062 | void intel_modeset_cleanup(struct drm_device *dev) | 11062 | void intel_modeset_cleanup(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 9fa5da723871..7f50a858b16f 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | |||
| @@ -73,7 +73,7 @@ struct nouveau_i2c { | |||
| 73 | int (*identify)(struct nouveau_i2c *, int index, | 73 | int (*identify)(struct nouveau_i2c *, int index, |
| 74 | const char *what, struct nouveau_i2c_board_info *, | 74 | const char *what, struct nouveau_i2c_board_info *, |
| 75 | bool (*match)(struct nouveau_i2c_port *, | 75 | bool (*match)(struct nouveau_i2c_port *, |
| 76 | struct i2c_board_info *)); | 76 | struct i2c_board_info *, void *), void *); |
| 77 | struct list_head ports; | 77 | struct list_head ports; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index ec7a54e91a08..4aca33887aaa 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h | |||
| @@ -50,6 +50,13 @@ struct nouveau_instmem { | |||
| 50 | static inline struct nouveau_instmem * | 50 | static inline struct nouveau_instmem * |
| 51 | nouveau_instmem(void *obj) | 51 | nouveau_instmem(void *obj) |
| 52 | { | 52 | { |
| 53 | /* nv04/nv40 impls need to create objects in their constructor, | ||
| 54 | * which is before the subdev pointer is valid | ||
| 55 | */ | ||
| 56 | if (nv_iclass(obj, NV_SUBDEV_CLASS) && | ||
| 57 | nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM) | ||
| 58 | return obj; | ||
| 59 | |||
| 53 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; | 60 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM]; |
| 54 | } | 61 | } |
| 55 | 62 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 041fd5edaebf..c33c03d2f4af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | |||
| @@ -197,7 +197,7 @@ static int | |||
| 197 | nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, | 197 | nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, |
| 198 | struct nouveau_i2c_board_info *info, | 198 | struct nouveau_i2c_board_info *info, |
| 199 | bool (*match)(struct nouveau_i2c_port *, | 199 | bool (*match)(struct nouveau_i2c_port *, |
| 200 | struct i2c_board_info *)) | 200 | struct i2c_board_info *, void *), void *data) |
| 201 | { | 201 | { |
| 202 | struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); | 202 | struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); |
| 203 | int i; | 203 | int i; |
| @@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, | |||
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | if (nv_probe_i2c(port, info[i].dev.addr) && | 223 | if (nv_probe_i2c(port, info[i].dev.addr) && |
| 224 | (!match || match(port, &info[i].dev))) { | 224 | (!match || match(port, &info[i].dev, data))) { |
| 225 | nv_info(i2c, "detected %s: %s\n", what, | 225 | nv_info(i2c, "detected %s: %s\n", what, |
| 226 | info[i].dev.type); | 226 | info[i].dev.type); |
| 227 | return i; | 227 | return i; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e44ed7b93c6d..7610fc5f8fa2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | |||
| @@ -29,9 +29,9 @@ | |||
| 29 | 29 | ||
| 30 | static bool | 30 | static bool |
| 31 | probe_monitoring_device(struct nouveau_i2c_port *i2c, | 31 | probe_monitoring_device(struct nouveau_i2c_port *i2c, |
| 32 | struct i2c_board_info *info) | 32 | struct i2c_board_info *info, void *data) |
| 33 | { | 33 | { |
| 34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); | 34 | struct nouveau_therm_priv *priv = data; |
| 35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | 35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; |
| 36 | struct i2c_client *client; | 36 | struct i2c_client *client; |
| 37 | 37 | ||
| @@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 98 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
| 99 | board, probe_monitoring_device); | 99 | board, probe_monitoring_device, therm); |
| 100 | if (priv->ic) | 100 | if (priv->ic) |
| 101 | return; | 101 | return; |
| 102 | } | 102 | } |
| @@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 110 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
| 111 | board, probe_monitoring_device); | 111 | board, probe_monitoring_device, therm); |
| 112 | if (priv->ic) | 112 | if (priv->ic) |
| 113 | return; | 113 | return; |
| 114 | } | 114 | } |
| @@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) | |||
| 117 | device. Let's try our static list. | 117 | device. Let's try our static list. |
| 118 | */ | 118 | */ |
| 119 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", | 119 | i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", |
| 120 | nv_board_infos, probe_monitoring_device); | 120 | nv_board_infos, probe_monitoring_device, therm); |
| 121 | } | 121 | } |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 936a71c59080..7fdc51e2a571 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c | |||
| @@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) | |||
| 643 | get_tmds_slave(encoder)) | 643 | get_tmds_slave(encoder)) |
| 644 | return; | 644 | return; |
| 645 | 645 | ||
| 646 | type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); | 646 | type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL); |
| 647 | if (type < 0) | 647 | if (type < 0) |
| 648 | return; | 648 | return; |
| 649 | 649 | ||
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index cc4b208ce546..244822df8ffc 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | |||
| @@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) | |||
| 59 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | 59 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |
| 60 | 60 | ||
| 61 | return i2c->identify(i2c, i2c_index, "TV encoder", | 61 | return i2c->identify(i2c, i2c_index, "TV encoder", |
| 62 | nv04_tv_encoder_info, NULL); | 62 | nv04_tv_encoder_info, NULL, NULL); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | 65 | ||
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 78be66176840..942509892895 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
| @@ -52,7 +52,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); | |||
| 52 | 52 | ||
| 53 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ | 53 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
| 54 | #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ | 54 | #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ |
| 55 | #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ | 55 | #define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */ |
| 56 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ | 56 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
| 57 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) | 57 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
| 58 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) | 58 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 21f4d7ff0da2..369d919bdafe 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1077,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
| 1077 | rdev->raid_disk = -1; | 1077 | rdev->raid_disk = -1; |
| 1078 | clear_bit(Faulty, &rdev->flags); | 1078 | clear_bit(Faulty, &rdev->flags); |
| 1079 | clear_bit(In_sync, &rdev->flags); | 1079 | clear_bit(In_sync, &rdev->flags); |
| 1080 | clear_bit(Bitmap_sync, &rdev->flags); | ||
| 1080 | clear_bit(WriteMostly, &rdev->flags); | 1081 | clear_bit(WriteMostly, &rdev->flags); |
| 1081 | 1082 | ||
| 1082 | if (mddev->raid_disks == 0) { | 1083 | if (mddev->raid_disks == 0) { |
| @@ -1155,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
| 1155 | */ | 1156 | */ |
| 1156 | if (ev1 < mddev->bitmap->events_cleared) | 1157 | if (ev1 < mddev->bitmap->events_cleared) |
| 1157 | return 0; | 1158 | return 0; |
| 1159 | if (ev1 < mddev->events) | ||
| 1160 | set_bit(Bitmap_sync, &rdev->flags); | ||
| 1158 | } else { | 1161 | } else { |
| 1159 | if (ev1 < mddev->events) | 1162 | if (ev1 < mddev->events) |
| 1160 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1163 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
| @@ -1563,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
| 1563 | rdev->raid_disk = -1; | 1566 | rdev->raid_disk = -1; |
| 1564 | clear_bit(Faulty, &rdev->flags); | 1567 | clear_bit(Faulty, &rdev->flags); |
| 1565 | clear_bit(In_sync, &rdev->flags); | 1568 | clear_bit(In_sync, &rdev->flags); |
| 1569 | clear_bit(Bitmap_sync, &rdev->flags); | ||
| 1566 | clear_bit(WriteMostly, &rdev->flags); | 1570 | clear_bit(WriteMostly, &rdev->flags); |
| 1567 | 1571 | ||
| 1568 | if (mddev->raid_disks == 0) { | 1572 | if (mddev->raid_disks == 0) { |
| @@ -1645,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
| 1645 | */ | 1649 | */ |
| 1646 | if (ev1 < mddev->bitmap->events_cleared) | 1650 | if (ev1 < mddev->bitmap->events_cleared) |
| 1647 | return 0; | 1651 | return 0; |
| 1652 | if (ev1 < mddev->events) | ||
| 1653 | set_bit(Bitmap_sync, &rdev->flags); | ||
| 1648 | } else { | 1654 | } else { |
| 1649 | if (ev1 < mddev->events) | 1655 | if (ev1 < mddev->events) |
| 1650 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1656 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
| @@ -2788,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
| 2788 | else | 2794 | else |
| 2789 | rdev->saved_raid_disk = -1; | 2795 | rdev->saved_raid_disk = -1; |
| 2790 | clear_bit(In_sync, &rdev->flags); | 2796 | clear_bit(In_sync, &rdev->flags); |
| 2797 | clear_bit(Bitmap_sync, &rdev->flags); | ||
| 2791 | err = rdev->mddev->pers-> | 2798 | err = rdev->mddev->pers-> |
| 2792 | hot_add_disk(rdev->mddev, rdev); | 2799 | hot_add_disk(rdev->mddev, rdev); |
| 2793 | if (err) { | 2800 | if (err) { |
| @@ -5760,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) | |||
| 5760 | info->raid_disk < mddev->raid_disks) { | 5767 | info->raid_disk < mddev->raid_disks) { |
| 5761 | rdev->raid_disk = info->raid_disk; | 5768 | rdev->raid_disk = info->raid_disk; |
| 5762 | set_bit(In_sync, &rdev->flags); | 5769 | set_bit(In_sync, &rdev->flags); |
| 5770 | clear_bit(Bitmap_sync, &rdev->flags); | ||
| 5763 | } else | 5771 | } else |
| 5764 | rdev->raid_disk = -1; | 5772 | rdev->raid_disk = -1; |
| 5765 | } else | 5773 | } else |
| @@ -7706,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev, | |||
| 7706 | if (test_bit(Faulty, &rdev->flags)) | 7714 | if (test_bit(Faulty, &rdev->flags)) |
| 7707 | continue; | 7715 | continue; |
| 7708 | if (mddev->ro && | 7716 | if (mddev->ro && |
| 7709 | rdev->saved_raid_disk < 0) | 7717 | ! (rdev->saved_raid_disk >= 0 && |
| 7718 | !test_bit(Bitmap_sync, &rdev->flags))) | ||
| 7710 | continue; | 7719 | continue; |
| 7711 | 7720 | ||
| 7712 | rdev->recovery_offset = 0; | 7721 | rdev->recovery_offset = 0; |
| @@ -7787,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev) | |||
| 7787 | * As we only add devices that are already in-sync, | 7796 | * As we only add devices that are already in-sync, |
| 7788 | * we can activate the spares immediately. | 7797 | * we can activate the spares immediately. |
| 7789 | */ | 7798 | */ |
| 7790 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
| 7791 | remove_and_add_spares(mddev, NULL); | 7799 | remove_and_add_spares(mddev, NULL); |
| 7792 | mddev->pers->spare_active(mddev); | 7800 | /* There is no thread, but we need to call |
| 7801 | * ->spare_active and clear saved_raid_disk | ||
| 7802 | */ | ||
| 7803 | md_reap_sync_thread(mddev); | ||
| 7804 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
| 7793 | goto unlock; | 7805 | goto unlock; |
| 7794 | } | 7806 | } |
| 7795 | 7807 | ||
diff --git a/drivers/md/md.h b/drivers/md/md.h index 2f5cc8a7ef3e..0095ec84ffc7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -129,6 +129,9 @@ struct md_rdev { | |||
| 129 | enum flag_bits { | 129 | enum flag_bits { |
| 130 | Faulty, /* device is known to have a fault */ | 130 | Faulty, /* device is known to have a fault */ |
| 131 | In_sync, /* device is in_sync with rest of array */ | 131 | In_sync, /* device is in_sync with rest of array */ |
| 132 | Bitmap_sync, /* ..actually, not quite In_sync. Need a | ||
| 133 | * bitmap-based recovery to get fully in sync | ||
| 134 | */ | ||
| 132 | Unmerged, /* device is being added to array and should | 135 | Unmerged, /* device is being added to array and should |
| 133 | * be considerred for bvec_merge_fn but not | 136 | * be considerred for bvec_merge_fn but not |
| 134 | * yet for actual IO | 137 | * yet for actual IO |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1e5a540995e9..a49cfcc7a343 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) | |||
| 924 | conf->next_window_requests++; | 924 | conf->next_window_requests++; |
| 925 | else | 925 | else |
| 926 | conf->current_window_requests++; | 926 | conf->current_window_requests++; |
| 927 | } | ||
| 928 | if (bio->bi_sector >= conf->start_next_window) | ||
| 929 | sector = conf->start_next_window; | 927 | sector = conf->start_next_window; |
| 928 | } | ||
| 930 | } | 929 | } |
| 931 | 930 | ||
| 932 | conf->nr_pending++; | 931 | conf->nr_pending++; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c504e8389e69..06eeb99ea6fc 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -1319,7 +1319,7 @@ read_again: | |||
| 1319 | /* Could not read all from this device, so we will | 1319 | /* Could not read all from this device, so we will |
| 1320 | * need another r10_bio. | 1320 | * need another r10_bio. |
| 1321 | */ | 1321 | */ |
| 1322 | sectors_handled = (r10_bio->sectors + max_sectors | 1322 | sectors_handled = (r10_bio->sector + max_sectors |
| 1323 | - bio->bi_sector); | 1323 | - bio->bi_sector); |
| 1324 | r10_bio->sectors = max_sectors; | 1324 | r10_bio->sectors = max_sectors; |
| 1325 | spin_lock_irq(&conf->device_lock); | 1325 | spin_lock_irq(&conf->device_lock); |
| @@ -1327,7 +1327,7 @@ read_again: | |||
| 1327 | bio->bi_phys_segments = 2; | 1327 | bio->bi_phys_segments = 2; |
| 1328 | else | 1328 | else |
| 1329 | bio->bi_phys_segments++; | 1329 | bio->bi_phys_segments++; |
| 1330 | spin_unlock(&conf->device_lock); | 1330 | spin_unlock_irq(&conf->device_lock); |
| 1331 | /* Cannot call generic_make_request directly | 1331 | /* Cannot call generic_make_request directly |
| 1332 | * as that will be queued in __generic_make_request | 1332 | * as that will be queued in __generic_make_request |
| 1333 | * and subsequent mempool_alloc might block | 1333 | * and subsequent mempool_alloc might block |
| @@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
| 3218 | if (j == conf->copies) { | 3218 | if (j == conf->copies) { |
| 3219 | /* Cannot recover, so abort the recovery or | 3219 | /* Cannot recover, so abort the recovery or |
| 3220 | * record a bad block */ | 3220 | * record a bad block */ |
| 3221 | put_buf(r10_bio); | ||
| 3222 | if (rb2) | ||
| 3223 | atomic_dec(&rb2->remaining); | ||
| 3224 | r10_bio = rb2; | ||
| 3225 | if (any_working) { | 3221 | if (any_working) { |
| 3226 | /* problem is that there are bad blocks | 3222 | /* problem is that there are bad blocks |
| 3227 | * on other device(s) | 3223 | * on other device(s) |
| @@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
| 3253 | mirror->recovery_disabled | 3249 | mirror->recovery_disabled |
| 3254 | = mddev->recovery_disabled; | 3250 | = mddev->recovery_disabled; |
| 3255 | } | 3251 | } |
| 3252 | put_buf(r10_bio); | ||
| 3253 | if (rb2) | ||
| 3254 | atomic_dec(&rb2->remaining); | ||
| 3255 | r10_bio = rb2; | ||
| 3256 | break; | 3256 | break; |
| 3257 | } | 3257 | } |
| 3258 | } | 3258 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cc055da02e2a..cbb15716a5db 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector, | |||
| 687 | } else { | 687 | } else { |
| 688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
| 689 | atomic_inc(&conf->active_stripes); | 689 | atomic_inc(&conf->active_stripes); |
| 690 | BUG_ON(list_empty(&sh->lru)); | 690 | BUG_ON(list_empty(&sh->lru) && |
| 691 | !test_bit(STRIPE_EXPANDING, &sh->state)); | ||
| 691 | list_del_init(&sh->lru); | 692 | list_del_init(&sh->lru); |
| 692 | if (sh->group) { | 693 | if (sh->group) { |
| 693 | sh->group->stripes_cnt--; | 694 | sh->group->stripes_cnt--; |
| @@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
| 3608 | */ | 3609 | */ |
| 3609 | set_bit(R5_Insync, &dev->flags); | 3610 | set_bit(R5_Insync, &dev->flags); |
| 3610 | 3611 | ||
| 3611 | if (rdev && test_bit(R5_WriteError, &dev->flags)) { | 3612 | if (test_bit(R5_WriteError, &dev->flags)) { |
| 3612 | /* This flag does not apply to '.replacement' | 3613 | /* This flag does not apply to '.replacement' |
| 3613 | * only to .rdev, so make sure to check that*/ | 3614 | * only to .rdev, so make sure to check that*/ |
| 3614 | struct md_rdev *rdev2 = rcu_dereference( | 3615 | struct md_rdev *rdev2 = rcu_dereference( |
| @@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
| 3621 | } else | 3622 | } else |
| 3622 | clear_bit(R5_WriteError, &dev->flags); | 3623 | clear_bit(R5_WriteError, &dev->flags); |
| 3623 | } | 3624 | } |
| 3624 | if (rdev && test_bit(R5_MadeGood, &dev->flags)) { | 3625 | if (test_bit(R5_MadeGood, &dev->flags)) { |
| 3625 | /* This flag does not apply to '.replacement' | 3626 | /* This flag does not apply to '.replacement' |
| 3626 | * only to .rdev, so make sure to check that*/ | 3627 | * only to .rdev, so make sure to check that*/ |
| 3627 | struct md_rdev *rdev2 = rcu_dereference( | 3628 | struct md_rdev *rdev2 = rcu_dereference( |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1f4a10ece2f1..e0259a163f98 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, | |||
| 516 | } | 516 | } |
| 517 | WARN_ON(inode->i_state & I_SYNC); | 517 | WARN_ON(inode->i_state & I_SYNC); |
| 518 | /* | 518 | /* |
| 519 | * Skip inode if it is clean. We don't want to mess with writeback | 519 | * Skip inode if it is clean and we have no outstanding writeback in |
| 520 | * lists in this function since flusher thread may be doing for example | 520 | * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this |
| 521 | * sync in parallel and if we move the inode, it could get skipped. So | 521 | * function since flusher thread may be doing for example sync in |
| 522 | * here we make sure inode is on some writeback list and leave it there | 522 | * parallel and if we move the inode, it could get skipped. So here we |
| 523 | * unless we have completely cleaned the inode. | 523 | * make sure inode is on some writeback list and leave it there unless |
| 524 | * we have completely cleaned the inode. | ||
| 524 | */ | 525 | */ |
| 525 | if (!(inode->i_state & I_DIRTY)) | 526 | if (!(inode->i_state & I_DIRTY) && |
| 527 | (wbc->sync_mode != WB_SYNC_ALL || | ||
| 528 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))) | ||
| 526 | goto out; | 529 | goto out; |
| 527 | inode->i_state |= I_SYNC; | 530 | inode->i_state |= I_SYNC; |
| 528 | spin_unlock(&inode->i_lock); | 531 | spin_unlock(&inode->i_lock); |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9f6b486b6c01..a1a191634abc 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -1440,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, | |||
| 1440 | 1440 | ||
| 1441 | nilfs_clear_logs(&sci->sc_segbufs); | 1441 | nilfs_clear_logs(&sci->sc_segbufs); |
| 1442 | 1442 | ||
| 1443 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); | ||
| 1444 | if (unlikely(err)) | ||
| 1445 | return err; | ||
| 1446 | |||
| 1447 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { | 1443 | if (sci->sc_stage.flags & NILFS_CF_SUFREED) { |
| 1448 | err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, | 1444 | err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, |
| 1449 | sci->sc_freesegs, | 1445 | sci->sc_freesegs, |
| 1450 | sci->sc_nfreesegs, | 1446 | sci->sc_nfreesegs, |
| 1451 | NULL); | 1447 | NULL); |
| 1452 | WARN_ON(err); /* do not happen */ | 1448 | WARN_ON(err); /* do not happen */ |
| 1449 | sci->sc_stage.flags &= ~NILFS_CF_SUFREED; | ||
| 1453 | } | 1450 | } |
| 1451 | |||
| 1452 | err = nilfs_segctor_extend_segments(sci, nilfs, nadd); | ||
| 1453 | if (unlikely(err)) | ||
| 1454 | return err; | ||
| 1455 | |||
| 1454 | nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); | 1456 | nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); |
| 1455 | sci->sc_stage = prev_stage; | 1457 | sci->sc_stage = prev_stage; |
| 1456 | } | 1458 | } |
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index fe68a5a98583..7032518f8542 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | #include <linux/proc_fs.h> | 6 | #include <linux/proc_fs.h> |
| 7 | #include <linux/elf.h> | 7 | #include <linux/elf.h> |
| 8 | 8 | ||
| 9 | #include <asm/pgtable.h> /* for pgprot_t */ | ||
| 10 | |||
| 9 | #define ELFCORE_ADDR_MAX (-1ULL) | 11 | #define ELFCORE_ADDR_MAX (-1ULL) |
| 10 | #define ELFCORE_ADDR_ERR (-2ULL) | 12 | #define ELFCORE_ADDR_ERR (-2ULL) |
| 11 | 13 | ||
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index eff50e062be8..d9c8dbd3373f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
| @@ -445,7 +445,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) | |||
| 445 | static inline struct i2c_adapter * | 445 | static inline struct i2c_adapter * |
| 446 | i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) | 446 | i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) |
| 447 | { | 447 | { |
| 448 | #if IS_ENABLED(I2C_MUX) | 448 | #if IS_ENABLED(CONFIG_I2C_MUX) |
| 449 | struct device *parent = adapter->dev.parent; | 449 | struct device *parent = adapter->dev.parent; |
| 450 | 450 | ||
| 451 | if (parent != NULL && parent->type == &i2c_adapter_type) | 451 | if (parent != NULL && parent->type == &i2c_adapter_type) |
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index 7473ee3b4ee7..1da85bb1bc07 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c | |||
| @@ -82,10 +82,10 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) | |||
| 82 | unsigned long flags; | 82 | unsigned long flags; |
| 83 | raw_spin_lock_irqsave(&fbc->lock, flags); | 83 | raw_spin_lock_irqsave(&fbc->lock, flags); |
| 84 | fbc->count += count; | 84 | fbc->count += count; |
| 85 | __this_cpu_sub(*fbc->counters, count); | ||
| 85 | raw_spin_unlock_irqrestore(&fbc->lock, flags); | 86 | raw_spin_unlock_irqrestore(&fbc->lock, flags); |
| 86 | __this_cpu_write(*fbc->counters, 0); | ||
| 87 | } else { | 87 | } else { |
| 88 | __this_cpu_write(*fbc->counters, count); | 88 | this_cpu_add(*fbc->counters, amount); |
| 89 | } | 89 | } |
| 90 | preempt_enable(); | 90 | preempt_enable(); |
| 91 | } | 91 | } |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 9c0b17295ba0..95d1acb0f3d2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
| @@ -1154,7 +1154,7 @@ alloc: | |||
| 1154 | new_page = NULL; | 1154 | new_page = NULL; |
| 1155 | 1155 | ||
| 1156 | if (unlikely(!new_page)) { | 1156 | if (unlikely(!new_page)) { |
| 1157 | if (is_huge_zero_pmd(orig_pmd)) { | 1157 | if (!page) { |
| 1158 | ret = do_huge_pmd_wp_zero_page_fallback(mm, vma, | 1158 | ret = do_huge_pmd_wp_zero_page_fallback(mm, vma, |
| 1159 | address, pmd, orig_pmd, haddr); | 1159 | address, pmd, orig_pmd, haddr); |
| 1160 | } else { | 1160 | } else { |
| @@ -1181,7 +1181,7 @@ alloc: | |||
| 1181 | 1181 | ||
| 1182 | count_vm_event(THP_FAULT_ALLOC); | 1182 | count_vm_event(THP_FAULT_ALLOC); |
| 1183 | 1183 | ||
| 1184 | if (is_huge_zero_pmd(orig_pmd)) | 1184 | if (!page) |
| 1185 | clear_huge_page(new_page, haddr, HPAGE_PMD_NR); | 1185 | clear_huge_page(new_page, haddr, HPAGE_PMD_NR); |
| 1186 | else | 1186 | else |
| 1187 | copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR); | 1187 | copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR); |
| @@ -1207,7 +1207,7 @@ alloc: | |||
| 1207 | page_add_new_anon_rmap(new_page, vma, haddr); | 1207 | page_add_new_anon_rmap(new_page, vma, haddr); |
| 1208 | set_pmd_at(mm, haddr, pmd, entry); | 1208 | set_pmd_at(mm, haddr, pmd, entry); |
| 1209 | update_mmu_cache_pmd(vma, address, pmd); | 1209 | update_mmu_cache_pmd(vma, address, pmd); |
| 1210 | if (is_huge_zero_pmd(orig_pmd)) { | 1210 | if (!page) { |
| 1211 | add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); | 1211 | add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR); |
| 1212 | put_huge_zero_page(); | 1212 | put_huge_zero_page(); |
| 1213 | } else { | 1213 | } else { |
| @@ -390,7 +390,10 @@ struct address_space *page_mapping(struct page *page) | |||
| 390 | { | 390 | { |
| 391 | struct address_space *mapping = page->mapping; | 391 | struct address_space *mapping = page->mapping; |
| 392 | 392 | ||
| 393 | VM_BUG_ON(PageSlab(page)); | 393 | /* This happens if someone calls flush_dcache_page on slab page */ |
| 394 | if (unlikely(PageSlab(page))) | ||
| 395 | return NULL; | ||
| 396 | |||
| 394 | if (unlikely(PageSwapCache(page))) { | 397 | if (unlikely(PageSwapCache(page))) { |
| 395 | swp_entry_t entry; | 398 | swp_entry_t entry; |
| 396 | 399 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6625699f497c..57b0b49f4e6e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -234,6 +234,14 @@ static int inode_alloc_security(struct inode *inode) | |||
| 234 | return 0; | 234 | return 0; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | static void inode_free_rcu(struct rcu_head *head) | ||
| 238 | { | ||
| 239 | struct inode_security_struct *isec; | ||
| 240 | |||
| 241 | isec = container_of(head, struct inode_security_struct, rcu); | ||
| 242 | kmem_cache_free(sel_inode_cache, isec); | ||
| 243 | } | ||
| 244 | |||
| 237 | static void inode_free_security(struct inode *inode) | 245 | static void inode_free_security(struct inode *inode) |
| 238 | { | 246 | { |
| 239 | struct inode_security_struct *isec = inode->i_security; | 247 | struct inode_security_struct *isec = inode->i_security; |
| @@ -244,8 +252,16 @@ static void inode_free_security(struct inode *inode) | |||
| 244 | list_del_init(&isec->list); | 252 | list_del_init(&isec->list); |
| 245 | spin_unlock(&sbsec->isec_lock); | 253 | spin_unlock(&sbsec->isec_lock); |
| 246 | 254 | ||
| 247 | inode->i_security = NULL; | 255 | /* |
| 248 | kmem_cache_free(sel_inode_cache, isec); | 256 | * The inode may still be referenced in a path walk and |
| 257 | * a call to selinux_inode_permission() can be made | ||
| 258 | * after inode_free_security() is called. Ideally, the VFS | ||
| 259 | * wouldn't do this, but fixing that is a much harder | ||
| 260 | * job. For now, simply free the i_security via RCU, and | ||
| 261 | * leave the current inode->i_security pointer intact. | ||
| 262 | * The inode will be freed after the RCU grace period too. | ||
| 263 | */ | ||
| 264 | call_rcu(&isec->rcu, inode_free_rcu); | ||
| 249 | } | 265 | } |
| 250 | 266 | ||
| 251 | static int file_alloc_security(struct file *file) | 267 | static int file_alloc_security(struct file *file) |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index b1dfe1049450..078e553f52f2 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -38,7 +38,10 @@ struct task_security_struct { | |||
| 38 | 38 | ||
| 39 | struct inode_security_struct { | 39 | struct inode_security_struct { |
| 40 | struct inode *inode; /* back pointer to inode object */ | 40 | struct inode *inode; /* back pointer to inode object */ |
| 41 | struct list_head list; /* list of inode_security_struct */ | 41 | union { |
| 42 | struct list_head list; /* list of inode_security_struct */ | ||
| 43 | struct rcu_head rcu; /* for freeing the inode_security_struct */ | ||
| 44 | }; | ||
| 42 | u32 task_sid; /* SID of creating task */ | 45 | u32 task_sid; /* SID of creating task */ |
| 43 | u32 sid; /* SID of this object */ | 46 | u32 sid; /* SID of this object */ |
| 44 | u16 sclass; /* security class of this object */ | 47 | u16 sclass; /* security class of this object */ |
