diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 19:31:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 19:31:41 -0500 |
commit | 5a62f995446be44811fefa48f91f9efb7ea172d7 (patch) | |
tree | e297371f0d513dc6278bb67d582d2216eb7d74ed /arch/powerpc/kernel | |
parent | f1d6d6cd9029daa7e7d4a0b14347b5392320f22a (diff) | |
parent | 5d7d8072edc11080a7cf6cc37c9f4e61ca1e93c9 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (72 commits)
powerpc/pseries: Fix build of topology stuff without CONFIG_NUMA
powerpc/pseries: Fix VPHN build errors on non-SMP systems
powerpc/83xx: add mpc8308_p1m DMA controller device-tree node
powerpc/83xx: add DMA controller to mpc8308 device-tree node
powerpc/512x: try to free dma descriptors in case of allocation failure
powerpc/512x: add MPC8308 dma support
powerpc/512x: fix the hanged dma transfer issue
powerpc/512x: scatter/gather dma fix
powerpc/powermac: Make auto-loading of therm_pm72 possible
of/address: Use propper endianess in get_flags
powerpc/pci: Use printf extension %pR for struct resource
powerpc: Remove unnecessary casts of void ptr
powerpc: Disable VPHN polling during a suspend operation
powerpc/pseries: Poll VPA for topology changes and update NUMA maps
powerpc: iommu: Add device name to iommu error printks
powerpc: Record vma->phys_addr in ioremap()
powerpc: Update compat_arch_ptrace
powerpc: Fix PPC_PTRACE_SETHWDEBUG on PPC_BOOK3S
powerpc/time: printk time stamp init not correct
powerpc: Minor cleanups for machdep.h
...
Diffstat (limited to 'arch/powerpc/kernel')
29 files changed, 301 insertions, 366 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 36c30f31ec93..3bb2a3e6a337 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -29,8 +29,10 @@ endif | |||
29 | obj-y := cputable.o ptrace.o syscalls.o \ | 29 | obj-y := cputable.o ptrace.o syscalls.o \ |
30 | irq.o align.o signal_32.o pmc.o vdso.o \ | 30 | irq.o align.o signal_32.o pmc.o vdso.o \ |
31 | init_task.o process.o systbl.o idle.o \ | 31 | init_task.o process.o systbl.o idle.o \ |
32 | signal.o sysfs.o cacheinfo.o | 32 | signal.o sysfs.o cacheinfo.o time.o \ |
33 | obj-y += vdso32/ | 33 | prom.o traps.o setup-common.o \ |
34 | udbg.o misc.o io.o dma.o \ | ||
35 | misc_$(CONFIG_WORD_SIZE).o vdso32/ | ||
34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ | 36 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
35 | signal_64.o ptrace32.o \ | 37 | signal_64.o ptrace32.o \ |
36 | paca.o nvram_64.o firmware.o | 38 | paca.o nvram_64.o firmware.o |
@@ -80,9 +82,6 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | |||
80 | extra-$(CONFIG_8xx) := head_8xx.o | 82 | extra-$(CONFIG_8xx) := head_8xx.o |
81 | extra-y += vmlinux.lds | 83 | extra-y += vmlinux.lds |
82 | 84 | ||
83 | obj-y += time.o prom.o traps.o setup-common.o \ | ||
84 | udbg.o misc.o io.o dma.o \ | ||
85 | misc_$(CONFIG_WORD_SIZE).o | ||
86 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o | 85 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o |
87 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o | 86 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o |
88 | obj-$(CONFIG_KGDB) += kgdb.o | 87 | obj-$(CONFIG_KGDB) += kgdb.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index bd0df2e6aa8f..23e6a93145ab 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -209,7 +209,6 @@ int main(void) | |||
209 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); | 209 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); |
210 | 210 | ||
211 | /* Interrupt register frame */ | 211 | /* Interrupt register frame */ |
212 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | ||
213 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); | 212 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); |
214 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | 213 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); |
215 | #ifdef CONFIG_PPC64 | 214 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 96a908f1cd87..be5ab18b03b5 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -457,16 +457,26 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
457 | .dcache_bsize = 128, | 457 | .dcache_bsize = 128, |
458 | .num_pmcs = 6, | 458 | .num_pmcs = 6, |
459 | .pmc_type = PPC_PMC_IBM, | 459 | .pmc_type = PPC_PMC_IBM, |
460 | .cpu_setup = __setup_cpu_power7, | ||
461 | .cpu_restore = __restore_cpu_power7, | ||
462 | .oprofile_cpu_type = "ppc64/power7", | 460 | .oprofile_cpu_type = "ppc64/power7", |
463 | .oprofile_type = PPC_OPROFILE_POWER4, | 461 | .oprofile_type = PPC_OPROFILE_POWER4, |
464 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
465 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
466 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
467 | POWER6_MMCRA_OTHER, | ||
468 | .platform = "power7", | 462 | .platform = "power7", |
469 | }, | 463 | }, |
464 | { /* Power7+ */ | ||
465 | .pvr_mask = 0xffff0000, | ||
466 | .pvr_value = 0x004A0000, | ||
467 | .cpu_name = "POWER7+ (raw)", | ||
468 | .cpu_features = CPU_FTRS_POWER7, | ||
469 | .cpu_user_features = COMMON_USER_POWER7, | ||
470 | .mmu_features = MMU_FTR_HPTE_TABLE | | ||
471 | MMU_FTR_TLBIE_206, | ||
472 | .icache_bsize = 128, | ||
473 | .dcache_bsize = 128, | ||
474 | .num_pmcs = 6, | ||
475 | .pmc_type = PPC_PMC_IBM, | ||
476 | .oprofile_cpu_type = "ppc64/power7", | ||
477 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
478 | .platform = "power7+", | ||
479 | }, | ||
470 | { /* Cell Broadband Engine */ | 480 | { /* Cell Broadband Engine */ |
471 | .pvr_mask = 0xffff0000, | 481 | .pvr_mask = 0xffff0000, |
472 | .pvr_value = 0x00700000, | 482 | .pvr_value = 0x00700000, |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 8e05c16344e4..0a2af50243cb 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/firmware.h> | 20 | #include <asm/firmware.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include <asm/rtas.h> | ||
22 | 23 | ||
23 | #ifdef DEBUG | 24 | #ifdef DEBUG |
24 | #include <asm/udbg.h> | 25 | #include <asm/udbg.h> |
@@ -141,3 +142,35 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
141 | 142 | ||
142 | return csize; | 143 | return csize; |
143 | } | 144 | } |
145 | |||
146 | #ifdef CONFIG_PPC_RTAS | ||
147 | /* | ||
148 | * The crashkernel region will almost always overlap the RTAS region, so | ||
149 | * we have to be careful when shrinking the crashkernel region. | ||
150 | */ | ||
151 | void crash_free_reserved_phys_range(unsigned long begin, unsigned long end) | ||
152 | { | ||
153 | unsigned long addr; | ||
154 | const u32 *basep, *sizep; | ||
155 | unsigned int rtas_start = 0, rtas_end = 0; | ||
156 | |||
157 | basep = of_get_property(rtas.dev, "linux,rtas-base", NULL); | ||
158 | sizep = of_get_property(rtas.dev, "rtas-size", NULL); | ||
159 | |||
160 | if (basep && sizep) { | ||
161 | rtas_start = *basep; | ||
162 | rtas_end = *basep + *sizep; | ||
163 | } | ||
164 | |||
165 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
166 | /* Does this page overlap with the RTAS region? */ | ||
167 | if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start)) | ||
168 | continue; | ||
169 | |||
170 | ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); | ||
171 | init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); | ||
172 | free_page((unsigned long)__va(addr)); | ||
173 | totalram_pages++; | ||
174 | } | ||
175 | } | ||
176 | #endif | ||
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 6e54a0fd31aa..e7554154a6de 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c | |||
@@ -19,7 +19,7 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size, | |||
19 | dma_addr_t *dma_handle, gfp_t flag) | 19 | dma_addr_t *dma_handle, gfp_t flag) |
20 | { | 20 | { |
21 | return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, | 21 | return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size, |
22 | dma_handle, device_to_mask(dev), flag, | 22 | dma_handle, dev->coherent_dma_mask, flag, |
23 | dev_to_node(dev)); | 23 | dev_to_node(dev)); |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index ed4aeb96398b..c22dc1ec1c94 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/asm-offsets.h> | 31 | #include <asm/asm-offsets.h> |
32 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
33 | #include <asm/ftrace.h> | 33 | #include <asm/ftrace.h> |
34 | #include <asm/ptrace.h> | ||
34 | 35 | ||
35 | #undef SHOW_SYSCALLS | 36 | #undef SHOW_SYSCALLS |
36 | #undef SHOW_SYSCALLS_TASK | 37 | #undef SHOW_SYSCALLS_TASK |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 9f8b01d6466f..8a817995b4cd 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <asm/exception-64s.h> | 15 | #include <asm/exception-64s.h> |
16 | #include <asm/ptrace.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * We layout physical memory as follows: | 19 | * We layout physical memory as follows: |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e86c040ae585..de369558bf0a 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/thread_info.h> | 23 | #include <asm/thread_info.h> |
24 | #include <asm/ppc_asm.h> | 24 | #include <asm/ppc_asm.h> |
25 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
26 | #include <asm/ptrace.h> | ||
26 | 27 | ||
27 | #ifdef CONFIG_VSX | 28 | #ifdef CONFIG_VSX |
28 | #define REST_32FPVSRS(n,c,base) \ | 29 | #define REST_32FPVSRS(n,c,base) \ |
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index 8278e8bad5a0..9dd21a8c4d52 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/thread_info.h> | 40 | #include <asm/thread_info.h> |
41 | #include <asm/ppc_asm.h> | 41 | #include <asm/ppc_asm.h> |
42 | #include <asm/asm-offsets.h> | 42 | #include <asm/asm-offsets.h> |
43 | #include <asm/ptrace.h> | ||
43 | 44 | ||
44 | /* As with the other PowerPC ports, it is expected that when code | 45 | /* As with the other PowerPC ports, it is expected that when code |
45 | * execution begins here, the following registers contain valid, yet | 46 | * execution begins here, the following registers contain valid, yet |
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 562305b40a8e..cbb3436b592d 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/thread_info.h> | 37 | #include <asm/thread_info.h> |
38 | #include <asm/ppc_asm.h> | 38 | #include <asm/ppc_asm.h> |
39 | #include <asm/asm-offsets.h> | 39 | #include <asm/asm-offsets.h> |
40 | #include <asm/ptrace.h> | ||
40 | #include <asm/synch.h> | 41 | #include <asm/synch.h> |
41 | #include "head_booke.h" | 42 | #include "head_booke.h" |
42 | 43 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index f0dd577e4a5b..782f23df7c85 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/page_64.h> | 38 | #include <asm/page_64.h> |
39 | #include <asm/irqflags.h> | 39 | #include <asm/irqflags.h> |
40 | #include <asm/kvm_book3s_asm.h> | 40 | #include <asm/kvm_book3s_asm.h> |
41 | #include <asm/ptrace.h> | ||
41 | 42 | ||
42 | /* The physical memory is layed out such that the secondary processor | 43 | /* The physical memory is layed out such that the secondary processor |
43 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow | 44 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow |
@@ -96,7 +97,7 @@ __secondary_hold_acknowledge: | |||
96 | .llong hvReleaseData-KERNELBASE | 97 | .llong hvReleaseData-KERNELBASE |
97 | #endif /* CONFIG_PPC_ISERIES */ | 98 | #endif /* CONFIG_PPC_ISERIES */ |
98 | 99 | ||
99 | #ifdef CONFIG_CRASH_DUMP | 100 | #ifdef CONFIG_RELOCATABLE |
100 | /* This flag is set to 1 by a loader if the kernel should run | 101 | /* This flag is set to 1 by a loader if the kernel should run |
101 | * at the loaded address instead of the linked address. This | 102 | * at the loaded address instead of the linked address. This |
102 | * is used by kexec-tools to keep the the kdump kernel in the | 103 | * is used by kexec-tools to keep the the kdump kernel in the |
@@ -384,12 +385,10 @@ _STATIC(__after_prom_start) | |||
384 | /* process relocations for the final address of the kernel */ | 385 | /* process relocations for the final address of the kernel */ |
385 | lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ | 386 | lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ |
386 | sldi r25,r25,32 | 387 | sldi r25,r25,32 |
387 | #ifdef CONFIG_CRASH_DUMP | ||
388 | lwz r7,__run_at_load-_stext(r26) | 388 | lwz r7,__run_at_load-_stext(r26) |
389 | cmplwi cr0,r7,1 /* kdump kernel ? - stay where we are */ | 389 | cmplwi cr0,r7,1 /* flagged to stay where we are ? */ |
390 | bne 1f | 390 | bne 1f |
391 | add r25,r25,r26 | 391 | add r25,r25,r26 |
392 | #endif | ||
393 | 1: mr r3,r25 | 392 | 1: mr r3,r25 |
394 | bl .relocate | 393 | bl .relocate |
395 | #endif | 394 | #endif |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 1f1a04b5c2a4..1cbf64e6b416 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/thread_info.h> | 29 | #include <asm/thread_info.h> |
30 | #include <asm/ppc_asm.h> | 30 | #include <asm/ppc_asm.h> |
31 | #include <asm/asm-offsets.h> | 31 | #include <asm/asm-offsets.h> |
32 | #include <asm/ptrace.h> | ||
32 | 33 | ||
33 | /* Macro to make the code more readable. */ | 34 | /* Macro to make the code more readable. */ |
34 | #ifdef CONFIG_8xx_CPU6 | 35 | #ifdef CONFIG_8xx_CPU6 |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 529b817f473b..3e02710d9562 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <asm/ppc_asm.h> | 41 | #include <asm/ppc_asm.h> |
42 | #include <asm/asm-offsets.h> | 42 | #include <asm/asm-offsets.h> |
43 | #include <asm/cache.h> | 43 | #include <asm/cache.h> |
44 | #include <asm/ptrace.h> | ||
44 | #include "head_booke.h" | 45 | #include "head_booke.h" |
45 | 46 | ||
46 | /* As with the other PowerPC ports, it is expected that when code | 47 | /* As with the other PowerPC ports, it is expected that when code |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index d5839179ec77..961bb03413f3 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -311,8 +311,9 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
311 | /* Handle failure */ | 311 | /* Handle failure */ |
312 | if (unlikely(entry == DMA_ERROR_CODE)) { | 312 | if (unlikely(entry == DMA_ERROR_CODE)) { |
313 | if (printk_ratelimit()) | 313 | if (printk_ratelimit()) |
314 | printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %lx" | 314 | dev_info(dev, "iommu_alloc failed, tbl %p " |
315 | " npages %lx\n", tbl, vaddr, npages); | 315 | "vaddr %lx npages %lu\n", tbl, vaddr, |
316 | npages); | ||
316 | goto failure; | 317 | goto failure; |
317 | } | 318 | } |
318 | 319 | ||
@@ -579,9 +580,9 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl, | |||
579 | attrs); | 580 | attrs); |
580 | if (dma_handle == DMA_ERROR_CODE) { | 581 | if (dma_handle == DMA_ERROR_CODE) { |
581 | if (printk_ratelimit()) { | 582 | if (printk_ratelimit()) { |
582 | printk(KERN_INFO "iommu_alloc failed, " | 583 | dev_info(dev, "iommu_alloc failed, tbl %p " |
583 | "tbl %p vaddr %p npages %d\n", | 584 | "vaddr %p npages %d\n", tbl, vaddr, |
584 | tbl, vaddr, npages); | 585 | npages); |
585 | } | 586 | } |
586 | } else | 587 | } else |
587 | dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); | 588 | dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); |
@@ -627,7 +628,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, | |||
627 | * the tce tables. | 628 | * the tce tables. |
628 | */ | 629 | */ |
629 | if (order >= IOMAP_MAX_ORDER) { | 630 | if (order >= IOMAP_MAX_ORDER) { |
630 | printk("iommu_alloc_consistent size too large: 0x%lx\n", size); | 631 | dev_info(dev, "iommu_alloc_consistent size too large: 0x%lx\n", |
632 | size); | ||
631 | return NULL; | 633 | return NULL; |
632 | } | 634 | } |
633 | 635 | ||
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 2d29752cbe16..b69463ec2010 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -122,8 +122,3 @@ _GLOBAL(longjmp) | |||
122 | mtlr r0 | 122 | mtlr r0 |
123 | mr r3,r4 | 123 | mr r3,r4 |
124 | blr | 124 | blr |
125 | |||
126 | _GLOBAL(__setup_cpu_power7) | ||
127 | _GLOBAL(__restore_cpu_power7) | ||
128 | /* place holder */ | ||
129 | blr | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index a7a570dcdd57..094bd9821ad4 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
31 | #include <asm/kexec.h> | 31 | #include <asm/kexec.h> |
32 | #include <asm/bug.h> | 32 | #include <asm/bug.h> |
33 | #include <asm/ptrace.h> | ||
33 | 34 | ||
34 | .text | 35 | .text |
35 | 36 | ||
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index e5144906a56d..206a321a71d3 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/cputable.h> | 25 | #include <asm/cputable.h> |
26 | #include <asm/thread_info.h> | 26 | #include <asm/thread_info.h> |
27 | #include <asm/kexec.h> | 27 | #include <asm/kexec.h> |
28 | #include <asm/ptrace.h> | ||
28 | 29 | ||
29 | .text | 30 | .text |
30 | 31 | ||
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 9cf197f01e94..bb12b3248f13 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -34,15 +34,26 @@ | |||
34 | 34 | ||
35 | #undef DEBUG_NVRAM | 35 | #undef DEBUG_NVRAM |
36 | 36 | ||
37 | static struct nvram_partition * nvram_part; | 37 | #define NVRAM_HEADER_LEN sizeof(struct nvram_header) |
38 | static long nvram_error_log_index = -1; | 38 | #define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN |
39 | static long nvram_error_log_size = 0; | 39 | |
40 | /* If change this size, then change the size of NVNAME_LEN */ | ||
41 | struct nvram_header { | ||
42 | unsigned char signature; | ||
43 | unsigned char checksum; | ||
44 | unsigned short length; | ||
45 | /* Terminating null required only for names < 12 chars. */ | ||
46 | char name[12]; | ||
47 | }; | ||
40 | 48 | ||
41 | struct err_log_info { | 49 | struct nvram_partition { |
42 | int error_type; | 50 | struct list_head partition; |
43 | unsigned int seq_num; | 51 | struct nvram_header header; |
52 | unsigned int index; | ||
44 | }; | 53 | }; |
45 | 54 | ||
55 | static LIST_HEAD(nvram_partitions); | ||
56 | |||
46 | static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) | 57 | static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) |
47 | { | 58 | { |
48 | int size; | 59 | int size; |
@@ -186,14 +197,12 @@ static struct miscdevice nvram_dev = { | |||
186 | #ifdef DEBUG_NVRAM | 197 | #ifdef DEBUG_NVRAM |
187 | static void __init nvram_print_partitions(char * label) | 198 | static void __init nvram_print_partitions(char * label) |
188 | { | 199 | { |
189 | struct list_head * p; | ||
190 | struct nvram_partition * tmp_part; | 200 | struct nvram_partition * tmp_part; |
191 | 201 | ||
192 | printk(KERN_WARNING "--------%s---------\n", label); | 202 | printk(KERN_WARNING "--------%s---------\n", label); |
193 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); | 203 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); |
194 | list_for_each(p, &nvram_part->partition) { | 204 | list_for_each_entry(tmp_part, &nvram_partitions, partition) { |
195 | tmp_part = list_entry(p, struct nvram_partition, partition); | 205 | printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12s\n", |
196 | printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", | ||
197 | tmp_part->index, tmp_part->header.signature, | 206 | tmp_part->index, tmp_part->header.signature, |
198 | tmp_part->header.checksum, tmp_part->header.length, | 207 | tmp_part->header.checksum, tmp_part->header.length, |
199 | tmp_part->header.name); | 208 | tmp_part->header.name); |
@@ -228,95 +237,113 @@ static unsigned char __init nvram_checksum(struct nvram_header *p) | |||
228 | return c_sum; | 237 | return c_sum; |
229 | } | 238 | } |
230 | 239 | ||
231 | static int __init nvram_remove_os_partition(void) | 240 | /** |
241 | * nvram_remove_partition - Remove one or more partitions in nvram | ||
242 | * @name: name of the partition to remove, or NULL for a | ||
243 | * signature only match | ||
244 | * @sig: signature of the partition(s) to remove | ||
245 | */ | ||
246 | |||
247 | int __init nvram_remove_partition(const char *name, int sig) | ||
232 | { | 248 | { |
233 | struct list_head *i; | 249 | struct nvram_partition *part, *prev, *tmp; |
234 | struct list_head *j; | ||
235 | struct nvram_partition * part; | ||
236 | struct nvram_partition * cur_part; | ||
237 | int rc; | 250 | int rc; |
238 | 251 | ||
239 | list_for_each(i, &nvram_part->partition) { | 252 | list_for_each_entry(part, &nvram_partitions, partition) { |
240 | part = list_entry(i, struct nvram_partition, partition); | 253 | if (part->header.signature != sig) |
241 | if (part->header.signature != NVRAM_SIG_OS) | ||
242 | continue; | 254 | continue; |
243 | 255 | if (name && strncmp(name, part->header.name, 12)) | |
244 | /* Make os partition a free partition */ | 256 | continue; |
257 | |||
258 | /* Make partition a free partition */ | ||
245 | part->header.signature = NVRAM_SIG_FREE; | 259 | part->header.signature = NVRAM_SIG_FREE; |
246 | sprintf(part->header.name, "wwwwwwwwwwww"); | 260 | strncpy(part->header.name, "wwwwwwwwwwww", 12); |
247 | part->header.checksum = nvram_checksum(&part->header); | 261 | part->header.checksum = nvram_checksum(&part->header); |
248 | |||
249 | /* Merge contiguous free partitions backwards */ | ||
250 | list_for_each_prev(j, &part->partition) { | ||
251 | cur_part = list_entry(j, struct nvram_partition, partition); | ||
252 | if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | part->header.length += cur_part->header.length; | ||
257 | part->header.checksum = nvram_checksum(&part->header); | ||
258 | part->index = cur_part->index; | ||
259 | |||
260 | list_del(&cur_part->partition); | ||
261 | kfree(cur_part); | ||
262 | j = &part->partition; /* fixup our loop */ | ||
263 | } | ||
264 | |||
265 | /* Merge contiguous free partitions forwards */ | ||
266 | list_for_each(j, &part->partition) { | ||
267 | cur_part = list_entry(j, struct nvram_partition, partition); | ||
268 | if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | part->header.length += cur_part->header.length; | ||
273 | part->header.checksum = nvram_checksum(&part->header); | ||
274 | |||
275 | list_del(&cur_part->partition); | ||
276 | kfree(cur_part); | ||
277 | j = &part->partition; /* fixup our loop */ | ||
278 | } | ||
279 | |||
280 | rc = nvram_write_header(part); | 262 | rc = nvram_write_header(part); |
281 | if (rc <= 0) { | 263 | if (rc <= 0) { |
282 | printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc); | 264 | printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc); |
283 | return rc; | 265 | return rc; |
284 | } | 266 | } |
267 | } | ||
285 | 268 | ||
269 | /* Merge contiguous ones */ | ||
270 | prev = NULL; | ||
271 | list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) { | ||
272 | if (part->header.signature != NVRAM_SIG_FREE) { | ||
273 | prev = NULL; | ||
274 | continue; | ||
275 | } | ||
276 | if (prev) { | ||
277 | prev->header.length += part->header.length; | ||
278 | prev->header.checksum = nvram_checksum(&part->header); | ||
279 | rc = nvram_write_header(part); | ||
280 | if (rc <= 0) { | ||
281 | printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc); | ||
282 | return rc; | ||
283 | } | ||
284 | list_del(&part->partition); | ||
285 | kfree(part); | ||
286 | } else | ||
287 | prev = part; | ||
286 | } | 288 | } |
287 | 289 | ||
288 | return 0; | 290 | return 0; |
289 | } | 291 | } |
290 | 292 | ||
291 | /* nvram_create_os_partition | 293 | /** |
294 | * nvram_create_partition - Create a partition in nvram | ||
295 | * @name: name of the partition to create | ||
296 | * @sig: signature of the partition to create | ||
297 | * @req_size: size of data to allocate in bytes | ||
298 | * @min_size: minimum acceptable size (0 means req_size) | ||
292 | * | 299 | * |
293 | * Create a OS linux partition to buffer error logs. | 300 | * Returns a negative error code or a positive nvram index |
294 | * Will create a partition starting at the first free | 301 | * of the beginning of the data area of the newly created |
295 | * space found if space has enough room. | 302 | * partition. If you provided a min_size smaller than req_size |
303 | * you need to query for the actual size yourself after the | ||
304 | * call using nvram_partition_get_size(). | ||
296 | */ | 305 | */ |
297 | static int __init nvram_create_os_partition(void) | 306 | loff_t __init nvram_create_partition(const char *name, int sig, |
307 | int req_size, int min_size) | ||
298 | { | 308 | { |
299 | struct nvram_partition *part; | 309 | struct nvram_partition *part; |
300 | struct nvram_partition *new_part; | 310 | struct nvram_partition *new_part; |
301 | struct nvram_partition *free_part = NULL; | 311 | struct nvram_partition *free_part = NULL; |
302 | int seq_init[2] = { 0, 0 }; | 312 | static char nv_init_vals[16]; |
303 | loff_t tmp_index; | 313 | loff_t tmp_index; |
304 | long size = 0; | 314 | long size = 0; |
305 | int rc; | 315 | int rc; |
306 | 316 | ||
317 | /* Convert sizes from bytes to blocks */ | ||
318 | req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN; | ||
319 | min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN; | ||
320 | |||
321 | /* If no minimum size specified, make it the same as the | ||
322 | * requested size | ||
323 | */ | ||
324 | if (min_size == 0) | ||
325 | min_size = req_size; | ||
326 | if (min_size > req_size) | ||
327 | return -EINVAL; | ||
328 | |||
329 | /* Now add one block to each for the header */ | ||
330 | req_size += 1; | ||
331 | min_size += 1; | ||
332 | |||
307 | /* Find a free partition that will give us the maximum needed size | 333 | /* Find a free partition that will give us the maximum needed size |
308 | If can't find one that will give us the minimum size needed */ | 334 | If can't find one that will give us the minimum size needed */ |
309 | list_for_each_entry(part, &nvram_part->partition, partition) { | 335 | list_for_each_entry(part, &nvram_partitions, partition) { |
310 | if (part->header.signature != NVRAM_SIG_FREE) | 336 | if (part->header.signature != NVRAM_SIG_FREE) |
311 | continue; | 337 | continue; |
312 | 338 | ||
313 | if (part->header.length >= NVRAM_MAX_REQ) { | 339 | if (part->header.length >= req_size) { |
314 | size = NVRAM_MAX_REQ; | 340 | size = req_size; |
315 | free_part = part; | 341 | free_part = part; |
316 | break; | 342 | break; |
317 | } | 343 | } |
318 | if (!size && part->header.length >= NVRAM_MIN_REQ) { | 344 | if (part->header.length > size && |
319 | size = NVRAM_MIN_REQ; | 345 | part->header.length >= min_size) { |
346 | size = part->header.length; | ||
320 | free_part = part; | 347 | free_part = part; |
321 | } | 348 | } |
322 | } | 349 | } |
@@ -326,136 +353,95 @@ static int __init nvram_create_os_partition(void) | |||
326 | /* Create our OS partition */ | 353 | /* Create our OS partition */ |
327 | new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); | 354 | new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); |
328 | if (!new_part) { | 355 | if (!new_part) { |
329 | printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); | 356 | pr_err("nvram_create_os_partition: kmalloc failed\n"); |
330 | return -ENOMEM; | 357 | return -ENOMEM; |
331 | } | 358 | } |
332 | 359 | ||
333 | new_part->index = free_part->index; | 360 | new_part->index = free_part->index; |
334 | new_part->header.signature = NVRAM_SIG_OS; | 361 | new_part->header.signature = sig; |
335 | new_part->header.length = size; | 362 | new_part->header.length = size; |
336 | strcpy(new_part->header.name, "ppc64,linux"); | 363 | strncpy(new_part->header.name, name, 12); |
337 | new_part->header.checksum = nvram_checksum(&new_part->header); | 364 | new_part->header.checksum = nvram_checksum(&new_part->header); |
338 | 365 | ||
339 | rc = nvram_write_header(new_part); | 366 | rc = nvram_write_header(new_part); |
340 | if (rc <= 0) { | 367 | if (rc <= 0) { |
341 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " | 368 | pr_err("nvram_create_os_partition: nvram_write_header " |
342 | "failed (%d)\n", rc); | ||
343 | return rc; | ||
344 | } | ||
345 | |||
346 | /* make sure and initialize to zero the sequence number and the error | ||
347 | type logged */ | ||
348 | tmp_index = new_part->index + NVRAM_HEADER_LEN; | ||
349 | rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); | ||
350 | if (rc <= 0) { | ||
351 | printk(KERN_ERR "nvram_create_os_partition: nvram_write " | ||
352 | "failed (%d)\n", rc); | 369 | "failed (%d)\n", rc); |
353 | return rc; | 370 | return rc; |
354 | } | 371 | } |
355 | |||
356 | nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; | ||
357 | nvram_error_log_size = ((part->header.length - 1) * | ||
358 | NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); | ||
359 | |||
360 | list_add_tail(&new_part->partition, &free_part->partition); | 372 | list_add_tail(&new_part->partition, &free_part->partition); |
361 | 373 | ||
362 | if (free_part->header.length <= size) { | 374 | /* Adjust or remove the partition we stole the space from */ |
375 | if (free_part->header.length > size) { | ||
376 | free_part->index += size * NVRAM_BLOCK_LEN; | ||
377 | free_part->header.length -= size; | ||
378 | free_part->header.checksum = nvram_checksum(&free_part->header); | ||
379 | rc = nvram_write_header(free_part); | ||
380 | if (rc <= 0) { | ||
381 | pr_err("nvram_create_os_partition: nvram_write_header " | ||
382 | "failed (%d)\n", rc); | ||
383 | return rc; | ||
384 | } | ||
385 | } else { | ||
363 | list_del(&free_part->partition); | 386 | list_del(&free_part->partition); |
364 | kfree(free_part); | 387 | kfree(free_part); |
365 | return 0; | ||
366 | } | 388 | } |
367 | 389 | ||
368 | /* Adjust the partition we stole the space from */ | 390 | /* Clear the new partition */ |
369 | free_part->index += size * NVRAM_BLOCK_LEN; | 391 | for (tmp_index = new_part->index + NVRAM_HEADER_LEN; |
370 | free_part->header.length -= size; | 392 | tmp_index < ((size - 1) * NVRAM_BLOCK_LEN); |
371 | free_part->header.checksum = nvram_checksum(&free_part->header); | 393 | tmp_index += NVRAM_BLOCK_LEN) { |
372 | 394 | rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index); | |
373 | rc = nvram_write_header(free_part); | 395 | if (rc <= 0) { |
374 | if (rc <= 0) { | 396 | pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc); |
375 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " | 397 | return rc; |
376 | "failed (%d)\n", rc); | 398 | } |
377 | return rc; | ||
378 | } | 399 | } |
379 | 400 | ||
380 | return 0; | 401 | return new_part->index + NVRAM_HEADER_LEN; |
381 | } | 402 | } |
382 | 403 | ||
383 | 404 | /** | |
384 | /* nvram_setup_partition | 405 | * nvram_get_partition_size - Get the data size of an nvram partition |
385 | * | 406 | * @data_index: This is the offset of the start of the data of |
386 | * This will setup the partition we need for buffering the | 407 | * the partition. The same value that is returned by |
387 | * error logs and cleanup partitions if needed. | 408 | * nvram_create_partition(). |
388 | * | ||
389 | * The general strategy is the following: | ||
390 | * 1.) If there is ppc64,linux partition large enough then use it. | ||
391 | * 2.) If there is not a ppc64,linux partition large enough, search | ||
392 | * for a free partition that is large enough. | ||
393 | * 3.) If there is not a free partition large enough remove | ||
394 | * _all_ OS partitions and consolidate the space. | ||
395 | * 4.) Will first try getting a chunk that will satisfy the maximum | ||
396 | * error log size (NVRAM_MAX_REQ). | ||
397 | * 5.) If the max chunk cannot be allocated then try finding a chunk | ||
398 | * that will satisfy the minum needed (NVRAM_MIN_REQ). | ||
399 | */ | 409 | */ |
400 | static int __init nvram_setup_partition(void) | 410 | int nvram_get_partition_size(loff_t data_index) |
401 | { | 411 | { |
402 | struct list_head * p; | 412 | struct nvram_partition *part; |
403 | struct nvram_partition * part; | 413 | |
404 | int rc; | 414 | list_for_each_entry(part, &nvram_partitions, partition) { |
405 | 415 | if (part->index + NVRAM_HEADER_LEN == data_index) | |
406 | /* For now, we don't do any of this on pmac, until I | 416 | return (part->header.length - 1) * NVRAM_BLOCK_LEN; |
407 | * have figured out if it's worth killing some unused stuffs | 417 | } |
408 | * in our nvram, as Apple defined partitions use pretty much | 418 | return -1; |
409 | * all of the space | 419 | } |
410 | */ | ||
411 | if (machine_is(powermac)) | ||
412 | return -ENOSPC; | ||
413 | |||
414 | /* see if we have an OS partition that meets our needs. | ||
415 | will try getting the max we need. If not we'll delete | ||
416 | partitions and try again. */ | ||
417 | list_for_each(p, &nvram_part->partition) { | ||
418 | part = list_entry(p, struct nvram_partition, partition); | ||
419 | if (part->header.signature != NVRAM_SIG_OS) | ||
420 | continue; | ||
421 | 420 | ||
422 | if (strcmp(part->header.name, "ppc64,linux")) | ||
423 | continue; | ||
424 | 421 | ||
425 | if (part->header.length >= NVRAM_MIN_REQ) { | 422 | /** |
426 | /* found our partition */ | 423 | * nvram_find_partition - Find an nvram partition by signature and name |
427 | nvram_error_log_index = part->index + NVRAM_HEADER_LEN; | 424 | * @name: Name of the partition or NULL for any name |
428 | nvram_error_log_size = ((part->header.length - 1) * | 425 | * @sig: Signature to test against |
429 | NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); | 426 | * @out_size: if non-NULL, returns the size of the data part of the partition |
430 | return 0; | 427 | */ |
428 | loff_t nvram_find_partition(const char *name, int sig, int *out_size) | ||
429 | { | ||
430 | struct nvram_partition *p; | ||
431 | |||
432 | list_for_each_entry(p, &nvram_partitions, partition) { | ||
433 | if (p->header.signature == sig && | ||
434 | (!name || !strncmp(p->header.name, name, 12))) { | ||
435 | if (out_size) | ||
436 | *out_size = (p->header.length - 1) * | ||
437 | NVRAM_BLOCK_LEN; | ||
438 | return p->index + NVRAM_HEADER_LEN; | ||
431 | } | 439 | } |
432 | } | 440 | } |
433 | |||
434 | /* try creating a partition with the free space we have */ | ||
435 | rc = nvram_create_os_partition(); | ||
436 | if (!rc) { | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /* need to free up some space */ | ||
441 | rc = nvram_remove_os_partition(); | ||
442 | if (rc) { | ||
443 | return rc; | ||
444 | } | ||
445 | |||
446 | /* create a partition in this new space */ | ||
447 | rc = nvram_create_os_partition(); | ||
448 | if (rc) { | ||
449 | printk(KERN_ERR "nvram_create_os_partition: Could not find a " | ||
450 | "NVRAM partition large enough\n"); | ||
451 | return rc; | ||
452 | } | ||
453 | |||
454 | return 0; | 441 | return 0; |
455 | } | 442 | } |
456 | 443 | ||
457 | 444 | int __init nvram_scan_partitions(void) | |
458 | static int __init nvram_scan_partitions(void) | ||
459 | { | 445 | { |
460 | loff_t cur_index = 0; | 446 | loff_t cur_index = 0; |
461 | struct nvram_header phead; | 447 | struct nvram_header phead; |
@@ -465,7 +451,7 @@ static int __init nvram_scan_partitions(void) | |||
465 | int total_size; | 451 | int total_size; |
466 | int err; | 452 | int err; |
467 | 453 | ||
468 | if (ppc_md.nvram_size == NULL) | 454 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) |
469 | return -ENODEV; | 455 | return -ENODEV; |
470 | total_size = ppc_md.nvram_size(); | 456 | total_size = ppc_md.nvram_size(); |
471 | 457 | ||
@@ -512,12 +498,16 @@ static int __init nvram_scan_partitions(void) | |||
512 | 498 | ||
513 | memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); | 499 | memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); |
514 | tmp_part->index = cur_index; | 500 | tmp_part->index = cur_index; |
515 | list_add_tail(&tmp_part->partition, &nvram_part->partition); | 501 | list_add_tail(&tmp_part->partition, &nvram_partitions); |
516 | 502 | ||
517 | cur_index += phead.length * NVRAM_BLOCK_LEN; | 503 | cur_index += phead.length * NVRAM_BLOCK_LEN; |
518 | } | 504 | } |
519 | err = 0; | 505 | err = 0; |
520 | 506 | ||
507 | #ifdef DEBUG_NVRAM | ||
508 | nvram_print_partitions("NVRAM Partitions"); | ||
509 | #endif | ||
510 | |||
521 | out: | 511 | out: |
522 | kfree(header); | 512 | kfree(header); |
523 | return err; | 513 | return err; |
@@ -525,9 +515,10 @@ static int __init nvram_scan_partitions(void) | |||
525 | 515 | ||
526 | static int __init nvram_init(void) | 516 | static int __init nvram_init(void) |
527 | { | 517 | { |
528 | int error; | ||
529 | int rc; | 518 | int rc; |
530 | 519 | ||
520 | BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16); | ||
521 | |||
531 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) | 522 | if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) |
532 | return -ENODEV; | 523 | return -ENODEV; |
533 | 524 | ||
@@ -537,29 +528,6 @@ static int __init nvram_init(void) | |||
537 | return rc; | 528 | return rc; |
538 | } | 529 | } |
539 | 530 | ||
540 | /* initialize our anchor for the nvram partition list */ | ||
541 | nvram_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); | ||
542 | if (!nvram_part) { | ||
543 | printk(KERN_ERR "nvram_init: Failed kmalloc\n"); | ||
544 | return -ENOMEM; | ||
545 | } | ||
546 | INIT_LIST_HEAD(&nvram_part->partition); | ||
547 | |||
548 | /* Get all the NVRAM partitions */ | ||
549 | error = nvram_scan_partitions(); | ||
550 | if (error) { | ||
551 | printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); | ||
552 | return error; | ||
553 | } | ||
554 | |||
555 | if(nvram_setup_partition()) | ||
556 | printk(KERN_WARNING "nvram_init: Could not find nvram partition" | ||
557 | " for nvram buffered error logging.\n"); | ||
558 | |||
559 | #ifdef DEBUG_NVRAM | ||
560 | nvram_print_partitions("NVRAM Partitions"); | ||
561 | #endif | ||
562 | |||
563 | return rc; | 531 | return rc; |
564 | } | 532 | } |
565 | 533 | ||
@@ -568,135 +536,6 @@ void __exit nvram_cleanup(void) | |||
568 | misc_deregister( &nvram_dev ); | 536 | misc_deregister( &nvram_dev ); |
569 | } | 537 | } |
570 | 538 | ||
571 | |||
572 | #ifdef CONFIG_PPC_PSERIES | ||
573 | |||
574 | /* nvram_write_error_log | ||
575 | * | ||
576 | * We need to buffer the error logs into nvram to ensure that we have | ||
577 | * the failure information to decode. If we have a severe error there | ||
578 | * is no way to guarantee that the OS or the machine is in a state to | ||
579 | * get back to user land and write the error to disk. For example if | ||
580 | * the SCSI device driver causes a Machine Check by writing to a bad | ||
581 | * IO address, there is no way of guaranteeing that the device driver | ||
582 | * is in any state that is would also be able to write the error data | ||
583 | * captured to disk, thus we buffer it in NVRAM for analysis on the | ||
584 | * next boot. | ||
585 | * | ||
586 | * In NVRAM the partition containing the error log buffer will looks like: | ||
587 | * Header (in bytes): | ||
588 | * +-----------+----------+--------+------------+------------------+ | ||
589 | * | signature | checksum | length | name | data | | ||
590 | * |0 |1 |2 3|4 15|16 length-1| | ||
591 | * +-----------+----------+--------+------------+------------------+ | ||
592 | * | ||
593 | * The 'data' section would look like (in bytes): | ||
594 | * +--------------+------------+-----------------------------------+ | ||
595 | * | event_logged | sequence # | error log | | ||
596 | * |0 3|4 7|8 nvram_error_log_size-1| | ||
597 | * +--------------+------------+-----------------------------------+ | ||
598 | * | ||
599 | * event_logged: 0 if event has not been logged to syslog, 1 if it has | ||
600 | * sequence #: The unique sequence # for each event. (until it wraps) | ||
601 | * error log: The error log from event_scan | ||
602 | */ | ||
603 | int nvram_write_error_log(char * buff, int length, | ||
604 | unsigned int err_type, unsigned int error_log_cnt) | ||
605 | { | ||
606 | int rc; | ||
607 | loff_t tmp_index; | ||
608 | struct err_log_info info; | ||
609 | |||
610 | if (nvram_error_log_index == -1) { | ||
611 | return -ESPIPE; | ||
612 | } | ||
613 | |||
614 | if (length > nvram_error_log_size) { | ||
615 | length = nvram_error_log_size; | ||
616 | } | ||
617 | |||
618 | info.error_type = err_type; | ||
619 | info.seq_num = error_log_cnt; | ||
620 | |||
621 | tmp_index = nvram_error_log_index; | ||
622 | |||
623 | rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
624 | if (rc <= 0) { | ||
625 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
626 | return rc; | ||
627 | } | ||
628 | |||
629 | rc = ppc_md.nvram_write(buff, length, &tmp_index); | ||
630 | if (rc <= 0) { | ||
631 | printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); | ||
632 | return rc; | ||
633 | } | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | /* nvram_read_error_log | ||
639 | * | ||
640 | * Reads nvram for error log for at most 'length' | ||
641 | */ | ||
642 | int nvram_read_error_log(char * buff, int length, | ||
643 | unsigned int * err_type, unsigned int * error_log_cnt) | ||
644 | { | ||
645 | int rc; | ||
646 | loff_t tmp_index; | ||
647 | struct err_log_info info; | ||
648 | |||
649 | if (nvram_error_log_index == -1) | ||
650 | return -1; | ||
651 | |||
652 | if (length > nvram_error_log_size) | ||
653 | length = nvram_error_log_size; | ||
654 | |||
655 | tmp_index = nvram_error_log_index; | ||
656 | |||
657 | rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); | ||
658 | if (rc <= 0) { | ||
659 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
660 | return rc; | ||
661 | } | ||
662 | |||
663 | rc = ppc_md.nvram_read(buff, length, &tmp_index); | ||
664 | if (rc <= 0) { | ||
665 | printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); | ||
666 | return rc; | ||
667 | } | ||
668 | |||
669 | *error_log_cnt = info.seq_num; | ||
670 | *err_type = info.error_type; | ||
671 | |||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /* This doesn't actually zero anything, but it sets the event_logged | ||
676 | * word to tell that this event is safely in syslog. | ||
677 | */ | ||
678 | int nvram_clear_error_log(void) | ||
679 | { | ||
680 | loff_t tmp_index; | ||
681 | int clear_word = ERR_FLAG_ALREADY_LOGGED; | ||
682 | int rc; | ||
683 | |||
684 | if (nvram_error_log_index == -1) | ||
685 | return -1; | ||
686 | |||
687 | tmp_index = nvram_error_log_index; | ||
688 | |||
689 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); | ||
690 | if (rc <= 0) { | ||
691 | printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); | ||
692 | return rc; | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | #endif /* CONFIG_PPC_PSERIES */ | ||
699 | |||
700 | module_init(nvram_init); | 539 | module_init(nvram_init); |
701 | module_exit(nvram_cleanup); | 540 | module_exit(nvram_cleanup); |
702 | MODULE_LICENSE("GPL"); | 541 | MODULE_LICENSE("GPL"); |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index d43fc65749c1..851577608a78 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) | |||
193 | hose->io_resource.start += io_virt_offset; | 193 | hose->io_resource.start += io_virt_offset; |
194 | hose->io_resource.end += io_virt_offset; | 194 | hose->io_resource.end += io_virt_offset; |
195 | 195 | ||
196 | pr_debug(" hose->io_resource=0x%016llx...0x%016llx\n", | 196 | pr_debug(" hose->io_resource=%pR\n", &hose->io_resource); |
197 | hose->io_resource.start, hose->io_resource.end); | ||
198 | 197 | ||
199 | return 0; | 198 | return 0; |
200 | } | 199 | } |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index ab3e392ac63c..ef3ef566235e 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -186,3 +186,10 @@ EXPORT_SYMBOL(__mtdcr); | |||
186 | EXPORT_SYMBOL(__mfdcr); | 186 | EXPORT_SYMBOL(__mfdcr); |
187 | #endif | 187 | #endif |
188 | EXPORT_SYMBOL(empty_zero_page); | 188 | EXPORT_SYMBOL(empty_zero_page); |
189 | |||
190 | #ifdef CONFIG_PPC64 | ||
191 | EXPORT_SYMBOL(__arch_hweight8); | ||
192 | EXPORT_SYMBOL(__arch_hweight16); | ||
193 | EXPORT_SYMBOL(__arch_hweight32); | ||
194 | EXPORT_SYMBOL(__arch_hweight64); | ||
195 | #endif | ||
diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index 5113bd2285e1..e83ba3f078e4 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
14 | #include <asm/ptrace.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Grab the register values as they are now. | 17 | * Grab the register values as they are now. |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index a9b32967cff6..906536998291 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -1316,6 +1316,10 @@ static int set_dac_range(struct task_struct *child, | |||
1316 | static long ppc_set_hwdebug(struct task_struct *child, | 1316 | static long ppc_set_hwdebug(struct task_struct *child, |
1317 | struct ppc_hw_breakpoint *bp_info) | 1317 | struct ppc_hw_breakpoint *bp_info) |
1318 | { | 1318 | { |
1319 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | ||
1320 | unsigned long dabr; | ||
1321 | #endif | ||
1322 | |||
1319 | if (bp_info->version != 1) | 1323 | if (bp_info->version != 1) |
1320 | return -ENOTSUPP; | 1324 | return -ENOTSUPP; |
1321 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1325 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
@@ -1353,11 +1357,10 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1353 | /* | 1357 | /* |
1354 | * We only support one data breakpoint | 1358 | * We only support one data breakpoint |
1355 | */ | 1359 | */ |
1356 | if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) || | 1360 | if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || |
1357 | ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) || | 1361 | (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || |
1358 | (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) || | 1362 | bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT || |
1359 | (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) || | 1363 | bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) |
1360 | (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) | ||
1361 | return -EINVAL; | 1364 | return -EINVAL; |
1362 | 1365 | ||
1363 | if (child->thread.dabr) | 1366 | if (child->thread.dabr) |
@@ -1366,7 +1369,14 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
1366 | if ((unsigned long)bp_info->addr >= TASK_SIZE) | 1369 | if ((unsigned long)bp_info->addr >= TASK_SIZE) |
1367 | return -EIO; | 1370 | return -EIO; |
1368 | 1371 | ||
1369 | child->thread.dabr = (unsigned long)bp_info->addr; | 1372 | dabr = (unsigned long)bp_info->addr & ~7UL; |
1373 | dabr |= DABR_TRANSLATION; | ||
1374 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
1375 | dabr |= DABR_DATA_READ; | ||
1376 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
1377 | dabr |= DABR_DATA_WRITE; | ||
1378 | |||
1379 | child->thread.dabr = dabr; | ||
1370 | 1380 | ||
1371 | return 1; | 1381 | return 1; |
1372 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | 1382 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 8a6daf4129f6..69c4be917d07 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -280,7 +280,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
280 | /* We only support one DABR and no IABRS at the moment */ | 280 | /* We only support one DABR and no IABRS at the moment */ |
281 | if (addr > 0) | 281 | if (addr > 0) |
282 | break; | 282 | break; |
283 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
284 | ret = put_user(child->thread.dac1, (u32 __user *)data); | ||
285 | #else | ||
283 | ret = put_user(child->thread.dabr, (u32 __user *)data); | 286 | ret = put_user(child->thread.dabr, (u32 __user *)data); |
287 | #endif | ||
284 | break; | 288 | break; |
285 | } | 289 | } |
286 | 290 | ||
@@ -312,6 +316,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
312 | case PTRACE_SET_DEBUGREG: | 316 | case PTRACE_SET_DEBUGREG: |
313 | case PTRACE_SYSCALL: | 317 | case PTRACE_SYSCALL: |
314 | case PTRACE_CONT: | 318 | case PTRACE_CONT: |
319 | case PPC_PTRACE_GETHWDBGINFO: | ||
320 | case PPC_PTRACE_SETHWDEBUG: | ||
321 | case PPC_PTRACE_DELHWDEBUG: | ||
315 | ret = arch_ptrace(child, request, addr, data); | 322 | ret = arch_ptrace(child, request, addr, data); |
316 | break; | 323 | break; |
317 | 324 | ||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8fe8bc61c10a..2097f2b3cba8 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <asm/atomic.h> | 41 | #include <asm/atomic.h> |
42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
43 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
44 | #include <asm/topology.h> | ||
44 | 45 | ||
45 | struct rtas_t rtas = { | 46 | struct rtas_t rtas = { |
46 | .lock = __ARCH_SPIN_LOCK_UNLOCKED | 47 | .lock = __ARCH_SPIN_LOCK_UNLOCKED |
@@ -713,6 +714,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w | |||
713 | int cpu; | 714 | int cpu; |
714 | 715 | ||
715 | slb_set_size(SLB_MIN_SIZE); | 716 | slb_set_size(SLB_MIN_SIZE); |
717 | stop_topology_update(); | ||
716 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); | 718 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); |
717 | 719 | ||
718 | while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && | 720 | while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && |
@@ -728,6 +730,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w | |||
728 | rc = atomic_read(&data->error); | 730 | rc = atomic_read(&data->error); |
729 | 731 | ||
730 | atomic_set(&data->error, rc); | 732 | atomic_set(&data->error, rc); |
733 | start_topology_update(); | ||
731 | 734 | ||
732 | if (wake_when_done) { | 735 | if (wake_when_done) { |
733 | atomic_set(&data->done, 1); | 736 | atomic_set(&data->done, 1); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ce6f61c6f871..5a0401fcaebd 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -437,8 +437,8 @@ static void __init irqstack_early_init(void) | |||
437 | unsigned int i; | 437 | unsigned int i; |
438 | 438 | ||
439 | /* | 439 | /* |
440 | * interrupt stacks must be under 256MB, we cannot afford to take | 440 | * Interrupt stacks must be in the first segment since we |
441 | * SLB misses on them. | 441 | * cannot afford to take SLB misses on them. |
442 | */ | 442 | */ |
443 | for_each_possible_cpu(i) { | 443 | for_each_possible_cpu(i) { |
444 | softirq_ctx[i] = (struct thread_info *) | 444 | softirq_ctx[i] = (struct thread_info *) |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 68034bbf2e4f..981360509172 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -466,7 +466,20 @@ out: | |||
466 | return id; | 466 | return id; |
467 | } | 467 | } |
468 | 468 | ||
469 | /* Must be called when no change can occur to cpu_present_mask, | 469 | /* Helper routines for cpu to core mapping */ |
470 | int cpu_core_index_of_thread(int cpu) | ||
471 | { | ||
472 | return cpu >> threads_shift; | ||
473 | } | ||
474 | EXPORT_SYMBOL_GPL(cpu_core_index_of_thread); | ||
475 | |||
476 | int cpu_first_thread_of_core(int core) | ||
477 | { | ||
478 | return core << threads_shift; | ||
479 | } | ||
480 | EXPORT_SYMBOL_GPL(cpu_first_thread_of_core); | ||
481 | |||
482 | /* Must be called when no change can occur to cpu_present_map, | ||
470 | * i.e. during cpu online or offline. | 483 | * i.e. during cpu online or offline. |
471 | */ | 484 | */ |
472 | static struct device_node *cpu_to_l2cache(int cpu) | 485 | static struct device_node *cpu_to_l2cache(int cpu) |
@@ -514,7 +527,7 @@ int __devinit start_secondary(void *unused) | |||
514 | notify_cpu_starting(cpu); | 527 | notify_cpu_starting(cpu); |
515 | set_cpu_online(cpu, true); | 528 | set_cpu_online(cpu, true); |
516 | /* Update sibling maps */ | 529 | /* Update sibling maps */ |
517 | base = cpu_first_thread_in_core(cpu); | 530 | base = cpu_first_thread_sibling(cpu); |
518 | for (i = 0; i < threads_per_core; i++) { | 531 | for (i = 0; i < threads_per_core; i++) { |
519 | if (cpu_is_offline(base + i)) | 532 | if (cpu_is_offline(base + i)) |
520 | continue; | 533 | continue; |
@@ -600,7 +613,7 @@ int __cpu_disable(void) | |||
600 | return err; | 613 | return err; |
601 | 614 | ||
602 | /* Update sibling maps */ | 615 | /* Update sibling maps */ |
603 | base = cpu_first_thread_in_core(cpu); | 616 | base = cpu_first_thread_sibling(cpu); |
604 | for (i = 0; i < threads_per_core; i++) { | 617 | for (i = 0; i < threads_per_core; i++) { |
605 | cpumask_clear_cpu(cpu, cpu_sibling_mask(base + i)); | 618 | cpumask_clear_cpu(cpu, cpu_sibling_mask(base + i)); |
606 | cpumask_clear_cpu(base + i, cpu_sibling_mask(cpu)); | 619 | cpumask_clear_cpu(base + i, cpu_sibling_mask(cpu)); |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 010406958d97..09e4dea4a85a 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(rtc_lock); | |||
155 | 155 | ||
156 | static u64 tb_to_ns_scale __read_mostly; | 156 | static u64 tb_to_ns_scale __read_mostly; |
157 | static unsigned tb_to_ns_shift __read_mostly; | 157 | static unsigned tb_to_ns_shift __read_mostly; |
158 | static unsigned long boot_tb __read_mostly; | 158 | static u64 boot_tb __read_mostly; |
159 | 159 | ||
160 | extern struct timezone sys_tz; | 160 | extern struct timezone sys_tz; |
161 | static long timezone_offset; | 161 | static long timezone_offset; |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index fe460482fa68..9de6f396cf85 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <asm/cputable.h> | 5 | #include <asm/cputable.h> |
6 | #include <asm/thread_info.h> | 6 | #include <asm/thread_info.h> |
7 | #include <asm/page.h> | 7 | #include <asm/page.h> |
8 | #include <asm/ptrace.h> | ||
8 | 9 | ||
9 | /* | 10 | /* |
10 | * load_up_altivec(unused, unused, tsk) | 11 | * load_up_altivec(unused, unused, tsk) |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 441d2a722f06..1b695fdc362b 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -600,6 +600,11 @@ static void vio_dma_iommu_unmap_sg(struct device *dev, | |||
600 | vio_cmo_dealloc(viodev, alloc_size); | 600 | vio_cmo_dealloc(viodev, alloc_size); |
601 | } | 601 | } |
602 | 602 | ||
603 | static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask) | ||
604 | { | ||
605 | return dma_iommu_ops.dma_supported(dev, mask); | ||
606 | } | ||
607 | |||
603 | struct dma_map_ops vio_dma_mapping_ops = { | 608 | struct dma_map_ops vio_dma_mapping_ops = { |
604 | .alloc_coherent = vio_dma_iommu_alloc_coherent, | 609 | .alloc_coherent = vio_dma_iommu_alloc_coherent, |
605 | .free_coherent = vio_dma_iommu_free_coherent, | 610 | .free_coherent = vio_dma_iommu_free_coherent, |
@@ -607,6 +612,7 @@ struct dma_map_ops vio_dma_mapping_ops = { | |||
607 | .unmap_sg = vio_dma_iommu_unmap_sg, | 612 | .unmap_sg = vio_dma_iommu_unmap_sg, |
608 | .map_page = vio_dma_iommu_map_page, | 613 | .map_page = vio_dma_iommu_map_page, |
609 | .unmap_page = vio_dma_iommu_unmap_page, | 614 | .unmap_page = vio_dma_iommu_unmap_page, |
615 | .dma_supported = vio_dma_iommu_dma_supported, | ||
610 | 616 | ||
611 | }; | 617 | }; |
612 | 618 | ||
@@ -858,8 +864,7 @@ static void vio_cmo_bus_remove(struct vio_dev *viodev) | |||
858 | 864 | ||
859 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) | 865 | static void vio_cmo_set_dma_ops(struct vio_dev *viodev) |
860 | { | 866 | { |
861 | vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported; | 867 | set_dma_ops(&viodev->dev, &vio_dma_mapping_ops); |
862 | viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops; | ||
863 | } | 868 | } |
864 | 869 | ||
865 | /** | 870 | /** |
@@ -1244,7 +1249,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1244 | if (firmware_has_feature(FW_FEATURE_CMO)) | 1249 | if (firmware_has_feature(FW_FEATURE_CMO)) |
1245 | vio_cmo_set_dma_ops(viodev); | 1250 | vio_cmo_set_dma_ops(viodev); |
1246 | else | 1251 | else |
1247 | viodev->dev.archdata.dma_ops = &dma_iommu_ops; | 1252 | set_dma_ops(&viodev->dev, &dma_iommu_ops); |
1248 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); | 1253 | set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev)); |
1249 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); | 1254 | set_dev_node(&viodev->dev, of_node_to_nid(of_node)); |
1250 | 1255 | ||
@@ -1252,6 +1257,10 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1252 | viodev->dev.parent = &vio_bus_device.dev; | 1257 | viodev->dev.parent = &vio_bus_device.dev; |
1253 | viodev->dev.bus = &vio_bus_type; | 1258 | viodev->dev.bus = &vio_bus_type; |
1254 | viodev->dev.release = vio_dev_release; | 1259 | viodev->dev.release = vio_dev_release; |
1260 | /* needed to ensure proper operation of coherent allocations | ||
1261 | * later, in case driver doesn't set it explicitly */ | ||
1262 | dma_set_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1263 | dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1255 | 1264 | ||
1256 | /* register with generic device framework */ | 1265 | /* register with generic device framework */ |
1257 | if (device_register(&viodev->dev)) { | 1266 | if (device_register(&viodev->dev)) { |