diff options
Diffstat (limited to 'arch/powerpc')
23 files changed, 929 insertions, 499 deletions
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 0b5469fb6e0f..7994955c29d3 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.24-rc4 | 3 | # Linux kernel version: 2.6.24-rc8 |
4 | # Tue Dec 4 22:49:57 2007 | 4 | # Wed Jan 16 14:31:21 2008 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | 7 | ||
@@ -103,6 +103,7 @@ CONFIG_VM_EVENT_COUNTERS=y | |||
103 | CONFIG_SLAB=y | 103 | CONFIG_SLAB=y |
104 | # CONFIG_SLUB is not set | 104 | # CONFIG_SLUB is not set |
105 | # CONFIG_SLOB is not set | 105 | # CONFIG_SLOB is not set |
106 | CONFIG_SLABINFO=y | ||
106 | CONFIG_RT_MUTEXES=y | 107 | CONFIG_RT_MUTEXES=y |
107 | # CONFIG_TINY_SHMEM is not set | 108 | # CONFIG_TINY_SHMEM is not set |
108 | CONFIG_BASE_SMALL=0 | 109 | CONFIG_BASE_SMALL=0 |
@@ -154,7 +155,6 @@ CONFIG_PPC_PS3=y | |||
154 | # CONFIG_PS3_ADVANCED is not set | 155 | # CONFIG_PS3_ADVANCED is not set |
155 | CONFIG_PS3_HTAB_SIZE=20 | 156 | CONFIG_PS3_HTAB_SIZE=20 |
156 | # CONFIG_PS3_DYNAMIC_DMA is not set | 157 | # CONFIG_PS3_DYNAMIC_DMA is not set |
157 | CONFIG_PS3_USE_LPAR_ADDR=y | ||
158 | CONFIG_PS3_VUART=y | 158 | CONFIG_PS3_VUART=y |
159 | CONFIG_PS3_PS3AV=y | 159 | CONFIG_PS3_PS3AV=y |
160 | CONFIG_PS3_SYS_MANAGER=y | 160 | CONFIG_PS3_SYS_MANAGER=y |
@@ -162,6 +162,7 @@ CONFIG_PS3_STORAGE=y | |||
162 | CONFIG_PS3_DISK=y | 162 | CONFIG_PS3_DISK=y |
163 | CONFIG_PS3_ROM=y | 163 | CONFIG_PS3_ROM=y |
164 | CONFIG_PS3_FLASH=y | 164 | CONFIG_PS3_FLASH=y |
165 | CONFIG_PS3_LPM=m | ||
165 | CONFIG_PPC_CELL=y | 166 | CONFIG_PPC_CELL=y |
166 | # CONFIG_PPC_CELL_NATIVE is not set | 167 | # CONFIG_PPC_CELL_NATIVE is not set |
167 | # CONFIG_PPC_IBM_CELL_BLADE is not set | 168 | # CONFIG_PPC_IBM_CELL_BLADE is not set |
@@ -225,7 +226,7 @@ CONFIG_HAVE_MEMORY_PRESENT=y | |||
225 | # CONFIG_SPARSEMEM_STATIC is not set | 226 | # CONFIG_SPARSEMEM_STATIC is not set |
226 | CONFIG_SPARSEMEM_EXTREME=y | 227 | CONFIG_SPARSEMEM_EXTREME=y |
227 | CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y | 228 | CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y |
228 | CONFIG_SPARSEMEM_VMEMMAP=y | 229 | # CONFIG_SPARSEMEM_VMEMMAP is not set |
229 | CONFIG_MEMORY_HOTPLUG=y | 230 | CONFIG_MEMORY_HOTPLUG=y |
230 | CONFIG_MEMORY_HOTPLUG_SPARSE=y | 231 | CONFIG_MEMORY_HOTPLUG_SPARSE=y |
231 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 232 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
@@ -338,7 +339,26 @@ CONFIG_IPV6_SIT=y | |||
338 | # CONFIG_NET_PKTGEN is not set | 339 | # CONFIG_NET_PKTGEN is not set |
339 | # CONFIG_HAMRADIO is not set | 340 | # CONFIG_HAMRADIO is not set |
340 | # CONFIG_IRDA is not set | 341 | # CONFIG_IRDA is not set |
341 | # CONFIG_BT is not set | 342 | CONFIG_BT=m |
343 | CONFIG_BT_L2CAP=m | ||
344 | CONFIG_BT_SCO=m | ||
345 | CONFIG_BT_RFCOMM=m | ||
346 | CONFIG_BT_RFCOMM_TTY=y | ||
347 | CONFIG_BT_BNEP=m | ||
348 | CONFIG_BT_BNEP_MC_FILTER=y | ||
349 | CONFIG_BT_BNEP_PROTO_FILTER=y | ||
350 | CONFIG_BT_HIDP=m | ||
351 | |||
352 | # | ||
353 | # Bluetooth device drivers | ||
354 | # | ||
355 | CONFIG_BT_HCIUSB=m | ||
356 | CONFIG_BT_HCIUSB_SCO=y | ||
357 | # CONFIG_BT_HCIUART is not set | ||
358 | # CONFIG_BT_HCIBCM203X is not set | ||
359 | # CONFIG_BT_HCIBPA10X is not set | ||
360 | # CONFIG_BT_HCIBFUSB is not set | ||
361 | # CONFIG_BT_HCIVHCI is not set | ||
342 | # CONFIG_AF_RXRPC is not set | 362 | # CONFIG_AF_RXRPC is not set |
343 | 363 | ||
344 | # | 364 | # |
@@ -666,14 +686,14 @@ CONFIG_LOGO_LINUX_CLUT224=y | |||
666 | # | 686 | # |
667 | # Sound | 687 | # Sound |
668 | # | 688 | # |
669 | CONFIG_SOUND=y | 689 | CONFIG_SOUND=m |
670 | 690 | ||
671 | # | 691 | # |
672 | # Advanced Linux Sound Architecture | 692 | # Advanced Linux Sound Architecture |
673 | # | 693 | # |
674 | CONFIG_SND=y | 694 | CONFIG_SND=m |
675 | CONFIG_SND_TIMER=y | 695 | CONFIG_SND_TIMER=m |
676 | CONFIG_SND_PCM=y | 696 | CONFIG_SND_PCM=m |
677 | # CONFIG_SND_SEQUENCER is not set | 697 | # CONFIG_SND_SEQUENCER is not set |
678 | # CONFIG_SND_MIXER_OSS is not set | 698 | # CONFIG_SND_MIXER_OSS is not set |
679 | # CONFIG_SND_PCM_OSS is not set | 699 | # CONFIG_SND_PCM_OSS is not set |
@@ -702,7 +722,7 @@ CONFIG_SND_VERBOSE_PROCFS=y | |||
702 | # | 722 | # |
703 | # ALSA PowerPC devices | 723 | # ALSA PowerPC devices |
704 | # | 724 | # |
705 | CONFIG_SND_PS3=y | 725 | CONFIG_SND_PS3=m |
706 | CONFIG_SND_PS3_DEFAULT_START_DELAY=2000 | 726 | CONFIG_SND_PS3_DEFAULT_START_DELAY=2000 |
707 | 727 | ||
708 | # | 728 | # |
@@ -747,7 +767,7 @@ CONFIG_USB_SUPPORT=y | |||
747 | CONFIG_USB_ARCH_HAS_HCD=y | 767 | CONFIG_USB_ARCH_HAS_HCD=y |
748 | CONFIG_USB_ARCH_HAS_OHCI=y | 768 | CONFIG_USB_ARCH_HAS_OHCI=y |
749 | CONFIG_USB_ARCH_HAS_EHCI=y | 769 | CONFIG_USB_ARCH_HAS_EHCI=y |
750 | CONFIG_USB=y | 770 | CONFIG_USB=m |
751 | # CONFIG_USB_DEBUG is not set | 771 | # CONFIG_USB_DEBUG is not set |
752 | 772 | ||
753 | # | 773 | # |
@@ -761,13 +781,13 @@ CONFIG_USB_DEVICEFS=y | |||
761 | # | 781 | # |
762 | # USB Host Controller Drivers | 782 | # USB Host Controller Drivers |
763 | # | 783 | # |
764 | CONFIG_USB_EHCI_HCD=y | 784 | CONFIG_USB_EHCI_HCD=m |
765 | # CONFIG_USB_EHCI_SPLIT_ISO is not set | 785 | # CONFIG_USB_EHCI_SPLIT_ISO is not set |
766 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | 786 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set |
767 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | 787 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set |
768 | CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y | 788 | CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y |
769 | # CONFIG_USB_ISP116X_HCD is not set | 789 | # CONFIG_USB_ISP116X_HCD is not set |
770 | CONFIG_USB_OHCI_HCD=y | 790 | CONFIG_USB_OHCI_HCD=m |
771 | # CONFIG_USB_OHCI_HCD_PPC_OF is not set | 791 | # CONFIG_USB_OHCI_HCD_PPC_OF is not set |
772 | # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set | 792 | # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set |
773 | CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y | 793 | CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y |
@@ -1033,7 +1053,8 @@ CONFIG_HAS_IOMEM=y | |||
1033 | CONFIG_HAS_IOPORT=y | 1053 | CONFIG_HAS_IOPORT=y |
1034 | CONFIG_HAS_DMA=y | 1054 | CONFIG_HAS_DMA=y |
1035 | CONFIG_INSTRUMENTATION=y | 1055 | CONFIG_INSTRUMENTATION=y |
1036 | # CONFIG_PROFILING is not set | 1056 | CONFIG_PROFILING=y |
1057 | CONFIG_OPROFILE=m | ||
1037 | # CONFIG_KPROBES is not set | 1058 | # CONFIG_KPROBES is not set |
1038 | # CONFIG_MARKERS is not set | 1059 | # CONFIG_MARKERS is not set |
1039 | 1060 | ||
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 77c749a13378..571132ed12c1 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <asm/lmb.h> | 32 | #include <asm/lmb.h> |
33 | #include <asm/firmware.h> | 33 | #include <asm/firmware.h> |
34 | #include <asm/smp.h> | 34 | #include <asm/smp.h> |
35 | #include <asm/system.h> | ||
36 | #include <asm/setjmp.h> | ||
35 | 37 | ||
36 | #ifdef DEBUG | 38 | #ifdef DEBUG |
37 | #include <asm/udbg.h> | 39 | #include <asm/udbg.h> |
@@ -45,6 +47,11 @@ int crashing_cpu = -1; | |||
45 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; | 47 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; |
46 | cpumask_t cpus_in_sr = CPU_MASK_NONE; | 48 | cpumask_t cpus_in_sr = CPU_MASK_NONE; |
47 | 49 | ||
50 | #define CRASH_HANDLER_MAX 1 | ||
51 | /* NULL terminated list of shutdown handles */ | ||
52 | static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1]; | ||
53 | static DEFINE_SPINLOCK(crash_handlers_lock); | ||
54 | |||
48 | #ifdef CONFIG_SMP | 55 | #ifdef CONFIG_SMP |
49 | static atomic_t enter_on_soft_reset = ATOMIC_INIT(0); | 56 | static atomic_t enter_on_soft_reset = ATOMIC_INIT(0); |
50 | 57 | ||
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus(void) | |||
285 | } | 292 | } |
286 | #endif /* CONFIG_SPU_BASE */ | 293 | #endif /* CONFIG_SPU_BASE */ |
287 | 294 | ||
295 | /* | ||
296 | * Register a function to be called on shutdown. Only use this if you | ||
297 | * can't reset your device in the second kernel. | ||
298 | */ | ||
299 | int crash_shutdown_register(crash_shutdown_t handler) | ||
300 | { | ||
301 | unsigned int i, rc; | ||
302 | |||
303 | spin_lock(&crash_handlers_lock); | ||
304 | for (i = 0 ; i < CRASH_HANDLER_MAX; i++) | ||
305 | if (!crash_shutdown_handles[i]) { | ||
306 | /* Insert handle at first empty entry */ | ||
307 | crash_shutdown_handles[i] = handler; | ||
308 | rc = 0; | ||
309 | break; | ||
310 | } | ||
311 | |||
312 | if (i == CRASH_HANDLER_MAX) { | ||
313 | printk(KERN_ERR "Crash shutdown handles full, " | ||
314 | "not registered.\n"); | ||
315 | rc = 1; | ||
316 | } | ||
317 | |||
318 | spin_unlock(&crash_handlers_lock); | ||
319 | return rc; | ||
320 | } | ||
321 | EXPORT_SYMBOL(crash_shutdown_register); | ||
322 | |||
323 | int crash_shutdown_unregister(crash_shutdown_t handler) | ||
324 | { | ||
325 | unsigned int i, rc; | ||
326 | |||
327 | spin_lock(&crash_handlers_lock); | ||
328 | for (i = 0 ; i < CRASH_HANDLER_MAX; i++) | ||
329 | if (crash_shutdown_handles[i] == handler) | ||
330 | break; | ||
331 | |||
332 | if (i == CRASH_HANDLER_MAX) { | ||
333 | printk(KERN_ERR "Crash shutdown handle not found\n"); | ||
334 | rc = 1; | ||
335 | } else { | ||
336 | /* Shift handles down */ | ||
337 | for (; crash_shutdown_handles[i]; i++) | ||
338 | crash_shutdown_handles[i] = | ||
339 | crash_shutdown_handles[i+1]; | ||
340 | rc = 0; | ||
341 | } | ||
342 | |||
343 | spin_unlock(&crash_handlers_lock); | ||
344 | return rc; | ||
345 | } | ||
346 | EXPORT_SYMBOL(crash_shutdown_unregister); | ||
347 | |||
348 | static unsigned long crash_shutdown_buf[JMP_BUF_LEN]; | ||
349 | |||
350 | static int handle_fault(struct pt_regs *regs) | ||
351 | { | ||
352 | longjmp(crash_shutdown_buf, 1); | ||
353 | return 0; | ||
354 | } | ||
355 | |||
288 | void default_machine_crash_shutdown(struct pt_regs *regs) | 356 | void default_machine_crash_shutdown(struct pt_regs *regs) |
289 | { | 357 | { |
290 | unsigned int irq; | 358 | unsigned int i; |
359 | int (*old_handler)(struct pt_regs *regs); | ||
360 | |||
291 | 361 | ||
292 | /* | 362 | /* |
293 | * This function is only called after the system | 363 | * This function is only called after the system |
@@ -301,15 +371,36 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
301 | */ | 371 | */ |
302 | hard_irq_disable(); | 372 | hard_irq_disable(); |
303 | 373 | ||
304 | for_each_irq(irq) { | 374 | for_each_irq(i) { |
305 | struct irq_desc *desc = irq_desc + irq; | 375 | struct irq_desc *desc = irq_desc + i; |
306 | 376 | ||
307 | if (desc->status & IRQ_INPROGRESS) | 377 | if (desc->status & IRQ_INPROGRESS) |
308 | desc->chip->eoi(irq); | 378 | desc->chip->eoi(i); |
309 | 379 | ||
310 | if (!(desc->status & IRQ_DISABLED)) | 380 | if (!(desc->status & IRQ_DISABLED)) |
311 | desc->chip->disable(irq); | 381 | desc->chip->disable(i); |
382 | } | ||
383 | |||
384 | /* | ||
385 | * Call registered shutdown routines savely. Swap out | ||
386 | * __debugger_fault_handler, and replace on exit. | ||
387 | */ | ||
388 | old_handler = __debugger_fault_handler; | ||
389 | __debugger_fault_handler = handle_fault; | ||
390 | for (i = 0; crash_shutdown_handles[i]; i++) { | ||
391 | if (setjmp(crash_shutdown_buf) == 0) { | ||
392 | /* | ||
393 | * Insert syncs and delay to ensure | ||
394 | * instructions in the dangerous region don't | ||
395 | * leak away from this protected region. | ||
396 | */ | ||
397 | asm volatile("sync; isync"); | ||
398 | /* dangerous region */ | ||
399 | crash_shutdown_handles[i](); | ||
400 | asm volatile("sync; isync"); | ||
401 | } | ||
312 | } | 402 | } |
403 | __debugger_fault_handler = old_handler; | ||
313 | 404 | ||
314 | /* | 405 | /* |
315 | * Make a note of crashing cpu. Will be used in machine_kexec | 406 | * Make a note of crashing cpu. Will be used in machine_kexec |
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 14206e3f0819..84239076a5b8 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c | |||
@@ -112,10 +112,16 @@ EXPORT_SYMBOL(dma_iommu_ops); | |||
112 | /* | 112 | /* |
113 | * Generic direct DMA implementation | 113 | * Generic direct DMA implementation |
114 | * | 114 | * |
115 | * This implementation supports a global offset that can be applied if | 115 | * This implementation supports a per-device offset that can be applied if |
116 | * the address at which memory is visible to devices is not 0. | 116 | * the address at which memory is visible to devices is not 0. Platform code |
117 | * can set archdata.dma_data to an unsigned long holding the offset. By | ||
118 | * default the offset is zero. | ||
117 | */ | 119 | */ |
118 | unsigned long dma_direct_offset; | 120 | |
121 | static unsigned long get_dma_direct_offset(struct device *dev) | ||
122 | { | ||
123 | return (unsigned long)dev->archdata.dma_data; | ||
124 | } | ||
119 | 125 | ||
120 | static void *dma_direct_alloc_coherent(struct device *dev, size_t size, | 126 | static void *dma_direct_alloc_coherent(struct device *dev, size_t size, |
121 | dma_addr_t *dma_handle, gfp_t flag) | 127 | dma_addr_t *dma_handle, gfp_t flag) |
@@ -124,13 +130,12 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size, | |||
124 | void *ret; | 130 | void *ret; |
125 | int node = dev->archdata.numa_node; | 131 | int node = dev->archdata.numa_node; |
126 | 132 | ||
127 | /* TODO: Maybe use the numa node here too ? */ | ||
128 | page = alloc_pages_node(node, flag, get_order(size)); | 133 | page = alloc_pages_node(node, flag, get_order(size)); |
129 | if (page == NULL) | 134 | if (page == NULL) |
130 | return NULL; | 135 | return NULL; |
131 | ret = page_address(page); | 136 | ret = page_address(page); |
132 | memset(ret, 0, size); | 137 | memset(ret, 0, size); |
133 | *dma_handle = virt_to_abs(ret) | dma_direct_offset; | 138 | *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); |
134 | 139 | ||
135 | return ret; | 140 | return ret; |
136 | } | 141 | } |
@@ -145,7 +150,7 @@ static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr, | |||
145 | size_t size, | 150 | size_t size, |
146 | enum dma_data_direction direction) | 151 | enum dma_data_direction direction) |
147 | { | 152 | { |
148 | return virt_to_abs(ptr) | dma_direct_offset; | 153 | return virt_to_abs(ptr) + get_dma_direct_offset(dev); |
149 | } | 154 | } |
150 | 155 | ||
151 | static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, | 156 | static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, |
@@ -161,7 +166,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, | |||
161 | int i; | 166 | int i; |
162 | 167 | ||
163 | for_each_sg(sgl, sg, nents, i) { | 168 | for_each_sg(sgl, sg, nents, i) { |
164 | sg->dma_address = sg_phys(sg) | dma_direct_offset; | 169 | sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); |
165 | sg->dma_length = sg->length; | 170 | sg->dma_length = sg->length; |
166 | } | 171 | } |
167 | 172 | ||
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index fd5ae8d17c96..2f50bb5d00f9 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -198,16 +198,13 @@ int ibmebus_register_driver(struct of_platform_driver *drv) | |||
198 | /* If the driver uses devices that ibmebus doesn't know, add them */ | 198 | /* If the driver uses devices that ibmebus doesn't know, add them */ |
199 | ibmebus_create_devices(drv->match_table); | 199 | ibmebus_create_devices(drv->match_table); |
200 | 200 | ||
201 | drv->driver.name = drv->name; | 201 | return of_register_driver(drv, &ibmebus_bus_type); |
202 | drv->driver.bus = &ibmebus_bus_type; | ||
203 | |||
204 | return driver_register(&drv->driver); | ||
205 | } | 202 | } |
206 | EXPORT_SYMBOL(ibmebus_register_driver); | 203 | EXPORT_SYMBOL(ibmebus_register_driver); |
207 | 204 | ||
208 | void ibmebus_unregister_driver(struct of_platform_driver *drv) | 205 | void ibmebus_unregister_driver(struct of_platform_driver *drv) |
209 | { | 206 | { |
210 | driver_unregister(&drv->driver); | 207 | of_unregister_driver(drv); |
211 | } | 208 | } |
212 | EXPORT_SYMBOL(ibmebus_unregister_driver); | 209 | EXPORT_SYMBOL(ibmebus_unregister_driver); |
213 | 210 | ||
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 74ce0c7a7b1e..7b9160220698 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -8,6 +8,8 @@ | |||
8 | * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) | 8 | * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) |
9 | * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) | 9 | * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) |
10 | * | 10 | * |
11 | * setjmp/longjmp code by Paul Mackerras. | ||
12 | * | ||
11 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
13 | * as published by the Free Software Foundation; either version | 15 | * as published by the Free Software Foundation; either version |
@@ -15,6 +17,8 @@ | |||
15 | */ | 17 | */ |
16 | #include <asm/ppc_asm.h> | 18 | #include <asm/ppc_asm.h> |
17 | #include <asm/unistd.h> | 19 | #include <asm/unistd.h> |
20 | #include <asm/asm-compat.h> | ||
21 | #include <asm/asm-offsets.h> | ||
18 | 22 | ||
19 | .text | 23 | .text |
20 | 24 | ||
@@ -51,3 +55,64 @@ _GLOBAL(kernel_execve) | |||
51 | bnslr | 55 | bnslr |
52 | neg r3,r3 | 56 | neg r3,r3 |
53 | blr | 57 | blr |
58 | |||
59 | _GLOBAL(setjmp) | ||
60 | mflr r0 | ||
61 | PPC_STL r0,0(r3) | ||
62 | PPC_STL r1,SZL(r3) | ||
63 | PPC_STL r2,2*SZL(r3) | ||
64 | mfcr r0 | ||
65 | PPC_STL r0,3*SZL(r3) | ||
66 | PPC_STL r13,4*SZL(r3) | ||
67 | PPC_STL r14,5*SZL(r3) | ||
68 | PPC_STL r15,6*SZL(r3) | ||
69 | PPC_STL r16,7*SZL(r3) | ||
70 | PPC_STL r17,8*SZL(r3) | ||
71 | PPC_STL r18,9*SZL(r3) | ||
72 | PPC_STL r19,10*SZL(r3) | ||
73 | PPC_STL r20,11*SZL(r3) | ||
74 | PPC_STL r21,12*SZL(r3) | ||
75 | PPC_STL r22,13*SZL(r3) | ||
76 | PPC_STL r23,14*SZL(r3) | ||
77 | PPC_STL r24,15*SZL(r3) | ||
78 | PPC_STL r25,16*SZL(r3) | ||
79 | PPC_STL r26,17*SZL(r3) | ||
80 | PPC_STL r27,18*SZL(r3) | ||
81 | PPC_STL r28,19*SZL(r3) | ||
82 | PPC_STL r29,20*SZL(r3) | ||
83 | PPC_STL r30,21*SZL(r3) | ||
84 | PPC_STL r31,22*SZL(r3) | ||
85 | li r3,0 | ||
86 | blr | ||
87 | |||
88 | _GLOBAL(longjmp) | ||
89 | PPC_LCMPI r4,0 | ||
90 | bne 1f | ||
91 | li r4,1 | ||
92 | 1: PPC_LL r13,4*SZL(r3) | ||
93 | PPC_LL r14,5*SZL(r3) | ||
94 | PPC_LL r15,6*SZL(r3) | ||
95 | PPC_LL r16,7*SZL(r3) | ||
96 | PPC_LL r17,8*SZL(r3) | ||
97 | PPC_LL r18,9*SZL(r3) | ||
98 | PPC_LL r19,10*SZL(r3) | ||
99 | PPC_LL r20,11*SZL(r3) | ||
100 | PPC_LL r21,12*SZL(r3) | ||
101 | PPC_LL r22,13*SZL(r3) | ||
102 | PPC_LL r23,14*SZL(r3) | ||
103 | PPC_LL r24,15*SZL(r3) | ||
104 | PPC_LL r25,16*SZL(r3) | ||
105 | PPC_LL r26,17*SZL(r3) | ||
106 | PPC_LL r27,18*SZL(r3) | ||
107 | PPC_LL r28,19*SZL(r3) | ||
108 | PPC_LL r29,20*SZL(r3) | ||
109 | PPC_LL r30,21*SZL(r3) | ||
110 | PPC_LL r31,22*SZL(r3) | ||
111 | PPC_LL r0,3*SZL(r3) | ||
112 | mtcrf 0x38,r0 | ||
113 | PPC_LL r0,0(r3) | ||
114 | PPC_LL r1,SZL(r3) | ||
115 | PPC_LL r2,2*SZL(r3) | ||
116 | mtlr r0 | ||
117 | mr r3,r4 | ||
118 | blr | ||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 1930f393d01c..52750745edfd 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -357,7 +357,6 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
357 | struct pci_bus *bus; | 357 | struct pci_bus *bus; |
358 | struct device_node *node = hose->dn; | 358 | struct device_node *node = hose->dn; |
359 | int i, mode; | 359 | int i, mode; |
360 | struct resource *res; | ||
361 | 360 | ||
362 | DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); | 361 | DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); |
363 | 362 | ||
@@ -375,12 +374,10 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
375 | pcibios_map_io_space(bus); | 374 | pcibios_map_io_space(bus); |
376 | 375 | ||
377 | /* Wire up PHB bus resources */ | 376 | /* Wire up PHB bus resources */ |
378 | if (hose->io_resource.flags) { | 377 | DBG("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", |
379 | DBG("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", | 378 | hose->io_resource.start, hose->io_resource.end, |
380 | hose->io_resource.start, hose->io_resource.end, | 379 | hose->io_resource.flags); |
381 | hose->io_resource.flags); | 380 | bus->resource[0] = &hose->io_resource; |
382 | bus->resource[0] = res = &hose->io_resource; | ||
383 | } | ||
384 | for (i = 0; i < 3; ++i) { | 381 | for (i = 0; i < 3; ++i) { |
385 | DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, | 382 | DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, |
386 | hose->mem_resources[i].start, | 383 | hose->mem_resources[i].start, |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 13ebeb2d71e6..aa9ff35b0e63 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -59,6 +59,7 @@ extern void single_step_exception(struct pt_regs *regs); | |||
59 | extern int sys_sigreturn(struct pt_regs *regs); | 59 | extern int sys_sigreturn(struct pt_regs *regs); |
60 | 60 | ||
61 | EXPORT_SYMBOL(clear_pages); | 61 | EXPORT_SYMBOL(clear_pages); |
62 | EXPORT_SYMBOL(copy_page); | ||
62 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | 63 | EXPORT_SYMBOL(ISA_DMA_THRESHOLD); |
63 | EXPORT_SYMBOL(DMA_MODE_READ); | 64 | EXPORT_SYMBOL(DMA_MODE_READ); |
64 | EXPORT_SYMBOL(DMA_MODE_WRITE); | 65 | EXPORT_SYMBOL(DMA_MODE_WRITE); |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 338950aeb6f6..be35ffae10f0 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -76,6 +76,8 @@ void smp_call_function_interrupt(void); | |||
76 | 76 | ||
77 | int smt_enabled_at_boot = 1; | 77 | int smt_enabled_at_boot = 1; |
78 | 78 | ||
79 | static int ipi_fail_ok; | ||
80 | |||
79 | static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL; | 81 | static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL; |
80 | 82 | ||
81 | #ifdef CONFIG_PPC64 | 83 | #ifdef CONFIG_PPC64 |
@@ -181,12 +183,13 @@ static struct call_data_struct { | |||
181 | * <wait> If true, wait (atomically) until function has completed on other CPUs. | 183 | * <wait> If true, wait (atomically) until function has completed on other CPUs. |
182 | * [RETURNS] 0 on success, else a negative status code. Does not return until | 184 | * [RETURNS] 0 on success, else a negative status code. Does not return until |
183 | * remote CPUs are nearly ready to execute <<func>> or are or have executed. | 185 | * remote CPUs are nearly ready to execute <<func>> or are or have executed. |
186 | * <map> is a cpu map of the cpus to send IPI to. | ||
184 | * | 187 | * |
185 | * You must not call this function with disabled interrupts or from a | 188 | * You must not call this function with disabled interrupts or from a |
186 | * hardware interrupt handler or from a bottom half handler. | 189 | * hardware interrupt handler or from a bottom half handler. |
187 | */ | 190 | */ |
188 | int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, | 191 | static int __smp_call_function_map(void (*func) (void *info), void *info, |
189 | int wait, cpumask_t map) | 192 | int nonatomic, int wait, cpumask_t map) |
190 | { | 193 | { |
191 | struct call_data_struct data; | 194 | struct call_data_struct data; |
192 | int ret = -1, num_cpus; | 195 | int ret = -1, num_cpus; |
@@ -203,8 +206,6 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, | |||
203 | if (wait) | 206 | if (wait) |
204 | atomic_set(&data.finished, 0); | 207 | atomic_set(&data.finished, 0); |
205 | 208 | ||
206 | spin_lock(&call_lock); | ||
207 | |||
208 | /* remove 'self' from the map */ | 209 | /* remove 'self' from the map */ |
209 | if (cpu_isset(smp_processor_id(), map)) | 210 | if (cpu_isset(smp_processor_id(), map)) |
210 | cpu_clear(smp_processor_id(), map); | 211 | cpu_clear(smp_processor_id(), map); |
@@ -231,7 +232,8 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, | |||
231 | printk("smp_call_function on cpu %d: other cpus not " | 232 | printk("smp_call_function on cpu %d: other cpus not " |
232 | "responding (%d)\n", smp_processor_id(), | 233 | "responding (%d)\n", smp_processor_id(), |
233 | atomic_read(&data.started)); | 234 | atomic_read(&data.started)); |
234 | debugger(NULL); | 235 | if (!ipi_fail_ok) |
236 | debugger(NULL); | ||
235 | goto out; | 237 | goto out; |
236 | } | 238 | } |
237 | } | 239 | } |
@@ -258,14 +260,18 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, | |||
258 | out: | 260 | out: |
259 | call_data = NULL; | 261 | call_data = NULL; |
260 | HMT_medium(); | 262 | HMT_medium(); |
261 | spin_unlock(&call_lock); | ||
262 | return ret; | 263 | return ret; |
263 | } | 264 | } |
264 | 265 | ||
265 | static int __smp_call_function(void (*func)(void *info), void *info, | 266 | static int __smp_call_function(void (*func)(void *info), void *info, |
266 | int nonatomic, int wait) | 267 | int nonatomic, int wait) |
267 | { | 268 | { |
268 | return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map); | 269 | int ret; |
270 | spin_lock(&call_lock); | ||
271 | ret =__smp_call_function_map(func, info, nonatomic, wait, | ||
272 | cpu_online_map); | ||
273 | spin_unlock(&call_lock); | ||
274 | return ret; | ||
269 | } | 275 | } |
270 | 276 | ||
271 | int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | 277 | int smp_call_function(void (*func) (void *info), void *info, int nonatomic, |
@@ -278,8 +284,8 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | |||
278 | } | 284 | } |
279 | EXPORT_SYMBOL(smp_call_function); | 285 | EXPORT_SYMBOL(smp_call_function); |
280 | 286 | ||
281 | int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, | 287 | int smp_call_function_single(int cpu, void (*func) (void *info), void *info, |
282 | int wait) | 288 | int nonatomic, int wait) |
283 | { | 289 | { |
284 | cpumask_t map = CPU_MASK_NONE; | 290 | cpumask_t map = CPU_MASK_NONE; |
285 | int ret = 0; | 291 | int ret = 0; |
@@ -291,9 +297,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int | |||
291 | return -EINVAL; | 297 | return -EINVAL; |
292 | 298 | ||
293 | cpu_set(cpu, map); | 299 | cpu_set(cpu, map); |
294 | if (cpu != get_cpu()) | 300 | if (cpu != get_cpu()) { |
295 | ret = smp_call_function_map(func,info,nonatomic,wait,map); | 301 | spin_lock(&call_lock); |
296 | else { | 302 | ret = __smp_call_function_map(func, info, nonatomic, wait, map); |
303 | spin_unlock(&call_lock); | ||
304 | } else { | ||
297 | local_irq_disable(); | 305 | local_irq_disable(); |
298 | func(info); | 306 | func(info); |
299 | local_irq_enable(); | 307 | local_irq_enable(); |
@@ -305,7 +313,22 @@ EXPORT_SYMBOL(smp_call_function_single); | |||
305 | 313 | ||
306 | void smp_send_stop(void) | 314 | void smp_send_stop(void) |
307 | { | 315 | { |
308 | __smp_call_function(stop_this_cpu, NULL, 1, 0); | 316 | int nolock; |
317 | |||
318 | /* It's OK to fail sending the IPI, since the alternative is to | ||
319 | * be stuck forever waiting on the other CPU to take the interrupt. | ||
320 | * | ||
321 | * It's better to at least continue and go through reboot, since this | ||
322 | * function is usually called at panic or reboot time in the first | ||
323 | * place. | ||
324 | */ | ||
325 | ipi_fail_ok = 1; | ||
326 | |||
327 | /* Don't deadlock in case we got called through panic */ | ||
328 | nolock = !spin_trylock(&call_lock); | ||
329 | __smp_call_function_map(stop_this_cpu, NULL, 1, 0, cpu_online_map); | ||
330 | if (!nolock) | ||
331 | spin_unlock(&call_lock); | ||
309 | } | 332 | } |
310 | 333 | ||
311 | void smp_call_function_interrupt(void) | 334 | void smp_call_function_interrupt(void) |
diff --git a/arch/powerpc/kernel/systbl_chk.c b/arch/powerpc/kernel/systbl_chk.c index 77824d1cb150..238aa63ced8f 100644 --- a/arch/powerpc/kernel/systbl_chk.c +++ b/arch/powerpc/kernel/systbl_chk.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Unfortunately, we cannot check for the correct ordering of entries | 6 | * Unfortunately, we cannot check for the correct ordering of entries |
7 | * using SYSX(). | 7 | * using SYSX(). |
8 | * | 8 | * |
9 | * Copyright © IBM Corporation | 9 | * Copyright © IBM Corporation |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
12 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
diff --git a/arch/powerpc/kernel/systbl_chk.sh b/arch/powerpc/kernel/systbl_chk.sh index 367d208301d2..19415e7674a5 100644 --- a/arch/powerpc/kernel/systbl_chk.sh +++ b/arch/powerpc/kernel/systbl_chk.sh | |||
@@ -3,7 +3,7 @@ | |||
3 | # Just process the CPP output from systbl_chk.c and complain | 3 | # Just process the CPP output from systbl_chk.c and complain |
4 | # if anything is out of order. | 4 | # if anything is out of order. |
5 | # | 5 | # |
6 | # Copyright © 2008 IBM Corporation | 6 | # Copyright © 2008 IBM Corporation |
7 | # | 7 | # |
8 | # This program is free software; you can redistribute it and/or | 8 | # This program is free software; you can redistribute it and/or |
9 | # modify it under the terms of the GNU General Public License | 9 | # modify it under the terms of the GNU General Public License |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 10dda224a361..7b2510799266 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
167 | if (notify_page_fault(regs)) | 167 | if (notify_page_fault(regs)) |
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | if (trap == 0x300) { | 170 | if (unlikely(debugger_fault_handler(regs))) |
171 | if (debugger_fault_handler(regs)) | 171 | return 0; |
172 | return 0; | ||
173 | } | ||
174 | 172 | ||
175 | /* On a kernel SLB miss we can only check for a valid exception entry */ | 173 | /* On a kernel SLB miss we can only check for a valid exception entry */ |
176 | if (!user_mode(regs) && (address >= TASK_SIZE)) | 174 | if (!user_mode(regs) && (address >= TASK_SIZE)) |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index bceb5e13da5c..eb2a94b0dc4c 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -310,8 +310,8 @@ static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long siz | |||
310 | { | 310 | { |
311 | struct page *page; | 311 | struct page *page; |
312 | int ret, i; | 312 | int ret, i; |
313 | unsigned long reg, segments, pages_per_segment, ptab_size, n_pte_pages; | 313 | unsigned long reg, segments, pages_per_segment, ptab_size, stab_size, |
314 | unsigned long xlate_base; | 314 | n_pte_pages, xlate_base; |
315 | unsigned int virq; | 315 | unsigned int virq; |
316 | 316 | ||
317 | if (cell_iommu_find_ioc(iommu->nid, &xlate_base)) | 317 | if (cell_iommu_find_ioc(iommu->nid, &xlate_base)) |
@@ -328,7 +328,8 @@ static void cell_iommu_setup_hardware(struct cbe_iommu *iommu, unsigned long siz | |||
328 | __FUNCTION__, iommu->nid, segments, pages_per_segment); | 328 | __FUNCTION__, iommu->nid, segments, pages_per_segment); |
329 | 329 | ||
330 | /* set up the segment table */ | 330 | /* set up the segment table */ |
331 | page = alloc_pages_node(iommu->nid, GFP_KERNEL, 0); | 331 | stab_size = segments * sizeof(unsigned long); |
332 | page = alloc_pages_node(iommu->nid, GFP_KERNEL, get_order(stab_size)); | ||
332 | BUG_ON(!page); | 333 | BUG_ON(!page); |
333 | iommu->stab = page_address(page); | 334 | iommu->stab = page_address(page); |
334 | clear_page(iommu->stab); | 335 | clear_page(iommu->stab); |
@@ -490,15 +491,18 @@ static struct cbe_iommu *cell_iommu_for_node(int nid) | |||
490 | return NULL; | 491 | return NULL; |
491 | } | 492 | } |
492 | 493 | ||
494 | static unsigned long cell_dma_direct_offset; | ||
495 | |||
493 | static void cell_dma_dev_setup(struct device *dev) | 496 | static void cell_dma_dev_setup(struct device *dev) |
494 | { | 497 | { |
495 | struct iommu_window *window; | 498 | struct iommu_window *window; |
496 | struct cbe_iommu *iommu; | 499 | struct cbe_iommu *iommu; |
497 | struct dev_archdata *archdata = &dev->archdata; | 500 | struct dev_archdata *archdata = &dev->archdata; |
498 | 501 | ||
499 | /* If we run without iommu, no need to do anything */ | 502 | if (get_pci_dma_ops() == &dma_direct_ops) { |
500 | if (get_pci_dma_ops() == &dma_direct_ops) | 503 | archdata->dma_data = (void *)cell_dma_direct_offset; |
501 | return; | 504 | return; |
505 | } | ||
502 | 506 | ||
503 | /* Current implementation uses the first window available in that | 507 | /* Current implementation uses the first window available in that |
504 | * node's iommu. We -might- do something smarter later though it may | 508 | * node's iommu. We -might- do something smarter later though it may |
@@ -654,7 +658,7 @@ static int __init cell_iommu_init_disabled(void) | |||
654 | 658 | ||
655 | /* If we have no Axon, we set up the spider DMA magic offset */ | 659 | /* If we have no Axon, we set up the spider DMA magic offset */ |
656 | if (of_find_node_by_name(NULL, "axon") == NULL) | 660 | if (of_find_node_by_name(NULL, "axon") == NULL) |
657 | dma_direct_offset = SPIDER_DMA_OFFSET; | 661 | cell_dma_direct_offset = SPIDER_DMA_OFFSET; |
658 | 662 | ||
659 | /* Now we need to check to see where the memory is mapped | 663 | /* Now we need to check to see where the memory is mapped |
660 | * in PCI space. We assume that all busses use the same dma | 664 | * in PCI space. We assume that all busses use the same dma |
@@ -688,10 +692,13 @@ static int __init cell_iommu_init_disabled(void) | |||
688 | return -ENODEV; | 692 | return -ENODEV; |
689 | } | 693 | } |
690 | 694 | ||
691 | dma_direct_offset += base; | 695 | cell_dma_direct_offset += base; |
696 | |||
697 | if (cell_dma_direct_offset != 0) | ||
698 | ppc_md.pci_dma_dev_setup = cell_pci_dma_dev_setup; | ||
692 | 699 | ||
693 | printk("iommu: disabled, direct DMA offset is 0x%lx\n", | 700 | printk("iommu: disabled, direct DMA offset is 0x%lx\n", |
694 | dma_direct_offset); | 701 | cell_dma_direct_offset); |
695 | 702 | ||
696 | return 0; | 703 | return 0; |
697 | } | 704 | } |
diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index 41e1e6f8e059..93b0efddd658 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c | |||
@@ -52,6 +52,8 @@ static int __init find_dma_window(u64 *io_space_id, u64 *ioid, | |||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static unsigned long celleb_dma_direct_offset; | ||
56 | |||
55 | static void __init celleb_init_direct_mapping(void) | 57 | static void __init celleb_init_direct_mapping(void) |
56 | { | 58 | { |
57 | u64 lpar_addr, io_addr; | 59 | u64 lpar_addr, io_addr; |
@@ -69,7 +71,18 @@ static void __init celleb_init_direct_mapping(void) | |||
69 | ioid, DMA_FLAGS); | 71 | ioid, DMA_FLAGS); |
70 | } | 72 | } |
71 | 73 | ||
72 | dma_direct_offset = dma_base; | 74 | celleb_dma_direct_offset = dma_base; |
75 | } | ||
76 | |||
77 | static void celleb_dma_dev_setup(struct device *dev) | ||
78 | { | ||
79 | dev->archdata.dma_ops = get_pci_dma_ops(); | ||
80 | dev->archdata.dma_data = (void *)celleb_dma_direct_offset; | ||
81 | } | ||
82 | |||
83 | static void celleb_pci_dma_dev_setup(struct pci_dev *pdev) | ||
84 | { | ||
85 | celleb_dma_dev_setup(&pdev->dev); | ||
73 | } | 86 | } |
74 | 87 | ||
75 | static int celleb_of_bus_notify(struct notifier_block *nb, | 88 | static int celleb_of_bus_notify(struct notifier_block *nb, |
@@ -81,7 +94,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb, | |||
81 | if (action != BUS_NOTIFY_ADD_DEVICE) | 94 | if (action != BUS_NOTIFY_ADD_DEVICE) |
82 | return 0; | 95 | return 0; |
83 | 96 | ||
84 | dev->archdata.dma_ops = get_pci_dma_ops(); | 97 | celleb_dma_dev_setup(dev); |
85 | 98 | ||
86 | return 0; | 99 | return 0; |
87 | } | 100 | } |
@@ -94,6 +107,7 @@ static int __init celleb_init_iommu(void) | |||
94 | { | 107 | { |
95 | celleb_init_direct_mapping(); | 108 | celleb_init_direct_mapping(); |
96 | set_pci_dma_ops(&dma_direct_ops); | 109 | set_pci_dma_ops(&dma_direct_ops); |
110 | ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup; | ||
97 | bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); | 111 | bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); |
98 | 112 | ||
99 | return 0; | 113 | return 0; |
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index d51f83aeef7f..609c46db4a1b 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -354,7 +354,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, | |||
354 | * mode as well. The same fixup must be done to the class-code property in | 354 | * mode as well. The same fixup must be done to the class-code property in |
355 | * the IDE node /pci@80000000/ide@C,1 | 355 | * the IDE node /pci@80000000/ide@C,1 |
356 | */ | 356 | */ |
357 | static void __devinit chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) | 357 | static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) |
358 | { | 358 | { |
359 | u8 progif; | 359 | u8 progif; |
360 | struct pci_dev *viaisa; | 360 | struct pci_dev *viaisa; |
@@ -375,4 +375,4 @@ static void __devinit chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide) | |||
375 | 375 | ||
376 | pci_dev_put(viaisa); | 376 | pci_dev_put(viaisa); |
377 | } | 377 | } |
378 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata); | 378 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata); |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 42a21bab76c8..116babbaaf81 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -256,6 +256,57 @@ static void briq_restart(char *cmd) | |||
256 | for(;;); | 256 | for(;;); |
257 | } | 257 | } |
258 | 258 | ||
259 | /* | ||
260 | * Per default, input/output-device points to the keyboard/screen | ||
261 | * If no card is installed, the built-in serial port is used as a fallback. | ||
262 | * But unfortunately, the firmware does not connect /chosen/{stdin,stdout} | ||
263 | * the the built-in serial node. Instead, a /failsafe node is created. | ||
264 | */ | ||
265 | static void chrp_init_early(void) | ||
266 | { | ||
267 | struct device_node *node; | ||
268 | const char *property; | ||
269 | |||
270 | if (strstr(cmd_line, "console=")) | ||
271 | return; | ||
272 | /* find the boot console from /chosen/stdout */ | ||
273 | if (!of_chosen) | ||
274 | return; | ||
275 | node = of_find_node_by_path("/"); | ||
276 | if (!node) | ||
277 | return; | ||
278 | property = of_get_property(node, "model", NULL); | ||
279 | if (!property) | ||
280 | goto out_put; | ||
281 | if (strcmp(property, "Pegasos2")) | ||
282 | goto out_put; | ||
283 | /* this is a Pegasos2 */ | ||
284 | property = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
285 | if (!property) | ||
286 | goto out_put; | ||
287 | of_node_put(node); | ||
288 | node = of_find_node_by_path(property); | ||
289 | if (!node) | ||
290 | return; | ||
291 | property = of_get_property(node, "device_type", NULL); | ||
292 | if (!property) | ||
293 | goto out_put; | ||
294 | if (strcmp(property, "serial")) | ||
295 | goto out_put; | ||
296 | /* | ||
297 | * The 9pin connector is either /failsafe | ||
298 | * or /pci@80000000/isa@C/serial@i2F8 | ||
299 | * The optional graphics card has also type 'serial' in VGA mode. | ||
300 | */ | ||
301 | property = of_get_property(node, "name", NULL); | ||
302 | if (!property) | ||
303 | goto out_put; | ||
304 | if (!strcmp(property, "failsafe") || !strcmp(property, "serial")) | ||
305 | add_preferred_console("ttyS", 0, NULL); | ||
306 | out_put: | ||
307 | of_node_put(node); | ||
308 | } | ||
309 | |||
259 | void __init chrp_setup_arch(void) | 310 | void __init chrp_setup_arch(void) |
260 | { | 311 | { |
261 | struct device_node *root = of_find_node_by_path("/"); | 312 | struct device_node *root = of_find_node_by_path("/"); |
@@ -599,6 +650,7 @@ define_machine(chrp) { | |||
599 | .probe = chrp_probe, | 650 | .probe = chrp_probe, |
600 | .setup_arch = chrp_setup_arch, | 651 | .setup_arch = chrp_setup_arch, |
601 | .init = chrp_init2, | 652 | .init = chrp_init2, |
653 | .init_early = chrp_init_early, | ||
602 | .show_cpuinfo = chrp_show_cpuinfo, | 654 | .show_cpuinfo = chrp_show_cpuinfo, |
603 | .init_IRQ = chrp_init_IRQ, | 655 | .init_IRQ = chrp_init_IRQ, |
604 | .restart = rtas_restart, | 656 | .restart = rtas_restart, |
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 298f1c9679fb..a5f4e95dfc3d 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig | |||
@@ -61,17 +61,6 @@ config PS3_DYNAMIC_DMA | |||
61 | This support is mainly for Linux kernel development. If unsure, | 61 | This support is mainly for Linux kernel development. If unsure, |
62 | say N. | 62 | say N. |
63 | 63 | ||
64 | config PS3_USE_LPAR_ADDR | ||
65 | depends on PPC_PS3 && EXPERIMENTAL | ||
66 | bool "PS3 use lpar address space" | ||
67 | default y | ||
68 | help | ||
69 | This option is solely for experimentation by experts. Disables | ||
70 | translation of lpar addresses. SPE support currently won't work | ||
71 | without this set to y. | ||
72 | |||
73 | If you have any doubt, choose the default y. | ||
74 | |||
75 | config PS3_VUART | 64 | config PS3_VUART |
76 | depends on PPC_PS3 | 65 | depends on PPC_PS3 |
77 | tristate | 66 | tristate |
@@ -138,4 +127,17 @@ config PS3_FLASH | |||
138 | be disabled on the kernel command line using "ps3flash=off", to | 127 | be disabled on the kernel command line using "ps3flash=off", to |
139 | not allocate this fixed buffer. | 128 | not allocate this fixed buffer. |
140 | 129 | ||
130 | config PS3_LPM | ||
131 | tristate "PS3 Logical Performance Monitor support" | ||
132 | depends on PPC_PS3 | ||
133 | help | ||
134 | Include support for the PS3 Logical Performance Monitor. | ||
135 | |||
136 | This support is required to use the logical performance monitor | ||
137 | of the PS3's LV1 hypervisor. | ||
138 | |||
139 | If you intend to use the advanced performance monitoring and | ||
140 | profiling support of the Cell processor with programs like | ||
141 | oprofile and perfmon2, then say Y or M, otherwise say N. | ||
142 | |||
141 | endmenu | 143 | endmenu |
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c index fd063fe0c9b3..9d251d0ca8c6 100644 --- a/arch/powerpc/platforms/ps3/device-init.c +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/reboot.h> | ||
26 | 27 | ||
27 | #include <asm/firmware.h> | 28 | #include <asm/firmware.h> |
28 | #include <asm/lv1call.h> | 29 | #include <asm/lv1call.h> |
@@ -30,6 +31,89 @@ | |||
30 | 31 | ||
31 | #include "platform.h" | 32 | #include "platform.h" |
32 | 33 | ||
34 | static int __init ps3_register_lpm_devices(void) | ||
35 | { | ||
36 | int result; | ||
37 | u64 tmp1; | ||
38 | u64 tmp2; | ||
39 | struct ps3_system_bus_device *dev; | ||
40 | |||
41 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
42 | |||
43 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
44 | if (!dev) | ||
45 | return -ENOMEM; | ||
46 | |||
47 | dev->match_id = PS3_MATCH_ID_LPM; | ||
48 | dev->dev_type = PS3_DEVICE_TYPE_LPM; | ||
49 | |||
50 | /* The current lpm driver only supports a single BE processor. */ | ||
51 | |||
52 | result = ps3_repository_read_be_node_id(0, &dev->lpm.node_id); | ||
53 | |||
54 | if (result) { | ||
55 | pr_debug("%s:%d: ps3_repository_read_be_node_id failed \n", | ||
56 | __func__, __LINE__); | ||
57 | goto fail_read_repo; | ||
58 | } | ||
59 | |||
60 | result = ps3_repository_read_lpm_privileges(dev->lpm.node_id, &tmp1, | ||
61 | &dev->lpm.rights); | ||
62 | |||
63 | if (result) { | ||
64 | pr_debug("%s:%d: ps3_repository_read_lpm_privleges failed \n", | ||
65 | __func__, __LINE__); | ||
66 | goto fail_read_repo; | ||
67 | } | ||
68 | |||
69 | lv1_get_logical_partition_id(&tmp2); | ||
70 | |||
71 | if (tmp1 != tmp2) { | ||
72 | pr_debug("%s:%d: wrong lpar\n", | ||
73 | __func__, __LINE__); | ||
74 | result = -ENODEV; | ||
75 | goto fail_rights; | ||
76 | } | ||
77 | |||
78 | if (!(dev->lpm.rights & PS3_LPM_RIGHTS_USE_LPM)) { | ||
79 | pr_debug("%s:%d: don't have rights to use lpm\n", | ||
80 | __func__, __LINE__); | ||
81 | result = -EPERM; | ||
82 | goto fail_rights; | ||
83 | } | ||
84 | |||
85 | pr_debug("%s:%d: pu_id %lu, rights %lu(%lxh)\n", | ||
86 | __func__, __LINE__, dev->lpm.pu_id, dev->lpm.rights, | ||
87 | dev->lpm.rights); | ||
88 | |||
89 | result = ps3_repository_read_pu_id(0, &dev->lpm.pu_id); | ||
90 | |||
91 | if (result) { | ||
92 | pr_debug("%s:%d: ps3_repository_read_pu_id failed \n", | ||
93 | __func__, __LINE__); | ||
94 | goto fail_read_repo; | ||
95 | } | ||
96 | |||
97 | result = ps3_system_bus_device_register(dev); | ||
98 | |||
99 | if (result) { | ||
100 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
101 | __func__, __LINE__); | ||
102 | goto fail_register; | ||
103 | } | ||
104 | |||
105 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
106 | return 0; | ||
107 | |||
108 | |||
109 | fail_register: | ||
110 | fail_rights: | ||
111 | fail_read_repo: | ||
112 | kfree(dev); | ||
113 | pr_debug(" <- %s:%d: failed\n", __func__, __LINE__); | ||
114 | return result; | ||
115 | } | ||
116 | |||
33 | /** | 117 | /** |
34 | * ps3_setup_gelic_device - Setup and register a gelic device instance. | 118 | * ps3_setup_gelic_device - Setup and register a gelic device instance. |
35 | * | 119 | * |
@@ -238,166 +322,6 @@ static int __init ps3_setup_vuart_device(enum ps3_match_id match_id, | |||
238 | return result; | 322 | return result; |
239 | } | 323 | } |
240 | 324 | ||
241 | static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, | ||
242 | unsigned int timeout) | ||
243 | { | ||
244 | int result = -1; | ||
245 | unsigned int retries = 0; | ||
246 | u64 status; | ||
247 | |||
248 | for (retries = 0; retries < timeout; retries++) { | ||
249 | result = lv1_storage_check_async_status(dev_id, tag, &status); | ||
250 | if (!result) | ||
251 | break; | ||
252 | |||
253 | msleep(1); | ||
254 | } | ||
255 | |||
256 | if (result) | ||
257 | pr_debug("%s:%u: check_async_status: %s, status %lx\n", | ||
258 | __func__, __LINE__, ps3_result(result), status); | ||
259 | |||
260 | return result; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * ps3_storage_wait_for_device - Wait for a storage device to become ready. | ||
265 | * @repo: The repository device to wait for. | ||
266 | * | ||
267 | * Uses the hypervisor's storage device notification mechanism to wait until | ||
268 | * a storage device is ready. The device notification mechanism uses a | ||
269 | * psuedo device (id = -1) to asynchronously notify the guest when storage | ||
270 | * devices become ready. The notification device has a block size of 512 | ||
271 | * bytes. | ||
272 | */ | ||
273 | |||
274 | static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | ||
275 | { | ||
276 | int error = -ENODEV; | ||
277 | int result; | ||
278 | const u64 notification_dev_id = (u64)-1LL; | ||
279 | const unsigned int timeout = HZ; | ||
280 | u64 lpar; | ||
281 | u64 tag; | ||
282 | void *buf; | ||
283 | enum ps3_notify_type { | ||
284 | notify_device_ready = 0, | ||
285 | notify_region_probe = 1, | ||
286 | notify_region_update = 2, | ||
287 | }; | ||
288 | struct { | ||
289 | u64 operation_code; /* must be zero */ | ||
290 | u64 event_mask; /* OR of 1UL << enum ps3_notify_type */ | ||
291 | } *notify_cmd; | ||
292 | struct { | ||
293 | u64 event_type; /* enum ps3_notify_type */ | ||
294 | u64 bus_id; | ||
295 | u64 dev_id; | ||
296 | u64 dev_type; | ||
297 | u64 dev_port; | ||
298 | } *notify_event; | ||
299 | |||
300 | pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id, | ||
301 | repo->dev_id, repo->dev_type); | ||
302 | |||
303 | buf = kzalloc(512, GFP_KERNEL); | ||
304 | if (!buf) | ||
305 | return -ENOMEM; | ||
306 | |||
307 | lpar = ps3_mm_phys_to_lpar(__pa(buf)); | ||
308 | notify_cmd = buf; | ||
309 | notify_event = buf; | ||
310 | |||
311 | result = lv1_open_device(repo->bus_id, notification_dev_id, 0); | ||
312 | if (result) { | ||
313 | printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, | ||
314 | __LINE__, ps3_result(result)); | ||
315 | goto fail_free; | ||
316 | } | ||
317 | |||
318 | /* Setup and write the request for device notification. */ | ||
319 | |||
320 | notify_cmd->operation_code = 0; /* must be zero */ | ||
321 | notify_cmd->event_mask = 1UL << notify_region_probe; | ||
322 | |||
323 | result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, | ||
324 | &tag); | ||
325 | if (result) { | ||
326 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, | ||
327 | ps3_result(result)); | ||
328 | goto fail_close; | ||
329 | } | ||
330 | |||
331 | /* Wait for the write completion */ | ||
332 | |||
333 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
334 | timeout); | ||
335 | if (result) { | ||
336 | printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, | ||
337 | __LINE__, ps3_result(result)); | ||
338 | goto fail_close; | ||
339 | } | ||
340 | |||
341 | /* Loop here processing the requested notification events. */ | ||
342 | |||
343 | while (1) { | ||
344 | memset(notify_event, 0, sizeof(*notify_event)); | ||
345 | |||
346 | result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, | ||
347 | lpar, &tag); | ||
348 | if (result) { | ||
349 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, | ||
350 | __LINE__, ps3_result(result)); | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
355 | timeout); | ||
356 | if (result) { | ||
357 | printk(KERN_ERR "%s:%u: read not completed %s\n", | ||
358 | __func__, __LINE__, ps3_result(result)); | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, " | ||
363 | "port %lu\n", __func__, __LINE__, repo->bus_index, | ||
364 | repo->dev_index, repo->dev_type, | ||
365 | notify_event->event_type, notify_event->dev_port); | ||
366 | |||
367 | if (notify_event->event_type != notify_region_probe || | ||
368 | notify_event->bus_id != repo->bus_id) { | ||
369 | pr_debug("%s:%u: bad notify_event: event %lu, " | ||
370 | "dev_id %lu, dev_type %lu\n", | ||
371 | __func__, __LINE__, notify_event->event_type, | ||
372 | notify_event->dev_id, notify_event->dev_type); | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | if (notify_event->dev_id == repo->dev_id && | ||
377 | notify_event->dev_type == repo->dev_type) { | ||
378 | pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__, | ||
379 | __LINE__, repo->bus_index, repo->dev_index, | ||
380 | repo->dev_type); | ||
381 | error = 0; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | if (notify_event->dev_id == repo->dev_id && | ||
386 | notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { | ||
387 | pr_debug("%s:%u: no access: dev_id %u\n", __func__, | ||
388 | __LINE__, repo->dev_id); | ||
389 | break; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | fail_close: | ||
394 | lv1_close_device(repo->bus_id, notification_dev_id); | ||
395 | fail_free: | ||
396 | kfree(buf); | ||
397 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
398 | return error; | ||
399 | } | ||
400 | |||
401 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | 325 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, |
402 | enum ps3_match_id match_id) | 326 | enum ps3_match_id match_id) |
403 | { | 327 | { |
@@ -449,16 +373,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | |||
449 | goto fail_find_interrupt; | 373 | goto fail_find_interrupt; |
450 | } | 374 | } |
451 | 375 | ||
452 | /* FIXME: Arrange to only do this on a 'cold' boot */ | ||
453 | |||
454 | result = ps3_storage_wait_for_device(repo); | ||
455 | if (result) { | ||
456 | printk(KERN_ERR "%s:%u: storage_notification failed %d\n", | ||
457 | __func__, __LINE__, result); | ||
458 | result = -ENODEV; | ||
459 | goto fail_probe_notification; | ||
460 | } | ||
461 | |||
462 | for (i = 0; i < num_regions; i++) { | 376 | for (i = 0; i < num_regions; i++) { |
463 | unsigned int id; | 377 | unsigned int id; |
464 | u64 start, size; | 378 | u64 start, size; |
@@ -494,7 +408,6 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | |||
494 | 408 | ||
495 | fail_device_register: | 409 | fail_device_register: |
496 | fail_read_region: | 410 | fail_read_region: |
497 | fail_probe_notification: | ||
498 | fail_find_interrupt: | 411 | fail_find_interrupt: |
499 | kfree(p); | 412 | kfree(p); |
500 | fail_malloc: | 413 | fail_malloc: |
@@ -659,62 +572,268 @@ static int ps3_register_repository_device( | |||
659 | return result; | 572 | return result; |
660 | } | 573 | } |
661 | 574 | ||
575 | static void ps3_find_and_add_device(u64 bus_id, u64 dev_id) | ||
576 | { | ||
577 | struct ps3_repository_device repo; | ||
578 | int res; | ||
579 | unsigned int retries; | ||
580 | unsigned long rem; | ||
581 | |||
582 | /* | ||
583 | * On some firmware versions (e.g. 1.90), the device may not show up | ||
584 | * in the repository immediately | ||
585 | */ | ||
586 | for (retries = 0; retries < 10; retries++) { | ||
587 | res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id); | ||
588 | if (!res) | ||
589 | goto found; | ||
590 | |||
591 | rem = msleep_interruptible(100); | ||
592 | if (rem) | ||
593 | break; | ||
594 | } | ||
595 | pr_warning("%s:%u: device %lu:%lu not found\n", __func__, __LINE__, | ||
596 | bus_id, dev_id); | ||
597 | return; | ||
598 | |||
599 | found: | ||
600 | if (retries) | ||
601 | pr_debug("%s:%u: device %lu:%lu found after %u retries\n", | ||
602 | __func__, __LINE__, bus_id, dev_id, retries); | ||
603 | |||
604 | ps3_register_repository_device(&repo); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | #define PS3_NOTIFICATION_DEV_ID ULONG_MAX | ||
609 | #define PS3_NOTIFICATION_INTERRUPT_ID 0 | ||
610 | |||
611 | struct ps3_notification_device { | ||
612 | struct ps3_system_bus_device sbd; | ||
613 | spinlock_t lock; | ||
614 | u64 tag; | ||
615 | u64 lv1_status; | ||
616 | struct completion done; | ||
617 | }; | ||
618 | |||
619 | enum ps3_notify_type { | ||
620 | notify_device_ready = 0, | ||
621 | notify_region_probe = 1, | ||
622 | notify_region_update = 2, | ||
623 | }; | ||
624 | |||
625 | struct ps3_notify_cmd { | ||
626 | u64 operation_code; /* must be zero */ | ||
627 | u64 event_mask; /* OR of 1UL << enum ps3_notify_type */ | ||
628 | }; | ||
629 | |||
630 | struct ps3_notify_event { | ||
631 | u64 event_type; /* enum ps3_notify_type */ | ||
632 | u64 bus_id; | ||
633 | u64 dev_id; | ||
634 | u64 dev_type; | ||
635 | u64 dev_port; | ||
636 | }; | ||
637 | |||
638 | static irqreturn_t ps3_notification_interrupt(int irq, void *data) | ||
639 | { | ||
640 | struct ps3_notification_device *dev = data; | ||
641 | int res; | ||
642 | u64 tag, status; | ||
643 | |||
644 | spin_lock(&dev->lock); | ||
645 | res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag, | ||
646 | &status); | ||
647 | if (tag != dev->tag) | ||
648 | pr_err("%s:%u: tag mismatch, got %lx, expected %lx\n", | ||
649 | __func__, __LINE__, tag, dev->tag); | ||
650 | |||
651 | if (res) { | ||
652 | pr_err("%s:%u: res %d status 0x%lx\n", __func__, __LINE__, res, | ||
653 | status); | ||
654 | } else { | ||
655 | pr_debug("%s:%u: completed, status 0x%lx\n", __func__, | ||
656 | __LINE__, status); | ||
657 | dev->lv1_status = status; | ||
658 | complete(&dev->done); | ||
659 | } | ||
660 | spin_unlock(&dev->lock); | ||
661 | return IRQ_HANDLED; | ||
662 | } | ||
663 | |||
664 | static int ps3_notification_read_write(struct ps3_notification_device *dev, | ||
665 | u64 lpar, int write) | ||
666 | { | ||
667 | const char *op = write ? "write" : "read"; | ||
668 | unsigned long flags; | ||
669 | int res; | ||
670 | |||
671 | init_completion(&dev->done); | ||
672 | spin_lock_irqsave(&dev->lock, flags); | ||
673 | res = write ? lv1_storage_write(dev->sbd.dev_id, 0, 0, 1, 0, lpar, | ||
674 | &dev->tag) | ||
675 | : lv1_storage_read(dev->sbd.dev_id, 0, 0, 1, 0, lpar, | ||
676 | &dev->tag); | ||
677 | spin_unlock_irqrestore(&dev->lock, flags); | ||
678 | if (res) { | ||
679 | pr_err("%s:%u: %s failed %d\n", __func__, __LINE__, op, res); | ||
680 | return -EPERM; | ||
681 | } | ||
682 | pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op); | ||
683 | |||
684 | res = wait_event_interruptible(dev->done.wait, | ||
685 | dev->done.done || kthread_should_stop()); | ||
686 | if (kthread_should_stop()) | ||
687 | res = -EINTR; | ||
688 | if (res) { | ||
689 | pr_debug("%s:%u: interrupted %s\n", __func__, __LINE__, op); | ||
690 | return res; | ||
691 | } | ||
692 | |||
693 | if (dev->lv1_status) { | ||
694 | pr_err("%s:%u: %s not completed, status 0x%lx\n", __func__, | ||
695 | __LINE__, op, dev->lv1_status); | ||
696 | return -EIO; | ||
697 | } | ||
698 | pr_debug("%s:%u: notification %s completed\n", __func__, __LINE__, op); | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static struct task_struct *probe_task; | ||
704 | |||
662 | /** | 705 | /** |
663 | * ps3_probe_thread - Background repository probing at system startup. | 706 | * ps3_probe_thread - Background repository probing at system startup. |
664 | * | 707 | * |
665 | * This implementation only supports background probing on a single bus. | 708 | * This implementation only supports background probing on a single bus. |
709 | * It uses the hypervisor's storage device notification mechanism to wait until | ||
710 | * a storage device is ready. The device notification mechanism uses a | ||
711 | * pseudo device to asynchronously notify the guest when storage devices become | ||
712 | * ready. The notification device has a block size of 512 bytes. | ||
666 | */ | 713 | */ |
667 | 714 | ||
668 | static int ps3_probe_thread(void *data) | 715 | static int ps3_probe_thread(void *data) |
669 | { | 716 | { |
670 | struct ps3_repository_device *repo = data; | 717 | struct ps3_notification_device dev; |
671 | int result; | 718 | int res; |
672 | unsigned int ms = 250; | 719 | unsigned int irq; |
720 | u64 lpar; | ||
721 | void *buf; | ||
722 | struct ps3_notify_cmd *notify_cmd; | ||
723 | struct ps3_notify_event *notify_event; | ||
673 | 724 | ||
674 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); | 725 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); |
675 | 726 | ||
727 | buf = kzalloc(512, GFP_KERNEL); | ||
728 | if (!buf) | ||
729 | return -ENOMEM; | ||
730 | |||
731 | lpar = ps3_mm_phys_to_lpar(__pa(buf)); | ||
732 | notify_cmd = buf; | ||
733 | notify_event = buf; | ||
734 | |||
735 | /* dummy system bus device */ | ||
736 | dev.sbd.bus_id = (u64)data; | ||
737 | dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID; | ||
738 | dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID; | ||
739 | |||
740 | res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0); | ||
741 | if (res) { | ||
742 | pr_err("%s:%u: lv1_open_device failed %s\n", __func__, | ||
743 | __LINE__, ps3_result(res)); | ||
744 | goto fail_free; | ||
745 | } | ||
746 | |||
747 | res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY, | ||
748 | &irq); | ||
749 | if (res) { | ||
750 | pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n", | ||
751 | __func__, __LINE__, res); | ||
752 | goto fail_close_device; | ||
753 | } | ||
754 | |||
755 | spin_lock_init(&dev.lock); | ||
756 | |||
757 | res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED, | ||
758 | "ps3_notification", &dev); | ||
759 | if (res) { | ||
760 | pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__, | ||
761 | res); | ||
762 | goto fail_sb_event_receive_port_destroy; | ||
763 | } | ||
764 | |||
765 | /* Setup and write the request for device notification. */ | ||
766 | notify_cmd->operation_code = 0; /* must be zero */ | ||
767 | notify_cmd->event_mask = 1UL << notify_region_probe; | ||
768 | |||
769 | res = ps3_notification_read_write(&dev, lpar, 1); | ||
770 | if (res) | ||
771 | goto fail_free_irq; | ||
772 | |||
773 | /* Loop here processing the requested notification events. */ | ||
676 | do { | 774 | do { |
677 | try_to_freeze(); | 775 | try_to_freeze(); |
678 | 776 | ||
679 | pr_debug("%s:%u: probing...\n", __func__, __LINE__); | 777 | memset(notify_event, 0, sizeof(*notify_event)); |
680 | 778 | ||
681 | do { | 779 | res = ps3_notification_read_write(&dev, lpar, 0); |
682 | result = ps3_repository_find_device(repo); | 780 | if (res) |
683 | |||
684 | if (result == -ENODEV) | ||
685 | pr_debug("%s:%u: nothing new\n", __func__, | ||
686 | __LINE__); | ||
687 | else if (result) | ||
688 | pr_debug("%s:%u: find device error.\n", | ||
689 | __func__, __LINE__); | ||
690 | else { | ||
691 | pr_debug("%s:%u: found device (%u:%u:%u)\n", | ||
692 | __func__, __LINE__, repo->bus_index, | ||
693 | repo->dev_index, repo->dev_type); | ||
694 | ps3_register_repository_device(repo); | ||
695 | ps3_repository_bump_device(repo); | ||
696 | ms = 250; | ||
697 | } | ||
698 | } while (!result); | ||
699 | |||
700 | pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms); | ||
701 | |||
702 | if ( ms > 60000) | ||
703 | break; | 781 | break; |
704 | 782 | ||
705 | msleep_interruptible(ms); | 783 | pr_debug("%s:%u: notify event type 0x%lx bus id %lu dev id %lu" |
784 | " type %lu port %lu\n", __func__, __LINE__, | ||
785 | notify_event->event_type, notify_event->bus_id, | ||
786 | notify_event->dev_id, notify_event->dev_type, | ||
787 | notify_event->dev_port); | ||
706 | 788 | ||
707 | /* An exponential backoff. */ | 789 | if (notify_event->event_type != notify_region_probe || |
708 | ms <<= 1; | 790 | notify_event->bus_id != dev.sbd.bus_id) { |
791 | pr_warning("%s:%u: bad notify_event: event %lu, " | ||
792 | "dev_id %lu, dev_type %lu\n", | ||
793 | __func__, __LINE__, notify_event->event_type, | ||
794 | notify_event->dev_id, | ||
795 | notify_event->dev_type); | ||
796 | continue; | ||
797 | } | ||
798 | |||
799 | ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id); | ||
709 | 800 | ||
710 | } while (!kthread_should_stop()); | 801 | } while (!kthread_should_stop()); |
711 | 802 | ||
803 | fail_free_irq: | ||
804 | free_irq(irq, &dev); | ||
805 | fail_sb_event_receive_port_destroy: | ||
806 | ps3_sb_event_receive_port_destroy(&dev.sbd, irq); | ||
807 | fail_close_device: | ||
808 | lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id); | ||
809 | fail_free: | ||
810 | kfree(buf); | ||
811 | |||
812 | probe_task = NULL; | ||
813 | |||
712 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); | 814 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); |
713 | 815 | ||
714 | return 0; | 816 | return 0; |
715 | } | 817 | } |
716 | 818 | ||
717 | /** | 819 | /** |
820 | * ps3_stop_probe_thread - Stops the background probe thread. | ||
821 | * | ||
822 | */ | ||
823 | |||
824 | static int ps3_stop_probe_thread(struct notifier_block *nb, unsigned long code, | ||
825 | void *data) | ||
826 | { | ||
827 | if (probe_task) | ||
828 | kthread_stop(probe_task); | ||
829 | return 0; | ||
830 | } | ||
831 | |||
832 | static struct notifier_block nb = { | ||
833 | .notifier_call = ps3_stop_probe_thread | ||
834 | }; | ||
835 | |||
836 | /** | ||
718 | * ps3_start_probe_thread - Starts the background probe thread. | 837 | * ps3_start_probe_thread - Starts the background probe thread. |
719 | * | 838 | * |
720 | */ | 839 | */ |
@@ -723,7 +842,7 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
723 | { | 842 | { |
724 | int result; | 843 | int result; |
725 | struct task_struct *task; | 844 | struct task_struct *task; |
726 | static struct ps3_repository_device repo; /* must be static */ | 845 | struct ps3_repository_device repo; |
727 | 846 | ||
728 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 847 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
729 | 848 | ||
@@ -746,7 +865,8 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
746 | return -ENODEV; | 865 | return -ENODEV; |
747 | } | 866 | } |
748 | 867 | ||
749 | task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); | 868 | task = kthread_run(ps3_probe_thread, (void *)repo.bus_id, |
869 | "ps3-probe-%u", bus_type); | ||
750 | 870 | ||
751 | if (IS_ERR(task)) { | 871 | if (IS_ERR(task)) { |
752 | result = PTR_ERR(task); | 872 | result = PTR_ERR(task); |
@@ -755,6 +875,9 @@ static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | |||
755 | return result; | 875 | return result; |
756 | } | 876 | } |
757 | 877 | ||
878 | probe_task = task; | ||
879 | register_reboot_notifier(&nb); | ||
880 | |||
758 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 881 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
759 | return 0; | 882 | return 0; |
760 | } | 883 | } |
@@ -787,6 +910,8 @@ static int __init ps3_register_devices(void) | |||
787 | 910 | ||
788 | ps3_register_sound_devices(); | 911 | ps3_register_sound_devices(); |
789 | 912 | ||
913 | ps3_register_lpm_devices(); | ||
914 | |||
790 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 915 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
791 | return 0; | 916 | return 0; |
792 | } | 917 | } |
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 7bb3e1620974..68900476c842 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c | |||
@@ -36,11 +36,6 @@ | |||
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | enum { | 38 | enum { |
39 | #if defined(CONFIG_PS3_USE_LPAR_ADDR) | ||
40 | USE_LPAR_ADDR = 1, | ||
41 | #else | ||
42 | USE_LPAR_ADDR = 0, | ||
43 | #endif | ||
44 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 39 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
45 | USE_DYNAMIC_DMA = 1, | 40 | USE_DYNAMIC_DMA = 1, |
46 | #else | 41 | #else |
@@ -137,11 +132,8 @@ static struct map map; | |||
137 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr) | 132 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr) |
138 | { | 133 | { |
139 | BUG_ON(is_kernel_addr(phys_addr)); | 134 | BUG_ON(is_kernel_addr(phys_addr)); |
140 | if (USE_LPAR_ADDR) | 135 | return (phys_addr < map.rm.size || phys_addr >= map.total) |
141 | return phys_addr; | 136 | ? phys_addr : phys_addr + map.r1.offset; |
142 | else | ||
143 | return (phys_addr < map.rm.size || phys_addr >= map.total) | ||
144 | ? phys_addr : phys_addr + map.r1.offset; | ||
145 | } | 137 | } |
146 | 138 | ||
147 | EXPORT_SYMBOL(ps3_mm_phys_to_lpar); | 139 | EXPORT_SYMBOL(ps3_mm_phys_to_lpar); |
@@ -309,7 +301,7 @@ static int __init ps3_mm_add_memory(void) | |||
309 | 301 | ||
310 | BUG_ON(!mem_init_done); | 302 | BUG_ON(!mem_init_done); |
311 | 303 | ||
312 | start_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; | 304 | start_addr = map.rm.size; |
313 | start_pfn = start_addr >> PAGE_SHIFT; | 305 | start_pfn = start_addr >> PAGE_SHIFT; |
314 | nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 306 | nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
315 | 307 | ||
@@ -359,7 +351,7 @@ static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r, | |||
359 | static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, | 351 | static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, |
360 | const char *func, int line) | 352 | const char *func, int line) |
361 | { | 353 | { |
362 | DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, | 354 | DBG("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id, |
363 | r->dev->dev_id); | 355 | r->dev->dev_id); |
364 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); | 356 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); |
365 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 357 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
@@ -394,7 +386,7 @@ struct dma_chunk { | |||
394 | static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, | 386 | static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, |
395 | int line) | 387 | int line) |
396 | { | 388 | { |
397 | DBG("%s:%d: r.dev %u:%u\n", func, line, | 389 | DBG("%s:%d: r.dev %lu:%lu\n", func, line, |
398 | c->region->dev->bus_id, c->region->dev->dev_id); | 390 | c->region->dev->bus_id, c->region->dev->dev_id); |
399 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); | 391 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); |
400 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); | 392 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); |
@@ -658,7 +650,7 @@ static int dma_sb_region_create(struct ps3_dma_region *r) | |||
658 | BUG_ON(!r); | 650 | BUG_ON(!r); |
659 | 651 | ||
660 | if (!r->dev->bus_id) { | 652 | if (!r->dev->bus_id) { |
661 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | 653 | pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__, |
662 | r->dev->bus_id, r->dev->dev_id); | 654 | r->dev->bus_id, r->dev->dev_id); |
663 | return 0; | 655 | return 0; |
664 | } | 656 | } |
@@ -724,7 +716,7 @@ static int dma_sb_region_free(struct ps3_dma_region *r) | |||
724 | BUG_ON(!r); | 716 | BUG_ON(!r); |
725 | 717 | ||
726 | if (!r->dev->bus_id) { | 718 | if (!r->dev->bus_id) { |
727 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | 719 | pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__, |
728 | r->dev->bus_id, r->dev->dev_id); | 720 | r->dev->bus_id, r->dev->dev_id); |
729 | return 0; | 721 | return 0; |
730 | } | 722 | } |
@@ -1007,7 +999,7 @@ static int dma_sb_region_create_linear(struct ps3_dma_region *r) | |||
1007 | 999 | ||
1008 | if (r->offset + r->len > map.rm.size) { | 1000 | if (r->offset + r->len > map.rm.size) { |
1009 | /* Map (part of) 2nd RAM chunk */ | 1001 | /* Map (part of) 2nd RAM chunk */ |
1010 | virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; | 1002 | virt_addr = map.rm.size; |
1011 | len = r->len; | 1003 | len = r->len; |
1012 | if (r->offset >= map.rm.size) | 1004 | if (r->offset >= map.rm.size) |
1013 | virt_addr += r->offset - map.rm.size; | 1005 | virt_addr += r->offset - map.rm.size; |
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 01f0c9506e11..235c13ebacd9 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -89,13 +89,11 @@ enum ps3_dev_type { | |||
89 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ | 89 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ |
90 | PS3_DEV_TYPE_SB_GPIO = 6, | 90 | PS3_DEV_TYPE_SB_GPIO = 6, |
91 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ | 91 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ |
92 | PS3_DEV_TYPE_STOR_DUMMY = 32, | ||
93 | PS3_DEV_TYPE_NOACCESS = 255, | ||
94 | }; | 92 | }; |
95 | 93 | ||
96 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 94 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
97 | u64 *value); | 95 | u64 *value); |
98 | int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id); | 96 | int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id); |
99 | int ps3_repository_read_bus_type(unsigned int bus_index, | 97 | int ps3_repository_read_bus_type(unsigned int bus_index, |
100 | enum ps3_bus_type *bus_type); | 98 | enum ps3_bus_type *bus_type); |
101 | int ps3_repository_read_bus_num_dev(unsigned int bus_index, | 99 | int ps3_repository_read_bus_num_dev(unsigned int bus_index, |
@@ -119,7 +117,7 @@ enum ps3_reg_type { | |||
119 | int ps3_repository_read_dev_str(unsigned int bus_index, | 117 | int ps3_repository_read_dev_str(unsigned int bus_index, |
120 | unsigned int dev_index, const char *dev_str, u64 *value); | 118 | unsigned int dev_index, const char *dev_str, u64 *value); |
121 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, | 119 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, |
122 | unsigned int *dev_id); | 120 | u64 *dev_id); |
123 | int ps3_repository_read_dev_type(unsigned int bus_index, | 121 | int ps3_repository_read_dev_type(unsigned int bus_index, |
124 | unsigned int dev_index, enum ps3_dev_type *dev_type); | 122 | unsigned int dev_index, enum ps3_dev_type *dev_type); |
125 | int ps3_repository_read_dev_intr(unsigned int bus_index, | 123 | int ps3_repository_read_dev_intr(unsigned int bus_index, |
@@ -138,21 +136,17 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, | |||
138 | /* repository bus enumerators */ | 136 | /* repository bus enumerators */ |
139 | 137 | ||
140 | struct ps3_repository_device { | 138 | struct ps3_repository_device { |
141 | enum ps3_bus_type bus_type; | ||
142 | unsigned int bus_index; | 139 | unsigned int bus_index; |
143 | unsigned int bus_id; | ||
144 | enum ps3_dev_type dev_type; | ||
145 | unsigned int dev_index; | 140 | unsigned int dev_index; |
146 | unsigned int dev_id; | 141 | enum ps3_bus_type bus_type; |
142 | enum ps3_dev_type dev_type; | ||
143 | u64 bus_id; | ||
144 | u64 dev_id; | ||
147 | }; | 145 | }; |
148 | 146 | ||
149 | static inline struct ps3_repository_device *ps3_repository_bump_device( | ||
150 | struct ps3_repository_device *repo) | ||
151 | { | ||
152 | repo->dev_index++; | ||
153 | return repo; | ||
154 | } | ||
155 | int ps3_repository_find_device(struct ps3_repository_device *repo); | 147 | int ps3_repository_find_device(struct ps3_repository_device *repo); |
148 | int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, | ||
149 | u64 bus_id, u64 dev_id); | ||
156 | int ps3_repository_find_devices(enum ps3_bus_type bus_type, | 150 | int ps3_repository_find_devices(enum ps3_bus_type bus_type, |
157 | int (*callback)(const struct ps3_repository_device *repo)); | 151 | int (*callback)(const struct ps3_repository_device *repo)); |
158 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, | 152 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, |
@@ -186,10 +180,10 @@ int ps3_repository_read_stor_dev_region(unsigned int bus_index, | |||
186 | unsigned int dev_index, unsigned int region_index, | 180 | unsigned int dev_index, unsigned int region_index, |
187 | unsigned int *region_id, u64 *region_start, u64 *region_size); | 181 | unsigned int *region_id, u64 *region_start, u64 *region_size); |
188 | 182 | ||
189 | /* repository pu and memory info */ | 183 | /* repository logical pu and memory info */ |
190 | 184 | ||
191 | int ps3_repository_read_num_pu(unsigned int *num_pu); | 185 | int ps3_repository_read_num_pu(u64 *num_pu); |
192 | int ps3_repository_read_ppe_id(unsigned int *pu_index, unsigned int *ppe_id); | 186 | int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id); |
193 | int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base); | 187 | int ps3_repository_read_rm_base(unsigned int ppe_id, u64 *rm_base); |
194 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); | 188 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size); |
195 | int ps3_repository_read_region_total(u64 *region_total); | 189 | int ps3_repository_read_region_total(u64 *region_total); |
@@ -200,9 +194,15 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, | |||
200 | 194 | ||
201 | int ps3_repository_read_num_be(unsigned int *num_be); | 195 | int ps3_repository_read_num_be(unsigned int *num_be); |
202 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id); | 196 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id); |
197 | int ps3_repository_read_be_id(u64 node_id, u64 *be_id); | ||
203 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq); | 198 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq); |
204 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq); | 199 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq); |
205 | 200 | ||
201 | /* repository performance monitor info */ | ||
202 | |||
203 | int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar, | ||
204 | u64 *rights); | ||
205 | |||
206 | /* repository 'Other OS' area */ | 206 | /* repository 'Other OS' area */ |
207 | 207 | ||
208 | int ps3_repository_read_boot_dat_addr(u64 *lpar_addr); | 208 | int ps3_repository_read_boot_dat_addr(u64 *lpar_addr); |
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index 1c94824f7b63..22063adeb38b 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c | |||
@@ -33,7 +33,7 @@ enum ps3_lpar_id { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) | 35 | #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) |
36 | static void _dump_field(const char *hdr, u64 n, const char* func, int line) | 36 | static void _dump_field(const char *hdr, u64 n, const char *func, int line) |
37 | { | 37 | { |
38 | #if defined(DEBUG) | 38 | #if defined(DEBUG) |
39 | char s[16]; | 39 | char s[16]; |
@@ -50,8 +50,8 @@ static void _dump_field(const char *hdr, u64 n, const char* func, int line) | |||
50 | 50 | ||
51 | #define dump_node_name(_a, _b, _c, _d, _e) \ | 51 | #define dump_node_name(_a, _b, _c, _d, _e) \ |
52 | _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) | 52 | _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) |
53 | static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3, | 53 | static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, |
54 | u64 n4, const char* func, int line) | 54 | u64 n4, const char *func, int line) |
55 | { | 55 | { |
56 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); | 56 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); |
57 | _dump_field("n1: ", n1, func, line); | 57 | _dump_field("n1: ", n1, func, line); |
@@ -63,7 +63,7 @@ static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3, | |||
63 | #define dump_node(_a, _b, _c, _d, _e, _f, _g) \ | 63 | #define dump_node(_a, _b, _c, _d, _e, _f, _g) \ |
64 | _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | 64 | _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) |
65 | static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | 65 | static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, |
66 | u64 v1, u64 v2, const char* func, int line) | 66 | u64 v1, u64 v2, const char *func, int line) |
67 | { | 67 | { |
68 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); | 68 | pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id); |
69 | _dump_field("n1: ", n1, func, line); | 69 | _dump_field("n1: ", n1, func, line); |
@@ -165,21 +165,18 @@ int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | |||
165 | make_first_field("bus", bus_index), | 165 | make_first_field("bus", bus_index), |
166 | make_field(bus_str, 0), | 166 | make_field(bus_str, 0), |
167 | 0, 0, | 167 | 0, 0, |
168 | value, 0); | 168 | value, NULL); |
169 | } | 169 | } |
170 | 170 | ||
171 | int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id) | 171 | int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id) |
172 | { | 172 | { |
173 | int result; | 173 | int result; |
174 | u64 v1; | ||
175 | u64 v2; /* unused */ | ||
176 | 174 | ||
177 | result = read_node(PS3_LPAR_ID_PME, | 175 | result = read_node(PS3_LPAR_ID_PME, |
178 | make_first_field("bus", bus_index), | 176 | make_first_field("bus", bus_index), |
179 | make_field("id", 0), | 177 | make_field("id", 0), |
180 | 0, 0, | 178 | 0, 0, |
181 | &v1, &v2); | 179 | bus_id, NULL); |
182 | *bus_id = v1; | ||
183 | return result; | 180 | return result; |
184 | } | 181 | } |
185 | 182 | ||
@@ -193,7 +190,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index, | |||
193 | make_first_field("bus", bus_index), | 190 | make_first_field("bus", bus_index), |
194 | make_field("type", 0), | 191 | make_field("type", 0), |
195 | 0, 0, | 192 | 0, 0, |
196 | &v1, 0); | 193 | &v1, NULL); |
197 | *bus_type = v1; | 194 | *bus_type = v1; |
198 | return result; | 195 | return result; |
199 | } | 196 | } |
@@ -208,7 +205,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index, | |||
208 | make_first_field("bus", bus_index), | 205 | make_first_field("bus", bus_index), |
209 | make_field("num_dev", 0), | 206 | make_field("num_dev", 0), |
210 | 0, 0, | 207 | 0, 0, |
211 | &v1, 0); | 208 | &v1, NULL); |
212 | *num_dev = v1; | 209 | *num_dev = v1; |
213 | return result; | 210 | return result; |
214 | } | 211 | } |
@@ -221,22 +218,20 @@ int ps3_repository_read_dev_str(unsigned int bus_index, | |||
221 | make_field("dev", dev_index), | 218 | make_field("dev", dev_index), |
222 | make_field(dev_str, 0), | 219 | make_field(dev_str, 0), |
223 | 0, | 220 | 0, |
224 | value, 0); | 221 | value, NULL); |
225 | } | 222 | } |
226 | 223 | ||
227 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, | 224 | int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, |
228 | unsigned int *dev_id) | 225 | u64 *dev_id) |
229 | { | 226 | { |
230 | int result; | 227 | int result; |
231 | u64 v1; | ||
232 | 228 | ||
233 | result = read_node(PS3_LPAR_ID_PME, | 229 | result = read_node(PS3_LPAR_ID_PME, |
234 | make_first_field("bus", bus_index), | 230 | make_first_field("bus", bus_index), |
235 | make_field("dev", dev_index), | 231 | make_field("dev", dev_index), |
236 | make_field("id", 0), | 232 | make_field("id", 0), |
237 | 0, | 233 | 0, |
238 | &v1, 0); | 234 | dev_id, NULL); |
239 | *dev_id = v1; | ||
240 | return result; | 235 | return result; |
241 | } | 236 | } |
242 | 237 | ||
@@ -251,14 +246,14 @@ int ps3_repository_read_dev_type(unsigned int bus_index, | |||
251 | make_field("dev", dev_index), | 246 | make_field("dev", dev_index), |
252 | make_field("type", 0), | 247 | make_field("type", 0), |
253 | 0, | 248 | 0, |
254 | &v1, 0); | 249 | &v1, NULL); |
255 | *dev_type = v1; | 250 | *dev_type = v1; |
256 | return result; | 251 | return result; |
257 | } | 252 | } |
258 | 253 | ||
259 | int ps3_repository_read_dev_intr(unsigned int bus_index, | 254 | int ps3_repository_read_dev_intr(unsigned int bus_index, |
260 | unsigned int dev_index, unsigned int intr_index, | 255 | unsigned int dev_index, unsigned int intr_index, |
261 | enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id) | 256 | enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id) |
262 | { | 257 | { |
263 | int result; | 258 | int result; |
264 | u64 v1; | 259 | u64 v1; |
@@ -287,7 +282,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index, | |||
287 | make_field("dev", dev_index), | 282 | make_field("dev", dev_index), |
288 | make_field("reg", reg_index), | 283 | make_field("reg", reg_index), |
289 | make_field("type", 0), | 284 | make_field("type", 0), |
290 | &v1, 0); | 285 | &v1, NULL); |
291 | *reg_type = v1; | 286 | *reg_type = v1; |
292 | return result; | 287 | return result; |
293 | } | 288 | } |
@@ -332,7 +327,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) | |||
332 | return result; | 327 | return result; |
333 | } | 328 | } |
334 | 329 | ||
335 | pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", | 330 | pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %lu, num_dev %u\n", |
336 | __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, | 331 | __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, |
337 | num_dev); | 332 | num_dev); |
338 | 333 | ||
@@ -349,47 +344,95 @@ int ps3_repository_find_device(struct ps3_repository_device *repo) | |||
349 | return result; | 344 | return result; |
350 | } | 345 | } |
351 | 346 | ||
352 | if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) { | 347 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, |
353 | /* | 348 | &tmp.dev_id); |
354 | * A storage device may show up in the repository before the | ||
355 | * hypervisor has finished probing its type and regions | ||
356 | */ | ||
357 | unsigned int num_regions; | ||
358 | |||
359 | if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) { | ||
360 | pr_debug("%s:%u storage device not ready\n", __func__, | ||
361 | __LINE__); | ||
362 | return -ENODEV; | ||
363 | } | ||
364 | 349 | ||
365 | result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index, | 350 | if (result) { |
366 | tmp.dev_index, | 351 | pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, |
367 | &num_regions); | 352 | __LINE__); |
353 | return result; | ||
354 | } | ||
355 | |||
356 | pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %lu\n", | ||
357 | __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); | ||
358 | |||
359 | *repo = tmp; | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, | ||
364 | u64 bus_id, u64 dev_id) | ||
365 | { | ||
366 | int result = -ENODEV; | ||
367 | struct ps3_repository_device tmp; | ||
368 | unsigned int num_dev; | ||
369 | |||
370 | pr_debug(" -> %s:%u: find device by id %lu:%lu\n", __func__, __LINE__, | ||
371 | bus_id, dev_id); | ||
372 | |||
373 | for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) { | ||
374 | result = ps3_repository_read_bus_id(tmp.bus_index, | ||
375 | &tmp.bus_id); | ||
368 | if (result) { | 376 | if (result) { |
369 | pr_debug("%s:%d read_stor_dev_num_regions failed\n", | 377 | pr_debug("%s:%u read_bus_id(%u) failed\n", __func__, |
370 | __func__, __LINE__); | 378 | __LINE__, tmp.bus_index); |
371 | return result; | 379 | return result; |
372 | } | 380 | } |
373 | 381 | ||
374 | if (!num_regions) { | 382 | if (tmp.bus_id == bus_id) |
375 | pr_debug("%s:%u storage device has no regions yet\n", | 383 | goto found_bus; |
376 | __func__, __LINE__); | 384 | |
377 | return -ENODEV; | 385 | pr_debug("%s:%u: skip, bus_id %lu\n", __func__, __LINE__, |
378 | } | 386 | tmp.bus_id); |
379 | } | 387 | } |
388 | pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); | ||
389 | return result; | ||
380 | 390 | ||
381 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, | 391 | found_bus: |
382 | &tmp.dev_id); | 392 | result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type); |
393 | if (result) { | ||
394 | pr_debug("%s:%u read_bus_type(%u) failed\n", __func__, | ||
395 | __LINE__, tmp.bus_index); | ||
396 | return result; | ||
397 | } | ||
383 | 398 | ||
399 | result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); | ||
384 | if (result) { | 400 | if (result) { |
385 | pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, | 401 | pr_debug("%s:%u read_bus_num_dev failed\n", __func__, |
386 | __LINE__); | 402 | __LINE__); |
387 | return result; | 403 | return result; |
388 | } | 404 | } |
389 | 405 | ||
390 | pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", | 406 | for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) { |
391 | __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); | 407 | result = ps3_repository_read_dev_id(tmp.bus_index, |
408 | tmp.dev_index, | ||
409 | &tmp.dev_id); | ||
410 | if (result) { | ||
411 | pr_debug("%s:%u read_dev_id(%u:%u) failed\n", __func__, | ||
412 | __LINE__, tmp.bus_index, tmp.dev_index); | ||
413 | return result; | ||
414 | } | ||
392 | 415 | ||
416 | if (tmp.dev_id == dev_id) | ||
417 | goto found_dev; | ||
418 | |||
419 | pr_debug("%s:%u: skip, dev_id %lu\n", __func__, __LINE__, | ||
420 | tmp.dev_id); | ||
421 | } | ||
422 | pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__); | ||
423 | return result; | ||
424 | |||
425 | found_dev: | ||
426 | result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, | ||
427 | &tmp.dev_type); | ||
428 | if (result) { | ||
429 | pr_debug("%s:%u read_dev_type failed\n", __func__, __LINE__); | ||
430 | return result; | ||
431 | } | ||
432 | |||
433 | pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%lu:%lu)\n", | ||
434 | __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index, | ||
435 | tmp.dev_index, tmp.bus_id, tmp.dev_id); | ||
393 | *repo = tmp; | 436 | *repo = tmp; |
394 | return 0; | 437 | return 0; |
395 | } | 438 | } |
@@ -402,50 +445,34 @@ int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, | |||
402 | 445 | ||
403 | pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); | 446 | pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); |
404 | 447 | ||
405 | for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { | 448 | repo.bus_type = bus_type; |
449 | result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); | ||
450 | if (result) { | ||
451 | pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__); | ||
452 | return result; | ||
453 | } | ||
406 | 454 | ||
407 | result = ps3_repository_read_bus_type(repo.bus_index, | 455 | result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); |
408 | &repo.bus_type); | 456 | if (result) { |
457 | pr_debug("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, | ||
458 | repo.bus_index); | ||
459 | return result; | ||
460 | } | ||
409 | 461 | ||
410 | if (result) { | 462 | for (repo.dev_index = 0; ; repo.dev_index++) { |
411 | pr_debug("%s:%d read_bus_type(%u) failed\n", | 463 | result = ps3_repository_find_device(&repo); |
412 | __func__, __LINE__, repo.bus_index); | 464 | if (result == -ENODEV) { |
465 | result = 0; | ||
466 | break; | ||
467 | } else if (result) | ||
413 | break; | 468 | break; |
414 | } | ||
415 | |||
416 | if (repo.bus_type != bus_type) { | ||
417 | pr_debug("%s:%d: skip, bus_type %u\n", __func__, | ||
418 | __LINE__, repo.bus_type); | ||
419 | continue; | ||
420 | } | ||
421 | |||
422 | result = ps3_repository_read_bus_id(repo.bus_index, | ||
423 | &repo.bus_id); | ||
424 | 469 | ||
470 | result = callback(&repo); | ||
425 | if (result) { | 471 | if (result) { |
426 | pr_debug("%s:%d read_bus_id(%u) failed\n", | 472 | pr_debug("%s:%d: abort at callback\n", __func__, |
427 | __func__, __LINE__, repo.bus_index); | 473 | __LINE__); |
428 | continue; | 474 | break; |
429 | } | ||
430 | |||
431 | for (repo.dev_index = 0; ; repo.dev_index++) { | ||
432 | result = ps3_repository_find_device(&repo); | ||
433 | |||
434 | if (result == -ENODEV) { | ||
435 | result = 0; | ||
436 | break; | ||
437 | } else if (result) | ||
438 | break; | ||
439 | |||
440 | result = callback(&repo); | ||
441 | |||
442 | if (result) { | ||
443 | pr_debug("%s:%d: abort at callback\n", __func__, | ||
444 | __LINE__); | ||
445 | break; | ||
446 | } | ||
447 | } | 475 | } |
448 | break; | ||
449 | } | 476 | } |
450 | 477 | ||
451 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 478 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
@@ -561,7 +588,7 @@ int ps3_repository_read_stor_dev_port(unsigned int bus_index, | |||
561 | make_first_field("bus", bus_index), | 588 | make_first_field("bus", bus_index), |
562 | make_field("dev", dev_index), | 589 | make_field("dev", dev_index), |
563 | make_field("port", 0), | 590 | make_field("port", 0), |
564 | 0, port, 0); | 591 | 0, port, NULL); |
565 | } | 592 | } |
566 | 593 | ||
567 | int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, | 594 | int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, |
@@ -571,7 +598,7 @@ int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, | |||
571 | make_first_field("bus", bus_index), | 598 | make_first_field("bus", bus_index), |
572 | make_field("dev", dev_index), | 599 | make_field("dev", dev_index), |
573 | make_field("blk_size", 0), | 600 | make_field("blk_size", 0), |
574 | 0, blk_size, 0); | 601 | 0, blk_size, NULL); |
575 | } | 602 | } |
576 | 603 | ||
577 | int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, | 604 | int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, |
@@ -581,7 +608,7 @@ int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, | |||
581 | make_first_field("bus", bus_index), | 608 | make_first_field("bus", bus_index), |
582 | make_field("dev", dev_index), | 609 | make_field("dev", dev_index), |
583 | make_field("n_blocks", 0), | 610 | make_field("n_blocks", 0), |
584 | 0, num_blocks, 0); | 611 | 0, num_blocks, NULL); |
585 | } | 612 | } |
586 | 613 | ||
587 | int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, | 614 | int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, |
@@ -594,7 +621,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, | |||
594 | make_first_field("bus", bus_index), | 621 | make_first_field("bus", bus_index), |
595 | make_field("dev", dev_index), | 622 | make_field("dev", dev_index), |
596 | make_field("n_regs", 0), | 623 | make_field("n_regs", 0), |
597 | 0, &v1, 0); | 624 | 0, &v1, NULL); |
598 | *num_regions = v1; | 625 | *num_regions = v1; |
599 | return result; | 626 | return result; |
600 | } | 627 | } |
@@ -611,7 +638,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, | |||
611 | make_field("dev", dev_index), | 638 | make_field("dev", dev_index), |
612 | make_field("region", region_index), | 639 | make_field("region", region_index), |
613 | make_field("id", 0), | 640 | make_field("id", 0), |
614 | &v1, 0); | 641 | &v1, NULL); |
615 | *region_id = v1; | 642 | *region_id = v1; |
616 | return result; | 643 | return result; |
617 | } | 644 | } |
@@ -624,7 +651,7 @@ int ps3_repository_read_stor_dev_region_size(unsigned int bus_index, | |||
624 | make_field("dev", dev_index), | 651 | make_field("dev", dev_index), |
625 | make_field("region", region_index), | 652 | make_field("region", region_index), |
626 | make_field("size", 0), | 653 | make_field("size", 0), |
627 | region_size, 0); | 654 | region_size, NULL); |
628 | } | 655 | } |
629 | 656 | ||
630 | int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, | 657 | int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, |
@@ -635,7 +662,7 @@ int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, | |||
635 | make_field("dev", dev_index), | 662 | make_field("dev", dev_index), |
636 | make_field("region", region_index), | 663 | make_field("region", region_index), |
637 | make_field("start", 0), | 664 | make_field("start", 0), |
638 | region_start, 0); | 665 | region_start, NULL); |
639 | } | 666 | } |
640 | 667 | ||
641 | int ps3_repository_read_stor_dev_info(unsigned int bus_index, | 668 | int ps3_repository_read_stor_dev_info(unsigned int bus_index, |
@@ -684,6 +711,35 @@ int ps3_repository_read_stor_dev_region(unsigned int bus_index, | |||
684 | return result; | 711 | return result; |
685 | } | 712 | } |
686 | 713 | ||
714 | /** | ||
715 | * ps3_repository_read_num_pu - Number of logical PU processors for this lpar. | ||
716 | */ | ||
717 | |||
718 | int ps3_repository_read_num_pu(u64 *num_pu) | ||
719 | { | ||
720 | *num_pu = 0; | ||
721 | return read_node(PS3_LPAR_ID_CURRENT, | ||
722 | make_first_field("bi", 0), | ||
723 | make_field("pun", 0), | ||
724 | 0, 0, | ||
725 | num_pu, NULL); | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * ps3_repository_read_pu_id - Read the logical PU id. | ||
730 | * @pu_index: Zero based index. | ||
731 | * @pu_id: The logical PU id. | ||
732 | */ | ||
733 | |||
734 | int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id) | ||
735 | { | ||
736 | return read_node(PS3_LPAR_ID_CURRENT, | ||
737 | make_first_field("bi", 0), | ||
738 | make_field("pu", pu_index), | ||
739 | 0, 0, | ||
740 | pu_id, NULL); | ||
741 | } | ||
742 | |||
687 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) | 743 | int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) |
688 | { | 744 | { |
689 | return read_node(PS3_LPAR_ID_CURRENT, | 745 | return read_node(PS3_LPAR_ID_CURRENT, |
@@ -691,7 +747,7 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) | |||
691 | make_field("pu", 0), | 747 | make_field("pu", 0), |
692 | ppe_id, | 748 | ppe_id, |
693 | make_field("rm_size", 0), | 749 | make_field("rm_size", 0), |
694 | rm_size, 0); | 750 | rm_size, NULL); |
695 | } | 751 | } |
696 | 752 | ||
697 | int ps3_repository_read_region_total(u64 *region_total) | 753 | int ps3_repository_read_region_total(u64 *region_total) |
@@ -700,7 +756,7 @@ int ps3_repository_read_region_total(u64 *region_total) | |||
700 | make_first_field("bi", 0), | 756 | make_first_field("bi", 0), |
701 | make_field("rgntotal", 0), | 757 | make_field("rgntotal", 0), |
702 | 0, 0, | 758 | 0, 0, |
703 | region_total, 0); | 759 | region_total, NULL); |
704 | } | 760 | } |
705 | 761 | ||
706 | /** | 762 | /** |
@@ -736,7 +792,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) | |||
736 | make_first_field("bi", 0), | 792 | make_first_field("bi", 0), |
737 | make_field("spun", 0), | 793 | make_field("spun", 0), |
738 | 0, 0, | 794 | 0, 0, |
739 | &v1, 0); | 795 | &v1, NULL); |
740 | *num_spu_reserved = v1; | 796 | *num_spu_reserved = v1; |
741 | return result; | 797 | return result; |
742 | } | 798 | } |
@@ -755,7 +811,7 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) | |||
755 | make_first_field("bi", 0), | 811 | make_first_field("bi", 0), |
756 | make_field("spursvn", 0), | 812 | make_field("spursvn", 0), |
757 | 0, 0, | 813 | 0, 0, |
758 | &v1, 0); | 814 | &v1, NULL); |
759 | *num_resource_id = v1; | 815 | *num_resource_id = v1; |
760 | return result; | 816 | return result; |
761 | } | 817 | } |
@@ -768,7 +824,7 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) | |||
768 | */ | 824 | */ |
769 | 825 | ||
770 | int ps3_repository_read_spu_resource_id(unsigned int res_index, | 826 | int ps3_repository_read_spu_resource_id(unsigned int res_index, |
771 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id) | 827 | enum ps3_spu_resource_type *resource_type, unsigned int *resource_id) |
772 | { | 828 | { |
773 | int result; | 829 | int result; |
774 | u64 v1; | 830 | u64 v1; |
@@ -785,14 +841,14 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index, | |||
785 | return result; | 841 | return result; |
786 | } | 842 | } |
787 | 843 | ||
788 | int ps3_repository_read_boot_dat_address(u64 *address) | 844 | static int ps3_repository_read_boot_dat_address(u64 *address) |
789 | { | 845 | { |
790 | return read_node(PS3_LPAR_ID_CURRENT, | 846 | return read_node(PS3_LPAR_ID_CURRENT, |
791 | make_first_field("bi", 0), | 847 | make_first_field("bi", 0), |
792 | make_field("boot_dat", 0), | 848 | make_field("boot_dat", 0), |
793 | make_field("address", 0), | 849 | make_field("address", 0), |
794 | 0, | 850 | 0, |
795 | address, 0); | 851 | address, NULL); |
796 | } | 852 | } |
797 | 853 | ||
798 | int ps3_repository_read_boot_dat_size(unsigned int *size) | 854 | int ps3_repository_read_boot_dat_size(unsigned int *size) |
@@ -805,7 +861,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) | |||
805 | make_field("boot_dat", 0), | 861 | make_field("boot_dat", 0), |
806 | make_field("size", 0), | 862 | make_field("size", 0), |
807 | 0, | 863 | 0, |
808 | &v1, 0); | 864 | &v1, NULL); |
809 | *size = v1; | 865 | *size = v1; |
810 | return result; | 866 | return result; |
811 | } | 867 | } |
@@ -820,7 +876,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port) | |||
820 | make_field("vir_uart", 0), | 876 | make_field("vir_uart", 0), |
821 | make_field("port", 0), | 877 | make_field("port", 0), |
822 | make_field("avset", 0), | 878 | make_field("avset", 0), |
823 | &v1, 0); | 879 | &v1, NULL); |
824 | *port = v1; | 880 | *port = v1; |
825 | return result; | 881 | return result; |
826 | } | 882 | } |
@@ -835,7 +891,7 @@ int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) | |||
835 | make_field("vir_uart", 0), | 891 | make_field("vir_uart", 0), |
836 | make_field("port", 0), | 892 | make_field("port", 0), |
837 | make_field("sysmgr", 0), | 893 | make_field("sysmgr", 0), |
838 | &v1, 0); | 894 | &v1, NULL); |
839 | *port = v1; | 895 | *port = v1; |
840 | return result; | 896 | return result; |
841 | } | 897 | } |
@@ -856,6 +912,10 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) | |||
856 | : ps3_repository_read_boot_dat_size(size); | 912 | : ps3_repository_read_boot_dat_size(size); |
857 | } | 913 | } |
858 | 914 | ||
915 | /** | ||
916 | * ps3_repository_read_num_be - Number of physical BE processors in the system. | ||
917 | */ | ||
918 | |||
859 | int ps3_repository_read_num_be(unsigned int *num_be) | 919 | int ps3_repository_read_num_be(unsigned int *num_be) |
860 | { | 920 | { |
861 | int result; | 921 | int result; |
@@ -866,11 +926,17 @@ int ps3_repository_read_num_be(unsigned int *num_be) | |||
866 | 0, | 926 | 0, |
867 | 0, | 927 | 0, |
868 | 0, | 928 | 0, |
869 | &v1, 0); | 929 | &v1, NULL); |
870 | *num_be = v1; | 930 | *num_be = v1; |
871 | return result; | 931 | return result; |
872 | } | 932 | } |
873 | 933 | ||
934 | /** | ||
935 | * ps3_repository_read_be_node_id - Read the physical BE processor node id. | ||
936 | * @be_index: Zero based index. | ||
937 | * @node_id: The BE processor node id. | ||
938 | */ | ||
939 | |||
874 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) | 940 | int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) |
875 | { | 941 | { |
876 | return read_node(PS3_LPAR_ID_PME, | 942 | return read_node(PS3_LPAR_ID_PME, |
@@ -878,7 +944,23 @@ int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) | |||
878 | 0, | 944 | 0, |
879 | 0, | 945 | 0, |
880 | 0, | 946 | 0, |
881 | node_id, 0); | 947 | node_id, NULL); |
948 | } | ||
949 | |||
950 | /** | ||
951 | * ps3_repository_read_be_id - Read the physical BE processor id. | ||
952 | * @node_id: The BE processor node id. | ||
953 | * @be_id: The BE processor id. | ||
954 | */ | ||
955 | |||
956 | int ps3_repository_read_be_id(u64 node_id, u64 *be_id) | ||
957 | { | ||
958 | return read_node(PS3_LPAR_ID_PME, | ||
959 | make_first_field("be", 0), | ||
960 | node_id, | ||
961 | 0, | ||
962 | 0, | ||
963 | be_id, NULL); | ||
882 | } | 964 | } |
883 | 965 | ||
884 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) | 966 | int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) |
@@ -888,7 +970,7 @@ int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) | |||
888 | node_id, | 970 | node_id, |
889 | make_field("clock", 0), | 971 | make_field("clock", 0), |
890 | 0, | 972 | 0, |
891 | tb_freq, 0); | 973 | tb_freq, NULL); |
892 | } | 974 | } |
893 | 975 | ||
894 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) | 976 | int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) |
@@ -897,11 +979,29 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) | |||
897 | u64 node_id; | 979 | u64 node_id; |
898 | 980 | ||
899 | *tb_freq = 0; | 981 | *tb_freq = 0; |
900 | result = ps3_repository_read_be_node_id(0, &node_id); | 982 | result = ps3_repository_read_be_node_id(be_index, &node_id); |
901 | return result ? result | 983 | return result ? result |
902 | : ps3_repository_read_tb_freq(node_id, tb_freq); | 984 | : ps3_repository_read_tb_freq(node_id, tb_freq); |
903 | } | 985 | } |
904 | 986 | ||
987 | int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar, | ||
988 | u64 *rights) | ||
989 | { | ||
990 | int result; | ||
991 | u64 node_id; | ||
992 | |||
993 | *lpar = 0; | ||
994 | *rights = 0; | ||
995 | result = ps3_repository_read_be_node_id(be_index, &node_id); | ||
996 | return result ? result | ||
997 | : read_node(PS3_LPAR_ID_PME, | ||
998 | make_first_field("be", 0), | ||
999 | node_id, | ||
1000 | make_field("lpm", 0), | ||
1001 | make_field("priv", 0), | ||
1002 | lpar, rights); | ||
1003 | } | ||
1004 | |||
905 | #if defined(DEBUG) | 1005 | #if defined(DEBUG) |
906 | 1006 | ||
907 | int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) | 1007 | int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) |
@@ -1034,7 +1134,7 @@ static int dump_device_info(struct ps3_repository_device *repo, | |||
1034 | continue; | 1134 | continue; |
1035 | } | 1135 | } |
1036 | 1136 | ||
1037 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | 1137 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__, |
1038 | __LINE__, repo->bus_index, repo->dev_index, | 1138 | __LINE__, repo->bus_index, repo->dev_index, |
1039 | repo->dev_type, repo->dev_id); | 1139 | repo->dev_type, repo->dev_id); |
1040 | 1140 | ||
@@ -1091,7 +1191,7 @@ int ps3_repository_dump_bus_info(void) | |||
1091 | continue; | 1191 | continue; |
1092 | } | 1192 | } |
1093 | 1193 | ||
1094 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | 1194 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n", |
1095 | __func__, __LINE__, repo.bus_index, repo.bus_type, | 1195 | __func__, __LINE__, repo.bus_index, repo.bus_type, |
1096 | repo.bus_id, num_dev); | 1196 | repo.bus_id, num_dev); |
1097 | 1197 | ||
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 6405f4a36763..43c493fca2d0 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
@@ -42,8 +42,8 @@ struct { | |||
42 | int gpu; | 42 | int gpu; |
43 | } static usage_hack; | 43 | } static usage_hack; |
44 | 44 | ||
45 | static int ps3_is_device(struct ps3_system_bus_device *dev, | 45 | static int ps3_is_device(struct ps3_system_bus_device *dev, u64 bus_id, |
46 | unsigned int bus_id, unsigned int dev_id) | 46 | u64 dev_id) |
47 | { | 47 | { |
48 | return dev->bus_id == bus_id && dev->dev_id == dev_id; | 48 | return dev->bus_id == bus_id && dev->dev_id == dev_id; |
49 | } | 49 | } |
@@ -182,8 +182,8 @@ int ps3_open_hv_device(struct ps3_system_bus_device *dev) | |||
182 | case PS3_MATCH_ID_SYSTEM_MANAGER: | 182 | case PS3_MATCH_ID_SYSTEM_MANAGER: |
183 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | 183 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, |
184 | __LINE__, dev->match_id); | 184 | __LINE__, dev->match_id); |
185 | pr_debug("%s:%d: bus_id: %u\n", __func__, | 185 | pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__, |
186 | __LINE__, dev->bus_id); | 186 | dev->bus_id); |
187 | BUG(); | 187 | BUG(); |
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | 189 | ||
@@ -220,8 +220,8 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev) | |||
220 | case PS3_MATCH_ID_SYSTEM_MANAGER: | 220 | case PS3_MATCH_ID_SYSTEM_MANAGER: |
221 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | 221 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, |
222 | __LINE__, dev->match_id); | 222 | __LINE__, dev->match_id); |
223 | pr_debug("%s:%d: bus_id: %u\n", __func__, | 223 | pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__, |
224 | __LINE__, dev->bus_id); | 224 | dev->bus_id); |
225 | BUG(); | 225 | BUG(); |
226 | return -EINVAL; | 226 | return -EINVAL; |
227 | 227 | ||
@@ -240,7 +240,7 @@ EXPORT_SYMBOL_GPL(ps3_close_hv_device); | |||
240 | static void _dump_mmio_region(const struct ps3_mmio_region* r, | 240 | static void _dump_mmio_region(const struct ps3_mmio_region* r, |
241 | const char* func, int line) | 241 | const char* func, int line) |
242 | { | 242 | { |
243 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, | 243 | pr_debug("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id, |
244 | r->dev->dev_id); | 244 | r->dev->dev_id); |
245 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 245 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
246 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); | 246 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); |
@@ -715,6 +715,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) | |||
715 | static unsigned int dev_ioc0_count; | 715 | static unsigned int dev_ioc0_count; |
716 | static unsigned int dev_sb_count; | 716 | static unsigned int dev_sb_count; |
717 | static unsigned int dev_vuart_count; | 717 | static unsigned int dev_vuart_count; |
718 | static unsigned int dev_lpm_count; | ||
718 | 719 | ||
719 | if (!dev->core.parent) | 720 | if (!dev->core.parent) |
720 | dev->core.parent = &ps3_system_bus; | 721 | dev->core.parent = &ps3_system_bus; |
@@ -737,6 +738,10 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) | |||
737 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | 738 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), |
738 | "vuart_%02x", ++dev_vuart_count); | 739 | "vuart_%02x", ++dev_vuart_count); |
739 | break; | 740 | break; |
741 | case PS3_DEVICE_TYPE_LPM: | ||
742 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
743 | "lpm_%02x", ++dev_lpm_count); | ||
744 | break; | ||
740 | default: | 745 | default: |
741 | BUG(); | 746 | BUG(); |
742 | }; | 747 | }; |
diff --git a/arch/powerpc/xmon/setjmp.S b/arch/powerpc/xmon/setjmp.S index 96a91f10e2ec..04c0b305ad4a 100644 --- a/arch/powerpc/xmon/setjmp.S +++ b/arch/powerpc/xmon/setjmp.S | |||
@@ -12,67 +12,6 @@ | |||
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 | 14 | ||
15 | _GLOBAL(xmon_setjmp) | ||
16 | mflr r0 | ||
17 | PPC_STL r0,0(r3) | ||
18 | PPC_STL r1,SZL(r3) | ||
19 | PPC_STL r2,2*SZL(r3) | ||
20 | mfcr r0 | ||
21 | PPC_STL r0,3*SZL(r3) | ||
22 | PPC_STL r13,4*SZL(r3) | ||
23 | PPC_STL r14,5*SZL(r3) | ||
24 | PPC_STL r15,6*SZL(r3) | ||
25 | PPC_STL r16,7*SZL(r3) | ||
26 | PPC_STL r17,8*SZL(r3) | ||
27 | PPC_STL r18,9*SZL(r3) | ||
28 | PPC_STL r19,10*SZL(r3) | ||
29 | PPC_STL r20,11*SZL(r3) | ||
30 | PPC_STL r21,12*SZL(r3) | ||
31 | PPC_STL r22,13*SZL(r3) | ||
32 | PPC_STL r23,14*SZL(r3) | ||
33 | PPC_STL r24,15*SZL(r3) | ||
34 | PPC_STL r25,16*SZL(r3) | ||
35 | PPC_STL r26,17*SZL(r3) | ||
36 | PPC_STL r27,18*SZL(r3) | ||
37 | PPC_STL r28,19*SZL(r3) | ||
38 | PPC_STL r29,20*SZL(r3) | ||
39 | PPC_STL r30,21*SZL(r3) | ||
40 | PPC_STL r31,22*SZL(r3) | ||
41 | li r3,0 | ||
42 | blr | ||
43 | |||
44 | _GLOBAL(xmon_longjmp) | ||
45 | PPC_LCMPI r4,0 | ||
46 | bne 1f | ||
47 | li r4,1 | ||
48 | 1: PPC_LL r13,4*SZL(r3) | ||
49 | PPC_LL r14,5*SZL(r3) | ||
50 | PPC_LL r15,6*SZL(r3) | ||
51 | PPC_LL r16,7*SZL(r3) | ||
52 | PPC_LL r17,8*SZL(r3) | ||
53 | PPC_LL r18,9*SZL(r3) | ||
54 | PPC_LL r19,10*SZL(r3) | ||
55 | PPC_LL r20,11*SZL(r3) | ||
56 | PPC_LL r21,12*SZL(r3) | ||
57 | PPC_LL r22,13*SZL(r3) | ||
58 | PPC_LL r23,14*SZL(r3) | ||
59 | PPC_LL r24,15*SZL(r3) | ||
60 | PPC_LL r25,16*SZL(r3) | ||
61 | PPC_LL r26,17*SZL(r3) | ||
62 | PPC_LL r27,18*SZL(r3) | ||
63 | PPC_LL r28,19*SZL(r3) | ||
64 | PPC_LL r29,20*SZL(r3) | ||
65 | PPC_LL r30,21*SZL(r3) | ||
66 | PPC_LL r31,22*SZL(r3) | ||
67 | PPC_LL r0,3*SZL(r3) | ||
68 | mtcrf 0x38,r0 | ||
69 | PPC_LL r0,0(r3) | ||
70 | PPC_LL r1,SZL(r3) | ||
71 | PPC_LL r2,2*SZL(r3) | ||
72 | mtlr r0 | ||
73 | mr r3,r4 | ||
74 | blr | ||
75 | |||
76 | /* | 15 | /* |
77 | * Grab the register values as they are now. | 16 | * Grab the register values as they are now. |
78 | * This won't do a particularily good job because we really | 17 | * This won't do a particularily good job because we really |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 865e36751f21..a34172ddc468 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/spu.h> | 40 | #include <asm/spu.h> |
41 | #include <asm/spu_priv1.h> | 41 | #include <asm/spu_priv1.h> |
42 | #include <asm/firmware.h> | 42 | #include <asm/firmware.h> |
43 | #include <asm/setjmp.h> | ||
43 | 44 | ||
44 | #ifdef CONFIG_PPC64 | 45 | #ifdef CONFIG_PPC64 |
45 | #include <asm/hvcall.h> | 46 | #include <asm/hvcall.h> |
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096; | |||
71 | static int termch; | 72 | static int termch; |
72 | static char tmpstr[128]; | 73 | static char tmpstr[128]; |
73 | 74 | ||
74 | #define JMP_BUF_LEN 23 | ||
75 | static long bus_error_jmp[JMP_BUF_LEN]; | 75 | static long bus_error_jmp[JMP_BUF_LEN]; |
76 | static int catch_memory_errors; | 76 | static int catch_memory_errors; |
77 | static long *xmon_fault_jmp[NR_CPUS]; | 77 | static long *xmon_fault_jmp[NR_CPUS]; |
78 | #define setjmp xmon_setjmp | ||
79 | #define longjmp xmon_longjmp | ||
80 | 78 | ||
81 | /* Breakpoint stuff */ | 79 | /* Breakpoint stuff */ |
82 | struct bpt { | 80 | struct bpt { |
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace; | |||
162 | extern void xmon_enter(void); | 160 | extern void xmon_enter(void); |
163 | extern void xmon_leave(void); | 161 | extern void xmon_leave(void); |
164 | 162 | ||
165 | extern long setjmp(long *); | ||
166 | extern void longjmp(long *, long); | ||
167 | extern void xmon_save_regs(struct pt_regs *); | 163 | extern void xmon_save_regs(struct pt_regs *); |
168 | 164 | ||
169 | #ifdef CONFIG_PPC64 | 165 | #ifdef CONFIG_PPC64 |