diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 23:41:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 23:41:28 -0400 |
commit | b04d0a90908cdb733e490486287e1ba8c568ffb0 (patch) | |
tree | c3e1157eb236ff45edfc29ed6d3dda89868fbf0c | |
parent | 054cfaacf88865bff1dd58d305443d5d6c068a08 (diff) | |
parent | c816be7b5f24585baa9eba1f2413935f771d6ad6 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6: (33 commits)
sparc32: Fix might-be-used-uninitialized warning in do_sparc_fault().
sparc: Fix .size directive for do_int_load
sparc64: Fix build errors with gcc-4.6.0
sparc32,sun4m: percpu and global register definitions moved to irq.h
sparc32: introduce build_device_irq
sparc32: introduce sparc_irq_config
sparc32: fix build with leon or floppy enabled
sparc: convert to clocksource_register_hz/khz
sparc64: Sharpen address space randomization calculations.
sparc32: irq_32.c cleanup
sparc32, sun4d: add comment in empty statement in sun4d_request_irq()
sparc32,sun4d: drop unused code in sun4d_distribute_irqs()
sparc32,sun4d: irq, smp files cleanup
sparc32,sun4m: irq, smp files cleanup
sparc32,sun4c: irq file cleanup
sparc32: add irq + smp declarations to headers
sparc32: remove tick14.c
sparc32/leon: FPU-FSR only available when FPU present
SPARC/LEON: power down instruction different of different LEONs
sparc32: added U-Boot build target: uImage
...
47 files changed, 1117 insertions, 1059 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 95695e97703e..e48f471be547 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -51,6 +51,7 @@ config SPARC64 | |||
51 | select HAVE_PERF_EVENTS | 51 | select HAVE_PERF_EVENTS |
52 | select PERF_USE_VMALLOC | 52 | select PERF_USE_VMALLOC |
53 | select HAVE_GENERIC_HARDIRQS | 53 | select HAVE_GENERIC_HARDIRQS |
54 | select GENERIC_HARDIRQS_NO_DEPRECATED | ||
54 | 55 | ||
55 | config ARCH_DEFCONFIG | 56 | config ARCH_DEFCONFIG |
56 | string | 57 | string |
@@ -460,6 +461,39 @@ config SPARC_LEON | |||
460 | from www.gaisler.com. You can download a sparc-linux cross-compilation | 461 | from www.gaisler.com. You can download a sparc-linux cross-compilation |
461 | toolchain at www.gaisler.com. | 462 | toolchain at www.gaisler.com. |
462 | 463 | ||
464 | if SPARC_LEON | ||
465 | menu "U-Boot options" | ||
466 | |||
467 | config UBOOT_LOAD_ADDR | ||
468 | hex "uImage Load Address" | ||
469 | default 0x40004000 | ||
470 | ---help--- | ||
471 | U-Boot kernel load address, the address in physical address space | ||
472 | where u-boot will place the Linux kernel before booting it. | ||
473 | This address is normally the base address of main memory + 0x4000. | ||
474 | |||
475 | config UBOOT_FLASH_ADDR | ||
476 | hex "uImage.o Load Address" | ||
477 | default 0x00080000 | ||
478 | ---help--- | ||
479 | Optional setting only affecting the uImage.o ELF-image used to | ||
480 | download the uImage file to the target using a ELF-loader other than | ||
481 | U-Boot. It may for example be used to download an uImage to FLASH with | ||
482 | the GRMON utility before even starting u-boot. | ||
483 | |||
484 | config UBOOT_ENTRY_ADDR | ||
485 | hex "uImage Entry Address" | ||
486 | default 0xf0004000 | ||
487 | ---help--- | ||
488 | Do not change this unless you know what you're doing. This is | ||
489 | hardcoded by the SPARC32 and LEON port. | ||
490 | |||
491 | This is the virtual address u-boot jumps to when booting the Linux | ||
492 | Kernel. | ||
493 | |||
494 | endmenu | ||
495 | endif | ||
496 | |||
463 | endmenu | 497 | endmenu |
464 | 498 | ||
465 | menu "Bus options (PCI etc.)" | 499 | menu "Bus options (PCI etc.)" |
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 113225b241e0..ad1fb5d969f3 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile | |||
@@ -88,7 +88,7 @@ boot := arch/sparc/boot | |||
88 | # Default target | 88 | # Default target |
89 | all: zImage | 89 | all: zImage |
90 | 90 | ||
91 | image zImage tftpboot.img vmlinux.aout: vmlinux | 91 | image zImage uImage tftpboot.img vmlinux.aout: vmlinux |
92 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | 92 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ |
93 | 93 | ||
94 | archclean: | 94 | archclean: |
@@ -102,6 +102,7 @@ ifeq ($(ARCH),sparc) | |||
102 | define archhelp | 102 | define archhelp |
103 | echo '* image - kernel image ($(boot)/image)' | 103 | echo '* image - kernel image ($(boot)/image)' |
104 | echo '* zImage - stripped kernel image ($(boot)/zImage)' | 104 | echo '* zImage - stripped kernel image ($(boot)/zImage)' |
105 | echo ' uImage - U-Boot SPARC32 Image (only for LEON)' | ||
105 | echo ' tftpboot.img - image prepared for tftp' | 106 | echo ' tftpboot.img - image prepared for tftp' |
106 | endef | 107 | endef |
107 | else | 108 | else |
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index a2c5898c1ab1..9205416b1e67 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | ROOT_IMG := /usr/src/root.img | 6 | ROOT_IMG := /usr/src/root.img |
7 | ELFTOAOUT := elftoaout | 7 | ELFTOAOUT := elftoaout |
8 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
8 | 9 | ||
9 | hostprogs-y := piggyback btfixupprep | 10 | hostprogs-y := piggyback btfixupprep |
10 | targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout | 11 | targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout |
@@ -77,6 +78,36 @@ $(obj)/zImage: $(obj)/image | |||
77 | $(obj)/vmlinux.aout: vmlinux FORCE | 78 | $(obj)/vmlinux.aout: vmlinux FORCE |
78 | $(call if_changed,elftoaout) | 79 | $(call if_changed,elftoaout) |
79 | @echo ' kernel: $@ is ready' | 80 | @echo ' kernel: $@ is ready' |
81 | else | ||
82 | |||
83 | # The following lines make a readable image for U-Boot. | ||
84 | # uImage - Binary file read by U-boot | ||
85 | # uImage.o - object file of uImage for loading with a | ||
86 | # flash programmer understanding ELF. | ||
87 | |||
88 | OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment | ||
89 | $(obj)/image.bin: $(obj)/image FORCE | ||
90 | $(call if_changed,objcopy) | ||
91 | |||
92 | $(obj)/image.gz: $(obj)/image.bin | ||
93 | $(call if_changed,gzip) | ||
94 | |||
95 | quiet_cmd_uimage = UIMAGE $@ | ||
96 | cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \ | ||
97 | -C gzip -a $(CONFIG_UBOOT_LOAD_ADDR) \ | ||
98 | -e $(CONFIG_UBOOT_ENTRY_ADDR) -n 'Linux-$(KERNELRELEASE)' \ | ||
99 | -d $< $@ | ||
100 | |||
101 | quiet_cmd_uimage.o = UIMAGE.O $@ | ||
102 | cmd_uimage.o = $(LD) -Tdata $(CONFIG_UBOOT_FLASH_ADDR) \ | ||
103 | -r -b binary $@ -o $@.o | ||
104 | |||
105 | targets += uImage | ||
106 | $(obj)/uImage: $(obj)/image.gz | ||
107 | $(call if_changed,uimage) | ||
108 | $(call if_changed,uimage.o) | ||
109 | @echo ' Image $@ is ready' | ||
110 | |||
80 | endif | 111 | endif |
81 | 112 | ||
82 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE | 113 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE |
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index a0b443cb3c1f..4f09666f0798 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h | |||
@@ -33,34 +33,34 @@ | |||
33 | 33 | ||
34 | /* The largest number of unique interrupt sources we support. | 34 | /* The largest number of unique interrupt sources we support. |
35 | * If this needs to ever be larger than 255, you need to change | 35 | * If this needs to ever be larger than 255, you need to change |
36 | * the type of ino_bucket->virt_irq as appropriate. | 36 | * the type of ino_bucket->irq as appropriate. |
37 | * | 37 | * |
38 | * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq(). | 38 | * ino_bucket->irq allocation is made during {sun4v_,}build_irq(). |
39 | */ | 39 | */ |
40 | #define NR_IRQS 255 | 40 | #define NR_IRQS 255 |
41 | 41 | ||
42 | extern void irq_install_pre_handler(int virt_irq, | 42 | extern void irq_install_pre_handler(int irq, |
43 | void (*func)(unsigned int, void *, void *), | 43 | void (*func)(unsigned int, void *, void *), |
44 | void *arg1, void *arg2); | 44 | void *arg1, void *arg2); |
45 | #define irq_canonicalize(irq) (irq) | 45 | #define irq_canonicalize(irq) (irq) |
46 | extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); | 46 | extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); |
47 | extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); | 47 | extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); |
48 | extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino); | 48 | extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino); |
49 | extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, | 49 | extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *irq_p, |
50 | unsigned int msi_devino_start, | 50 | unsigned int msi_devino_start, |
51 | unsigned int msi_devino_end); | 51 | unsigned int msi_devino_end); |
52 | extern void sun4v_destroy_msi(unsigned int virt_irq); | 52 | extern void sun4v_destroy_msi(unsigned int irq); |
53 | extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p, | 53 | extern unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p, |
54 | unsigned int msi_devino_start, | 54 | unsigned int msi_devino_start, |
55 | unsigned int msi_devino_end, | 55 | unsigned int msi_devino_end, |
56 | unsigned long imap_base, | 56 | unsigned long imap_base, |
57 | unsigned long iclr_base); | 57 | unsigned long iclr_base); |
58 | extern void sun4u_destroy_msi(unsigned int virt_irq); | 58 | extern void sun4u_destroy_msi(unsigned int irq); |
59 | 59 | ||
60 | extern unsigned char virt_irq_alloc(unsigned int dev_handle, | 60 | extern unsigned char irq_alloc(unsigned int dev_handle, |
61 | unsigned int dev_ino); | 61 | unsigned int dev_ino); |
62 | #ifdef CONFIG_PCI_MSI | 62 | #ifdef CONFIG_PCI_MSI |
63 | extern void virt_irq_free(unsigned int virt_irq); | 63 | extern void irq_free(unsigned int irq); |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | extern void __init init_IRQ(void); | 66 | extern void __init init_IRQ(void); |
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 8580d1764f90..c04f96fb753c 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h | |||
@@ -375,9 +375,6 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); | |||
375 | 375 | ||
376 | extern unsigned int real_irq_entry[], smpleon_ticker[]; | 376 | extern unsigned int real_irq_entry[], smpleon_ticker[]; |
377 | extern unsigned int patchme_maybe_smp_msg[]; | 377 | extern unsigned int patchme_maybe_smp_msg[]; |
378 | extern unsigned long trapbase_cpu1[]; | ||
379 | extern unsigned long trapbase_cpu2[]; | ||
380 | extern unsigned long trapbase_cpu3[]; | ||
381 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; | 378 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; |
382 | extern unsigned int linux_trap_ipi15_sun4m[]; | 379 | extern unsigned int linux_trap_ipi15_sun4m[]; |
383 | 380 | ||
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h index 263c719e96f5..e50f326e71bd 100644 --- a/arch/sparc/include/asm/leon_amba.h +++ b/arch/sparc/include/asm/leon_amba.h | |||
@@ -180,6 +180,7 @@ struct amba_ahb_device { | |||
180 | struct device_node; | 180 | struct device_node; |
181 | void _amba_init(struct device_node *dp, struct device_node ***nextp); | 181 | void _amba_init(struct device_node *dp, struct device_node ***nextp); |
182 | 182 | ||
183 | extern unsigned long amba_system_id; | ||
183 | extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; | 184 | extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; |
184 | extern struct leon3_gptimer_regs_map *leon3_gptimer_regs; | 185 | extern struct leon3_gptimer_regs_map *leon3_gptimer_regs; |
185 | extern struct amba_apb_device leon_percpu_timer_dev[16]; | 186 | extern struct amba_apb_device leon_percpu_timer_dev[16]; |
@@ -254,6 +255,11 @@ extern unsigned int sparc_leon_eirq; | |||
254 | #define GAISLER_L2C 0xffe /* internal device: leon2compat */ | 255 | #define GAISLER_L2C 0xffe /* internal device: leon2compat */ |
255 | #define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */ | 256 | #define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */ |
256 | 257 | ||
258 | /* Chip IDs */ | ||
259 | #define AEROFLEX_UT699 0x0699 | ||
260 | #define LEON4_NEXTREME1 0x0102 | ||
261 | #define GAISLER_GR712RC 0x0712 | ||
262 | |||
257 | #define amba_vendor(x) (((x) >> 24) & 0xff) | 263 | #define amba_vendor(x) (((x) >> 24) & 0xff) |
258 | 264 | ||
259 | #define amba_device(x) (((x) >> 12) & 0xfff) | 265 | #define amba_device(x) (((x) >> 12) & 0xfff) |
diff --git a/arch/sparc/include/asm/mmu_32.h b/arch/sparc/include/asm/mmu_32.h index ccd36d26615a..6f056e535cf8 100644 --- a/arch/sparc/include/asm/mmu_32.h +++ b/arch/sparc/include/asm/mmu_32.h | |||
@@ -4,4 +4,7 @@ | |||
4 | /* Default "unsigned long" context */ | 4 | /* Default "unsigned long" context */ |
5 | typedef unsigned long mm_context_t; | 5 | typedef unsigned long mm_context_t; |
6 | 6 | ||
7 | /* mm/srmmu.c */ | ||
8 | extern ctxd_t *srmmu_ctx_table_phys; | ||
9 | |||
7 | #endif | 10 | #endif |
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h index 841905c10215..d82d7f4c0a79 100644 --- a/arch/sparc/include/asm/smp_32.h +++ b/arch/sparc/include/asm/smp_32.h | |||
@@ -29,10 +29,16 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | extern unsigned char boot_cpu_id; | 31 | extern unsigned char boot_cpu_id; |
32 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | ||
33 | extern cpumask_t smp_commenced_mask; | ||
34 | extern struct linux_prom_registers smp_penguin_ctable; | ||
32 | 35 | ||
33 | typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long, | 36 | typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long, |
34 | unsigned long, unsigned long); | 37 | unsigned long, unsigned long); |
35 | 38 | ||
39 | void cpu_panic(void); | ||
40 | extern void smp4m_irq_rotate(int cpu); | ||
41 | |||
36 | /* | 42 | /* |
37 | * General functions that each host system must provide. | 43 | * General functions that each host system must provide. |
38 | */ | 44 | */ |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 599398fbbc7c..99aa4db6e9c2 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
@@ -42,7 +42,6 @@ obj-$(CONFIG_SPARC32) += windows.o | |||
42 | obj-y += cpu.o | 42 | obj-y += cpu.o |
43 | obj-$(CONFIG_SPARC32) += devices.o | 43 | obj-$(CONFIG_SPARC32) += devices.o |
44 | obj-$(CONFIG_SPARC32) += tadpole.o | 44 | obj-$(CONFIG_SPARC32) += tadpole.o |
45 | obj-$(CONFIG_SPARC32) += tick14.o | ||
46 | obj-y += ptrace_$(BITS).o | 45 | obj-y += ptrace_$(BITS).o |
47 | obj-y += unaligned_$(BITS).o | 46 | obj-y += unaligned_$(BITS).o |
48 | obj-y += una_asm_$(BITS).o | 47 | obj-y += una_asm_$(BITS).o |
@@ -54,6 +53,7 @@ obj-y += of_device_$(BITS).o | |||
54 | obj-$(CONFIG_SPARC64) += prom_irqtrans.o | 53 | obj-$(CONFIG_SPARC64) += prom_irqtrans.o |
55 | 54 | ||
56 | obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o | 55 | obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o |
56 | obj-$(CONFIG_SPARC_LEON)+= leon_pmc.o | ||
57 | 57 | ||
58 | obj-$(CONFIG_SPARC64) += reboot.o | 58 | obj-$(CONFIG_SPARC64) += reboot.o |
59 | obj-$(CONFIG_SPARC64) += sysfs.o | 59 | obj-$(CONFIG_SPARC64) += sysfs.o |
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 0dc714fa23d8..7925c54f4133 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c | |||
@@ -324,7 +324,7 @@ void __cpuinit cpu_probe(void) | |||
324 | psr = get_psr(); | 324 | psr = get_psr(); |
325 | put_psr(psr | PSR_EF); | 325 | put_psr(psr | PSR_EF); |
326 | #ifdef CONFIG_SPARC_LEON | 326 | #ifdef CONFIG_SPARC_LEON |
327 | fpu_vers = 7; | 327 | fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7; |
328 | #else | 328 | #else |
329 | fpu_vers = ((get_fsr() >> 17) & 0x7); | 329 | fpu_vers = ((get_fsr() >> 17) & 0x7); |
330 | #endif | 330 | #endif |
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index c011b932bb17..d1f1361c4167 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h | |||
@@ -213,8 +213,8 @@ extern struct cheetah_err_info *cheetah_error_log; | |||
213 | struct ino_bucket { | 213 | struct ino_bucket { |
214 | /*0x00*/unsigned long __irq_chain_pa; | 214 | /*0x00*/unsigned long __irq_chain_pa; |
215 | 215 | ||
216 | /* Virtual interrupt number assigned to this INO. */ | 216 | /* Interrupt number assigned to this INO. */ |
217 | /*0x08*/unsigned int __virt_irq; | 217 | /*0x08*/unsigned int __irq; |
218 | /*0x0c*/unsigned int __pad; | 218 | /*0x0c*/unsigned int __pad; |
219 | }; | 219 | }; |
220 | 220 | ||
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 72509d0e34be..6f01e8c83197 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c | |||
@@ -333,13 +333,10 @@ static void dma_4u_free_coherent(struct device *dev, size_t size, | |||
333 | void *cpu, dma_addr_t dvma) | 333 | void *cpu, dma_addr_t dvma) |
334 | { | 334 | { |
335 | struct iommu *iommu; | 335 | struct iommu *iommu; |
336 | iopte_t *iopte; | ||
337 | unsigned long flags, order, npages; | 336 | unsigned long flags, order, npages; |
338 | 337 | ||
339 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; | 338 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; |
340 | iommu = dev->archdata.iommu; | 339 | iommu = dev->archdata.iommu; |
341 | iopte = iommu->page_table + | ||
342 | ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); | ||
343 | 340 | ||
344 | spin_lock_irqsave(&iommu->lock, flags); | 341 | spin_lock_irqsave(&iommu->lock, flags); |
345 | 342 | ||
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 41f7e4e0f72a..c6ce9a6a4790 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -50,10 +50,14 @@ | |||
50 | #include <asm/io-unit.h> | 50 | #include <asm/io-unit.h> |
51 | #include <asm/leon.h> | 51 | #include <asm/leon.h> |
52 | 52 | ||
53 | #ifdef CONFIG_SPARC_LEON | 53 | #ifndef CONFIG_SPARC_LEON |
54 | #define mmu_inval_dma_area(p, l) leon_flush_dcache_all() | ||
55 | #else | ||
56 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ | 54 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ |
55 | #else | ||
56 | static inline void mmu_inval_dma_area(void *va, unsigned long len) | ||
57 | { | ||
58 | if (!sparc_leon3_snooping_enabled()) | ||
59 | leon_flush_dcache_all(); | ||
60 | } | ||
57 | #endif | 61 | #endif |
58 | 62 | ||
59 | static struct resource *_sparc_find_resource(struct resource *r, | 63 | static struct resource *_sparc_find_resource(struct resource *r, |
@@ -254,7 +258,7 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
254 | dma_addr_t *dma_addrp, gfp_t gfp) | 258 | dma_addr_t *dma_addrp, gfp_t gfp) |
255 | { | 259 | { |
256 | struct platform_device *op = to_platform_device(dev); | 260 | struct platform_device *op = to_platform_device(dev); |
257 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; | 261 | unsigned long len_total = PAGE_ALIGN(len); |
258 | unsigned long va; | 262 | unsigned long va; |
259 | struct resource *res; | 263 | struct resource *res; |
260 | int order; | 264 | int order; |
@@ -280,7 +284,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
280 | printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total); | 284 | printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total); |
281 | goto err_nova; | 285 | goto err_nova; |
282 | } | 286 | } |
283 | mmu_inval_dma_area(va, len_total); | 287 | mmu_inval_dma_area((void *)va, len_total); |
288 | |||
284 | // XXX The mmu_map_dma_area does this for us below, see comments. | 289 | // XXX The mmu_map_dma_area does this for us below, see comments. |
285 | // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); | 290 | // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); |
286 | /* | 291 | /* |
@@ -297,9 +302,9 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
297 | err_noiommu: | 302 | err_noiommu: |
298 | release_resource(res); | 303 | release_resource(res); |
299 | err_nova: | 304 | err_nova: |
300 | free_pages(va, order); | ||
301 | err_nomem: | ||
302 | kfree(res); | 305 | kfree(res); |
306 | err_nomem: | ||
307 | free_pages(va, order); | ||
303 | err_nopages: | 308 | err_nopages: |
304 | return NULL; | 309 | return NULL; |
305 | } | 310 | } |
@@ -321,7 +326,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p, | |||
321 | return; | 326 | return; |
322 | } | 327 | } |
323 | 328 | ||
324 | n = (n + PAGE_SIZE-1) & PAGE_MASK; | 329 | n = PAGE_ALIGN(n); |
325 | if ((res->end-res->start)+1 != n) { | 330 | if ((res->end-res->start)+1 != n) { |
326 | printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", | 331 | printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", |
327 | (long)((res->end-res->start)+1), n); | 332 | (long)((res->end-res->start)+1), n); |
@@ -408,9 +413,6 @@ struct dma_map_ops sbus_dma_ops = { | |||
408 | .sync_sg_for_device = sbus_sync_sg_for_device, | 413 | .sync_sg_for_device = sbus_sync_sg_for_device, |
409 | }; | 414 | }; |
410 | 415 | ||
411 | struct dma_map_ops *dma_ops = &sbus_dma_ops; | ||
412 | EXPORT_SYMBOL(dma_ops); | ||
413 | |||
414 | static int __init sparc_register_ioport(void) | 416 | static int __init sparc_register_ioport(void) |
415 | { | 417 | { |
416 | register_proc_sparc_ioport(); | 418 | register_proc_sparc_ioport(); |
@@ -422,7 +424,9 @@ arch_initcall(sparc_register_ioport); | |||
422 | 424 | ||
423 | #endif /* CONFIG_SBUS */ | 425 | #endif /* CONFIG_SBUS */ |
424 | 426 | ||
425 | #ifdef CONFIG_PCI | 427 | |
428 | /* LEON reuses PCI DMA ops */ | ||
429 | #if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON) | ||
426 | 430 | ||
427 | /* Allocate and map kernel buffer using consistent mode DMA for a device. | 431 | /* Allocate and map kernel buffer using consistent mode DMA for a device. |
428 | * hwdev should be valid struct pci_dev pointer for PCI devices. | 432 | * hwdev should be valid struct pci_dev pointer for PCI devices. |
@@ -430,8 +434,8 @@ arch_initcall(sparc_register_ioport); | |||
430 | static void *pci32_alloc_coherent(struct device *dev, size_t len, | 434 | static void *pci32_alloc_coherent(struct device *dev, size_t len, |
431 | dma_addr_t *pba, gfp_t gfp) | 435 | dma_addr_t *pba, gfp_t gfp) |
432 | { | 436 | { |
433 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; | 437 | unsigned long len_total = PAGE_ALIGN(len); |
434 | unsigned long va; | 438 | void *va; |
435 | struct resource *res; | 439 | struct resource *res; |
436 | int order; | 440 | int order; |
437 | 441 | ||
@@ -443,34 +447,34 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len, | |||
443 | } | 447 | } |
444 | 448 | ||
445 | order = get_order(len_total); | 449 | order = get_order(len_total); |
446 | va = __get_free_pages(GFP_KERNEL, order); | 450 | va = (void *) __get_free_pages(GFP_KERNEL, order); |
447 | if (va == 0) { | 451 | if (va == NULL) { |
448 | printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); | 452 | printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); |
449 | return NULL; | 453 | goto err_nopages; |
450 | } | 454 | } |
451 | 455 | ||
452 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { | 456 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { |
453 | free_pages(va, order); | ||
454 | printk("pci_alloc_consistent: no core\n"); | 457 | printk("pci_alloc_consistent: no core\n"); |
455 | return NULL; | 458 | goto err_nomem; |
456 | } | 459 | } |
457 | 460 | ||
458 | if (allocate_resource(&_sparc_dvma, res, len_total, | 461 | if (allocate_resource(&_sparc_dvma, res, len_total, |
459 | _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { | 462 | _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { |
460 | printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); | 463 | printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); |
461 | free_pages(va, order); | 464 | goto err_nova; |
462 | kfree(res); | ||
463 | return NULL; | ||
464 | } | 465 | } |
465 | mmu_inval_dma_area(va, len_total); | 466 | mmu_inval_dma_area(va, len_total); |
466 | #if 0 | ||
467 | /* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n", | ||
468 | (long)va, (long)res->start, (long)virt_to_phys(va), len_total); | ||
469 | #endif | ||
470 | sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); | 467 | sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); |
471 | 468 | ||
472 | *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ | 469 | *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ |
473 | return (void *) res->start; | 470 | return (void *) res->start; |
471 | |||
472 | err_nova: | ||
473 | kfree(res); | ||
474 | err_nomem: | ||
475 | free_pages((unsigned long)va, order); | ||
476 | err_nopages: | ||
477 | return NULL; | ||
474 | } | 478 | } |
475 | 479 | ||
476 | /* Free and unmap a consistent DMA buffer. | 480 | /* Free and unmap a consistent DMA buffer. |
@@ -485,7 +489,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, | |||
485 | dma_addr_t ba) | 489 | dma_addr_t ba) |
486 | { | 490 | { |
487 | struct resource *res; | 491 | struct resource *res; |
488 | unsigned long pgp; | 492 | void *pgp; |
489 | 493 | ||
490 | if ((res = _sparc_find_resource(&_sparc_dvma, | 494 | if ((res = _sparc_find_resource(&_sparc_dvma, |
491 | (unsigned long)p)) == NULL) { | 495 | (unsigned long)p)) == NULL) { |
@@ -498,21 +502,21 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, | |||
498 | return; | 502 | return; |
499 | } | 503 | } |
500 | 504 | ||
501 | n = (n + PAGE_SIZE-1) & PAGE_MASK; | 505 | n = PAGE_ALIGN(n); |
502 | if ((res->end-res->start)+1 != n) { | 506 | if ((res->end-res->start)+1 != n) { |
503 | printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", | 507 | printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", |
504 | (long)((res->end-res->start)+1), (long)n); | 508 | (long)((res->end-res->start)+1), (long)n); |
505 | return; | 509 | return; |
506 | } | 510 | } |
507 | 511 | ||
508 | pgp = (unsigned long) phys_to_virt(ba); /* bus_to_virt actually */ | 512 | pgp = phys_to_virt(ba); /* bus_to_virt actually */ |
509 | mmu_inval_dma_area(pgp, n); | 513 | mmu_inval_dma_area(pgp, n); |
510 | sparc_unmapiorange((unsigned long)p, n); | 514 | sparc_unmapiorange((unsigned long)p, n); |
511 | 515 | ||
512 | release_resource(res); | 516 | release_resource(res); |
513 | kfree(res); | 517 | kfree(res); |
514 | 518 | ||
515 | free_pages(pgp, get_order(n)); | 519 | free_pages((unsigned long)pgp, get_order(n)); |
516 | } | 520 | } |
517 | 521 | ||
518 | /* | 522 | /* |
@@ -527,6 +531,13 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page, | |||
527 | return page_to_phys(page) + offset; | 531 | return page_to_phys(page) + offset; |
528 | } | 532 | } |
529 | 533 | ||
534 | static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, | ||
535 | enum dma_data_direction dir, struct dma_attrs *attrs) | ||
536 | { | ||
537 | if (dir != PCI_DMA_TODEVICE) | ||
538 | mmu_inval_dma_area(phys_to_virt(ba), PAGE_ALIGN(size)); | ||
539 | } | ||
540 | |||
530 | /* Map a set of buffers described by scatterlist in streaming | 541 | /* Map a set of buffers described by scatterlist in streaming |
531 | * mode for DMA. This is the scather-gather version of the | 542 | * mode for DMA. This is the scather-gather version of the |
532 | * above pci_map_single interface. Here the scatter gather list | 543 | * above pci_map_single interface. Here the scatter gather list |
@@ -572,9 +583,8 @@ static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl, | |||
572 | if (dir != PCI_DMA_TODEVICE) { | 583 | if (dir != PCI_DMA_TODEVICE) { |
573 | for_each_sg(sgl, sg, nents, n) { | 584 | for_each_sg(sgl, sg, nents, n) { |
574 | BUG_ON(page_address(sg_page(sg)) == NULL); | 585 | BUG_ON(page_address(sg_page(sg)) == NULL); |
575 | mmu_inval_dma_area( | 586 | mmu_inval_dma_area(page_address(sg_page(sg)), |
576 | (unsigned long) page_address(sg_page(sg)), | 587 | PAGE_ALIGN(sg->length)); |
577 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
578 | } | 588 | } |
579 | } | 589 | } |
580 | } | 590 | } |
@@ -593,8 +603,8 @@ static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba, | |||
593 | size_t size, enum dma_data_direction dir) | 603 | size_t size, enum dma_data_direction dir) |
594 | { | 604 | { |
595 | if (dir != PCI_DMA_TODEVICE) { | 605 | if (dir != PCI_DMA_TODEVICE) { |
596 | mmu_inval_dma_area((unsigned long)phys_to_virt(ba), | 606 | mmu_inval_dma_area(phys_to_virt(ba), |
597 | (size + PAGE_SIZE-1) & PAGE_MASK); | 607 | PAGE_ALIGN(size)); |
598 | } | 608 | } |
599 | } | 609 | } |
600 | 610 | ||
@@ -602,8 +612,8 @@ static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba, | |||
602 | size_t size, enum dma_data_direction dir) | 612 | size_t size, enum dma_data_direction dir) |
603 | { | 613 | { |
604 | if (dir != PCI_DMA_TODEVICE) { | 614 | if (dir != PCI_DMA_TODEVICE) { |
605 | mmu_inval_dma_area((unsigned long)phys_to_virt(ba), | 615 | mmu_inval_dma_area(phys_to_virt(ba), |
606 | (size + PAGE_SIZE-1) & PAGE_MASK); | 616 | PAGE_ALIGN(size)); |
607 | } | 617 | } |
608 | } | 618 | } |
609 | 619 | ||
@@ -622,9 +632,8 @@ static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, | |||
622 | if (dir != PCI_DMA_TODEVICE) { | 632 | if (dir != PCI_DMA_TODEVICE) { |
623 | for_each_sg(sgl, sg, nents, n) { | 633 | for_each_sg(sgl, sg, nents, n) { |
624 | BUG_ON(page_address(sg_page(sg)) == NULL); | 634 | BUG_ON(page_address(sg_page(sg)) == NULL); |
625 | mmu_inval_dma_area( | 635 | mmu_inval_dma_area(page_address(sg_page(sg)), |
626 | (unsigned long) page_address(sg_page(sg)), | 636 | PAGE_ALIGN(sg->length)); |
627 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
628 | } | 637 | } |
629 | } | 638 | } |
630 | } | 639 | } |
@@ -638,9 +647,8 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist * | |||
638 | if (dir != PCI_DMA_TODEVICE) { | 647 | if (dir != PCI_DMA_TODEVICE) { |
639 | for_each_sg(sgl, sg, nents, n) { | 648 | for_each_sg(sgl, sg, nents, n) { |
640 | BUG_ON(page_address(sg_page(sg)) == NULL); | 649 | BUG_ON(page_address(sg_page(sg)) == NULL); |
641 | mmu_inval_dma_area( | 650 | mmu_inval_dma_area(page_address(sg_page(sg)), |
642 | (unsigned long) page_address(sg_page(sg)), | 651 | PAGE_ALIGN(sg->length)); |
643 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
644 | } | 652 | } |
645 | } | 653 | } |
646 | } | 654 | } |
@@ -649,6 +657,7 @@ struct dma_map_ops pci32_dma_ops = { | |||
649 | .alloc_coherent = pci32_alloc_coherent, | 657 | .alloc_coherent = pci32_alloc_coherent, |
650 | .free_coherent = pci32_free_coherent, | 658 | .free_coherent = pci32_free_coherent, |
651 | .map_page = pci32_map_page, | 659 | .map_page = pci32_map_page, |
660 | .unmap_page = pci32_unmap_page, | ||
652 | .map_sg = pci32_map_sg, | 661 | .map_sg = pci32_map_sg, |
653 | .unmap_sg = pci32_unmap_sg, | 662 | .unmap_sg = pci32_unmap_sg, |
654 | .sync_single_for_cpu = pci32_sync_single_for_cpu, | 663 | .sync_single_for_cpu = pci32_sync_single_for_cpu, |
@@ -658,7 +667,16 @@ struct dma_map_ops pci32_dma_ops = { | |||
658 | }; | 667 | }; |
659 | EXPORT_SYMBOL(pci32_dma_ops); | 668 | EXPORT_SYMBOL(pci32_dma_ops); |
660 | 669 | ||
661 | #endif /* CONFIG_PCI */ | 670 | #endif /* CONFIG_PCI || CONFIG_SPARC_LEON */ |
671 | |||
672 | #ifdef CONFIG_SPARC_LEON | ||
673 | struct dma_map_ops *dma_ops = &pci32_dma_ops; | ||
674 | #elif defined(CONFIG_SBUS) | ||
675 | struct dma_map_ops *dma_ops = &sbus_dma_ops; | ||
676 | #endif | ||
677 | |||
678 | EXPORT_SYMBOL(dma_ops); | ||
679 | |||
662 | 680 | ||
663 | /* | 681 | /* |
664 | * Return whether the given PCI device DMA address mask can be | 682 | * Return whether the given PCI device DMA address mask can be |
@@ -717,7 +735,7 @@ static const struct file_operations sparc_io_proc_fops = { | |||
717 | static struct resource *_sparc_find_resource(struct resource *root, | 735 | static struct resource *_sparc_find_resource(struct resource *root, |
718 | unsigned long hit) | 736 | unsigned long hit) |
719 | { | 737 | { |
720 | struct resource *tmp; | 738 | struct resource *tmp; |
721 | 739 | ||
722 | for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { | 740 | for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { |
723 | if (tmp->start <= hit && tmp->end >= hit) | 741 | if (tmp->start <= hit && tmp->end >= hit) |
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index db7513881530..008453b798ec 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h | |||
@@ -1,5 +1,41 @@ | |||
1 | #include <linux/platform_device.h> | ||
2 | |||
1 | #include <asm/btfixup.h> | 3 | #include <asm/btfixup.h> |
2 | 4 | ||
5 | /* sun4m specific type definitions */ | ||
6 | |||
7 | /* This maps direct to CPU specific interrupt registers */ | ||
8 | struct sun4m_irq_percpu { | ||
9 | u32 pending; | ||
10 | u32 clear; | ||
11 | u32 set; | ||
12 | }; | ||
13 | |||
14 | /* This maps direct to global interrupt registers */ | ||
15 | struct sun4m_irq_global { | ||
16 | u32 pending; | ||
17 | u32 mask; | ||
18 | u32 mask_clear; | ||
19 | u32 mask_set; | ||
20 | u32 interrupt_target; | ||
21 | }; | ||
22 | |||
23 | extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | ||
24 | extern struct sun4m_irq_global __iomem *sun4m_irq_global; | ||
25 | |||
26 | /* | ||
27 | * Platform specific irq configuration | ||
28 | * The individual platforms assign their platform | ||
29 | * specifics in their init functions. | ||
30 | */ | ||
31 | struct sparc_irq_config { | ||
32 | void (*init_timers)(irq_handler_t); | ||
33 | unsigned int (*build_device_irq)(struct platform_device *op, | ||
34 | unsigned int real_irq); | ||
35 | }; | ||
36 | extern struct sparc_irq_config sparc_irq_config; | ||
37 | |||
38 | |||
3 | /* Dave Redman (djhr@tadpole.co.uk) | 39 | /* Dave Redman (djhr@tadpole.co.uk) |
4 | * changed these to function pointers.. it saves cycles and will allow | 40 | * changed these to function pointers.. it saves cycles and will allow |
5 | * the irq dependencies to be split into different files at a later date | 41 | * the irq dependencies to be split into different files at a later date |
@@ -45,12 +81,6 @@ static inline void load_profile_irq(int cpu, int limit) | |||
45 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); | 81 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); |
46 | } | 82 | } |
47 | 83 | ||
48 | extern void (*sparc_init_timers)(irq_handler_t lvl10_irq); | ||
49 | |||
50 | extern void claim_ticker14(irq_handler_t irq_handler, | ||
51 | int irq, | ||
52 | unsigned int timeout); | ||
53 | |||
54 | #ifdef CONFIG_SMP | 84 | #ifdef CONFIG_SMP |
55 | BTFIXUPDEF_CALL(void, set_cpu_int, int, int) | 85 | BTFIXUPDEF_CALL(void, set_cpu_int, int, int) |
56 | BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) | 86 | BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) |
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index 5ad6e5c5dbb3..7c93df4099cb 100644 --- a/arch/sparc/kernel/irq_32.c +++ b/arch/sparc/kernel/irq_32.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the | 2 | * Interrupt request handling routines. On the |
3 | * Sparc the IRQs are basically 'cast in stone' | 3 | * Sparc the IRQs are basically 'cast in stone' |
4 | * and you are supposed to probe the prom's device | 4 | * and you are supposed to probe the prom's device |
5 | * node trees to find out who's got which IRQ. | 5 | * node trees to find out who's got which IRQ. |
6 | * | 6 | * |
7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | 7 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
8 | * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) | 8 | * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) |
@@ -11,40 +11,11 @@ | |||
11 | * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org) | 11 | * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org) |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/ptrace.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/linkage.h> | ||
19 | #include <linux/kernel_stat.h> | 14 | #include <linux/kernel_stat.h> |
20 | #include <linux/signal.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/random.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/smp.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/threads.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
30 | 16 | ||
31 | #include <asm/ptrace.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/system.h> | ||
34 | #include <asm/psr.h> | ||
35 | #include <asm/smp.h> | ||
36 | #include <asm/vaddrs.h> | ||
37 | #include <asm/timer.h> | ||
38 | #include <asm/openprom.h> | ||
39 | #include <asm/oplib.h> | ||
40 | #include <asm/traps.h> | ||
41 | #include <asm/irq.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/pgalloc.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/pcic.h> | ||
46 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
47 | #include <asm/irq_regs.h> | 18 | #include <asm/pcic.h> |
48 | #include <asm/leon.h> | 19 | #include <asm/leon.h> |
49 | 20 | ||
50 | #include "kernel.h" | 21 | #include "kernel.h" |
@@ -57,6 +28,10 @@ | |||
57 | #define SMP_NOP2 | 28 | #define SMP_NOP2 |
58 | #define SMP_NOP3 | 29 | #define SMP_NOP3 |
59 | #endif /* SMP */ | 30 | #endif /* SMP */ |
31 | |||
32 | /* platform specific irq setup */ | ||
33 | struct sparc_irq_config sparc_irq_config; | ||
34 | |||
60 | unsigned long arch_local_irq_save(void) | 35 | unsigned long arch_local_irq_save(void) |
61 | { | 36 | { |
62 | unsigned long retval; | 37 | unsigned long retval; |
@@ -128,15 +103,7 @@ EXPORT_SYMBOL(arch_local_irq_restore); | |||
128 | * | 103 | * |
129 | */ | 104 | */ |
130 | 105 | ||
131 | static void irq_panic(void) | ||
132 | { | ||
133 | extern char *cputypval; | ||
134 | prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval); | ||
135 | prom_halt(); | ||
136 | } | ||
137 | 106 | ||
138 | void (*sparc_init_timers)(irq_handler_t ) = | ||
139 | (void (*)(irq_handler_t )) irq_panic; | ||
140 | 107 | ||
141 | /* | 108 | /* |
142 | * Dave Redman (djhr@tadpole.co.uk) | 109 | * Dave Redman (djhr@tadpole.co.uk) |
@@ -145,7 +112,7 @@ void (*sparc_init_timers)(irq_handler_t ) = | |||
145 | * instead, because some of the devices attach very early, I do something | 112 | * instead, because some of the devices attach very early, I do something |
146 | * equally sucky but at least we'll never try to free statically allocated | 113 | * equally sucky but at least we'll never try to free statically allocated |
147 | * space or call kmalloc before kmalloc_init :(. | 114 | * space or call kmalloc before kmalloc_init :(. |
148 | * | 115 | * |
149 | * In fact it's the timer10 that attaches first.. then timer14 | 116 | * In fact it's the timer10 that attaches first.. then timer14 |
150 | * then kmalloc_init is called.. then the tty interrupts attach. | 117 | * then kmalloc_init is called.. then the tty interrupts attach. |
151 | * hmmm.... | 118 | * hmmm.... |
@@ -166,22 +133,20 @@ DEFINE_SPINLOCK(irq_action_lock); | |||
166 | 133 | ||
167 | int show_interrupts(struct seq_file *p, void *v) | 134 | int show_interrupts(struct seq_file *p, void *v) |
168 | { | 135 | { |
169 | int i = *(loff_t *) v; | 136 | int i = *(loff_t *)v; |
170 | struct irqaction * action; | 137 | struct irqaction *action; |
171 | unsigned long flags; | 138 | unsigned long flags; |
172 | #ifdef CONFIG_SMP | 139 | #ifdef CONFIG_SMP |
173 | int j; | 140 | int j; |
174 | #endif | 141 | #endif |
175 | 142 | ||
176 | if (sparc_cpu_model == sun4d) { | 143 | if (sparc_cpu_model == sun4d) |
177 | extern int show_sun4d_interrupts(struct seq_file *, void *); | ||
178 | |||
179 | return show_sun4d_interrupts(p, v); | 144 | return show_sun4d_interrupts(p, v); |
180 | } | 145 | |
181 | spin_lock_irqsave(&irq_action_lock, flags); | 146 | spin_lock_irqsave(&irq_action_lock, flags); |
182 | if (i < NR_IRQS) { | 147 | if (i < NR_IRQS) { |
183 | action = sparc_irq[i].action; | 148 | action = sparc_irq[i].action; |
184 | if (!action) | 149 | if (!action) |
185 | goto out_unlock; | 150 | goto out_unlock; |
186 | seq_printf(p, "%3d: ", i); | 151 | seq_printf(p, "%3d: ", i); |
187 | #ifndef CONFIG_SMP | 152 | #ifndef CONFIG_SMP |
@@ -195,7 +160,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
195 | seq_printf(p, " %c %s", | 160 | seq_printf(p, " %c %s", |
196 | (action->flags & IRQF_DISABLED) ? '+' : ' ', | 161 | (action->flags & IRQF_DISABLED) ? '+' : ' ', |
197 | action->name); | 162 | action->name); |
198 | for (action=action->next; action; action = action->next) { | 163 | for (action = action->next; action; action = action->next) { |
199 | seq_printf(p, ",%s %s", | 164 | seq_printf(p, ",%s %s", |
200 | (action->flags & IRQF_DISABLED) ? " +" : "", | 165 | (action->flags & IRQF_DISABLED) ? " +" : "", |
201 | action->name); | 166 | action->name); |
@@ -209,22 +174,20 @@ out_unlock: | |||
209 | 174 | ||
210 | void free_irq(unsigned int irq, void *dev_id) | 175 | void free_irq(unsigned int irq, void *dev_id) |
211 | { | 176 | { |
212 | struct irqaction * action; | 177 | struct irqaction *action; |
213 | struct irqaction **actionp; | 178 | struct irqaction **actionp; |
214 | unsigned long flags; | 179 | unsigned long flags; |
215 | unsigned int cpu_irq; | 180 | unsigned int cpu_irq; |
216 | 181 | ||
217 | if (sparc_cpu_model == sun4d) { | 182 | if (sparc_cpu_model == sun4d) { |
218 | extern void sun4d_free_irq(unsigned int, void *); | ||
219 | |||
220 | sun4d_free_irq(irq, dev_id); | 183 | sun4d_free_irq(irq, dev_id); |
221 | return; | 184 | return; |
222 | } | 185 | } |
223 | cpu_irq = irq & (NR_IRQS - 1); | 186 | cpu_irq = irq & (NR_IRQS - 1); |
224 | if (cpu_irq > 14) { /* 14 irq levels on the sparc */ | 187 | if (cpu_irq > 14) { /* 14 irq levels on the sparc */ |
225 | printk("Trying to free bogus IRQ %d\n", irq); | 188 | printk(KERN_ERR "Trying to free bogus IRQ %d\n", irq); |
226 | return; | 189 | return; |
227 | } | 190 | } |
228 | 191 | ||
229 | spin_lock_irqsave(&irq_action_lock, flags); | 192 | spin_lock_irqsave(&irq_action_lock, flags); |
230 | 193 | ||
@@ -232,7 +195,7 @@ void free_irq(unsigned int irq, void *dev_id) | |||
232 | action = *actionp; | 195 | action = *actionp; |
233 | 196 | ||
234 | if (!action->handler) { | 197 | if (!action->handler) { |
235 | printk("Trying to free free IRQ%d\n",irq); | 198 | printk(KERN_ERR "Trying to free free IRQ%d\n", irq); |
236 | goto out_unlock; | 199 | goto out_unlock; |
237 | } | 200 | } |
238 | if (dev_id) { | 201 | if (dev_id) { |
@@ -242,19 +205,21 @@ void free_irq(unsigned int irq, void *dev_id) | |||
242 | actionp = &action->next; | 205 | actionp = &action->next; |
243 | } | 206 | } |
244 | if (!action) { | 207 | if (!action) { |
245 | printk("Trying to free free shared IRQ%d\n",irq); | 208 | printk(KERN_ERR "Trying to free free shared IRQ%d\n", |
209 | irq); | ||
246 | goto out_unlock; | 210 | goto out_unlock; |
247 | } | 211 | } |
248 | } else if (action->flags & IRQF_SHARED) { | 212 | } else if (action->flags & IRQF_SHARED) { |
249 | printk("Trying to free shared IRQ%d with NULL device ID\n", irq); | 213 | printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n", |
214 | irq); | ||
250 | goto out_unlock; | 215 | goto out_unlock; |
251 | } | 216 | } |
252 | if (action->flags & SA_STATIC_ALLOC) | 217 | if (action->flags & SA_STATIC_ALLOC) { |
253 | { | 218 | /* |
254 | /* This interrupt is marked as specially allocated | 219 | * This interrupt is marked as specially allocated |
255 | * so it is a bad idea to free it. | 220 | * so it is a bad idea to free it. |
256 | */ | 221 | */ |
257 | printk("Attempt to free statically allocated IRQ%d (%s)\n", | 222 | printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n", |
258 | irq, action->name); | 223 | irq, action->name); |
259 | goto out_unlock; | 224 | goto out_unlock; |
260 | } | 225 | } |
@@ -275,7 +240,6 @@ void free_irq(unsigned int irq, void *dev_id) | |||
275 | out_unlock: | 240 | out_unlock: |
276 | spin_unlock_irqrestore(&irq_action_lock, flags); | 241 | spin_unlock_irqrestore(&irq_action_lock, flags); |
277 | } | 242 | } |
278 | |||
279 | EXPORT_SYMBOL(free_irq); | 243 | EXPORT_SYMBOL(free_irq); |
280 | 244 | ||
281 | /* | 245 | /* |
@@ -297,64 +261,62 @@ void synchronize_irq(unsigned int irq) | |||
297 | EXPORT_SYMBOL(synchronize_irq); | 261 | EXPORT_SYMBOL(synchronize_irq); |
298 | #endif /* SMP */ | 262 | #endif /* SMP */ |
299 | 263 | ||
300 | void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) | 264 | void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs) |
301 | { | 265 | { |
302 | int i; | 266 | int i; |
303 | struct irqaction * action; | 267 | struct irqaction *action; |
304 | unsigned int cpu_irq; | 268 | unsigned int cpu_irq; |
305 | 269 | ||
306 | cpu_irq = irq & (NR_IRQS - 1); | 270 | cpu_irq = irq & (NR_IRQS - 1); |
307 | action = sparc_irq[cpu_irq].action; | 271 | action = sparc_irq[cpu_irq].action; |
308 | 272 | ||
309 | printk("IO device interrupt, irq = %d\n", irq); | 273 | printk(KERN_ERR "IO device interrupt, irq = %d\n", irq); |
310 | printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, | 274 | printk(KERN_ERR "PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, |
311 | regs->npc, regs->u_regs[14]); | 275 | regs->npc, regs->u_regs[14]); |
312 | if (action) { | 276 | if (action) { |
313 | printk("Expecting: "); | 277 | printk(KERN_ERR "Expecting: "); |
314 | for (i = 0; i < 16; i++) | 278 | for (i = 0; i < 16; i++) |
315 | if (action->handler) | 279 | if (action->handler) |
316 | printk("[%s:%d:0x%x] ", action->name, | 280 | printk(KERN_CONT "[%s:%d:0x%x] ", action->name, |
317 | (int) i, (unsigned int) action->handler); | 281 | i, (unsigned int)action->handler); |
318 | } | 282 | } |
319 | printk("AIEEE\n"); | 283 | printk(KERN_ERR "AIEEE\n"); |
320 | panic("bogus interrupt received"); | 284 | panic("bogus interrupt received"); |
321 | } | 285 | } |
322 | 286 | ||
323 | void handler_irq(int irq, struct pt_regs * regs) | 287 | void handler_irq(int pil, struct pt_regs *regs) |
324 | { | 288 | { |
325 | struct pt_regs *old_regs; | 289 | struct pt_regs *old_regs; |
326 | struct irqaction * action; | 290 | struct irqaction *action; |
327 | int cpu = smp_processor_id(); | 291 | int cpu = smp_processor_id(); |
328 | #ifdef CONFIG_SMP | ||
329 | extern void smp4m_irq_rotate(int cpu); | ||
330 | #endif | ||
331 | 292 | ||
332 | old_regs = set_irq_regs(regs); | 293 | old_regs = set_irq_regs(regs); |
333 | irq_enter(); | 294 | irq_enter(); |
334 | disable_pil_irq(irq); | 295 | disable_pil_irq(pil); |
335 | #ifdef CONFIG_SMP | 296 | #ifdef CONFIG_SMP |
336 | /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ | 297 | /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ |
337 | if((sparc_cpu_model==sun4m) && (irq < 10)) | 298 | if ((sparc_cpu_model==sun4m) && (pil < 10)) |
338 | smp4m_irq_rotate(cpu); | 299 | smp4m_irq_rotate(cpu); |
339 | #endif | 300 | #endif |
340 | action = sparc_irq[irq].action; | 301 | action = sparc_irq[pil].action; |
341 | sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS; | 302 | sparc_irq[pil].flags |= SPARC_IRQ_INPROGRESS; |
342 | kstat_cpu(cpu).irqs[irq]++; | 303 | kstat_cpu(cpu).irqs[pil]++; |
343 | do { | 304 | do { |
344 | if (!action || !action->handler) | 305 | if (!action || !action->handler) |
345 | unexpected_irq(irq, NULL, regs); | 306 | unexpected_irq(pil, NULL, regs); |
346 | action->handler(irq, action->dev_id); | 307 | action->handler(pil, action->dev_id); |
347 | action = action->next; | 308 | action = action->next; |
348 | } while (action); | 309 | } while (action); |
349 | sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS; | 310 | sparc_irq[pil].flags &= ~SPARC_IRQ_INPROGRESS; |
350 | enable_pil_irq(irq); | 311 | enable_pil_irq(pil); |
351 | irq_exit(); | 312 | irq_exit(); |
352 | set_irq_regs(old_regs); | 313 | set_irq_regs(old_regs); |
353 | } | 314 | } |
354 | 315 | ||
355 | #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) | 316 | #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) |
356 | 317 | ||
357 | /* Fast IRQs on the Sparc can only have one routine attached to them, | 318 | /* |
319 | * Fast IRQs on the Sparc can only have one routine attached to them, | ||
358 | * thus no sharing possible. | 320 | * thus no sharing possible. |
359 | */ | 321 | */ |
360 | static int request_fast_irq(unsigned int irq, | 322 | static int request_fast_irq(unsigned int irq, |
@@ -367,15 +329,13 @@ static int request_fast_irq(unsigned int irq, | |||
367 | int ret; | 329 | int ret; |
368 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON | 330 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON |
369 | struct tt_entry *trap_table; | 331 | struct tt_entry *trap_table; |
370 | extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3; | ||
371 | #endif | 332 | #endif |
372 | |||
373 | cpu_irq = irq & (NR_IRQS - 1); | 333 | cpu_irq = irq & (NR_IRQS - 1); |
374 | if(cpu_irq > 14) { | 334 | if (cpu_irq > 14) { |
375 | ret = -EINVAL; | 335 | ret = -EINVAL; |
376 | goto out; | 336 | goto out; |
377 | } | 337 | } |
378 | if(!handler) { | 338 | if (!handler) { |
379 | ret = -EINVAL; | 339 | ret = -EINVAL; |
380 | goto out; | 340 | goto out; |
381 | } | 341 | } |
@@ -383,34 +343,33 @@ static int request_fast_irq(unsigned int irq, | |||
383 | spin_lock_irqsave(&irq_action_lock, flags); | 343 | spin_lock_irqsave(&irq_action_lock, flags); |
384 | 344 | ||
385 | action = sparc_irq[cpu_irq].action; | 345 | action = sparc_irq[cpu_irq].action; |
386 | if(action) { | 346 | if (action) { |
387 | if(action->flags & IRQF_SHARED) | 347 | if (action->flags & IRQF_SHARED) |
388 | panic("Trying to register fast irq when already shared.\n"); | 348 | panic("Trying to register fast irq when already shared.\n"); |
389 | if(irqflags & IRQF_SHARED) | 349 | if (irqflags & IRQF_SHARED) |
390 | panic("Trying to register fast irq as shared.\n"); | 350 | panic("Trying to register fast irq as shared.\n"); |
391 | 351 | ||
392 | /* Anyway, someone already owns it so cannot be made fast. */ | 352 | /* Anyway, someone already owns it so cannot be made fast. */ |
393 | printk("request_fast_irq: Trying to register yet already owned.\n"); | 353 | printk(KERN_ERR "request_fast_irq: Trying to register yet already owned.\n"); |
394 | ret = -EBUSY; | 354 | ret = -EBUSY; |
395 | goto out_unlock; | 355 | goto out_unlock; |
396 | } | 356 | } |
397 | 357 | ||
398 | /* If this is flagged as statically allocated then we use our | 358 | /* |
359 | * If this is flagged as statically allocated then we use our | ||
399 | * private struct which is never freed. | 360 | * private struct which is never freed. |
400 | */ | 361 | */ |
401 | if (irqflags & SA_STATIC_ALLOC) { | 362 | if (irqflags & SA_STATIC_ALLOC) { |
402 | if (static_irq_count < MAX_STATIC_ALLOC) | 363 | if (static_irq_count < MAX_STATIC_ALLOC) |
403 | action = &static_irqaction[static_irq_count++]; | 364 | action = &static_irqaction[static_irq_count++]; |
404 | else | 365 | else |
405 | printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", | 366 | printk(KERN_ERR "Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", |
406 | irq, devname); | 367 | irq, devname); |
407 | } | 368 | } |
408 | 369 | ||
409 | if (action == NULL) | 370 | if (action == NULL) |
410 | action = kmalloc(sizeof(struct irqaction), | 371 | action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); |
411 | GFP_ATOMIC); | 372 | if (!action) { |
412 | |||
413 | if (!action) { | ||
414 | ret = -ENOMEM; | 373 | ret = -ENOMEM; |
415 | goto out_unlock; | 374 | goto out_unlock; |
416 | } | 375 | } |
@@ -426,9 +385,12 @@ static int request_fast_irq(unsigned int irq, | |||
426 | 385 | ||
427 | INSTANTIATE(sparc_ttable) | 386 | INSTANTIATE(sparc_ttable) |
428 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON | 387 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON |
429 | trap_table = &trapbase_cpu1; INSTANTIATE(trap_table) | 388 | trap_table = &trapbase_cpu1; |
430 | trap_table = &trapbase_cpu2; INSTANTIATE(trap_table) | 389 | INSTANTIATE(trap_table) |
431 | trap_table = &trapbase_cpu3; INSTANTIATE(trap_table) | 390 | trap_table = &trapbase_cpu2; |
391 | INSTANTIATE(trap_table) | ||
392 | trap_table = &trapbase_cpu3; | ||
393 | INSTANTIATE(trap_table) | ||
432 | #endif | 394 | #endif |
433 | #undef INSTANTIATE | 395 | #undef INSTANTIATE |
434 | /* | 396 | /* |
@@ -454,7 +416,8 @@ out: | |||
454 | return ret; | 416 | return ret; |
455 | } | 417 | } |
456 | 418 | ||
457 | /* These variables are used to access state from the assembler | 419 | /* |
420 | * These variables are used to access state from the assembler | ||
458 | * interrupt handler, floppy_hardint, so we cannot put these in | 421 | * interrupt handler, floppy_hardint, so we cannot put these in |
459 | * the floppy driver image because that would not work in the | 422 | * the floppy driver image because that would not work in the |
460 | * modular case. | 423 | * modular case. |
@@ -477,8 +440,6 @@ EXPORT_SYMBOL(pdma_base); | |||
477 | unsigned long pdma_areasize; | 440 | unsigned long pdma_areasize; |
478 | EXPORT_SYMBOL(pdma_areasize); | 441 | EXPORT_SYMBOL(pdma_areasize); |
479 | 442 | ||
480 | extern void floppy_hardint(void); | ||
481 | |||
482 | static irq_handler_t floppy_irq_handler; | 443 | static irq_handler_t floppy_irq_handler; |
483 | 444 | ||
484 | void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) | 445 | void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) |
@@ -494,9 +455,11 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
494 | irq_exit(); | 455 | irq_exit(); |
495 | enable_pil_irq(irq); | 456 | enable_pil_irq(irq); |
496 | set_irq_regs(old_regs); | 457 | set_irq_regs(old_regs); |
497 | // XXX Eek, it's totally changed with preempt_count() and such | 458 | /* |
498 | // if (softirq_pending(cpu)) | 459 | * XXX Eek, it's totally changed with preempt_count() and such |
499 | // do_softirq(); | 460 | * if (softirq_pending(cpu)) |
461 | * do_softirq(); | ||
462 | */ | ||
500 | } | 463 | } |
501 | 464 | ||
502 | int sparc_floppy_request_irq(int irq, unsigned long flags, | 465 | int sparc_floppy_request_irq(int irq, unsigned long flags, |
@@ -511,21 +474,18 @@ EXPORT_SYMBOL(sparc_floppy_request_irq); | |||
511 | 474 | ||
512 | int request_irq(unsigned int irq, | 475 | int request_irq(unsigned int irq, |
513 | irq_handler_t handler, | 476 | irq_handler_t handler, |
514 | unsigned long irqflags, const char * devname, void *dev_id) | 477 | unsigned long irqflags, const char *devname, void *dev_id) |
515 | { | 478 | { |
516 | struct irqaction * action, **actionp; | 479 | struct irqaction *action, **actionp; |
517 | unsigned long flags; | 480 | unsigned long flags; |
518 | unsigned int cpu_irq; | 481 | unsigned int cpu_irq; |
519 | int ret; | 482 | int ret; |
520 | 483 | ||
521 | if (sparc_cpu_model == sun4d) { | 484 | if (sparc_cpu_model == sun4d) |
522 | extern int sun4d_request_irq(unsigned int, | ||
523 | irq_handler_t , | ||
524 | unsigned long, const char *, void *); | ||
525 | return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); | 485 | return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); |
526 | } | 486 | |
527 | cpu_irq = irq & (NR_IRQS - 1); | 487 | cpu_irq = irq & (NR_IRQS - 1); |
528 | if(cpu_irq > 14) { | 488 | if (cpu_irq > 14) { |
529 | ret = -EINVAL; | 489 | ret = -EINVAL; |
530 | goto out; | 490 | goto out; |
531 | } | 491 | } |
@@ -533,7 +493,7 @@ int request_irq(unsigned int irq, | |||
533 | ret = -EINVAL; | 493 | ret = -EINVAL; |
534 | goto out; | 494 | goto out; |
535 | } | 495 | } |
536 | 496 | ||
537 | spin_lock_irqsave(&irq_action_lock, flags); | 497 | spin_lock_irqsave(&irq_action_lock, flags); |
538 | 498 | ||
539 | actionp = &sparc_irq[cpu_irq].action; | 499 | actionp = &sparc_irq[cpu_irq].action; |
@@ -544,7 +504,8 @@ int request_irq(unsigned int irq, | |||
544 | goto out_unlock; | 504 | goto out_unlock; |
545 | } | 505 | } |
546 | if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { | 506 | if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { |
547 | printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); | 507 | printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n", |
508 | irq); | ||
548 | ret = -EBUSY; | 509 | ret = -EBUSY; |
549 | goto out_unlock; | 510 | goto out_unlock; |
550 | } | 511 | } |
@@ -559,14 +520,12 @@ int request_irq(unsigned int irq, | |||
559 | if (static_irq_count < MAX_STATIC_ALLOC) | 520 | if (static_irq_count < MAX_STATIC_ALLOC) |
560 | action = &static_irqaction[static_irq_count++]; | 521 | action = &static_irqaction[static_irq_count++]; |
561 | else | 522 | else |
562 | printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); | 523 | printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", |
524 | irq, devname); | ||
563 | } | 525 | } |
564 | |||
565 | if (action == NULL) | 526 | if (action == NULL) |
566 | action = kmalloc(sizeof(struct irqaction), | 527 | action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); |
567 | GFP_ATOMIC); | 528 | if (!action) { |
568 | |||
569 | if (!action) { | ||
570 | ret = -ENOMEM; | 529 | ret = -ENOMEM; |
571 | goto out_unlock; | 530 | goto out_unlock; |
572 | } | 531 | } |
@@ -587,7 +546,6 @@ out_unlock: | |||
587 | out: | 546 | out: |
588 | return ret; | 547 | return ret; |
589 | } | 548 | } |
590 | |||
591 | EXPORT_SYMBOL(request_irq); | 549 | EXPORT_SYMBOL(request_irq); |
592 | 550 | ||
593 | void disable_irq_nosync(unsigned int irq) | 551 | void disable_irq_nosync(unsigned int irq) |
@@ -606,26 +564,30 @@ void enable_irq(unsigned int irq) | |||
606 | { | 564 | { |
607 | __enable_irq(irq); | 565 | __enable_irq(irq); |
608 | } | 566 | } |
609 | |||
610 | EXPORT_SYMBOL(enable_irq); | 567 | EXPORT_SYMBOL(enable_irq); |
611 | 568 | ||
612 | /* We really don't need these at all on the Sparc. We only have | 569 | /* |
570 | * We really don't need these at all on the Sparc. We only have | ||
613 | * stubs here because they are exported to modules. | 571 | * stubs here because they are exported to modules. |
614 | */ | 572 | */ |
615 | unsigned long probe_irq_on(void) | 573 | unsigned long probe_irq_on(void) |
616 | { | 574 | { |
617 | return 0; | 575 | return 0; |
618 | } | 576 | } |
619 | |||
620 | EXPORT_SYMBOL(probe_irq_on); | 577 | EXPORT_SYMBOL(probe_irq_on); |
621 | 578 | ||
622 | int probe_irq_off(unsigned long mask) | 579 | int probe_irq_off(unsigned long mask) |
623 | { | 580 | { |
624 | return 0; | 581 | return 0; |
625 | } | 582 | } |
626 | |||
627 | EXPORT_SYMBOL(probe_irq_off); | 583 | EXPORT_SYMBOL(probe_irq_off); |
628 | 584 | ||
585 | static unsigned int build_device_irq(struct platform_device *op, | ||
586 | unsigned int real_irq) | ||
587 | { | ||
588 | return real_irq; | ||
589 | } | ||
590 | |||
629 | /* djhr | 591 | /* djhr |
630 | * This could probably be made indirect too and assigned in the CPU | 592 | * This could probably be made indirect too and assigned in the CPU |
631 | * bits of the code. That would be much nicer I think and would also | 593 | * bits of the code. That would be much nicer I think and would also |
@@ -636,11 +598,9 @@ EXPORT_SYMBOL(probe_irq_off); | |||
636 | 598 | ||
637 | void __init init_IRQ(void) | 599 | void __init init_IRQ(void) |
638 | { | 600 | { |
639 | extern void sun4c_init_IRQ( void ); | 601 | sparc_irq_config.build_device_irq = build_device_irq; |
640 | extern void sun4m_init_IRQ( void ); | ||
641 | extern void sun4d_init_IRQ( void ); | ||
642 | 602 | ||
643 | switch(sparc_cpu_model) { | 603 | switch (sparc_cpu_model) { |
644 | case sun4c: | 604 | case sun4c: |
645 | case sun4: | 605 | case sun4: |
646 | sun4c_init_IRQ(); | 606 | sun4c_init_IRQ(); |
@@ -656,7 +616,7 @@ void __init init_IRQ(void) | |||
656 | #endif | 616 | #endif |
657 | sun4m_init_IRQ(); | 617 | sun4m_init_IRQ(); |
658 | break; | 618 | break; |
659 | 619 | ||
660 | case sun4d: | 620 | case sun4d: |
661 | sun4d_init_IRQ(); | 621 | sun4d_init_IRQ(); |
662 | break; | 622 | break; |
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 830d70a3e20b..eb16e3b8a2dd 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
@@ -82,7 +82,7 @@ static void bucket_clear_chain_pa(unsigned long bucket_pa) | |||
82 | "i" (ASI_PHYS_USE_EC)); | 82 | "i" (ASI_PHYS_USE_EC)); |
83 | } | 83 | } |
84 | 84 | ||
85 | static unsigned int bucket_get_virt_irq(unsigned long bucket_pa) | 85 | static unsigned int bucket_get_irq(unsigned long bucket_pa) |
86 | { | 86 | { |
87 | unsigned int ret; | 87 | unsigned int ret; |
88 | 88 | ||
@@ -90,21 +90,20 @@ static unsigned int bucket_get_virt_irq(unsigned long bucket_pa) | |||
90 | : "=&r" (ret) | 90 | : "=&r" (ret) |
91 | : "r" (bucket_pa + | 91 | : "r" (bucket_pa + |
92 | offsetof(struct ino_bucket, | 92 | offsetof(struct ino_bucket, |
93 | __virt_irq)), | 93 | __irq)), |
94 | "i" (ASI_PHYS_USE_EC)); | 94 | "i" (ASI_PHYS_USE_EC)); |
95 | 95 | ||
96 | return ret; | 96 | return ret; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void bucket_set_virt_irq(unsigned long bucket_pa, | 99 | static void bucket_set_irq(unsigned long bucket_pa, unsigned int irq) |
100 | unsigned int virt_irq) | ||
101 | { | 100 | { |
102 | __asm__ __volatile__("stwa %0, [%1] %2" | 101 | __asm__ __volatile__("stwa %0, [%1] %2" |
103 | : /* no outputs */ | 102 | : /* no outputs */ |
104 | : "r" (virt_irq), | 103 | : "r" (irq), |
105 | "r" (bucket_pa + | 104 | "r" (bucket_pa + |
106 | offsetof(struct ino_bucket, | 105 | offsetof(struct ino_bucket, |
107 | __virt_irq)), | 106 | __irq)), |
108 | "i" (ASI_PHYS_USE_EC)); | 107 | "i" (ASI_PHYS_USE_EC)); |
109 | } | 108 | } |
110 | 109 | ||
@@ -114,50 +113,49 @@ static struct { | |||
114 | unsigned int dev_handle; | 113 | unsigned int dev_handle; |
115 | unsigned int dev_ino; | 114 | unsigned int dev_ino; |
116 | unsigned int in_use; | 115 | unsigned int in_use; |
117 | } virt_irq_table[NR_IRQS]; | 116 | } irq_table[NR_IRQS]; |
118 | static DEFINE_SPINLOCK(virt_irq_alloc_lock); | 117 | static DEFINE_SPINLOCK(irq_alloc_lock); |
119 | 118 | ||
120 | unsigned char virt_irq_alloc(unsigned int dev_handle, | 119 | unsigned char irq_alloc(unsigned int dev_handle, unsigned int dev_ino) |
121 | unsigned int dev_ino) | ||
122 | { | 120 | { |
123 | unsigned long flags; | 121 | unsigned long flags; |
124 | unsigned char ent; | 122 | unsigned char ent; |
125 | 123 | ||
126 | BUILD_BUG_ON(NR_IRQS >= 256); | 124 | BUILD_BUG_ON(NR_IRQS >= 256); |
127 | 125 | ||
128 | spin_lock_irqsave(&virt_irq_alloc_lock, flags); | 126 | spin_lock_irqsave(&irq_alloc_lock, flags); |
129 | 127 | ||
130 | for (ent = 1; ent < NR_IRQS; ent++) { | 128 | for (ent = 1; ent < NR_IRQS; ent++) { |
131 | if (!virt_irq_table[ent].in_use) | 129 | if (!irq_table[ent].in_use) |
132 | break; | 130 | break; |
133 | } | 131 | } |
134 | if (ent >= NR_IRQS) { | 132 | if (ent >= NR_IRQS) { |
135 | printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); | 133 | printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); |
136 | ent = 0; | 134 | ent = 0; |
137 | } else { | 135 | } else { |
138 | virt_irq_table[ent].dev_handle = dev_handle; | 136 | irq_table[ent].dev_handle = dev_handle; |
139 | virt_irq_table[ent].dev_ino = dev_ino; | 137 | irq_table[ent].dev_ino = dev_ino; |
140 | virt_irq_table[ent].in_use = 1; | 138 | irq_table[ent].in_use = 1; |
141 | } | 139 | } |
142 | 140 | ||
143 | spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); | 141 | spin_unlock_irqrestore(&irq_alloc_lock, flags); |
144 | 142 | ||
145 | return ent; | 143 | return ent; |
146 | } | 144 | } |
147 | 145 | ||
148 | #ifdef CONFIG_PCI_MSI | 146 | #ifdef CONFIG_PCI_MSI |
149 | void virt_irq_free(unsigned int virt_irq) | 147 | void irq_free(unsigned int irq) |
150 | { | 148 | { |
151 | unsigned long flags; | 149 | unsigned long flags; |
152 | 150 | ||
153 | if (virt_irq >= NR_IRQS) | 151 | if (irq >= NR_IRQS) |
154 | return; | 152 | return; |
155 | 153 | ||
156 | spin_lock_irqsave(&virt_irq_alloc_lock, flags); | 154 | spin_lock_irqsave(&irq_alloc_lock, flags); |
157 | 155 | ||
158 | virt_irq_table[virt_irq].in_use = 0; | 156 | irq_table[irq].in_use = 0; |
159 | 157 | ||
160 | spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); | 158 | spin_unlock_irqrestore(&irq_alloc_lock, flags); |
161 | } | 159 | } |
162 | #endif | 160 | #endif |
163 | 161 | ||
@@ -190,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
190 | for_each_online_cpu(j) | 188 | for_each_online_cpu(j) |
191 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | 189 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); |
192 | #endif | 190 | #endif |
193 | seq_printf(p, " %9s", irq_desc[i].chip->name); | 191 | seq_printf(p, " %9s", irq_desc[i].irq_data.chip->name); |
194 | seq_printf(p, " %s", action->name); | 192 | seq_printf(p, " %s", action->name); |
195 | 193 | ||
196 | for (action=action->next; action; action = action->next) | 194 | for (action=action->next; action; action = action->next) |
@@ -253,39 +251,38 @@ struct irq_handler_data { | |||
253 | }; | 251 | }; |
254 | 252 | ||
255 | #ifdef CONFIG_SMP | 253 | #ifdef CONFIG_SMP |
256 | static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity) | 254 | static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity) |
257 | { | 255 | { |
258 | cpumask_t mask; | 256 | cpumask_t mask; |
259 | int cpuid; | 257 | int cpuid; |
260 | 258 | ||
261 | cpumask_copy(&mask, affinity); | 259 | cpumask_copy(&mask, affinity); |
262 | if (cpus_equal(mask, cpu_online_map)) { | 260 | if (cpus_equal(mask, cpu_online_map)) { |
263 | cpuid = map_to_cpu(virt_irq); | 261 | cpuid = map_to_cpu(irq); |
264 | } else { | 262 | } else { |
265 | cpumask_t tmp; | 263 | cpumask_t tmp; |
266 | 264 | ||
267 | cpus_and(tmp, cpu_online_map, mask); | 265 | cpus_and(tmp, cpu_online_map, mask); |
268 | cpuid = cpus_empty(tmp) ? map_to_cpu(virt_irq) : first_cpu(tmp); | 266 | cpuid = cpus_empty(tmp) ? map_to_cpu(irq) : first_cpu(tmp); |
269 | } | 267 | } |
270 | 268 | ||
271 | return cpuid; | 269 | return cpuid; |
272 | } | 270 | } |
273 | #else | 271 | #else |
274 | #define irq_choose_cpu(virt_irq, affinity) \ | 272 | #define irq_choose_cpu(irq, affinity) \ |
275 | real_hard_smp_processor_id() | 273 | real_hard_smp_processor_id() |
276 | #endif | 274 | #endif |
277 | 275 | ||
278 | static void sun4u_irq_enable(unsigned int virt_irq) | 276 | static void sun4u_irq_enable(struct irq_data *data) |
279 | { | 277 | { |
280 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 278 | struct irq_handler_data *handler_data = data->handler_data; |
281 | 279 | ||
282 | if (likely(data)) { | 280 | if (likely(handler_data)) { |
283 | unsigned long cpuid, imap, val; | 281 | unsigned long cpuid, imap, val; |
284 | unsigned int tid; | 282 | unsigned int tid; |
285 | 283 | ||
286 | cpuid = irq_choose_cpu(virt_irq, | 284 | cpuid = irq_choose_cpu(data->irq, data->affinity); |
287 | irq_desc[virt_irq].affinity); | 285 | imap = handler_data->imap; |
288 | imap = data->imap; | ||
289 | 286 | ||
290 | tid = sun4u_compute_tid(imap, cpuid); | 287 | tid = sun4u_compute_tid(imap, cpuid); |
291 | 288 | ||
@@ -294,21 +291,21 @@ static void sun4u_irq_enable(unsigned int virt_irq) | |||
294 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); | 291 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); |
295 | val |= tid | IMAP_VALID; | 292 | val |= tid | IMAP_VALID; |
296 | upa_writeq(val, imap); | 293 | upa_writeq(val, imap); |
297 | upa_writeq(ICLR_IDLE, data->iclr); | 294 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
298 | } | 295 | } |
299 | } | 296 | } |
300 | 297 | ||
301 | static int sun4u_set_affinity(unsigned int virt_irq, | 298 | static int sun4u_set_affinity(struct irq_data *data, |
302 | const struct cpumask *mask) | 299 | const struct cpumask *mask, bool force) |
303 | { | 300 | { |
304 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 301 | struct irq_handler_data *handler_data = data->handler_data; |
305 | 302 | ||
306 | if (likely(data)) { | 303 | if (likely(handler_data)) { |
307 | unsigned long cpuid, imap, val; | 304 | unsigned long cpuid, imap, val; |
308 | unsigned int tid; | 305 | unsigned int tid; |
309 | 306 | ||
310 | cpuid = irq_choose_cpu(virt_irq, mask); | 307 | cpuid = irq_choose_cpu(data->irq, mask); |
311 | imap = data->imap; | 308 | imap = handler_data->imap; |
312 | 309 | ||
313 | tid = sun4u_compute_tid(imap, cpuid); | 310 | tid = sun4u_compute_tid(imap, cpuid); |
314 | 311 | ||
@@ -317,7 +314,7 @@ static int sun4u_set_affinity(unsigned int virt_irq, | |||
317 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); | 314 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); |
318 | val |= tid | IMAP_VALID; | 315 | val |= tid | IMAP_VALID; |
319 | upa_writeq(val, imap); | 316 | upa_writeq(val, imap); |
320 | upa_writeq(ICLR_IDLE, data->iclr); | 317 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
321 | } | 318 | } |
322 | 319 | ||
323 | return 0; | 320 | return 0; |
@@ -340,27 +337,26 @@ static int sun4u_set_affinity(unsigned int virt_irq, | |||
340 | * sees that, it also hooks up a default ->shutdown method which | 337 | * sees that, it also hooks up a default ->shutdown method which |
341 | * invokes ->mask() which we do not want. See irq_chip_set_defaults(). | 338 | * invokes ->mask() which we do not want. See irq_chip_set_defaults(). |
342 | */ | 339 | */ |
343 | static void sun4u_irq_disable(unsigned int virt_irq) | 340 | static void sun4u_irq_disable(struct irq_data *data) |
344 | { | 341 | { |
345 | } | 342 | } |
346 | 343 | ||
347 | static void sun4u_irq_eoi(unsigned int virt_irq) | 344 | static void sun4u_irq_eoi(struct irq_data *data) |
348 | { | 345 | { |
349 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 346 | struct irq_handler_data *handler_data = data->handler_data; |
350 | struct irq_desc *desc = irq_desc + virt_irq; | 347 | struct irq_desc *desc = irq_desc + data->irq; |
351 | 348 | ||
352 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 349 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
353 | return; | 350 | return; |
354 | 351 | ||
355 | if (likely(data)) | 352 | if (likely(handler_data)) |
356 | upa_writeq(ICLR_IDLE, data->iclr); | 353 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
357 | } | 354 | } |
358 | 355 | ||
359 | static void sun4v_irq_enable(unsigned int virt_irq) | 356 | static void sun4v_irq_enable(struct irq_data *data) |
360 | { | 357 | { |
361 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 358 | unsigned int ino = irq_table[data->irq].dev_ino; |
362 | unsigned long cpuid = irq_choose_cpu(virt_irq, | 359 | unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity); |
363 | irq_desc[virt_irq].affinity); | ||
364 | int err; | 360 | int err; |
365 | 361 | ||
366 | err = sun4v_intr_settarget(ino, cpuid); | 362 | err = sun4v_intr_settarget(ino, cpuid); |
@@ -377,11 +373,11 @@ static void sun4v_irq_enable(unsigned int virt_irq) | |||
377 | ino, err); | 373 | ino, err); |
378 | } | 374 | } |
379 | 375 | ||
380 | static int sun4v_set_affinity(unsigned int virt_irq, | 376 | static int sun4v_set_affinity(struct irq_data *data, |
381 | const struct cpumask *mask) | 377 | const struct cpumask *mask, bool force) |
382 | { | 378 | { |
383 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 379 | unsigned int ino = irq_table[data->irq].dev_ino; |
384 | unsigned long cpuid = irq_choose_cpu(virt_irq, mask); | 380 | unsigned long cpuid = irq_choose_cpu(data->irq, mask); |
385 | int err; | 381 | int err; |
386 | 382 | ||
387 | err = sun4v_intr_settarget(ino, cpuid); | 383 | err = sun4v_intr_settarget(ino, cpuid); |
@@ -392,9 +388,9 @@ static int sun4v_set_affinity(unsigned int virt_irq, | |||
392 | return 0; | 388 | return 0; |
393 | } | 389 | } |
394 | 390 | ||
395 | static void sun4v_irq_disable(unsigned int virt_irq) | 391 | static void sun4v_irq_disable(struct irq_data *data) |
396 | { | 392 | { |
397 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 393 | unsigned int ino = irq_table[data->irq].dev_ino; |
398 | int err; | 394 | int err; |
399 | 395 | ||
400 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); | 396 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); |
@@ -403,10 +399,10 @@ static void sun4v_irq_disable(unsigned int virt_irq) | |||
403 | "err(%d)\n", ino, err); | 399 | "err(%d)\n", ino, err); |
404 | } | 400 | } |
405 | 401 | ||
406 | static void sun4v_irq_eoi(unsigned int virt_irq) | 402 | static void sun4v_irq_eoi(struct irq_data *data) |
407 | { | 403 | { |
408 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 404 | unsigned int ino = irq_table[data->irq].dev_ino; |
409 | struct irq_desc *desc = irq_desc + virt_irq; | 405 | struct irq_desc *desc = irq_desc + data->irq; |
410 | int err; | 406 | int err; |
411 | 407 | ||
412 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 408 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
@@ -418,15 +414,15 @@ static void sun4v_irq_eoi(unsigned int virt_irq) | |||
418 | "err(%d)\n", ino, err); | 414 | "err(%d)\n", ino, err); |
419 | } | 415 | } |
420 | 416 | ||
421 | static void sun4v_virq_enable(unsigned int virt_irq) | 417 | static void sun4v_virq_enable(struct irq_data *data) |
422 | { | 418 | { |
423 | unsigned long cpuid, dev_handle, dev_ino; | 419 | unsigned long cpuid, dev_handle, dev_ino; |
424 | int err; | 420 | int err; |
425 | 421 | ||
426 | cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity); | 422 | cpuid = irq_choose_cpu(data->irq, data->affinity); |
427 | 423 | ||
428 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 424 | dev_handle = irq_table[data->irq].dev_handle; |
429 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 425 | dev_ino = irq_table[data->irq].dev_ino; |
430 | 426 | ||
431 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 427 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
432 | if (err != HV_EOK) | 428 | if (err != HV_EOK) |
@@ -447,16 +443,16 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
447 | dev_handle, dev_ino, err); | 443 | dev_handle, dev_ino, err); |
448 | } | 444 | } |
449 | 445 | ||
450 | static int sun4v_virt_set_affinity(unsigned int virt_irq, | 446 | static int sun4v_virt_set_affinity(struct irq_data *data, |
451 | const struct cpumask *mask) | 447 | const struct cpumask *mask, bool force) |
452 | { | 448 | { |
453 | unsigned long cpuid, dev_handle, dev_ino; | 449 | unsigned long cpuid, dev_handle, dev_ino; |
454 | int err; | 450 | int err; |
455 | 451 | ||
456 | cpuid = irq_choose_cpu(virt_irq, mask); | 452 | cpuid = irq_choose_cpu(data->irq, mask); |
457 | 453 | ||
458 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 454 | dev_handle = irq_table[data->irq].dev_handle; |
459 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 455 | dev_ino = irq_table[data->irq].dev_ino; |
460 | 456 | ||
461 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 457 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
462 | if (err != HV_EOK) | 458 | if (err != HV_EOK) |
@@ -467,13 +463,13 @@ static int sun4v_virt_set_affinity(unsigned int virt_irq, | |||
467 | return 0; | 463 | return 0; |
468 | } | 464 | } |
469 | 465 | ||
470 | static void sun4v_virq_disable(unsigned int virt_irq) | 466 | static void sun4v_virq_disable(struct irq_data *data) |
471 | { | 467 | { |
472 | unsigned long dev_handle, dev_ino; | 468 | unsigned long dev_handle, dev_ino; |
473 | int err; | 469 | int err; |
474 | 470 | ||
475 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 471 | dev_handle = irq_table[data->irq].dev_handle; |
476 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 472 | dev_ino = irq_table[data->irq].dev_ino; |
477 | 473 | ||
478 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 474 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
479 | HV_INTR_DISABLED); | 475 | HV_INTR_DISABLED); |
@@ -483,17 +479,17 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
483 | dev_handle, dev_ino, err); | 479 | dev_handle, dev_ino, err); |
484 | } | 480 | } |
485 | 481 | ||
486 | static void sun4v_virq_eoi(unsigned int virt_irq) | 482 | static void sun4v_virq_eoi(struct irq_data *data) |
487 | { | 483 | { |
488 | struct irq_desc *desc = irq_desc + virt_irq; | 484 | struct irq_desc *desc = irq_desc + data->irq; |
489 | unsigned long dev_handle, dev_ino; | 485 | unsigned long dev_handle, dev_ino; |
490 | int err; | 486 | int err; |
491 | 487 | ||
492 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 488 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
493 | return; | 489 | return; |
494 | 490 | ||
495 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 491 | dev_handle = irq_table[data->irq].dev_handle; |
496 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 492 | dev_ino = irq_table[data->irq].dev_ino; |
497 | 493 | ||
498 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 494 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
499 | HV_INTR_STATE_IDLE); | 495 | HV_INTR_STATE_IDLE); |
@@ -504,50 +500,49 @@ static void sun4v_virq_eoi(unsigned int virt_irq) | |||
504 | } | 500 | } |
505 | 501 | ||
506 | static struct irq_chip sun4u_irq = { | 502 | static struct irq_chip sun4u_irq = { |
507 | .name = "sun4u", | 503 | .name = "sun4u", |
508 | .enable = sun4u_irq_enable, | 504 | .irq_enable = sun4u_irq_enable, |
509 | .disable = sun4u_irq_disable, | 505 | .irq_disable = sun4u_irq_disable, |
510 | .eoi = sun4u_irq_eoi, | 506 | .irq_eoi = sun4u_irq_eoi, |
511 | .set_affinity = sun4u_set_affinity, | 507 | .irq_set_affinity = sun4u_set_affinity, |
512 | }; | 508 | }; |
513 | 509 | ||
514 | static struct irq_chip sun4v_irq = { | 510 | static struct irq_chip sun4v_irq = { |
515 | .name = "sun4v", | 511 | .name = "sun4v", |
516 | .enable = sun4v_irq_enable, | 512 | .irq_enable = sun4v_irq_enable, |
517 | .disable = sun4v_irq_disable, | 513 | .irq_disable = sun4v_irq_disable, |
518 | .eoi = sun4v_irq_eoi, | 514 | .irq_eoi = sun4v_irq_eoi, |
519 | .set_affinity = sun4v_set_affinity, | 515 | .irq_set_affinity = sun4v_set_affinity, |
520 | }; | 516 | }; |
521 | 517 | ||
522 | static struct irq_chip sun4v_virq = { | 518 | static struct irq_chip sun4v_virq = { |
523 | .name = "vsun4v", | 519 | .name = "vsun4v", |
524 | .enable = sun4v_virq_enable, | 520 | .irq_enable = sun4v_virq_enable, |
525 | .disable = sun4v_virq_disable, | 521 | .irq_disable = sun4v_virq_disable, |
526 | .eoi = sun4v_virq_eoi, | 522 | .irq_eoi = sun4v_virq_eoi, |
527 | .set_affinity = sun4v_virt_set_affinity, | 523 | .irq_set_affinity = sun4v_virt_set_affinity, |
528 | }; | 524 | }; |
529 | 525 | ||
530 | static void pre_flow_handler(unsigned int virt_irq, | 526 | static void pre_flow_handler(unsigned int irq, struct irq_desc *desc) |
531 | struct irq_desc *desc) | ||
532 | { | 527 | { |
533 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 528 | struct irq_handler_data *handler_data = get_irq_data(irq); |
534 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 529 | unsigned int ino = irq_table[irq].dev_ino; |
535 | 530 | ||
536 | data->pre_handler(ino, data->arg1, data->arg2); | 531 | handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2); |
537 | 532 | ||
538 | handle_fasteoi_irq(virt_irq, desc); | 533 | handle_fasteoi_irq(irq, desc); |
539 | } | 534 | } |
540 | 535 | ||
541 | void irq_install_pre_handler(int virt_irq, | 536 | void irq_install_pre_handler(int irq, |
542 | void (*func)(unsigned int, void *, void *), | 537 | void (*func)(unsigned int, void *, void *), |
543 | void *arg1, void *arg2) | 538 | void *arg1, void *arg2) |
544 | { | 539 | { |
545 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 540 | struct irq_handler_data *handler_data = get_irq_data(irq); |
546 | struct irq_desc *desc = irq_desc + virt_irq; | 541 | struct irq_desc *desc = irq_desc + irq; |
547 | 542 | ||
548 | data->pre_handler = func; | 543 | handler_data->pre_handler = func; |
549 | data->arg1 = arg1; | 544 | handler_data->arg1 = arg1; |
550 | data->arg2 = arg2; | 545 | handler_data->arg2 = arg2; |
551 | 546 | ||
552 | desc->handle_irq = pre_flow_handler; | 547 | desc->handle_irq = pre_flow_handler; |
553 | } | 548 | } |
@@ -555,81 +550,81 @@ void irq_install_pre_handler(int virt_irq, | |||
555 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) | 550 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) |
556 | { | 551 | { |
557 | struct ino_bucket *bucket; | 552 | struct ino_bucket *bucket; |
558 | struct irq_handler_data *data; | 553 | struct irq_handler_data *handler_data; |
559 | unsigned int virt_irq; | 554 | unsigned int irq; |
560 | int ino; | 555 | int ino; |
561 | 556 | ||
562 | BUG_ON(tlb_type == hypervisor); | 557 | BUG_ON(tlb_type == hypervisor); |
563 | 558 | ||
564 | ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; | 559 | ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; |
565 | bucket = &ivector_table[ino]; | 560 | bucket = &ivector_table[ino]; |
566 | virt_irq = bucket_get_virt_irq(__pa(bucket)); | 561 | irq = bucket_get_irq(__pa(bucket)); |
567 | if (!virt_irq) { | 562 | if (!irq) { |
568 | virt_irq = virt_irq_alloc(0, ino); | 563 | irq = irq_alloc(0, ino); |
569 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 564 | bucket_set_irq(__pa(bucket), irq); |
570 | set_irq_chip_and_handler_name(virt_irq, | 565 | set_irq_chip_and_handler_name(irq, |
571 | &sun4u_irq, | 566 | &sun4u_irq, |
572 | handle_fasteoi_irq, | 567 | handle_fasteoi_irq, |
573 | "IVEC"); | 568 | "IVEC"); |
574 | } | 569 | } |
575 | 570 | ||
576 | data = get_irq_chip_data(virt_irq); | 571 | handler_data = get_irq_data(irq); |
577 | if (unlikely(data)) | 572 | if (unlikely(handler_data)) |
578 | goto out; | 573 | goto out; |
579 | 574 | ||
580 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 575 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
581 | if (unlikely(!data)) { | 576 | if (unlikely(!handler_data)) { |
582 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); | 577 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
583 | prom_halt(); | 578 | prom_halt(); |
584 | } | 579 | } |
585 | set_irq_chip_data(virt_irq, data); | 580 | set_irq_data(irq, handler_data); |
586 | 581 | ||
587 | data->imap = imap; | 582 | handler_data->imap = imap; |
588 | data->iclr = iclr; | 583 | handler_data->iclr = iclr; |
589 | 584 | ||
590 | out: | 585 | out: |
591 | return virt_irq; | 586 | return irq; |
592 | } | 587 | } |
593 | 588 | ||
594 | static unsigned int sun4v_build_common(unsigned long sysino, | 589 | static unsigned int sun4v_build_common(unsigned long sysino, |
595 | struct irq_chip *chip) | 590 | struct irq_chip *chip) |
596 | { | 591 | { |
597 | struct ino_bucket *bucket; | 592 | struct ino_bucket *bucket; |
598 | struct irq_handler_data *data; | 593 | struct irq_handler_data *handler_data; |
599 | unsigned int virt_irq; | 594 | unsigned int irq; |
600 | 595 | ||
601 | BUG_ON(tlb_type != hypervisor); | 596 | BUG_ON(tlb_type != hypervisor); |
602 | 597 | ||
603 | bucket = &ivector_table[sysino]; | 598 | bucket = &ivector_table[sysino]; |
604 | virt_irq = bucket_get_virt_irq(__pa(bucket)); | 599 | irq = bucket_get_irq(__pa(bucket)); |
605 | if (!virt_irq) { | 600 | if (!irq) { |
606 | virt_irq = virt_irq_alloc(0, sysino); | 601 | irq = irq_alloc(0, sysino); |
607 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 602 | bucket_set_irq(__pa(bucket), irq); |
608 | set_irq_chip_and_handler_name(virt_irq, chip, | 603 | set_irq_chip_and_handler_name(irq, chip, |
609 | handle_fasteoi_irq, | 604 | handle_fasteoi_irq, |
610 | "IVEC"); | 605 | "IVEC"); |
611 | } | 606 | } |
612 | 607 | ||
613 | data = get_irq_chip_data(virt_irq); | 608 | handler_data = get_irq_data(irq); |
614 | if (unlikely(data)) | 609 | if (unlikely(handler_data)) |
615 | goto out; | 610 | goto out; |
616 | 611 | ||
617 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 612 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
618 | if (unlikely(!data)) { | 613 | if (unlikely(!handler_data)) { |
619 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); | 614 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
620 | prom_halt(); | 615 | prom_halt(); |
621 | } | 616 | } |
622 | set_irq_chip_data(virt_irq, data); | 617 | set_irq_data(irq, handler_data); |
623 | 618 | ||
624 | /* Catch accidental accesses to these things. IMAP/ICLR handling | 619 | /* Catch accidental accesses to these things. IMAP/ICLR handling |
625 | * is done by hypervisor calls on sun4v platforms, not by direct | 620 | * is done by hypervisor calls on sun4v platforms, not by direct |
626 | * register accesses. | 621 | * register accesses. |
627 | */ | 622 | */ |
628 | data->imap = ~0UL; | 623 | handler_data->imap = ~0UL; |
629 | data->iclr = ~0UL; | 624 | handler_data->iclr = ~0UL; |
630 | 625 | ||
631 | out: | 626 | out: |
632 | return virt_irq; | 627 | return irq; |
633 | } | 628 | } |
634 | 629 | ||
635 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | 630 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) |
@@ -641,11 +636,11 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | |||
641 | 636 | ||
642 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 637 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) |
643 | { | 638 | { |
644 | struct irq_handler_data *data; | 639 | struct irq_handler_data *handler_data; |
645 | unsigned long hv_err, cookie; | 640 | unsigned long hv_err, cookie; |
646 | struct ino_bucket *bucket; | 641 | struct ino_bucket *bucket; |
647 | struct irq_desc *desc; | 642 | struct irq_desc *desc; |
648 | unsigned int virt_irq; | 643 | unsigned int irq; |
649 | 644 | ||
650 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); | 645 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); |
651 | if (unlikely(!bucket)) | 646 | if (unlikely(!bucket)) |
@@ -662,32 +657,32 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
662 | ((unsigned long) bucket + | 657 | ((unsigned long) bucket + |
663 | sizeof(struct ino_bucket))); | 658 | sizeof(struct ino_bucket))); |
664 | 659 | ||
665 | virt_irq = virt_irq_alloc(devhandle, devino); | 660 | irq = irq_alloc(devhandle, devino); |
666 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 661 | bucket_set_irq(__pa(bucket), irq); |
667 | 662 | ||
668 | set_irq_chip_and_handler_name(virt_irq, &sun4v_virq, | 663 | set_irq_chip_and_handler_name(irq, &sun4v_virq, |
669 | handle_fasteoi_irq, | 664 | handle_fasteoi_irq, |
670 | "IVEC"); | 665 | "IVEC"); |
671 | 666 | ||
672 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 667 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
673 | if (unlikely(!data)) | 668 | if (unlikely(!handler_data)) |
674 | return 0; | 669 | return 0; |
675 | 670 | ||
676 | /* In order to make the LDC channel startup sequence easier, | 671 | /* In order to make the LDC channel startup sequence easier, |
677 | * especially wrt. locking, we do not let request_irq() enable | 672 | * especially wrt. locking, we do not let request_irq() enable |
678 | * the interrupt. | 673 | * the interrupt. |
679 | */ | 674 | */ |
680 | desc = irq_desc + virt_irq; | 675 | desc = irq_desc + irq; |
681 | desc->status |= IRQ_NOAUTOEN; | 676 | desc->status |= IRQ_NOAUTOEN; |
682 | 677 | ||
683 | set_irq_chip_data(virt_irq, data); | 678 | set_irq_data(irq, handler_data); |
684 | 679 | ||
685 | /* Catch accidental accesses to these things. IMAP/ICLR handling | 680 | /* Catch accidental accesses to these things. IMAP/ICLR handling |
686 | * is done by hypervisor calls on sun4v platforms, not by direct | 681 | * is done by hypervisor calls on sun4v platforms, not by direct |
687 | * register accesses. | 682 | * register accesses. |
688 | */ | 683 | */ |
689 | data->imap = ~0UL; | 684 | handler_data->imap = ~0UL; |
690 | data->iclr = ~0UL; | 685 | handler_data->iclr = ~0UL; |
691 | 686 | ||
692 | cookie = ~__pa(bucket); | 687 | cookie = ~__pa(bucket); |
693 | hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); | 688 | hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); |
@@ -697,30 +692,30 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
697 | prom_halt(); | 692 | prom_halt(); |
698 | } | 693 | } |
699 | 694 | ||
700 | return virt_irq; | 695 | return irq; |
701 | } | 696 | } |
702 | 697 | ||
703 | void ack_bad_irq(unsigned int virt_irq) | 698 | void ack_bad_irq(unsigned int irq) |
704 | { | 699 | { |
705 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 700 | unsigned int ino = irq_table[irq].dev_ino; |
706 | 701 | ||
707 | if (!ino) | 702 | if (!ino) |
708 | ino = 0xdeadbeef; | 703 | ino = 0xdeadbeef; |
709 | 704 | ||
710 | printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n", | 705 | printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n", |
711 | ino, virt_irq); | 706 | ino, irq); |
712 | } | 707 | } |
713 | 708 | ||
714 | void *hardirq_stack[NR_CPUS]; | 709 | void *hardirq_stack[NR_CPUS]; |
715 | void *softirq_stack[NR_CPUS]; | 710 | void *softirq_stack[NR_CPUS]; |
716 | 711 | ||
717 | void __irq_entry handler_irq(int irq, struct pt_regs *regs) | 712 | void __irq_entry handler_irq(int pil, struct pt_regs *regs) |
718 | { | 713 | { |
719 | unsigned long pstate, bucket_pa; | 714 | unsigned long pstate, bucket_pa; |
720 | struct pt_regs *old_regs; | 715 | struct pt_regs *old_regs; |
721 | void *orig_sp; | 716 | void *orig_sp; |
722 | 717 | ||
723 | clear_softint(1 << irq); | 718 | clear_softint(1 << pil); |
724 | 719 | ||
725 | old_regs = set_irq_regs(regs); | 720 | old_regs = set_irq_regs(regs); |
726 | irq_enter(); | 721 | irq_enter(); |
@@ -741,16 +736,16 @@ void __irq_entry handler_irq(int irq, struct pt_regs *regs) | |||
741 | while (bucket_pa) { | 736 | while (bucket_pa) { |
742 | struct irq_desc *desc; | 737 | struct irq_desc *desc; |
743 | unsigned long next_pa; | 738 | unsigned long next_pa; |
744 | unsigned int virt_irq; | 739 | unsigned int irq; |
745 | 740 | ||
746 | next_pa = bucket_get_chain_pa(bucket_pa); | 741 | next_pa = bucket_get_chain_pa(bucket_pa); |
747 | virt_irq = bucket_get_virt_irq(bucket_pa); | 742 | irq = bucket_get_irq(bucket_pa); |
748 | bucket_clear_chain_pa(bucket_pa); | 743 | bucket_clear_chain_pa(bucket_pa); |
749 | 744 | ||
750 | desc = irq_desc + virt_irq; | 745 | desc = irq_desc + irq; |
751 | 746 | ||
752 | if (!(desc->status & IRQ_DISABLED)) | 747 | if (!(desc->status & IRQ_DISABLED)) |
753 | desc->handle_irq(virt_irq, desc); | 748 | desc->handle_irq(irq, desc); |
754 | 749 | ||
755 | bucket_pa = next_pa; | 750 | bucket_pa = next_pa; |
756 | } | 751 | } |
@@ -798,9 +793,12 @@ void fixup_irqs(void) | |||
798 | raw_spin_lock_irqsave(&irq_desc[irq].lock, flags); | 793 | raw_spin_lock_irqsave(&irq_desc[irq].lock, flags); |
799 | if (irq_desc[irq].action && | 794 | if (irq_desc[irq].action && |
800 | !(irq_desc[irq].status & IRQ_PER_CPU)) { | 795 | !(irq_desc[irq].status & IRQ_PER_CPU)) { |
801 | if (irq_desc[irq].chip->set_affinity) | 796 | struct irq_data *data = irq_get_irq_data(irq); |
802 | irq_desc[irq].chip->set_affinity(irq, | 797 | |
803 | irq_desc[irq].affinity); | 798 | if (data->chip->irq_set_affinity) |
799 | data->chip->irq_set_affinity(data, | ||
800 | data->affinity, | ||
801 | false); | ||
804 | } | 802 | } |
805 | raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags); | 803 | raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags); |
806 | } | 804 | } |
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 15d8a3f645c9..24ad449886be 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #include <linux/interrupt.h> | 4 | #include <linux/interrupt.h> |
5 | 5 | ||
6 | #include <asm/traps.h> | ||
7 | |||
6 | /* cpu.c */ | 8 | /* cpu.c */ |
7 | extern const char *sparc_cpu_type; | 9 | extern const char *sparc_cpu_type; |
8 | extern const char *sparc_pmu_type; | 10 | extern const char *sparc_pmu_type; |
@@ -26,6 +28,53 @@ extern int static_irq_count; | |||
26 | extern spinlock_t irq_action_lock; | 28 | extern spinlock_t irq_action_lock; |
27 | 29 | ||
28 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); | 30 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); |
31 | extern void init_IRQ(void); | ||
32 | |||
33 | /* sun4c_irq.c */ | ||
34 | extern void sun4c_init_IRQ(void); | ||
35 | |||
36 | /* sun4m_irq.c */ | ||
37 | extern unsigned int lvl14_resolution; | ||
38 | |||
39 | extern void sun4m_init_IRQ(void); | ||
40 | extern void sun4m_clear_profile_irq(int cpu); | ||
41 | |||
42 | /* sun4d_irq.c */ | ||
43 | extern spinlock_t sun4d_imsk_lock; | ||
44 | |||
45 | extern void sun4d_init_IRQ(void); | ||
46 | extern int sun4d_request_irq(unsigned int irq, | ||
47 | irq_handler_t handler, | ||
48 | unsigned long irqflags, | ||
49 | const char *devname, void *dev_id); | ||
50 | extern int show_sun4d_interrupts(struct seq_file *, void *); | ||
51 | extern void sun4d_distribute_irqs(void); | ||
52 | extern void sun4d_free_irq(unsigned int irq, void *dev_id); | ||
53 | |||
54 | /* head_32.S */ | ||
55 | extern unsigned int t_nmi[]; | ||
56 | extern unsigned int linux_trap_ipi15_sun4d[]; | ||
57 | extern unsigned int linux_trap_ipi15_sun4m[]; | ||
58 | |||
59 | extern struct tt_entry trapbase_cpu1; | ||
60 | extern struct tt_entry trapbase_cpu2; | ||
61 | extern struct tt_entry trapbase_cpu3; | ||
62 | |||
63 | extern char cputypval[]; | ||
64 | |||
65 | /* entry.S */ | ||
66 | extern unsigned long lvl14_save[4]; | ||
67 | extern unsigned int real_irq_entry[]; | ||
68 | extern unsigned int smp4d_ticker[]; | ||
69 | extern unsigned int patchme_maybe_smp_msg[]; | ||
70 | |||
71 | extern void floppy_hardint(void); | ||
72 | |||
73 | /* trampoline_32.S */ | ||
74 | extern int __smp4m_processor_id(void); | ||
75 | extern int __smp4d_processor_id(void); | ||
76 | extern unsigned long sun4m_cpu_startup; | ||
77 | extern unsigned long sun4d_cpu_startup; | ||
29 | 78 | ||
30 | #else /* CONFIG_SPARC32 */ | 79 | #else /* CONFIG_SPARC32 */ |
31 | #endif /* CONFIG_SPARC32 */ | 80 | #endif /* CONFIG_SPARC32 */ |
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index df39a0f0d27a..732b0bce6001 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c | |||
@@ -790,16 +790,20 @@ static void send_events(struct ldc_channel *lp, unsigned int event_mask) | |||
790 | static irqreturn_t ldc_rx(int irq, void *dev_id) | 790 | static irqreturn_t ldc_rx(int irq, void *dev_id) |
791 | { | 791 | { |
792 | struct ldc_channel *lp = dev_id; | 792 | struct ldc_channel *lp = dev_id; |
793 | unsigned long orig_state, hv_err, flags; | 793 | unsigned long orig_state, flags; |
794 | unsigned int event_mask; | 794 | unsigned int event_mask; |
795 | 795 | ||
796 | spin_lock_irqsave(&lp->lock, flags); | 796 | spin_lock_irqsave(&lp->lock, flags); |
797 | 797 | ||
798 | orig_state = lp->chan_state; | 798 | orig_state = lp->chan_state; |
799 | hv_err = sun4v_ldc_rx_get_state(lp->id, | 799 | |
800 | &lp->rx_head, | 800 | /* We should probably check for hypervisor errors here and |
801 | &lp->rx_tail, | 801 | * reset the LDC channel if we get one. |
802 | &lp->chan_state); | 802 | */ |
803 | sun4v_ldc_rx_get_state(lp->id, | ||
804 | &lp->rx_head, | ||
805 | &lp->rx_tail, | ||
806 | &lp->chan_state); | ||
803 | 807 | ||
804 | ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", | 808 | ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", |
805 | orig_state, lp->chan_state, lp->rx_head, lp->rx_tail); | 809 | orig_state, lp->chan_state, lp->rx_head, lp->rx_tail); |
@@ -904,16 +908,20 @@ out: | |||
904 | static irqreturn_t ldc_tx(int irq, void *dev_id) | 908 | static irqreturn_t ldc_tx(int irq, void *dev_id) |
905 | { | 909 | { |
906 | struct ldc_channel *lp = dev_id; | 910 | struct ldc_channel *lp = dev_id; |
907 | unsigned long flags, hv_err, orig_state; | 911 | unsigned long flags, orig_state; |
908 | unsigned int event_mask = 0; | 912 | unsigned int event_mask = 0; |
909 | 913 | ||
910 | spin_lock_irqsave(&lp->lock, flags); | 914 | spin_lock_irqsave(&lp->lock, flags); |
911 | 915 | ||
912 | orig_state = lp->chan_state; | 916 | orig_state = lp->chan_state; |
913 | hv_err = sun4v_ldc_tx_get_state(lp->id, | 917 | |
914 | &lp->tx_head, | 918 | /* We should probably check for hypervisor errors here and |
915 | &lp->tx_tail, | 919 | * reset the LDC channel if we get one. |
916 | &lp->chan_state); | 920 | */ |
921 | sun4v_ldc_tx_get_state(lp->id, | ||
922 | &lp->tx_head, | ||
923 | &lp->tx_tail, | ||
924 | &lp->chan_state); | ||
917 | 925 | ||
918 | ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", | 926 | ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", |
919 | orig_state, lp->chan_state, lp->tx_head, lp->tx_tail); | 927 | orig_state, lp->chan_state, lp->tx_head, lp->tx_tail); |
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index fdab7f854f80..2969f777fa11 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -30,6 +30,7 @@ struct amba_apb_device leon_percpu_timer_dev[16]; | |||
30 | int leondebug_irq_disable; | 30 | int leondebug_irq_disable; |
31 | int leon_debug_irqout; | 31 | int leon_debug_irqout; |
32 | static int dummy_master_l10_counter; | 32 | static int dummy_master_l10_counter; |
33 | unsigned long amba_system_id; | ||
33 | 34 | ||
34 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ | 35 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
35 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | 36 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ |
@@ -117,10 +118,16 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
117 | master_l10_counter = (unsigned int *)&dummy_master_l10_counter; | 118 | master_l10_counter = (unsigned int *)&dummy_master_l10_counter; |
118 | dummy_master_l10_counter = 0; | 119 | dummy_master_l10_counter = 0; |
119 | 120 | ||
120 | /*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/ | ||
121 | rootnp = of_find_node_by_path("/ambapp0"); | 121 | rootnp = of_find_node_by_path("/ambapp0"); |
122 | if (!rootnp) | 122 | if (!rootnp) |
123 | goto bad; | 123 | goto bad; |
124 | |||
125 | /* Find System ID: GRLIB build ID and optional CHIP ID */ | ||
126 | pp = of_find_property(rootnp, "systemid", &len); | ||
127 | if (pp) | ||
128 | amba_system_id = *(unsigned long *)pp->value; | ||
129 | |||
130 | /* Find IRQMP IRQ Controller Registers base adr otherwise bail out */ | ||
124 | np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); | 131 | np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); |
125 | if (!np) { | 132 | if (!np) { |
126 | np = of_find_node_by_name(rootnp, "01_00d"); | 133 | np = of_find_node_by_name(rootnp, "01_00d"); |
@@ -340,7 +347,7 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) | |||
340 | 347 | ||
341 | void __init leon_init_IRQ(void) | 348 | void __init leon_init_IRQ(void) |
342 | { | 349 | { |
343 | sparc_init_timers = leon_init_timers; | 350 | sparc_irq_config.init_timers = leon_init_timers; |
344 | 351 | ||
345 | BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM); | 352 | BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM); |
346 | BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM); | 353 | BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM); |
diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c new file mode 100644 index 000000000000..519ca923f59f --- /dev/null +++ b/arch/sparc/kernel/leon_pmc.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* leon_pmc.c: LEON Power-down cpu_idle() handler | ||
2 | * | ||
3 | * Copyright (C) 2011 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB | ||
4 | */ | ||
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/pm.h> | ||
8 | |||
9 | #include <asm/leon_amba.h> | ||
10 | #include <asm/leon.h> | ||
11 | |||
12 | /* List of Systems that need fixup instructions around power-down instruction */ | ||
13 | unsigned int pmc_leon_fixup_ids[] = { | ||
14 | AEROFLEX_UT699, | ||
15 | GAISLER_GR712RC, | ||
16 | LEON4_NEXTREME1, | ||
17 | 0 | ||
18 | }; | ||
19 | |||
20 | int pmc_leon_need_fixup(void) | ||
21 | { | ||
22 | unsigned int systemid = amba_system_id >> 16; | ||
23 | unsigned int *id; | ||
24 | |||
25 | id = &pmc_leon_fixup_ids[0]; | ||
26 | while (*id != 0) { | ||
27 | if (*id == systemid) | ||
28 | return 1; | ||
29 | id++; | ||
30 | } | ||
31 | |||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * CPU idle callback function for systems that need some extra handling | ||
37 | * See .../arch/sparc/kernel/process.c | ||
38 | */ | ||
39 | void pmc_leon_idle_fixup(void) | ||
40 | { | ||
41 | /* Prepare an address to a non-cachable region. APB is always | ||
42 | * none-cachable. One instruction is executed after the Sleep | ||
43 | * instruction, we make sure to read the bus and throw away the | ||
44 | * value by accessing a non-cachable area, also we make sure the | ||
45 | * MMU does not get a TLB miss here by using the MMU BYPASS ASI. | ||
46 | */ | ||
47 | register unsigned int address = (unsigned int)leon3_irqctrl_regs; | ||
48 | __asm__ __volatile__ ( | ||
49 | "mov %%g0, %%asr19\n" | ||
50 | "lda [%0] %1, %%g0\n" | ||
51 | : | ||
52 | : "r"(address), "i"(ASI_LEON_BYPASS)); | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * CPU idle callback function | ||
57 | * See .../arch/sparc/kernel/process.c | ||
58 | */ | ||
59 | void pmc_leon_idle(void) | ||
60 | { | ||
61 | /* For systems without power-down, this will be no-op */ | ||
62 | __asm__ __volatile__ ("mov %g0, %asr19\n\t"); | ||
63 | } | ||
64 | |||
65 | /* Install LEON Power Down function */ | ||
66 | static int __init leon_pmc_install(void) | ||
67 | { | ||
68 | /* Assign power management IDLE handler */ | ||
69 | if (pmc_leon_need_fixup()) | ||
70 | pm_idle = pmc_leon_idle_fixup; | ||
71 | else | ||
72 | pm_idle = pmc_leon_idle; | ||
73 | |||
74 | printk(KERN_INFO "leon: power management initialized\n"); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | /* This driver is not critical to the boot process, don't care | ||
80 | * if initialized late. | ||
81 | */ | ||
82 | late_initcall(leon_pmc_install); | ||
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 16582d85368a..8f5de4aa3c0a 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #include <asm/leon.h> | 41 | #include <asm/leon.h> |
42 | #include <asm/leon_amba.h> | 42 | #include <asm/leon_amba.h> |
43 | 43 | ||
44 | #include "kernel.h" | ||
45 | |||
44 | #ifdef CONFIG_SPARC_LEON | 46 | #ifdef CONFIG_SPARC_LEON |
45 | 47 | ||
46 | #include "irq.h" | 48 | #include "irq.h" |
@@ -261,23 +263,23 @@ void __init leon_smp_done(void) | |||
261 | 263 | ||
262 | /* Free unneeded trap tables */ | 264 | /* Free unneeded trap tables */ |
263 | if (!cpu_isset(1, cpu_present_map)) { | 265 | if (!cpu_isset(1, cpu_present_map)) { |
264 | ClearPageReserved(virt_to_page(trapbase_cpu1)); | 266 | ClearPageReserved(virt_to_page(&trapbase_cpu1)); |
265 | init_page_count(virt_to_page(trapbase_cpu1)); | 267 | init_page_count(virt_to_page(&trapbase_cpu1)); |
266 | free_page((unsigned long)trapbase_cpu1); | 268 | free_page((unsigned long)&trapbase_cpu1); |
267 | totalram_pages++; | 269 | totalram_pages++; |
268 | num_physpages++; | 270 | num_physpages++; |
269 | } | 271 | } |
270 | if (!cpu_isset(2, cpu_present_map)) { | 272 | if (!cpu_isset(2, cpu_present_map)) { |
271 | ClearPageReserved(virt_to_page(trapbase_cpu2)); | 273 | ClearPageReserved(virt_to_page(&trapbase_cpu2)); |
272 | init_page_count(virt_to_page(trapbase_cpu2)); | 274 | init_page_count(virt_to_page(&trapbase_cpu2)); |
273 | free_page((unsigned long)trapbase_cpu2); | 275 | free_page((unsigned long)&trapbase_cpu2); |
274 | totalram_pages++; | 276 | totalram_pages++; |
275 | num_physpages++; | 277 | num_physpages++; |
276 | } | 278 | } |
277 | if (!cpu_isset(3, cpu_present_map)) { | 279 | if (!cpu_isset(3, cpu_present_map)) { |
278 | ClearPageReserved(virt_to_page(trapbase_cpu3)); | 280 | ClearPageReserved(virt_to_page(&trapbase_cpu3)); |
279 | init_page_count(virt_to_page(trapbase_cpu3)); | 281 | init_page_count(virt_to_page(&trapbase_cpu3)); |
280 | free_page((unsigned long)trapbase_cpu3); | 282 | free_page((unsigned long)&trapbase_cpu3); |
281 | totalram_pages++; | 283 | totalram_pages++; |
282 | num_physpages++; | 284 | num_physpages++; |
283 | } | 285 | } |
@@ -437,15 +439,6 @@ void __init leon_blackbox_current(unsigned *addr) | |||
437 | 439 | ||
438 | } | 440 | } |
439 | 441 | ||
440 | /* | ||
441 | * CPU idle callback function | ||
442 | * See .../arch/sparc/kernel/process.c | ||
443 | */ | ||
444 | void pmc_leon_idle(void) | ||
445 | { | ||
446 | __asm__ volatile ("mov %g0, %asr19"); | ||
447 | } | ||
448 | |||
449 | void __init leon_init_smp(void) | 442 | void __init leon_init_smp(void) |
450 | { | 443 | { |
451 | /* Patch ipi15 trap table */ | 444 | /* Patch ipi15 trap table */ |
@@ -456,13 +449,6 @@ void __init leon_init_smp(void) | |||
456 | BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); | 449 | BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); |
457 | BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, | 450 | BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, |
458 | BTFIXUPCALL_NORM); | 451 | BTFIXUPCALL_NORM); |
459 | |||
460 | #ifndef PMC_NO_IDLE | ||
461 | /* Assign power management IDLE handler */ | ||
462 | pm_idle = pmc_leon_idle; | ||
463 | printk(KERN_INFO "leon: power management initialized\n"); | ||
464 | #endif | ||
465 | |||
466 | } | 452 | } |
467 | 453 | ||
468 | #endif /* CONFIG_SPARC_LEON */ | 454 | #endif /* CONFIG_SPARC_LEON */ |
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c index 2d055a1e9cc2..a312af40ea84 100644 --- a/arch/sparc/kernel/of_device_32.c +++ b/arch/sparc/kernel/of_device_32.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/leon_amba.h> | 13 | #include <asm/leon_amba.h> |
14 | 14 | ||
15 | #include "of_device_common.h" | 15 | #include "of_device_common.h" |
16 | #include "irq.h" | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * PCI bus specific translator | 19 | * PCI bus specific translator |
@@ -355,7 +356,8 @@ static struct platform_device * __init scan_one_device(struct device_node *dp, | |||
355 | if (intr) { | 356 | if (intr) { |
356 | op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); | 357 | op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs); |
357 | for (i = 0; i < op->archdata.num_irqs; i++) | 358 | for (i = 0; i < op->archdata.num_irqs; i++) |
358 | op->archdata.irqs[i] = intr[i].pri; | 359 | op->archdata.irqs[i] = |
360 | sparc_irq_config.build_device_irq(op, intr[i].pri); | ||
359 | } else { | 361 | } else { |
360 | const unsigned int *irq = | 362 | const unsigned int *irq = |
361 | of_get_property(dp, "interrupts", &len); | 363 | of_get_property(dp, "interrupts", &len); |
@@ -363,64 +365,13 @@ static struct platform_device * __init scan_one_device(struct device_node *dp, | |||
363 | if (irq) { | 365 | if (irq) { |
364 | op->archdata.num_irqs = len / sizeof(unsigned int); | 366 | op->archdata.num_irqs = len / sizeof(unsigned int); |
365 | for (i = 0; i < op->archdata.num_irqs; i++) | 367 | for (i = 0; i < op->archdata.num_irqs; i++) |
366 | op->archdata.irqs[i] = irq[i]; | 368 | op->archdata.irqs[i] = |
369 | sparc_irq_config.build_device_irq(op, irq[i]); | ||
367 | } else { | 370 | } else { |
368 | op->archdata.num_irqs = 0; | 371 | op->archdata.num_irqs = 0; |
369 | } | 372 | } |
370 | } | 373 | } |
371 | if (sparc_cpu_model == sun4d) { | ||
372 | static int pil_to_sbus[] = { | ||
373 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | ||
374 | }; | ||
375 | struct device_node *io_unit, *sbi = dp->parent; | ||
376 | const struct linux_prom_registers *regs; | ||
377 | int board, slot; | ||
378 | |||
379 | while (sbi) { | ||
380 | if (!strcmp(sbi->name, "sbi")) | ||
381 | break; | ||
382 | |||
383 | sbi = sbi->parent; | ||
384 | } | ||
385 | if (!sbi) | ||
386 | goto build_resources; | ||
387 | |||
388 | regs = of_get_property(dp, "reg", NULL); | ||
389 | if (!regs) | ||
390 | goto build_resources; | ||
391 | |||
392 | slot = regs->which_io; | ||
393 | |||
394 | /* If SBI's parent is not io-unit or the io-unit lacks | ||
395 | * a "board#" property, something is very wrong. | ||
396 | */ | ||
397 | if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { | ||
398 | printk("%s: Error, parent is not io-unit.\n", | ||
399 | sbi->full_name); | ||
400 | goto build_resources; | ||
401 | } | ||
402 | io_unit = sbi->parent; | ||
403 | board = of_getintprop_default(io_unit, "board#", -1); | ||
404 | if (board == -1) { | ||
405 | printk("%s: Error, lacks board# property.\n", | ||
406 | io_unit->full_name); | ||
407 | goto build_resources; | ||
408 | } | ||
409 | |||
410 | for (i = 0; i < op->archdata.num_irqs; i++) { | ||
411 | int this_irq = op->archdata.irqs[i]; | ||
412 | int sbusl = pil_to_sbus[this_irq]; | ||
413 | |||
414 | if (sbusl) | ||
415 | this_irq = (((board + 1) << 5) + | ||
416 | (sbusl << 2) + | ||
417 | slot); | ||
418 | |||
419 | op->archdata.irqs[i] = this_irq; | ||
420 | } | ||
421 | } | ||
422 | 374 | ||
423 | build_resources: | ||
424 | build_device_resources(op, parent); | 375 | build_device_resources(op, parent); |
425 | 376 | ||
426 | op->dev.parent = parent; | 377 | op->dev.parent = parent; |
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 4137579d9adc..44f41e312f73 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c | |||
@@ -675,6 +675,7 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) | |||
675 | * humanoid. | 675 | * humanoid. |
676 | */ | 676 | */ |
677 | err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); | 677 | err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); |
678 | (void) err; | ||
678 | } | 679 | } |
679 | list_for_each_entry(child_bus, &bus->children, node) | 680 | list_for_each_entry(child_bus, &bus->children, node) |
680 | pci_bus_register_of_sysfs(child_bus); | 681 | pci_bus_register_of_sysfs(child_bus); |
@@ -1001,22 +1002,22 @@ EXPORT_SYMBOL(pci_domain_nr); | |||
1001 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | 1002 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
1002 | { | 1003 | { |
1003 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1004 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1004 | unsigned int virt_irq; | 1005 | unsigned int irq; |
1005 | 1006 | ||
1006 | if (!pbm->setup_msi_irq) | 1007 | if (!pbm->setup_msi_irq) |
1007 | return -EINVAL; | 1008 | return -EINVAL; |
1008 | 1009 | ||
1009 | return pbm->setup_msi_irq(&virt_irq, pdev, desc); | 1010 | return pbm->setup_msi_irq(&irq, pdev, desc); |
1010 | } | 1011 | } |
1011 | 1012 | ||
1012 | void arch_teardown_msi_irq(unsigned int virt_irq) | 1013 | void arch_teardown_msi_irq(unsigned int irq) |
1013 | { | 1014 | { |
1014 | struct msi_desc *entry = get_irq_msi(virt_irq); | 1015 | struct msi_desc *entry = get_irq_msi(irq); |
1015 | struct pci_dev *pdev = entry->dev; | 1016 | struct pci_dev *pdev = entry->dev; |
1016 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1017 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1017 | 1018 | ||
1018 | if (pbm->teardown_msi_irq) | 1019 | if (pbm->teardown_msi_irq) |
1019 | pbm->teardown_msi_irq(virt_irq, pdev); | 1020 | pbm->teardown_msi_irq(irq, pdev); |
1020 | } | 1021 | } |
1021 | #endif /* !(CONFIG_PCI_MSI) */ | 1022 | #endif /* !(CONFIG_PCI_MSI) */ |
1022 | 1023 | ||
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index 6c7a33af3ba6..6e3874b64488 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c | |||
@@ -295,14 +295,17 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
295 | unsigned int bus = bus_dev->number; | 295 | unsigned int bus = bus_dev->number; |
296 | unsigned int device = PCI_SLOT(devfn); | 296 | unsigned int device = PCI_SLOT(devfn); |
297 | unsigned int func = PCI_FUNC(devfn); | 297 | unsigned int func = PCI_FUNC(devfn); |
298 | unsigned long ret; | ||
299 | 298 | ||
300 | if (config_out_of_range(pbm, bus, devfn, where)) { | 299 | if (config_out_of_range(pbm, bus, devfn, where)) { |
301 | /* Do nothing. */ | 300 | /* Do nothing. */ |
302 | } else { | 301 | } else { |
303 | ret = pci_sun4v_config_put(devhandle, | 302 | /* We don't check for hypervisor errors here, but perhaps |
304 | HV_PCI_DEVICE_BUILD(bus, device, func), | 303 | * we should and influence our return value depending upon |
305 | where, size, value); | 304 | * what kind of error is thrown. |
305 | */ | ||
306 | pci_sun4v_config_put(devhandle, | ||
307 | HV_PCI_DEVICE_BUILD(bus, device, func), | ||
308 | where, size, value); | ||
306 | } | 309 | } |
307 | return PCIBIOS_SUCCESSFUL; | 310 | return PCIBIOS_SUCCESSFUL; |
308 | } | 311 | } |
diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c index be5e2441c6d7..3d70f8326efd 100644 --- a/arch/sparc/kernel/pci_fire.c +++ b/arch/sparc/kernel/pci_fire.c | |||
@@ -214,11 +214,9 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
214 | 214 | ||
215 | static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) | 215 | static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) |
216 | { | 216 | { |
217 | unsigned long msiqid; | ||
218 | u64 val; | 217 | u64 val; |
219 | 218 | ||
220 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); | 219 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
221 | msiqid = (val & MSI_MAP_EQNUM); | ||
222 | 220 | ||
223 | val &= ~MSI_MAP_VALID; | 221 | val &= ~MSI_MAP_VALID; |
224 | 222 | ||
@@ -277,7 +275,7 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
277 | { | 275 | { |
278 | unsigned long cregs = (unsigned long) pbm->pbm_regs; | 276 | unsigned long cregs = (unsigned long) pbm->pbm_regs; |
279 | unsigned long imap_reg, iclr_reg, int_ctrlr; | 277 | unsigned long imap_reg, iclr_reg, int_ctrlr; |
280 | unsigned int virt_irq; | 278 | unsigned int irq; |
281 | int fixup; | 279 | int fixup; |
282 | u64 val; | 280 | u64 val; |
283 | 281 | ||
@@ -293,14 +291,14 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
293 | 291 | ||
294 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; | 292 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; |
295 | 293 | ||
296 | virt_irq = build_irq(fixup, iclr_reg, imap_reg); | 294 | irq = build_irq(fixup, iclr_reg, imap_reg); |
297 | if (!virt_irq) | 295 | if (!irq) |
298 | return -ENOMEM; | 296 | return -ENOMEM; |
299 | 297 | ||
300 | upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, | 298 | upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, |
301 | pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); | 299 | pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); |
302 | 300 | ||
303 | return virt_irq; | 301 | return irq; |
304 | } | 302 | } |
305 | 303 | ||
306 | static const struct sparc64_msiq_ops pci_fire_msiq_ops = { | 304 | static const struct sparc64_msiq_ops pci_fire_msiq_ops = { |
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index e20ed5f06e9c..6beb60df31d0 100644 --- a/arch/sparc/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h | |||
@@ -131,9 +131,9 @@ struct pci_pbm_info { | |||
131 | void *msi_queues; | 131 | void *msi_queues; |
132 | unsigned long *msi_bitmap; | 132 | unsigned long *msi_bitmap; |
133 | unsigned int *msi_irq_table; | 133 | unsigned int *msi_irq_table; |
134 | int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, | 134 | int (*setup_msi_irq)(unsigned int *irq_p, struct pci_dev *pdev, |
135 | struct msi_desc *entry); | 135 | struct msi_desc *entry); |
136 | void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); | 136 | void (*teardown_msi_irq)(unsigned int irq, struct pci_dev *pdev); |
137 | const struct sparc64_msiq_ops *msi_ops; | 137 | const struct sparc64_msiq_ops *msi_ops; |
138 | #endif /* !(CONFIG_PCI_MSI) */ | 138 | #endif /* !(CONFIG_PCI_MSI) */ |
139 | 139 | ||
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c index b210416ace7b..550e937720e7 100644 --- a/arch/sparc/kernel/pci_msi.c +++ b/arch/sparc/kernel/pci_msi.c | |||
@@ -31,12 +31,12 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie) | |||
31 | err = ops->dequeue_msi(pbm, msiqid, &head, &msi); | 31 | err = ops->dequeue_msi(pbm, msiqid, &head, &msi); |
32 | if (likely(err > 0)) { | 32 | if (likely(err > 0)) { |
33 | struct irq_desc *desc; | 33 | struct irq_desc *desc; |
34 | unsigned int virt_irq; | 34 | unsigned int irq; |
35 | 35 | ||
36 | virt_irq = pbm->msi_irq_table[msi - pbm->msi_first]; | 36 | irq = pbm->msi_irq_table[msi - pbm->msi_first]; |
37 | desc = irq_desc + virt_irq; | 37 | desc = irq_desc + irq; |
38 | 38 | ||
39 | desc->handle_irq(virt_irq, desc); | 39 | desc->handle_irq(irq, desc); |
40 | } | 40 | } |
41 | 41 | ||
42 | if (unlikely(err < 0)) | 42 | if (unlikely(err < 0)) |
@@ -121,7 +121,7 @@ static struct irq_chip msi_irq = { | |||
121 | /* XXX affinity XXX */ | 121 | /* XXX affinity XXX */ |
122 | }; | 122 | }; |
123 | 123 | ||
124 | static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | 124 | static int sparc64_setup_msi_irq(unsigned int *irq_p, |
125 | struct pci_dev *pdev, | 125 | struct pci_dev *pdev, |
126 | struct msi_desc *entry) | 126 | struct msi_desc *entry) |
127 | { | 127 | { |
@@ -131,17 +131,17 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
131 | int msi, err; | 131 | int msi, err; |
132 | u32 msiqid; | 132 | u32 msiqid; |
133 | 133 | ||
134 | *virt_irq_p = virt_irq_alloc(0, 0); | 134 | *irq_p = irq_alloc(0, 0); |
135 | err = -ENOMEM; | 135 | err = -ENOMEM; |
136 | if (!*virt_irq_p) | 136 | if (!*irq_p) |
137 | goto out_err; | 137 | goto out_err; |
138 | 138 | ||
139 | set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq, | 139 | set_irq_chip_and_handler_name(*irq_p, &msi_irq, |
140 | handle_simple_irq, "MSI"); | 140 | handle_simple_irq, "MSI"); |
141 | 141 | ||
142 | err = alloc_msi(pbm); | 142 | err = alloc_msi(pbm); |
143 | if (unlikely(err < 0)) | 143 | if (unlikely(err < 0)) |
144 | goto out_virt_irq_free; | 144 | goto out_irq_free; |
145 | 145 | ||
146 | msi = err; | 146 | msi = err; |
147 | 147 | ||
@@ -152,7 +152,7 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
152 | if (err) | 152 | if (err) |
153 | goto out_msi_free; | 153 | goto out_msi_free; |
154 | 154 | ||
155 | pbm->msi_irq_table[msi - pbm->msi_first] = *virt_irq_p; | 155 | pbm->msi_irq_table[msi - pbm->msi_first] = *irq_p; |
156 | 156 | ||
157 | if (entry->msi_attrib.is_64) { | 157 | if (entry->msi_attrib.is_64) { |
158 | msg.address_hi = pbm->msi64_start >> 32; | 158 | msg.address_hi = pbm->msi64_start >> 32; |
@@ -163,24 +163,24 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
163 | } | 163 | } |
164 | msg.data = msi; | 164 | msg.data = msi; |
165 | 165 | ||
166 | set_irq_msi(*virt_irq_p, entry); | 166 | set_irq_msi(*irq_p, entry); |
167 | write_msi_msg(*virt_irq_p, &msg); | 167 | write_msi_msg(*irq_p, &msg); |
168 | 168 | ||
169 | return 0; | 169 | return 0; |
170 | 170 | ||
171 | out_msi_free: | 171 | out_msi_free: |
172 | free_msi(pbm, msi); | 172 | free_msi(pbm, msi); |
173 | 173 | ||
174 | out_virt_irq_free: | 174 | out_irq_free: |
175 | set_irq_chip(*virt_irq_p, NULL); | 175 | set_irq_chip(*irq_p, NULL); |
176 | virt_irq_free(*virt_irq_p); | 176 | irq_free(*irq_p); |
177 | *virt_irq_p = 0; | 177 | *irq_p = 0; |
178 | 178 | ||
179 | out_err: | 179 | out_err: |
180 | return err; | 180 | return err; |
181 | } | 181 | } |
182 | 182 | ||
183 | static void sparc64_teardown_msi_irq(unsigned int virt_irq, | 183 | static void sparc64_teardown_msi_irq(unsigned int irq, |
184 | struct pci_dev *pdev) | 184 | struct pci_dev *pdev) |
185 | { | 185 | { |
186 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 186 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
@@ -189,12 +189,12 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq, | |||
189 | int i, err; | 189 | int i, err; |
190 | 190 | ||
191 | for (i = 0; i < pbm->msi_num; i++) { | 191 | for (i = 0; i < pbm->msi_num; i++) { |
192 | if (pbm->msi_irq_table[i] == virt_irq) | 192 | if (pbm->msi_irq_table[i] == irq) |
193 | break; | 193 | break; |
194 | } | 194 | } |
195 | if (i >= pbm->msi_num) { | 195 | if (i >= pbm->msi_num) { |
196 | printk(KERN_ERR "%s: teardown: No MSI for irq %u\n", | 196 | printk(KERN_ERR "%s: teardown: No MSI for irq %u\n", |
197 | pbm->name, virt_irq); | 197 | pbm->name, irq); |
198 | return; | 198 | return; |
199 | } | 199 | } |
200 | 200 | ||
@@ -205,14 +205,14 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq, | |||
205 | if (err) { | 205 | if (err) { |
206 | printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, " | 206 | printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, " |
207 | "irq %u, gives error %d\n", | 207 | "irq %u, gives error %d\n", |
208 | pbm->name, msi_num, virt_irq, err); | 208 | pbm->name, msi_num, irq, err); |
209 | return; | 209 | return; |
210 | } | 210 | } |
211 | 211 | ||
212 | free_msi(pbm, msi_num); | 212 | free_msi(pbm, msi_num); |
213 | 213 | ||
214 | set_irq_chip(virt_irq, NULL); | 214 | set_irq_chip(irq, NULL); |
215 | virt_irq_free(virt_irq); | 215 | irq_free(irq); |
216 | } | 216 | } |
217 | 217 | ||
218 | static int msi_bitmap_alloc(struct pci_pbm_info *pbm) | 218 | static int msi_bitmap_alloc(struct pci_pbm_info *pbm) |
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 6783410ceb02..1d41af73a92f 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c | |||
@@ -1313,7 +1313,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, | |||
1313 | const struct linux_prom64_registers *regs; | 1313 | const struct linux_prom64_registers *regs; |
1314 | struct device_node *dp = op->dev.of_node; | 1314 | struct device_node *dp = op->dev.of_node; |
1315 | const char *chipset_name; | 1315 | const char *chipset_name; |
1316 | int is_pbm_a, err; | 1316 | int err; |
1317 | 1317 | ||
1318 | switch (chip_type) { | 1318 | switch (chip_type) { |
1319 | case PBM_CHIP_TYPE_TOMATILLO: | 1319 | case PBM_CHIP_TYPE_TOMATILLO: |
@@ -1343,8 +1343,6 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, | |||
1343 | */ | 1343 | */ |
1344 | regs = of_get_property(dp, "reg", NULL); | 1344 | regs = of_get_property(dp, "reg", NULL); |
1345 | 1345 | ||
1346 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); | ||
1347 | |||
1348 | pbm->next = pci_pbm_root; | 1346 | pbm->next = pci_pbm_root; |
1349 | pci_pbm_root = pbm; | 1347 | pci_pbm_root = pbm; |
1350 | 1348 | ||
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 158cd739b263..6cf534681788 100644 --- a/arch/sparc/kernel/pci_sun4v.c +++ b/arch/sparc/kernel/pci_sun4v.c | |||
@@ -580,7 +580,7 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
580 | { | 580 | { |
581 | static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; | 581 | static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; |
582 | struct iommu *iommu = pbm->iommu; | 582 | struct iommu *iommu = pbm->iommu; |
583 | unsigned long num_tsb_entries, sz, tsbsize; | 583 | unsigned long num_tsb_entries, sz; |
584 | u32 dma_mask, dma_offset; | 584 | u32 dma_mask, dma_offset; |
585 | const u32 *vdma; | 585 | const u32 *vdma; |
586 | 586 | ||
@@ -596,7 +596,6 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
596 | 596 | ||
597 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); | 597 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); |
598 | num_tsb_entries = vdma[1] / IO_PAGE_SIZE; | 598 | num_tsb_entries = vdma[1] / IO_PAGE_SIZE; |
599 | tsbsize = num_tsb_entries * sizeof(iopte_t); | ||
600 | 599 | ||
601 | dma_offset = vdma[0]; | 600 | dma_offset = vdma[0]; |
602 | 601 | ||
@@ -844,9 +843,9 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm, | |||
844 | unsigned long msiqid, | 843 | unsigned long msiqid, |
845 | unsigned long devino) | 844 | unsigned long devino) |
846 | { | 845 | { |
847 | unsigned int virt_irq = sun4v_build_irq(pbm->devhandle, devino); | 846 | unsigned int irq = sun4v_build_irq(pbm->devhandle, devino); |
848 | 847 | ||
849 | if (!virt_irq) | 848 | if (!irq) |
850 | return -ENOMEM; | 849 | return -ENOMEM; |
851 | 850 | ||
852 | if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) | 851 | if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) |
@@ -854,7 +853,7 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm, | |||
854 | if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) | 853 | if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) |
855 | return -EINVAL; | 854 | return -EINVAL; |
856 | 855 | ||
857 | return virt_irq; | 856 | return irq; |
858 | } | 857 | } |
859 | 858 | ||
860 | static const struct sparc64_msiq_ops pci_sun4v_msiq_ops = { | 859 | static const struct sparc64_msiq_ops pci_sun4v_msiq_ops = { |
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index 7c2ced612b8f..8ac23e660080 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c | |||
@@ -81,7 +81,7 @@ static void n2_pcr_write(u64 val) | |||
81 | unsigned long ret; | 81 | unsigned long ret; |
82 | 82 | ||
83 | ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); | 83 | ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); |
84 | if (val != HV_EOK) | 84 | if (ret != HV_EOK) |
85 | write_pcr(val); | 85 | write_pcr(val); |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/arch/sparc/kernel/prom_irqtrans.c b/arch/sparc/kernel/prom_irqtrans.c index ce651147fabc..570b98f6e897 100644 --- a/arch/sparc/kernel/prom_irqtrans.c +++ b/arch/sparc/kernel/prom_irqtrans.c | |||
@@ -227,7 +227,7 @@ static unsigned int sabre_irq_build(struct device_node *dp, | |||
227 | unsigned long imap, iclr; | 227 | unsigned long imap, iclr; |
228 | unsigned long imap_off, iclr_off; | 228 | unsigned long imap_off, iclr_off; |
229 | int inofixup = 0; | 229 | int inofixup = 0; |
230 | int virt_irq; | 230 | int irq; |
231 | 231 | ||
232 | ino &= 0x3f; | 232 | ino &= 0x3f; |
233 | if (ino < SABRE_ONBOARD_IRQ_BASE) { | 233 | if (ino < SABRE_ONBOARD_IRQ_BASE) { |
@@ -247,7 +247,7 @@ static unsigned int sabre_irq_build(struct device_node *dp, | |||
247 | if ((ino & 0x20) == 0) | 247 | if ((ino & 0x20) == 0) |
248 | inofixup = ino & 0x03; | 248 | inofixup = ino & 0x03; |
249 | 249 | ||
250 | virt_irq = build_irq(inofixup, iclr, imap); | 250 | irq = build_irq(inofixup, iclr, imap); |
251 | 251 | ||
252 | /* If the parent device is a PCI<->PCI bridge other than | 252 | /* If the parent device is a PCI<->PCI bridge other than |
253 | * APB, we have to install a pre-handler to ensure that | 253 | * APB, we have to install a pre-handler to ensure that |
@@ -256,13 +256,13 @@ static unsigned int sabre_irq_build(struct device_node *dp, | |||
256 | */ | 256 | */ |
257 | regs = of_get_property(dp, "reg", NULL); | 257 | regs = of_get_property(dp, "reg", NULL); |
258 | if (regs && sabre_device_needs_wsync(dp)) { | 258 | if (regs && sabre_device_needs_wsync(dp)) { |
259 | irq_install_pre_handler(virt_irq, | 259 | irq_install_pre_handler(irq, |
260 | sabre_wsync_handler, | 260 | sabre_wsync_handler, |
261 | (void *) (long) regs->phys_hi, | 261 | (void *) (long) regs->phys_hi, |
262 | (void *) irq_data); | 262 | (void *) irq_data); |
263 | } | 263 | } |
264 | 264 | ||
265 | return virt_irq; | 265 | return irq; |
266 | } | 266 | } |
267 | 267 | ||
268 | static void __init sabre_irq_trans_init(struct device_node *dp) | 268 | static void __init sabre_irq_trans_init(struct device_node *dp) |
@@ -382,7 +382,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, | |||
382 | unsigned long pbm_regs = irq_data->pbm_regs; | 382 | unsigned long pbm_regs = irq_data->pbm_regs; |
383 | unsigned long imap, iclr; | 383 | unsigned long imap, iclr; |
384 | int ign_fixup; | 384 | int ign_fixup; |
385 | int virt_irq; | 385 | int irq; |
386 | int is_tomatillo; | 386 | int is_tomatillo; |
387 | 387 | ||
388 | ino &= 0x3f; | 388 | ino &= 0x3f; |
@@ -409,17 +409,17 @@ static unsigned int schizo_irq_build(struct device_node *dp, | |||
409 | ign_fixup = (1 << 6); | 409 | ign_fixup = (1 << 6); |
410 | } | 410 | } |
411 | 411 | ||
412 | virt_irq = build_irq(ign_fixup, iclr, imap); | 412 | irq = build_irq(ign_fixup, iclr, imap); |
413 | 413 | ||
414 | if (is_tomatillo) { | 414 | if (is_tomatillo) { |
415 | irq_install_pre_handler(virt_irq, | 415 | irq_install_pre_handler(irq, |
416 | tomatillo_wsync_handler, | 416 | tomatillo_wsync_handler, |
417 | ((irq_data->chip_version <= 4) ? | 417 | ((irq_data->chip_version <= 4) ? |
418 | (void *) 1 : (void *) 0), | 418 | (void *) 1 : (void *) 0), |
419 | (void *) irq_data->sync_reg); | 419 | (void *) irq_data->sync_reg); |
420 | } | 420 | } |
421 | 421 | ||
422 | return virt_irq; | 422 | return irq; |
423 | } | 423 | } |
424 | 424 | ||
425 | static void __init __schizo_irq_trans_init(struct device_node *dp, | 425 | static void __init __schizo_irq_trans_init(struct device_node *dp, |
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 9ccc812bc09e..96ee50a80661 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c | |||
@@ -1086,6 +1086,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
1086 | 1086 | ||
1087 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 1087 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) |
1088 | { | 1088 | { |
1089 | #ifdef CONFIG_AUDITSYSCALL | ||
1089 | if (unlikely(current->audit_context)) { | 1090 | if (unlikely(current->audit_context)) { |
1090 | unsigned long tstate = regs->tstate; | 1091 | unsigned long tstate = regs->tstate; |
1091 | int result = AUDITSC_SUCCESS; | 1092 | int result = AUDITSC_SUCCESS; |
@@ -1095,7 +1096,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) | |||
1095 | 1096 | ||
1096 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | 1097 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); |
1097 | } | 1098 | } |
1098 | 1099 | #endif | |
1099 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 1100 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
1100 | trace_sys_exit(regs, regs->u_regs[UREG_G1]); | 1101 | trace_sys_exit(regs, regs->u_regs[UREG_G1]); |
1101 | 1102 | ||
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index 648f2161b851..7b8b76c9557f 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c | |||
@@ -184,7 +184,6 @@ static void __init boot_flags_init(char *commands) | |||
184 | */ | 184 | */ |
185 | 185 | ||
186 | extern void sun4c_probe_vac(void); | 186 | extern void sun4c_probe_vac(void); |
187 | extern char cputypval; | ||
188 | 187 | ||
189 | extern unsigned short root_flags; | 188 | extern unsigned short root_flags; |
190 | extern unsigned short root_dev; | 189 | extern unsigned short root_dev; |
@@ -218,21 +217,21 @@ void __init setup_arch(char **cmdline_p) | |||
218 | 217 | ||
219 | /* Set sparc_cpu_model */ | 218 | /* Set sparc_cpu_model */ |
220 | sparc_cpu_model = sun_unknown; | 219 | sparc_cpu_model = sun_unknown; |
221 | if (!strcmp(&cputypval,"sun4 ")) | 220 | if (!strcmp(&cputypval[0], "sun4 ")) |
222 | sparc_cpu_model = sun4; | 221 | sparc_cpu_model = sun4; |
223 | if (!strcmp(&cputypval,"sun4c")) | 222 | if (!strcmp(&cputypval[0], "sun4c")) |
224 | sparc_cpu_model = sun4c; | 223 | sparc_cpu_model = sun4c; |
225 | if (!strcmp(&cputypval,"sun4m")) | 224 | if (!strcmp(&cputypval[0], "sun4m")) |
226 | sparc_cpu_model = sun4m; | 225 | sparc_cpu_model = sun4m; |
227 | if (!strcmp(&cputypval,"sun4s")) | 226 | if (!strcmp(&cputypval[0], "sun4s")) |
228 | sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ | 227 | sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ |
229 | if (!strcmp(&cputypval,"sun4d")) | 228 | if (!strcmp(&cputypval[0], "sun4d")) |
230 | sparc_cpu_model = sun4d; | 229 | sparc_cpu_model = sun4d; |
231 | if (!strcmp(&cputypval,"sun4e")) | 230 | if (!strcmp(&cputypval[0], "sun4e")) |
232 | sparc_cpu_model = sun4e; | 231 | sparc_cpu_model = sun4e; |
233 | if (!strcmp(&cputypval,"sun4u")) | 232 | if (!strcmp(&cputypval[0], "sun4u")) |
234 | sparc_cpu_model = sun4u; | 233 | sparc_cpu_model = sun4u; |
235 | if (!strncmp(&cputypval, "leon" , 4)) | 234 | if (!strncmp(&cputypval[0], "leon" , 4)) |
236 | sparc_cpu_model = sparc_leon; | 235 | sparc_cpu_model = sparc_leon; |
237 | 236 | ||
238 | printk("ARCH: "); | 237 | printk("ARCH: "); |
@@ -335,7 +334,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) | |||
335 | prom_rev, | 334 | prom_rev, |
336 | romvec->pv_printrev >> 16, | 335 | romvec->pv_printrev >> 16, |
337 | romvec->pv_printrev & 0xffff, | 336 | romvec->pv_printrev & 0xffff, |
338 | &cputypval, | 337 | &cputypval[0], |
339 | ncpus_probed, | 338 | ncpus_probed, |
340 | num_online_cpus() | 339 | num_online_cpus() |
341 | #ifndef CONFIG_SMP | 340 | #ifndef CONFIG_SMP |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 555a76d1f4a1..3e94a8c23238 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -189,7 +189,7 @@ static inline long get_delta (long *rt, long *master) | |||
189 | void smp_synchronize_tick_client(void) | 189 | void smp_synchronize_tick_client(void) |
190 | { | 190 | { |
191 | long i, delta, adj, adjust_latency = 0, done = 0; | 191 | long i, delta, adj, adjust_latency = 0, done = 0; |
192 | unsigned long flags, rt, master_time_stamp, bound; | 192 | unsigned long flags, rt, master_time_stamp; |
193 | #if DEBUG_TICK_SYNC | 193 | #if DEBUG_TICK_SYNC |
194 | struct { | 194 | struct { |
195 | long rt; /* roundtrip time */ | 195 | long rt; /* roundtrip time */ |
@@ -208,10 +208,8 @@ void smp_synchronize_tick_client(void) | |||
208 | { | 208 | { |
209 | for (i = 0; i < NUM_ROUNDS; i++) { | 209 | for (i = 0; i < NUM_ROUNDS; i++) { |
210 | delta = get_delta(&rt, &master_time_stamp); | 210 | delta = get_delta(&rt, &master_time_stamp); |
211 | if (delta == 0) { | 211 | if (delta == 0) |
212 | done = 1; /* let's lock on to this... */ | 212 | done = 1; /* let's lock on to this... */ |
213 | bound = rt; | ||
214 | } | ||
215 | 213 | ||
216 | if (!done) { | 214 | if (!done) { |
217 | if (i > 0) { | 215 | if (i > 0) { |
@@ -933,13 +931,12 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) | |||
933 | void flush_dcache_page_all(struct mm_struct *mm, struct page *page) | 931 | void flush_dcache_page_all(struct mm_struct *mm, struct page *page) |
934 | { | 932 | { |
935 | void *pg_addr; | 933 | void *pg_addr; |
936 | int this_cpu; | ||
937 | u64 data0; | 934 | u64 data0; |
938 | 935 | ||
939 | if (tlb_type == hypervisor) | 936 | if (tlb_type == hypervisor) |
940 | return; | 937 | return; |
941 | 938 | ||
942 | this_cpu = get_cpu(); | 939 | preempt_disable(); |
943 | 940 | ||
944 | #ifdef CONFIG_DEBUG_DCFLUSH | 941 | #ifdef CONFIG_DEBUG_DCFLUSH |
945 | atomic_inc(&dcpage_flushes); | 942 | atomic_inc(&dcpage_flushes); |
@@ -964,7 +961,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) | |||
964 | } | 961 | } |
965 | __local_flush_dcache_page(page); | 962 | __local_flush_dcache_page(page); |
966 | 963 | ||
967 | put_cpu(); | 964 | preempt_enable(); |
968 | } | 965 | } |
969 | 966 | ||
970 | void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) | 967 | void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) |
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 892fb884910a..90eea38ad66f 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* sun4c_irq.c | 1 | /* |
2 | * arch/sparc/kernel/sun4c_irq.c: | 2 | * sun4c irq support |
3 | * | 3 | * |
4 | * djhr: Hacked out of irq.c into a CPU dependent version. | 4 | * djhr: Hacked out of irq.c into a CPU dependent version. |
5 | * | 5 | * |
@@ -9,31 +9,41 @@ | |||
9 | * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) | 9 | * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <linux/kernel_stat.h> | ||
15 | #include <linux/signal.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/init.h> | 12 | #include <linux/init.h> |
20 | #include <linux/of.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include "irq.h" | ||
23 | 13 | ||
24 | #include <asm/ptrace.h> | ||
25 | #include <asm/processor.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <asm/psr.h> | ||
28 | #include <asm/vaddrs.h> | ||
29 | #include <asm/timer.h> | ||
30 | #include <asm/openprom.h> | ||
31 | #include <asm/oplib.h> | 14 | #include <asm/oplib.h> |
32 | #include <asm/traps.h> | 15 | #include <asm/timer.h> |
33 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
34 | #include <asm/io.h> | 17 | #include <asm/io.h> |
35 | #include <asm/idprom.h> | 18 | |
36 | #include <asm/machines.h> | 19 | #include "irq.h" |
20 | |||
21 | /* Sun4c interrupts are typically laid out as follows: | ||
22 | * | ||
23 | * 1 - Software interrupt, SBUS level 1 | ||
24 | * 2 - SBUS level 2 | ||
25 | * 3 - ESP SCSI, SBUS level 3 | ||
26 | * 4 - Software interrupt | ||
27 | * 5 - Lance ethernet, SBUS level 4 | ||
28 | * 6 - Software interrupt | ||
29 | * 7 - Graphics card, SBUS level 5 | ||
30 | * 8 - SBUS level 6 | ||
31 | * 9 - SBUS level 7 | ||
32 | * 10 - Counter timer | ||
33 | * 11 - Floppy | ||
34 | * 12 - Zilog uart | ||
35 | * 13 - CS4231 audio | ||
36 | * 14 - Profiling timer | ||
37 | * 15 - NMI | ||
38 | * | ||
39 | * The interrupt enable bits in the interrupt mask register are | ||
40 | * really only used to enable/disable the timer interrupts, and | ||
41 | * for signalling software interrupts. There is also a master | ||
42 | * interrupt enable bit in this register. | ||
43 | * | ||
44 | * Interrupts are enabled by setting the SUN4C_INT_* bits, they | ||
45 | * are disabled by clearing those bits. | ||
46 | */ | ||
37 | 47 | ||
38 | /* | 48 | /* |
39 | * Bit field defines for the interrupt registers on various | 49 | * Bit field defines for the interrupt registers on various |
@@ -49,26 +59,21 @@ | |||
49 | #define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */ | 59 | #define SUN4C_INT_E4 0x04 /* Enable level 4 IRQ. */ |
50 | #define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */ | 60 | #define SUN4C_INT_E1 0x02 /* Enable level 1 IRQ. */ |
51 | 61 | ||
52 | /* Pointer to the interrupt enable byte | 62 | /* |
53 | * | 63 | * Pointer to the interrupt enable byte |
54 | * Dave Redman (djhr@tadpole.co.uk) | 64 | * Used by entry.S |
55 | * What you may not be aware of is that entry.S requires this variable. | ||
56 | * | ||
57 | * --- linux_trap_nmi_sun4c -- | ||
58 | * | ||
59 | * so don't go making it static, like I tried. sigh. | ||
60 | */ | 65 | */ |
61 | unsigned char __iomem *interrupt_enable = NULL; | 66 | unsigned char __iomem *interrupt_enable; |
62 | 67 | ||
63 | static void sun4c_disable_irq(unsigned int irq_nr) | 68 | static void sun4c_disable_irq(unsigned int irq_nr) |
64 | { | 69 | { |
65 | unsigned long flags; | 70 | unsigned long flags; |
66 | unsigned char current_mask, new_mask; | 71 | unsigned char current_mask, new_mask; |
67 | 72 | ||
68 | local_irq_save(flags); | 73 | local_irq_save(flags); |
69 | irq_nr &= (NR_IRQS - 1); | 74 | irq_nr &= (NR_IRQS - 1); |
70 | current_mask = sbus_readb(interrupt_enable); | 75 | current_mask = sbus_readb(interrupt_enable); |
71 | switch(irq_nr) { | 76 | switch (irq_nr) { |
72 | case 1: | 77 | case 1: |
73 | new_mask = ((current_mask) & (~(SUN4C_INT_E1))); | 78 | new_mask = ((current_mask) & (~(SUN4C_INT_E1))); |
74 | break; | 79 | break; |
@@ -93,11 +98,11 @@ static void sun4c_enable_irq(unsigned int irq_nr) | |||
93 | { | 98 | { |
94 | unsigned long flags; | 99 | unsigned long flags; |
95 | unsigned char current_mask, new_mask; | 100 | unsigned char current_mask, new_mask; |
96 | 101 | ||
97 | local_irq_save(flags); | 102 | local_irq_save(flags); |
98 | irq_nr &= (NR_IRQS - 1); | 103 | irq_nr &= (NR_IRQS - 1); |
99 | current_mask = sbus_readb(interrupt_enable); | 104 | current_mask = sbus_readb(interrupt_enable); |
100 | switch(irq_nr) { | 105 | switch (irq_nr) { |
101 | case 1: | 106 | case 1: |
102 | new_mask = ((current_mask) | SUN4C_INT_E1); | 107 | new_mask = ((current_mask) | SUN4C_INT_E1); |
103 | break; | 108 | break; |
@@ -180,12 +185,14 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) | |||
180 | prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); | 185 | prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); |
181 | prom_halt(); | 186 | prom_halt(); |
182 | } | 187 | } |
183 | 188 | ||
184 | sun4c_disable_irq(irq[1].pri); | 189 | sun4c_disable_irq(irq[1].pri); |
185 | } | 190 | } |
186 | 191 | ||
187 | #ifdef CONFIG_SMP | 192 | #ifdef CONFIG_SMP |
188 | static void sun4c_nop(void) {} | 193 | static void sun4c_nop(void) |
194 | { | ||
195 | } | ||
189 | #endif | 196 | #endif |
190 | 197 | ||
191 | void __init sun4c_init_IRQ(void) | 198 | void __init sun4c_init_IRQ(void) |
@@ -214,7 +221,9 @@ void __init sun4c_init_IRQ(void) | |||
214 | BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); | 221 | BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); |
215 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); | 222 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); |
216 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); | 223 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); |
217 | sparc_init_timers = sun4c_init_timers; | 224 | |
225 | sparc_irq_config.init_timers = sun4c_init_timers; | ||
226 | |||
218 | #ifdef CONFIG_SMP | 227 | #ifdef CONFIG_SMP |
219 | BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); | 228 | BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); |
220 | BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); | 229 | BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); |
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index e11b4612dabb..77b4a8992710 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c | |||
@@ -1,50 +1,42 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sparc/kernel/sun4d_irq.c: | 2 | * SS1000/SC2000 interrupt handling. |
3 | * SS1000/SC2000 interrupt handling. | ||
4 | * | 3 | * |
5 | * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | 4 | * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
6 | * Heavily based on arch/sparc/kernel/irq.c. | 5 | * Heavily based on arch/sparc/kernel/irq.c. |
7 | */ | 6 | */ |
8 | 7 | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/linkage.h> | ||
11 | #include <linux/kernel_stat.h> | 8 | #include <linux/kernel_stat.h> |
12 | #include <linux/signal.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/ptrace.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/random.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/smp.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
22 | #include <linux/of.h> | 10 | |
23 | #include <linux/of_device.h> | ||
24 | |||
25 | #include <asm/ptrace.h> | ||
26 | #include <asm/processor.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/psr.h> | ||
29 | #include <asm/smp.h> | ||
30 | #include <asm/vaddrs.h> | ||
31 | #include <asm/timer.h> | 11 | #include <asm/timer.h> |
32 | #include <asm/openprom.h> | ||
33 | #include <asm/oplib.h> | ||
34 | #include <asm/traps.h> | 12 | #include <asm/traps.h> |
35 | #include <asm/irq.h> | 13 | #include <asm/irq.h> |
36 | #include <asm/io.h> | 14 | #include <asm/io.h> |
37 | #include <asm/pgalloc.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/sbi.h> | 15 | #include <asm/sbi.h> |
40 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
41 | #include <asm/irq_regs.h> | ||
42 | 17 | ||
43 | #include "kernel.h" | 18 | #include "kernel.h" |
44 | #include "irq.h" | 19 | #include "irq.h" |
45 | 20 | ||
46 | /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ | 21 | /* Sun4d interrupts fall roughly into two categories. SBUS and |
47 | /* #define DISTRIBUTE_IRQS */ | 22 | * cpu local. CPU local interrupts cover the timer interrupts |
23 | * and whatnot, and we encode those as normal PILs between | ||
24 | * 0 and 15. | ||
25 | * | ||
26 | * SBUS interrupts are encoded integers including the board number | ||
27 | * (plus one), the SBUS level, and the SBUS slot number. Sun4D | ||
28 | * IRQ dispatch is done by: | ||
29 | * | ||
30 | * 1) Reading the BW local interrupt table in order to get the bus | ||
31 | * interrupt mask. | ||
32 | * | ||
33 | * This table is indexed by SBUS interrupt level which can be | ||
34 | * derived from the PIL we got interrupted on. | ||
35 | * | ||
36 | * 2) For each bus showing interrupt pending from #1, read the | ||
37 | * SBI interrupt state register. This will indicate which slots | ||
38 | * have interrupts pending for that SBUS interrupt level. | ||
39 | */ | ||
48 | 40 | ||
49 | struct sun4d_timer_regs { | 41 | struct sun4d_timer_regs { |
50 | u32 l10_timer_limit; | 42 | u32 l10_timer_limit; |
@@ -59,11 +51,9 @@ static struct sun4d_timer_regs __iomem *sun4d_timers; | |||
59 | #define TIMER_IRQ 10 | 51 | #define TIMER_IRQ 10 |
60 | 52 | ||
61 | #define MAX_STATIC_ALLOC 4 | 53 | #define MAX_STATIC_ALLOC 4 |
62 | extern int static_irq_count; | ||
63 | static unsigned char sbus_tid[32]; | 54 | static unsigned char sbus_tid[32]; |
64 | 55 | ||
65 | static struct irqaction *irq_action[NR_IRQS]; | 56 | static struct irqaction *irq_action[NR_IRQS]; |
66 | extern spinlock_t irq_action_lock; | ||
67 | 57 | ||
68 | static struct sbus_action { | 58 | static struct sbus_action { |
69 | struct irqaction *action; | 59 | struct irqaction *action; |
@@ -71,11 +61,33 @@ static struct sbus_action { | |||
71 | } *sbus_actions; | 61 | } *sbus_actions; |
72 | 62 | ||
73 | static int pil_to_sbus[] = { | 63 | static int pil_to_sbus[] = { |
74 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | 64 | 0, |
65 | 0, | ||
66 | 1, | ||
67 | 2, | ||
68 | 0, | ||
69 | 3, | ||
70 | 0, | ||
71 | 4, | ||
72 | 0, | ||
73 | 5, | ||
74 | 0, | ||
75 | 6, | ||
76 | 0, | ||
77 | 7, | ||
78 | 0, | ||
79 | 0, | ||
75 | }; | 80 | }; |
76 | 81 | ||
77 | static int sbus_to_pil[] = { | 82 | static int sbus_to_pil[] = { |
78 | 0, 2, 3, 5, 7, 9, 11, 13, | 83 | 0, |
84 | 2, | ||
85 | 3, | ||
86 | 5, | ||
87 | 7, | ||
88 | 9, | ||
89 | 11, | ||
90 | 13, | ||
79 | }; | 91 | }; |
80 | 92 | ||
81 | static int nsbi; | 93 | static int nsbi; |
@@ -86,7 +98,7 @@ DEFINE_SPINLOCK(sun4d_imsk_lock); | |||
86 | int show_sun4d_interrupts(struct seq_file *p, void *v) | 98 | int show_sun4d_interrupts(struct seq_file *p, void *v) |
87 | { | 99 | { |
88 | int i = *(loff_t *) v, j = 0, k = 0, sbusl; | 100 | int i = *(loff_t *) v, j = 0, k = 0, sbusl; |
89 | struct irqaction * action; | 101 | struct irqaction *action; |
90 | unsigned long flags; | 102 | unsigned long flags; |
91 | #ifdef CONFIG_SMP | 103 | #ifdef CONFIG_SMP |
92 | int x; | 104 | int x; |
@@ -96,13 +108,14 @@ int show_sun4d_interrupts(struct seq_file *p, void *v) | |||
96 | if (i < NR_IRQS) { | 108 | if (i < NR_IRQS) { |
97 | sbusl = pil_to_sbus[i]; | 109 | sbusl = pil_to_sbus[i]; |
98 | if (!sbusl) { | 110 | if (!sbusl) { |
99 | action = *(i + irq_action); | 111 | action = *(i + irq_action); |
100 | if (!action) | 112 | if (!action) |
101 | goto out_unlock; | 113 | goto out_unlock; |
102 | } else { | 114 | } else { |
103 | for (j = 0; j < nsbi; j++) { | 115 | for (j = 0; j < nsbi; j++) { |
104 | for (k = 0; k < 4; k++) | 116 | for (k = 0; k < 4; k++) |
105 | if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action)) | 117 | action = sbus_actions[(j << 5) + (sbusl << 2) + k].action; |
118 | if (action) | ||
106 | goto found_it; | 119 | goto found_it; |
107 | } | 120 | } |
108 | goto out_unlock; | 121 | goto out_unlock; |
@@ -125,15 +138,17 @@ found_it: seq_printf(p, "%3d: ", i); | |||
125 | (action->flags & IRQF_DISABLED) ? " +" : "", | 138 | (action->flags & IRQF_DISABLED) ? " +" : "", |
126 | action->name); | 139 | action->name); |
127 | } | 140 | } |
128 | if (!sbusl) break; | 141 | if (!sbusl) |
142 | break; | ||
129 | k++; | 143 | k++; |
130 | if (k < 4) | 144 | if (k < 4) { |
131 | action = sbus_actions [(j << 5) + (sbusl << 2) + k].action; | 145 | action = sbus_actions[(j << 5) + (sbusl << 2) + k].action; |
132 | else { | 146 | } else { |
133 | j++; | 147 | j++; |
134 | if (j == nsbi) break; | 148 | if (j == nsbi) |
149 | break; | ||
135 | k = 0; | 150 | k = 0; |
136 | action = sbus_actions [(j << 5) + (sbusl << 2)].action; | 151 | action = sbus_actions[(j << 5) + (sbusl << 2)].action; |
137 | } | 152 | } |
138 | } | 153 | } |
139 | seq_putc(p, '\n'); | 154 | seq_putc(p, '\n'); |
@@ -147,7 +162,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) | |||
147 | { | 162 | { |
148 | struct irqaction *action, **actionp; | 163 | struct irqaction *action, **actionp; |
149 | struct irqaction *tmp = NULL; | 164 | struct irqaction *tmp = NULL; |
150 | unsigned long flags; | 165 | unsigned long flags; |
151 | 166 | ||
152 | spin_lock_irqsave(&irq_action_lock, flags); | 167 | spin_lock_irqsave(&irq_action_lock, flags); |
153 | if (irq < 15) | 168 | if (irq < 15) |
@@ -156,7 +171,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) | |||
156 | actionp = &(sbus_actions[irq - (1 << 5)].action); | 171 | actionp = &(sbus_actions[irq - (1 << 5)].action); |
157 | action = *actionp; | 172 | action = *actionp; |
158 | if (!action) { | 173 | if (!action) { |
159 | printk("Trying to free free IRQ%d\n",irq); | 174 | printk(KERN_ERR "Trying to free free IRQ%d\n", irq); |
160 | goto out_unlock; | 175 | goto out_unlock; |
161 | } | 176 | } |
162 | if (dev_id) { | 177 | if (dev_id) { |
@@ -166,23 +181,25 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) | |||
166 | tmp = action; | 181 | tmp = action; |
167 | } | 182 | } |
168 | if (!action) { | 183 | if (!action) { |
169 | printk("Trying to free free shared IRQ%d\n",irq); | 184 | printk(KERN_ERR "Trying to free free shared IRQ%d\n", |
185 | irq); | ||
170 | goto out_unlock; | 186 | goto out_unlock; |
171 | } | 187 | } |
172 | } else if (action->flags & IRQF_SHARED) { | 188 | } else if (action->flags & IRQF_SHARED) { |
173 | printk("Trying to free shared IRQ%d with NULL device ID\n", irq); | 189 | printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n", |
190 | irq); | ||
174 | goto out_unlock; | 191 | goto out_unlock; |
175 | } | 192 | } |
176 | if (action->flags & SA_STATIC_ALLOC) | 193 | if (action->flags & SA_STATIC_ALLOC) { |
177 | { | 194 | /* |
178 | /* This interrupt is marked as specially allocated | 195 | * This interrupt is marked as specially allocated |
179 | * so it is a bad idea to free it. | 196 | * so it is a bad idea to free it. |
180 | */ | 197 | */ |
181 | printk("Attempt to free statically allocated IRQ%d (%s)\n", | 198 | printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n", |
182 | irq, action->name); | 199 | irq, action->name); |
183 | goto out_unlock; | 200 | goto out_unlock; |
184 | } | 201 | } |
185 | 202 | ||
186 | if (tmp) | 203 | if (tmp) |
187 | tmp->next = action->next; | 204 | tmp->next = action->next; |
188 | else | 205 | else |
@@ -203,30 +220,28 @@ out_unlock: | |||
203 | spin_unlock_irqrestore(&irq_action_lock, flags); | 220 | spin_unlock_irqrestore(&irq_action_lock, flags); |
204 | } | 221 | } |
205 | 222 | ||
206 | extern void unexpected_irq(int, void *, struct pt_regs *); | 223 | void sun4d_handler_irq(int pil, struct pt_regs *regs) |
207 | |||
208 | void sun4d_handler_irq(int irq, struct pt_regs * regs) | ||
209 | { | 224 | { |
210 | struct pt_regs *old_regs; | 225 | struct pt_regs *old_regs; |
211 | struct irqaction * action; | 226 | struct irqaction *action; |
212 | int cpu = smp_processor_id(); | 227 | int cpu = smp_processor_id(); |
213 | /* SBUS IRQ level (1 - 7) */ | 228 | /* SBUS IRQ level (1 - 7) */ |
214 | int sbusl = pil_to_sbus[irq]; | 229 | int sbusl = pil_to_sbus[pil]; |
215 | 230 | ||
216 | /* FIXME: Is this necessary?? */ | 231 | /* FIXME: Is this necessary?? */ |
217 | cc_get_ipen(); | 232 | cc_get_ipen(); |
218 | 233 | ||
219 | cc_set_iclr(1 << irq); | 234 | cc_set_iclr(1 << pil); |
220 | 235 | ||
221 | old_regs = set_irq_regs(regs); | 236 | old_regs = set_irq_regs(regs); |
222 | irq_enter(); | 237 | irq_enter(); |
223 | kstat_cpu(cpu).irqs[irq]++; | 238 | kstat_cpu(cpu).irqs[pil]++; |
224 | if (!sbusl) { | 239 | if (!sbusl) { |
225 | action = *(irq + irq_action); | 240 | action = *(pil + irq_action); |
226 | if (!action) | 241 | if (!action) |
227 | unexpected_irq(irq, NULL, regs); | 242 | unexpected_irq(pil, NULL, regs); |
228 | do { | 243 | do { |
229 | action->handler(irq, action->dev_id); | 244 | action->handler(pil, action->dev_id); |
230 | action = action->next; | 245 | action = action->next; |
231 | } while (action); | 246 | } while (action); |
232 | } else { | 247 | } else { |
@@ -235,9 +250,9 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) | |||
235 | struct sbus_action *actionp; | 250 | struct sbus_action *actionp; |
236 | unsigned mask, slot; | 251 | unsigned mask, slot; |
237 | int sbil = (sbusl << 2); | 252 | int sbil = (sbusl << 2); |
238 | 253 | ||
239 | bw_clear_intr_mask(sbusl, bus_mask); | 254 | bw_clear_intr_mask(sbusl, bus_mask); |
240 | 255 | ||
241 | /* Loop for each pending SBI */ | 256 | /* Loop for each pending SBI */ |
242 | for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) | 257 | for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) |
243 | if (bus_mask & 1) { | 258 | if (bus_mask & 1) { |
@@ -249,11 +264,11 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) | |||
249 | if (mask & slot) { | 264 | if (mask & slot) { |
250 | mask &= ~slot; | 265 | mask &= ~slot; |
251 | action = actionp->action; | 266 | action = actionp->action; |
252 | 267 | ||
253 | if (!action) | 268 | if (!action) |
254 | unexpected_irq(irq, NULL, regs); | 269 | unexpected_irq(pil, NULL, regs); |
255 | do { | 270 | do { |
256 | action->handler(irq, action->dev_id); | 271 | action->handler(pil, action->dev_id); |
257 | action = action->next; | 272 | action = action->next; |
258 | } while (action); | 273 | } while (action); |
259 | release_sbi(SBI2DEVID(sbino), slot); | 274 | release_sbi(SBI2DEVID(sbino), slot); |
@@ -266,13 +281,13 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) | |||
266 | 281 | ||
267 | int sun4d_request_irq(unsigned int irq, | 282 | int sun4d_request_irq(unsigned int irq, |
268 | irq_handler_t handler, | 283 | irq_handler_t handler, |
269 | unsigned long irqflags, const char * devname, void *dev_id) | 284 | unsigned long irqflags, const char *devname, void *dev_id) |
270 | { | 285 | { |
271 | struct irqaction *action, *tmp = NULL, **actionp; | 286 | struct irqaction *action, *tmp = NULL, **actionp; |
272 | unsigned long flags; | 287 | unsigned long flags; |
273 | int ret; | 288 | int ret; |
274 | 289 | ||
275 | if(irq > 14 && irq < (1 << 5)) { | 290 | if (irq > 14 && irq < (1 << 5)) { |
276 | ret = -EINVAL; | 291 | ret = -EINVAL; |
277 | goto out; | 292 | goto out; |
278 | } | 293 | } |
@@ -289,16 +304,18 @@ int sun4d_request_irq(unsigned int irq, | |||
289 | else | 304 | else |
290 | actionp = irq + irq_action; | 305 | actionp = irq + irq_action; |
291 | action = *actionp; | 306 | action = *actionp; |
292 | 307 | ||
293 | if (action) { | 308 | if (action) { |
294 | if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) { | 309 | if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) { |
295 | for (tmp = action; tmp->next; tmp = tmp->next); | 310 | for (tmp = action; tmp->next; tmp = tmp->next) |
311 | /* find last entry - tmp used below */; | ||
296 | } else { | 312 | } else { |
297 | ret = -EBUSY; | 313 | ret = -EBUSY; |
298 | goto out_unlock; | 314 | goto out_unlock; |
299 | } | 315 | } |
300 | if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) { | 316 | if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) { |
301 | printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); | 317 | printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n", |
318 | irq); | ||
302 | ret = -EBUSY; | 319 | ret = -EBUSY; |
303 | goto out_unlock; | 320 | goto out_unlock; |
304 | } | 321 | } |
@@ -312,14 +329,14 @@ int sun4d_request_irq(unsigned int irq, | |||
312 | if (static_irq_count < MAX_STATIC_ALLOC) | 329 | if (static_irq_count < MAX_STATIC_ALLOC) |
313 | action = &static_irqaction[static_irq_count++]; | 330 | action = &static_irqaction[static_irq_count++]; |
314 | else | 331 | else |
315 | printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); | 332 | printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", |
333 | irq, devname); | ||
316 | } | 334 | } |
317 | 335 | ||
318 | if (action == NULL) | 336 | if (action == NULL) |
319 | action = kmalloc(sizeof(struct irqaction), | 337 | action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); |
320 | GFP_ATOMIC); | 338 | |
321 | 339 | if (!action) { | |
322 | if (!action) { | ||
323 | ret = -ENOMEM; | 340 | ret = -ENOMEM; |
324 | goto out_unlock; | 341 | goto out_unlock; |
325 | } | 342 | } |
@@ -334,7 +351,7 @@ int sun4d_request_irq(unsigned int irq, | |||
334 | tmp->next = action; | 351 | tmp->next = action; |
335 | else | 352 | else |
336 | *actionp = action; | 353 | *actionp = action; |
337 | 354 | ||
338 | __enable_irq(irq); | 355 | __enable_irq(irq); |
339 | 356 | ||
340 | ret = 0; | 357 | ret = 0; |
@@ -348,7 +365,7 @@ static void sun4d_disable_irq(unsigned int irq) | |||
348 | { | 365 | { |
349 | int tid = sbus_tid[(irq >> 5) - 1]; | 366 | int tid = sbus_tid[(irq >> 5) - 1]; |
350 | unsigned long flags; | 367 | unsigned long flags; |
351 | 368 | ||
352 | if (irq < NR_IRQS) | 369 | if (irq < NR_IRQS) |
353 | return; | 370 | return; |
354 | 371 | ||
@@ -361,7 +378,7 @@ static void sun4d_enable_irq(unsigned int irq) | |||
361 | { | 378 | { |
362 | int tid = sbus_tid[(irq >> 5) - 1]; | 379 | int tid = sbus_tid[(irq >> 5) - 1]; |
363 | unsigned long flags; | 380 | unsigned long flags; |
364 | 381 | ||
365 | if (irq < NR_IRQS) | 382 | if (irq < NR_IRQS) |
366 | return; | 383 | return; |
367 | 384 | ||
@@ -389,44 +406,6 @@ void __init sun4d_distribute_irqs(void) | |||
389 | { | 406 | { |
390 | struct device_node *dp; | 407 | struct device_node *dp; |
391 | 408 | ||
392 | #ifdef DISTRIBUTE_IRQS | ||
393 | cpumask_t sbus_serving_map; | ||
394 | |||
395 | sbus_serving_map = cpu_present_map; | ||
396 | for_each_node_by_name(dp, "sbi") { | ||
397 | int board = of_getintprop_default(dp, "board#", 0); | ||
398 | |||
399 | if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map)) | ||
400 | sbus_tid[board] = (board * 2 + 1); | ||
401 | else if (cpu_isset(board * 2, cpu_present_map)) | ||
402 | sbus_tid[board] = (board * 2); | ||
403 | else if (cpu_isset(board * 2 + 1, cpu_present_map)) | ||
404 | sbus_tid[board] = (board * 2 + 1); | ||
405 | else | ||
406 | sbus_tid[board] = 0xff; | ||
407 | if (sbus_tid[board] != 0xff) | ||
408 | cpu_clear(sbus_tid[board], sbus_serving_map); | ||
409 | } | ||
410 | for_each_node_by_name(dp, "sbi") { | ||
411 | int board = of_getintprop_default(dp, "board#", 0); | ||
412 | if (sbus_tid[board] == 0xff) { | ||
413 | int i = 31; | ||
414 | |||
415 | if (cpus_empty(sbus_serving_map)) | ||
416 | sbus_serving_map = cpu_present_map; | ||
417 | while (cpu_isset(i, sbus_serving_map)) | ||
418 | i--; | ||
419 | sbus_tid[board] = i; | ||
420 | cpu_clear(i, sbus_serving_map); | ||
421 | } | ||
422 | } | ||
423 | for_each_node_by_name(dp, "sbi") { | ||
424 | int devid = of_getintprop_default(dp, "device-id", 0); | ||
425 | int board = of_getintprop_default(dp, "board#", 0); | ||
426 | printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]); | ||
427 | set_sbi_tid(devid, sbus_tid[board] << 3); | ||
428 | } | ||
429 | #else | ||
430 | int cpuid = cpu_logical_map(1); | 409 | int cpuid = cpu_logical_map(1); |
431 | 410 | ||
432 | if (cpuid == -1) | 411 | if (cpuid == -1) |
@@ -437,11 +416,10 @@ void __init sun4d_distribute_irqs(void) | |||
437 | sbus_tid[board] = cpuid; | 416 | sbus_tid[board] = cpuid; |
438 | set_sbi_tid(devid, cpuid << 3); | 417 | set_sbi_tid(devid, cpuid << 3); |
439 | } | 418 | } |
440 | printk("All sbus IRQs directed to CPU%d\n", cpuid); | 419 | printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid); |
441 | #endif | ||
442 | } | 420 | } |
443 | #endif | 421 | #endif |
444 | 422 | ||
445 | static void sun4d_clear_clock_irq(void) | 423 | static void sun4d_clear_clock_irq(void) |
446 | { | 424 | { |
447 | sbus_readl(&sun4d_timers->l10_timer_limit); | 425 | sbus_readl(&sun4d_timers->l10_timer_limit); |
@@ -462,14 +440,61 @@ static void __init sun4d_load_profile_irqs(void) | |||
462 | } | 440 | } |
463 | } | 441 | } |
464 | 442 | ||
443 | unsigned int sun4d_build_device_irq(struct platform_device *op, | ||
444 | unsigned int real_irq) | ||
445 | { | ||
446 | static int pil_to_sbus[] = { | ||
447 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | ||
448 | }; | ||
449 | struct device_node *dp = op->dev.of_node; | ||
450 | struct device_node *io_unit, *sbi = dp->parent; | ||
451 | const struct linux_prom_registers *regs; | ||
452 | int board, slot; | ||
453 | int sbusl; | ||
454 | |||
455 | while (sbi) { | ||
456 | if (!strcmp(sbi->name, "sbi")) | ||
457 | break; | ||
458 | |||
459 | sbi = sbi->parent; | ||
460 | } | ||
461 | if (!sbi) | ||
462 | goto err_out; | ||
463 | |||
464 | regs = of_get_property(dp, "reg", NULL); | ||
465 | if (!regs) | ||
466 | goto err_out; | ||
467 | |||
468 | slot = regs->which_io; | ||
469 | |||
470 | /* | ||
471 | * If SBI's parent is not io-unit or the io-unit lacks | ||
472 | * a "board#" property, something is very wrong. | ||
473 | */ | ||
474 | if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { | ||
475 | printk("%s: Error, parent is not io-unit.\n", sbi->full_name); | ||
476 | goto err_out; | ||
477 | } | ||
478 | io_unit = sbi->parent; | ||
479 | board = of_getintprop_default(io_unit, "board#", -1); | ||
480 | if (board == -1) { | ||
481 | printk("%s: Error, lacks board# property.\n", io_unit->full_name); | ||
482 | goto err_out; | ||
483 | } | ||
484 | |||
485 | sbusl = pil_to_sbus[real_irq]; | ||
486 | if (sbusl) | ||
487 | return (((board + 1) << 5) + (sbusl << 2) + slot); | ||
488 | |||
489 | err_out: | ||
490 | return real_irq; | ||
491 | } | ||
492 | |||
465 | static void __init sun4d_fixup_trap_table(void) | 493 | static void __init sun4d_fixup_trap_table(void) |
466 | { | 494 | { |
467 | #ifdef CONFIG_SMP | 495 | #ifdef CONFIG_SMP |
468 | unsigned long flags; | 496 | unsigned long flags; |
469 | extern unsigned long lvl14_save[4]; | ||
470 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; | 497 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; |
471 | extern unsigned int real_irq_entry[], smp4d_ticker[]; | ||
472 | extern unsigned int patchme_maybe_smp_msg[]; | ||
473 | 498 | ||
474 | /* Adjust so that we jump directly to smp4d_ticker */ | 499 | /* Adjust so that we jump directly to smp4d_ticker */ |
475 | lvl14_save[2] += smp4d_ticker - real_irq_entry; | 500 | lvl14_save[2] += smp4d_ticker - real_irq_entry; |
@@ -531,7 +556,8 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) | |||
531 | (IRQF_DISABLED | SA_STATIC_ALLOC), | 556 | (IRQF_DISABLED | SA_STATIC_ALLOC), |
532 | "timer", NULL); | 557 | "timer", NULL); |
533 | if (err) { | 558 | if (err) { |
534 | prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); | 559 | prom_printf("sun4d_init_timers: request_irq() failed with %d\n", |
560 | err); | ||
535 | prom_halt(); | 561 | prom_halt(); |
536 | } | 562 | } |
537 | sun4d_load_profile_irqs(); | 563 | sun4d_load_profile_irqs(); |
@@ -550,7 +576,7 @@ void __init sun4d_init_sbi_irq(void) | |||
550 | nsbi = 0; | 576 | nsbi = 0; |
551 | for_each_node_by_name(dp, "sbi") | 577 | for_each_node_by_name(dp, "sbi") |
552 | nsbi++; | 578 | nsbi++; |
553 | sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); | 579 | sbus_actions = kzalloc(nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); |
554 | if (!sbus_actions) { | 580 | if (!sbus_actions) { |
555 | prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); | 581 | prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); |
556 | prom_halt(); | 582 | prom_halt(); |
@@ -566,7 +592,8 @@ void __init sun4d_init_sbi_irq(void) | |||
566 | /* Get rid of pending irqs from PROM */ | 592 | /* Get rid of pending irqs from PROM */ |
567 | mask = acquire_sbi(devid, 0xffffffff); | 593 | mask = acquire_sbi(devid, 0xffffffff); |
568 | if (mask) { | 594 | if (mask) { |
569 | printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board); | 595 | printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n", |
596 | mask, board); | ||
570 | release_sbi(devid, mask); | 597 | release_sbi(devid, mask); |
571 | } | 598 | } |
572 | } | 599 | } |
@@ -580,7 +607,10 @@ void __init sun4d_init_IRQ(void) | |||
580 | BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); | 607 | BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); |
581 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); | 608 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); |
582 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); | 609 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); |
583 | sparc_init_timers = sun4d_init_timers; | 610 | |
611 | sparc_irq_config.init_timers = sun4d_init_timers; | ||
612 | sparc_irq_config.build_device_irq = sun4d_build_device_irq; | ||
613 | |||
584 | #ifdef CONFIG_SMP | 614 | #ifdef CONFIG_SMP |
585 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); | 615 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); |
586 | BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); | 616 | BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); |
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 482f2ab92692..475d50b96cd0 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* sun4d_smp.c: Sparc SS1000/SC2000 SMP support. | 1 | /* Sparc SS1000/SC2000 SMP support. |
2 | * | 2 | * |
3 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | 3 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
4 | * | 4 | * |
@@ -6,59 +6,23 @@ | |||
6 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | 6 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/head.h> | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/threads.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
16 | #include <linux/kernel_stat.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/swap.h> | ||
21 | #include <linux/profile.h> | 10 | #include <linux/profile.h> |
22 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
23 | #include <linux/cpu.h> | 12 | #include <linux/cpu.h> |
24 | 13 | ||
25 | #include <asm/ptrace.h> | ||
26 | #include <asm/atomic.h> | ||
27 | #include <asm/irq_regs.h> | ||
28 | |||
29 | #include <asm/irq.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/pgalloc.h> | ||
32 | #include <asm/pgtable.h> | ||
33 | #include <asm/oplib.h> | ||
34 | #include <asm/sbi.h> | 14 | #include <asm/sbi.h> |
15 | #include <asm/mmu.h> | ||
35 | #include <asm/tlbflush.h> | 16 | #include <asm/tlbflush.h> |
36 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
37 | #include <asm/cpudata.h> | ||
38 | 18 | ||
19 | #include "kernel.h" | ||
39 | #include "irq.h" | 20 | #include "irq.h" |
40 | #define IRQ_CROSS_CALL 15 | ||
41 | 21 | ||
42 | extern ctxd_t *srmmu_ctx_table_phys; | 22 | #define IRQ_CROSS_CALL 15 |
43 | 23 | ||
44 | static volatile int smp_processors_ready = 0; | 24 | static volatile int smp_processors_ready; |
45 | static int smp_highest_cpu; | 25 | static int smp_highest_cpu; |
46 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | ||
47 | extern cpuinfo_sparc cpu_data[NR_CPUS]; | ||
48 | extern unsigned char boot_cpu_id; | ||
49 | extern volatile int smp_process_available; | ||
50 | |||
51 | extern cpumask_t smp_commenced_mask; | ||
52 | |||
53 | extern int __smp4d_processor_id(void); | ||
54 | |||
55 | /* #define SMP_DEBUG */ | ||
56 | |||
57 | #ifdef SMP_DEBUG | ||
58 | #define SMP_PRINTK(x) printk x | ||
59 | #else | ||
60 | #define SMP_PRINTK(x) | ||
61 | #endif | ||
62 | 26 | ||
63 | static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned long val) | 27 | static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned long val) |
64 | { | 28 | { |
@@ -69,8 +33,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon | |||
69 | } | 33 | } |
70 | 34 | ||
71 | static void smp_setup_percpu_timer(void); | 35 | static void smp_setup_percpu_timer(void); |
72 | extern void cpu_probe(void); | ||
73 | extern void sun4d_distribute_irqs(void); | ||
74 | 36 | ||
75 | static unsigned char cpu_leds[32]; | 37 | static unsigned char cpu_leds[32]; |
76 | 38 | ||
@@ -86,9 +48,8 @@ static inline void show_leds(int cpuid) | |||
86 | void __cpuinit smp4d_callin(void) | 48 | void __cpuinit smp4d_callin(void) |
87 | { | 49 | { |
88 | int cpuid = hard_smp4d_processor_id(); | 50 | int cpuid = hard_smp4d_processor_id(); |
89 | extern spinlock_t sun4d_imsk_lock; | ||
90 | unsigned long flags; | 51 | unsigned long flags; |
91 | 52 | ||
92 | /* Show we are alive */ | 53 | /* Show we are alive */ |
93 | cpu_leds[cpuid] = 0x6; | 54 | cpu_leds[cpuid] = 0x6; |
94 | show_leds(cpuid); | 55 | show_leds(cpuid); |
@@ -118,15 +79,15 @@ void __cpuinit smp4d_callin(void) | |||
118 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); | 79 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); |
119 | local_flush_cache_all(); | 80 | local_flush_cache_all(); |
120 | local_flush_tlb_all(); | 81 | local_flush_tlb_all(); |
121 | 82 | ||
122 | cpu_probe(); | 83 | cpu_probe(); |
123 | 84 | ||
124 | while((unsigned long)current_set[cpuid] < PAGE_OFFSET) | 85 | while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) |
125 | barrier(); | 86 | barrier(); |
126 | 87 | ||
127 | while(current_set[cpuid]->cpu != cpuid) | 88 | while (current_set[cpuid]->cpu != cpuid) |
128 | barrier(); | 89 | barrier(); |
129 | 90 | ||
130 | /* Fix idle thread fields. */ | 91 | /* Fix idle thread fields. */ |
131 | __asm__ __volatile__("ld [%0], %%g6\n\t" | 92 | __asm__ __volatile__("ld [%0], %%g6\n\t" |
132 | : : "r" (¤t_set[cpuid]) | 93 | : : "r" (¤t_set[cpuid]) |
@@ -134,16 +95,16 @@ void __cpuinit smp4d_callin(void) | |||
134 | 95 | ||
135 | cpu_leds[cpuid] = 0x9; | 96 | cpu_leds[cpuid] = 0x9; |
136 | show_leds(cpuid); | 97 | show_leds(cpuid); |
137 | 98 | ||
138 | /* Attach to the address space of init_task. */ | 99 | /* Attach to the address space of init_task. */ |
139 | atomic_inc(&init_mm.mm_count); | 100 | atomic_inc(&init_mm.mm_count); |
140 | current->active_mm = &init_mm; | 101 | current->active_mm = &init_mm; |
141 | 102 | ||
142 | local_flush_cache_all(); | 103 | local_flush_cache_all(); |
143 | local_flush_tlb_all(); | 104 | local_flush_tlb_all(); |
144 | 105 | ||
145 | local_irq_enable(); /* We don't allow PIL 14 yet */ | 106 | local_irq_enable(); /* We don't allow PIL 14 yet */ |
146 | 107 | ||
147 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 108 | while (!cpu_isset(cpuid, smp_commenced_mask)) |
148 | barrier(); | 109 | barrier(); |
149 | 110 | ||
@@ -154,15 +115,9 @@ void __cpuinit smp4d_callin(void) | |||
154 | 115 | ||
155 | } | 116 | } |
156 | 117 | ||
157 | extern void init_IRQ(void); | ||
158 | extern void cpu_panic(void); | ||
159 | |||
160 | /* | 118 | /* |
161 | * Cycle through the processors asking the PROM to start each one. | 119 | * Cycle through the processors asking the PROM to start each one. |
162 | */ | 120 | */ |
163 | |||
164 | extern struct linux_prom_registers smp_penguin_ctable; | ||
165 | |||
166 | void __init smp4d_boot_cpus(void) | 121 | void __init smp4d_boot_cpus(void) |
167 | { | 122 | { |
168 | if (boot_cpu_id) | 123 | if (boot_cpu_id) |
@@ -173,43 +128,42 @@ void __init smp4d_boot_cpus(void) | |||
173 | 128 | ||
174 | int __cpuinit smp4d_boot_one_cpu(int i) | 129 | int __cpuinit smp4d_boot_one_cpu(int i) |
175 | { | 130 | { |
176 | extern unsigned long sun4d_cpu_startup; | 131 | unsigned long *entry = &sun4d_cpu_startup; |
177 | unsigned long *entry = &sun4d_cpu_startup; | 132 | struct task_struct *p; |
178 | struct task_struct *p; | 133 | int timeout; |
179 | int timeout; | 134 | int cpu_node; |
180 | int cpu_node; | ||
181 | 135 | ||
182 | cpu_find_by_instance(i, &cpu_node,NULL); | 136 | cpu_find_by_instance(i, &cpu_node, NULL); |
183 | /* Cook up an idler for this guy. */ | 137 | /* Cook up an idler for this guy. */ |
184 | p = fork_idle(i); | 138 | p = fork_idle(i); |
185 | current_set[i] = task_thread_info(p); | 139 | current_set[i] = task_thread_info(p); |
140 | |||
141 | /* | ||
142 | * Initialize the contexts table | ||
143 | * Since the call to prom_startcpu() trashes the structure, | ||
144 | * we need to re-initialize it for each cpu | ||
145 | */ | ||
146 | smp_penguin_ctable.which_io = 0; | ||
147 | smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys; | ||
148 | smp_penguin_ctable.reg_size = 0; | ||
149 | |||
150 | /* whirrr, whirrr, whirrrrrrrrr... */ | ||
151 | printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); | ||
152 | local_flush_cache_all(); | ||
153 | prom_startcpu(cpu_node, | ||
154 | &smp_penguin_ctable, 0, (char *)entry); | ||
155 | |||
156 | printk(KERN_INFO "prom_startcpu returned :)\n"); | ||
157 | |||
158 | /* wheee... it's going... */ | ||
159 | for (timeout = 0; timeout < 10000; timeout++) { | ||
160 | if (cpu_callin_map[i]) | ||
161 | break; | ||
162 | udelay(200); | ||
163 | } | ||
186 | 164 | ||
187 | /* | ||
188 | * Initialize the contexts table | ||
189 | * Since the call to prom_startcpu() trashes the structure, | ||
190 | * we need to re-initialize it for each cpu | ||
191 | */ | ||
192 | smp_penguin_ctable.which_io = 0; | ||
193 | smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys; | ||
194 | smp_penguin_ctable.reg_size = 0; | ||
195 | |||
196 | /* whirrr, whirrr, whirrrrrrrrr... */ | ||
197 | SMP_PRINTK(("Starting CPU %d at %p\n", i, entry)); | ||
198 | local_flush_cache_all(); | ||
199 | prom_startcpu(cpu_node, | ||
200 | &smp_penguin_ctable, 0, (char *)entry); | ||
201 | |||
202 | SMP_PRINTK(("prom_startcpu returned :)\n")); | ||
203 | |||
204 | /* wheee... it's going... */ | ||
205 | for(timeout = 0; timeout < 10000; timeout++) { | ||
206 | if(cpu_callin_map[i]) | ||
207 | break; | ||
208 | udelay(200); | ||
209 | } | ||
210 | |||
211 | if (!(cpu_callin_map[i])) { | 165 | if (!(cpu_callin_map[i])) { |
212 | printk("Processor %d is stuck.\n", i); | 166 | printk(KERN_ERR "Processor %d is stuck.\n", i); |
213 | return -ENODEV; | 167 | return -ENODEV; |
214 | 168 | ||
215 | } | 169 | } |
@@ -255,14 +209,17 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
255 | unsigned long arg2, unsigned long arg3, | 209 | unsigned long arg2, unsigned long arg3, |
256 | unsigned long arg4) | 210 | unsigned long arg4) |
257 | { | 211 | { |
258 | if(smp_processors_ready) { | 212 | if (smp_processors_ready) { |
259 | register int high = smp_highest_cpu; | 213 | register int high = smp_highest_cpu; |
260 | unsigned long flags; | 214 | unsigned long flags; |
261 | 215 | ||
262 | spin_lock_irqsave(&cross_call_lock, flags); | 216 | spin_lock_irqsave(&cross_call_lock, flags); |
263 | 217 | ||
264 | { | 218 | { |
265 | /* If you make changes here, make sure gcc generates proper code... */ | 219 | /* |
220 | * If you make changes here, make sure | ||
221 | * gcc generates proper code... | ||
222 | */ | ||
266 | register smpfunc_t f asm("i0") = func; | 223 | register smpfunc_t f asm("i0") = func; |
267 | register unsigned long a1 asm("i1") = arg1; | 224 | register unsigned long a1 asm("i1") = arg1; |
268 | register unsigned long a2 asm("i2") = arg2; | 225 | register unsigned long a2 asm("i2") = arg2; |
@@ -284,7 +241,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
284 | 241 | ||
285 | cpu_clear(smp_processor_id(), mask); | 242 | cpu_clear(smp_processor_id(), mask); |
286 | cpus_and(mask, cpu_online_map, mask); | 243 | cpus_and(mask, cpu_online_map, mask); |
287 | for(i = 0; i <= high; i++) { | 244 | for (i = 0; i <= high; i++) { |
288 | if (cpu_isset(i, mask)) { | 245 | if (cpu_isset(i, mask)) { |
289 | ccall_info.processors_in[i] = 0; | 246 | ccall_info.processors_in[i] = 0; |
290 | ccall_info.processors_out[i] = 0; | 247 | ccall_info.processors_out[i] = 0; |
@@ -300,17 +257,17 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
300 | do { | 257 | do { |
301 | if (!cpu_isset(i, mask)) | 258 | if (!cpu_isset(i, mask)) |
302 | continue; | 259 | continue; |
303 | while(!ccall_info.processors_in[i]) | 260 | while (!ccall_info.processors_in[i]) |
304 | barrier(); | 261 | barrier(); |
305 | } while(++i <= high); | 262 | } while (++i <= high); |
306 | 263 | ||
307 | i = 0; | 264 | i = 0; |
308 | do { | 265 | do { |
309 | if (!cpu_isset(i, mask)) | 266 | if (!cpu_isset(i, mask)) |
310 | continue; | 267 | continue; |
311 | while(!ccall_info.processors_out[i]) | 268 | while (!ccall_info.processors_out[i]) |
312 | barrier(); | 269 | barrier(); |
313 | } while(++i <= high); | 270 | } while (++i <= high); |
314 | } | 271 | } |
315 | 272 | ||
316 | spin_unlock_irqrestore(&cross_call_lock, flags); | 273 | spin_unlock_irqrestore(&cross_call_lock, flags); |
@@ -336,7 +293,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
336 | static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; | 293 | static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; |
337 | 294 | ||
338 | old_regs = set_irq_regs(regs); | 295 | old_regs = set_irq_regs(regs); |
339 | bw_get_prof_limit(cpu); | 296 | bw_get_prof_limit(cpu); |
340 | bw_clear_intr_mask(0, 1); /* INTR_TABLE[0] & 1 is Profile IRQ */ | 297 | bw_clear_intr_mask(0, 1); /* INTR_TABLE[0] & 1 is Profile IRQ */ |
341 | 298 | ||
342 | cpu_tick[cpu]++; | 299 | cpu_tick[cpu]++; |
@@ -349,7 +306,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
349 | 306 | ||
350 | profile_tick(CPU_PROFILING); | 307 | profile_tick(CPU_PROFILING); |
351 | 308 | ||
352 | if(!--prof_counter(cpu)) { | 309 | if (!--prof_counter(cpu)) { |
353 | int user = user_mode(regs); | 310 | int user = user_mode(regs); |
354 | 311 | ||
355 | irq_enter(); | 312 | irq_enter(); |
@@ -361,8 +318,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
361 | set_irq_regs(old_regs); | 318 | set_irq_regs(old_regs); |
362 | } | 319 | } |
363 | 320 | ||
364 | extern unsigned int lvl14_resolution; | ||
365 | |||
366 | static void __cpuinit smp_setup_percpu_timer(void) | 321 | static void __cpuinit smp_setup_percpu_timer(void) |
367 | { | 322 | { |
368 | int cpu = hard_smp4d_processor_id(); | 323 | int cpu = hard_smp4d_processor_id(); |
@@ -374,16 +329,16 @@ static void __cpuinit smp_setup_percpu_timer(void) | |||
374 | void __init smp4d_blackbox_id(unsigned *addr) | 329 | void __init smp4d_blackbox_id(unsigned *addr) |
375 | { | 330 | { |
376 | int rd = *addr & 0x3e000000; | 331 | int rd = *addr & 0x3e000000; |
377 | 332 | ||
378 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ | 333 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ |
379 | addr[1] = 0x01000000; /* nop */ | 334 | addr[1] = 0x01000000; /* nop */ |
380 | addr[2] = 0x01000000; /* nop */ | 335 | addr[2] = 0x01000000; /* nop */ |
381 | } | 336 | } |
382 | 337 | ||
383 | void __init smp4d_blackbox_current(unsigned *addr) | 338 | void __init smp4d_blackbox_current(unsigned *addr) |
384 | { | 339 | { |
385 | int rd = *addr & 0x3e000000; | 340 | int rd = *addr & 0x3e000000; |
386 | 341 | ||
387 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ | 342 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ |
388 | addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ | 343 | addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ |
389 | addr[4] = 0x01000000; /* nop */ | 344 | addr[4] = 0x01000000; /* nop */ |
@@ -392,17 +347,16 @@ void __init smp4d_blackbox_current(unsigned *addr) | |||
392 | void __init sun4d_init_smp(void) | 347 | void __init sun4d_init_smp(void) |
393 | { | 348 | { |
394 | int i; | 349 | int i; |
395 | extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[]; | ||
396 | 350 | ||
397 | /* Patch ipi15 trap table */ | 351 | /* Patch ipi15 trap table */ |
398 | t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); | 352 | t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); |
399 | 353 | ||
400 | /* And set btfixup... */ | 354 | /* And set btfixup... */ |
401 | BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); | 355 | BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); |
402 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); | 356 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); |
403 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); | 357 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); |
404 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); | 358 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); |
405 | 359 | ||
406 | for (i = 0; i < NR_CPUS; i++) { | 360 | for (i = 0; i < NR_CPUS; i++) { |
407 | ccall_info.processors_in[i] = 1; | 361 | ccall_info.processors_in[i] = 1; |
408 | ccall_info.processors_out[i] = 1; | 362 | ccall_info.processors_out[i] = 1; |
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 7f3b97ff62c1..69df6257a32e 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* sun4m_irq.c | 1 | /* |
2 | * arch/sparc/kernel/sun4m_irq.c: | 2 | * sun4m irq support |
3 | * | 3 | * |
4 | * djhr: Hacked out of irq.c into a CPU dependent version. | 4 | * djhr: Hacked out of irq.c into a CPU dependent version. |
5 | * | 5 | * |
@@ -9,101 +9,44 @@ | |||
9 | * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) | 9 | * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <linux/kernel_stat.h> | ||
15 | #include <linux/signal.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/smp.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
24 | |||
25 | #include <asm/ptrace.h> | ||
26 | #include <asm/processor.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/psr.h> | ||
29 | #include <asm/vaddrs.h> | ||
30 | #include <asm/timer.h> | 12 | #include <asm/timer.h> |
31 | #include <asm/openprom.h> | ||
32 | #include <asm/oplib.h> | ||
33 | #include <asm/traps.h> | 13 | #include <asm/traps.h> |
34 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
35 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
36 | #include <asm/smp.h> | ||
37 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
38 | #include <asm/io.h> | 17 | #include <asm/io.h> |
39 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
40 | 19 | ||
41 | #include "irq.h" | 20 | #include "irq.h" |
21 | #include "kernel.h" | ||
42 | 22 | ||
43 | struct sun4m_irq_percpu { | 23 | /* Sample sun4m IRQ layout: |
44 | u32 pending; | 24 | * |
45 | u32 clear; | 25 | * 0x22 - Power |
46 | u32 set; | 26 | * 0x24 - ESP SCSI |
47 | }; | 27 | * 0x26 - Lance ethernet |
48 | 28 | * 0x2b - Floppy | |
49 | struct sun4m_irq_global { | 29 | * 0x2c - Zilog uart |
50 | u32 pending; | 30 | * 0x32 - SBUS level 0 |
51 | u32 mask; | 31 | * 0x33 - Parallel port, SBUS level 1 |
52 | u32 mask_clear; | 32 | * 0x35 - SBUS level 2 |
53 | u32 mask_set; | 33 | * 0x37 - SBUS level 3 |
54 | u32 interrupt_target; | 34 | * 0x39 - Audio, Graphics card, SBUS level 4 |
55 | }; | 35 | * 0x3b - SBUS level 5 |
56 | 36 | * 0x3d - SBUS level 6 | |
57 | /* Code in entry.S needs to get at these register mappings. */ | 37 | * |
58 | struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | 38 | * Each interrupt source has a mask bit in the interrupt registers. |
59 | struct sun4m_irq_global __iomem *sun4m_irq_global; | 39 | * When the mask bit is set, this blocks interrupt deliver. So you |
60 | 40 | * clear the bit to enable the interrupt. | |
61 | /* Dave Redman (djhr@tadpole.co.uk) | 41 | * |
62 | * The sun4m interrupt registers. | 42 | * Interrupts numbered less than 0x10 are software triggered interrupts |
63 | */ | 43 | * and unused by Linux. |
64 | #define SUN4M_INT_ENABLE 0x80000000 | 44 | * |
65 | #define SUN4M_INT_E14 0x00000080 | 45 | * Interrupt level assignment on sun4m: |
66 | #define SUN4M_INT_E10 0x00080000 | ||
67 | |||
68 | #define SUN4M_HARD_INT(x) (0x000000001 << (x)) | ||
69 | #define SUN4M_SOFT_INT(x) (0x000010000 << (x)) | ||
70 | |||
71 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ | ||
72 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ | ||
73 | #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ | ||
74 | #define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ | ||
75 | #define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ | ||
76 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ | ||
77 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ | ||
78 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ | ||
79 | #define SUN4M_INT_REALTIME 0x00080000 /* system timer */ | ||
80 | #define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ | ||
81 | #define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ | ||
82 | #define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ | ||
83 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ | ||
84 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ | ||
85 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ | ||
86 | #define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ | ||
87 | |||
88 | #define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ | ||
89 | SUN4M_INT_M2S_WRITE_ERR | \ | ||
90 | SUN4M_INT_ECC_ERR | \ | ||
91 | SUN4M_INT_VME_ERR) | ||
92 | |||
93 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) | ||
94 | #define SUN4M_INT_VME(x) (1 << (x)) | ||
95 | |||
96 | /* Interrupt levels used by OBP */ | ||
97 | #define OBP_INT_LEVEL_SOFT 0x10 | ||
98 | #define OBP_INT_LEVEL_ONBOARD 0x20 | ||
99 | #define OBP_INT_LEVEL_SBUS 0x30 | ||
100 | #define OBP_INT_LEVEL_VME 0x40 | ||
101 | |||
102 | /* Interrupt level assignment on sun4m: | ||
103 | * | 46 | * |
104 | * level source | 47 | * level source |
105 | * ------------------------------------------------------------ | 48 | * ------------------------------------------------------------ |
106 | * 1 softint-1 | 49 | * 1 softint-1 |
107 | * 2 softint-2, VME/SBUS level 1 | 50 | * 2 softint-2, VME/SBUS level 1 |
108 | * 3 softint-3, VME/SBUS level 2 | 51 | * 3 softint-3, VME/SBUS level 2 |
109 | * 4 softint-4, onboard SCSI | 52 | * 4 softint-4, onboard SCSI |
@@ -138,10 +81,10 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; | |||
138 | * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and | 81 | * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and |
139 | * Tadpole S3 GX systems. | 82 | * Tadpole S3 GX systems. |
140 | * | 83 | * |
141 | * esp: 0x24 onboard ESP SCSI | 84 | * esp: 0x24 onboard ESP SCSI |
142 | * le: 0x26 onboard Lance ETHERNET | 85 | * le: 0x26 onboard Lance ETHERNET |
143 | * p9100: 0x32 SBUS level 1 P9100 video | 86 | * p9100: 0x32 SBUS level 1 P9100 video |
144 | * bpp: 0x33 SBUS level 2 BPP parallel port device | 87 | * bpp: 0x33 SBUS level 2 BPP parallel port device |
145 | * DBRI: 0x39 SBUS level 5 DBRI ISDN audio | 88 | * DBRI: 0x39 SBUS level 5 DBRI ISDN audio |
146 | * SUNW,leo: 0x39 SBUS level 5 LEO video | 89 | * SUNW,leo: 0x39 SBUS level 5 LEO video |
147 | * pcmcia: 0x3b SBUS level 6 PCMCIA controller | 90 | * pcmcia: 0x3b SBUS level 6 PCMCIA controller |
@@ -152,8 +95,57 @@ struct sun4m_irq_global __iomem *sun4m_irq_global; | |||
152 | * power: 0x22 onboard power device (XXX unknown mask bit XXX) | 95 | * power: 0x22 onboard power device (XXX unknown mask bit XXX) |
153 | */ | 96 | */ |
154 | 97 | ||
98 | |||
99 | /* Code in entry.S needs to get at these register mappings. */ | ||
100 | struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | ||
101 | struct sun4m_irq_global __iomem *sun4m_irq_global; | ||
102 | |||
103 | /* Dave Redman (djhr@tadpole.co.uk) | ||
104 | * The sun4m interrupt registers. | ||
105 | */ | ||
106 | #define SUN4M_INT_ENABLE 0x80000000 | ||
107 | #define SUN4M_INT_E14 0x00000080 | ||
108 | #define SUN4M_INT_E10 0x00080000 | ||
109 | |||
110 | #define SUN4M_HARD_INT(x) (0x000000001 << (x)) | ||
111 | #define SUN4M_SOFT_INT(x) (0x000010000 << (x)) | ||
112 | |||
113 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ | ||
114 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ | ||
115 | #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ | ||
116 | #define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ | ||
117 | #define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ | ||
118 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ | ||
119 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ | ||
120 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ | ||
121 | #define SUN4M_INT_REALTIME 0x00080000 /* system timer */ | ||
122 | #define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ | ||
123 | #define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ | ||
124 | #define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ | ||
125 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ | ||
126 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ | ||
127 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ | ||
128 | #define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ | ||
129 | |||
130 | #define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ | ||
131 | SUN4M_INT_M2S_WRITE_ERR | \ | ||
132 | SUN4M_INT_ECC_ERR | \ | ||
133 | SUN4M_INT_VME_ERR) | ||
134 | |||
135 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) | ||
136 | #define SUN4M_INT_VME(x) (1 << (x)) | ||
137 | |||
138 | /* Interrupt levels used by OBP */ | ||
139 | #define OBP_INT_LEVEL_SOFT 0x10 | ||
140 | #define OBP_INT_LEVEL_ONBOARD 0x20 | ||
141 | #define OBP_INT_LEVEL_SBUS 0x30 | ||
142 | #define OBP_INT_LEVEL_VME 0x40 | ||
143 | |||
144 | #define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) | ||
145 | #define SUM4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14) | ||
146 | |||
155 | static unsigned long irq_mask[0x50] = { | 147 | static unsigned long irq_mask[0x50] = { |
156 | /* SMP */ | 148 | /* 0x00 - SMP */ |
157 | 0, SUN4M_SOFT_INT(1), | 149 | 0, SUN4M_SOFT_INT(1), |
158 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), | 150 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
159 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), | 151 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
@@ -162,7 +154,7 @@ static unsigned long irq_mask[0x50] = { | |||
162 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | 154 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
163 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), | 155 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
164 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), | 156 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
165 | /* soft */ | 157 | /* 0x10 - soft */ |
166 | 0, SUN4M_SOFT_INT(1), | 158 | 0, SUN4M_SOFT_INT(1), |
167 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), | 159 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
168 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), | 160 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
@@ -171,19 +163,19 @@ static unsigned long irq_mask[0x50] = { | |||
171 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | 163 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
172 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), | 164 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
173 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), | 165 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
174 | /* onboard */ | 166 | /* 0x20 - onboard */ |
175 | 0, 0, 0, 0, | 167 | 0, 0, 0, 0, |
176 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, | 168 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, |
177 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, | 169 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, |
178 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, | 170 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, |
179 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), | 171 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), |
180 | SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, | 172 | SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, |
181 | /* sbus */ | 173 | /* 0x30 - sbus */ |
182 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), | 174 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), |
183 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), | 175 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), |
184 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), | 176 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), |
185 | 0, SUN4M_INT_SBUS(6), 0, 0, | 177 | 0, SUN4M_INT_SBUS(6), 0, 0, |
186 | /* vme */ | 178 | /* 0x40 - vme */ |
187 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), | 179 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), |
188 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), | 180 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), |
189 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), | 181 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), |
@@ -193,7 +185,7 @@ static unsigned long irq_mask[0x50] = { | |||
193 | static unsigned long sun4m_get_irqmask(unsigned int irq) | 185 | static unsigned long sun4m_get_irqmask(unsigned int irq) |
194 | { | 186 | { |
195 | unsigned long mask; | 187 | unsigned long mask; |
196 | 188 | ||
197 | if (irq < 0x50) | 189 | if (irq < 0x50) |
198 | mask = irq_mask[irq]; | 190 | mask = irq_mask[irq]; |
199 | else | 191 | else |
@@ -217,7 +209,7 @@ static void sun4m_disable_irq(unsigned int irq_nr) | |||
217 | sbus_writel(mask, &sun4m_irq_global->mask_set); | 209 | sbus_writel(mask, &sun4m_irq_global->mask_set); |
218 | else | 210 | else |
219 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); | 211 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); |
220 | local_irq_restore(flags); | 212 | local_irq_restore(flags); |
221 | } | 213 | } |
222 | 214 | ||
223 | static void sun4m_enable_irq(unsigned int irq_nr) | 215 | static void sun4m_enable_irq(unsigned int irq_nr) |
@@ -226,17 +218,17 @@ static void sun4m_enable_irq(unsigned int irq_nr) | |||
226 | int cpu = smp_processor_id(); | 218 | int cpu = smp_processor_id(); |
227 | 219 | ||
228 | /* Dreadful floppy hack. When we use 0x2b instead of | 220 | /* Dreadful floppy hack. When we use 0x2b instead of |
229 | * 0x0b the system blows (it starts to whistle!). | 221 | * 0x0b the system blows (it starts to whistle!). |
230 | * So we continue to use 0x0b. Fixme ASAP. --P3 | 222 | * So we continue to use 0x0b. Fixme ASAP. --P3 |
231 | */ | 223 | */ |
232 | if (irq_nr != 0x0b) { | 224 | if (irq_nr != 0x0b) { |
233 | mask = sun4m_get_irqmask(irq_nr); | 225 | mask = sun4m_get_irqmask(irq_nr); |
234 | local_irq_save(flags); | 226 | local_irq_save(flags); |
235 | if (irq_nr > 15) | 227 | if (irq_nr > 15) |
236 | sbus_writel(mask, &sun4m_irq_global->mask_clear); | 228 | sbus_writel(mask, &sun4m_irq_global->mask_clear); |
237 | else | 229 | else |
238 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); | 230 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); |
239 | local_irq_restore(flags); | 231 | local_irq_restore(flags); |
240 | } else { | 232 | } else { |
241 | local_irq_save(flags); | 233 | local_irq_save(flags); |
242 | sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); | 234 | sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); |
@@ -260,7 +252,7 @@ static unsigned long cpu_pil_to_imask[16] = { | |||
260 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, | 252 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, |
261 | /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, | 253 | /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, |
262 | /*14*/ SUN4M_INT_E14, | 254 | /*14*/ SUN4M_INT_E14, |
263 | /*15*/ SUN4M_INT_ERROR | 255 | /*15*/ SUN4M_INT_ERROR, |
264 | }; | 256 | }; |
265 | 257 | ||
266 | /* We assume the caller has disabled local interrupts when these are called, | 258 | /* We assume the caller has disabled local interrupts when these are called, |
@@ -280,12 +272,14 @@ static void sun4m_enable_pil_irq(unsigned int pil) | |||
280 | static void sun4m_send_ipi(int cpu, int level) | 272 | static void sun4m_send_ipi(int cpu, int level) |
281 | { | 273 | { |
282 | unsigned long mask = sun4m_get_irqmask(level); | 274 | unsigned long mask = sun4m_get_irqmask(level); |
275 | |||
283 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); | 276 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); |
284 | } | 277 | } |
285 | 278 | ||
286 | static void sun4m_clear_ipi(int cpu, int level) | 279 | static void sun4m_clear_ipi(int cpu, int level) |
287 | { | 280 | { |
288 | unsigned long mask = sun4m_get_irqmask(level); | 281 | unsigned long mask = sun4m_get_irqmask(level); |
282 | |||
289 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); | 283 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); |
290 | } | 284 | } |
291 | 285 | ||
@@ -314,7 +308,6 @@ struct sun4m_timer_global { | |||
314 | 308 | ||
315 | static struct sun4m_timer_global __iomem *timers_global; | 309 | static struct sun4m_timer_global __iomem *timers_global; |
316 | 310 | ||
317 | #define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) | ||
318 | 311 | ||
319 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); | 312 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); |
320 | 313 | ||
@@ -391,7 +384,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
391 | 384 | ||
392 | master_l10_counter = &timers_global->l10_count; | 385 | master_l10_counter = &timers_global->l10_count; |
393 | 386 | ||
394 | err = request_irq(TIMER_IRQ, counter_fn, | 387 | err = request_irq(SUN4M_TIMER_IRQ, counter_fn, |
395 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | 388 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); |
396 | if (err) { | 389 | if (err) { |
397 | printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", | 390 | printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", |
@@ -407,7 +400,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
407 | #ifdef CONFIG_SMP | 400 | #ifdef CONFIG_SMP |
408 | { | 401 | { |
409 | unsigned long flags; | 402 | unsigned long flags; |
410 | extern unsigned long lvl14_save[4]; | ||
411 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; | 403 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; |
412 | 404 | ||
413 | /* For SMP we use the level 14 ticker, however the bootup code | 405 | /* For SMP we use the level 14 ticker, however the bootup code |
@@ -466,7 +458,9 @@ void __init sun4m_init_IRQ(void) | |||
466 | BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); | 458 | BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); |
467 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); | 459 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); |
468 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); | 460 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); |
469 | sparc_init_timers = sun4m_init_timers; | 461 | |
462 | sparc_irq_config.init_timers = sun4m_init_timers; | ||
463 | |||
470 | #ifdef CONFIG_SMP | 464 | #ifdef CONFIG_SMP |
471 | BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); | 465 | BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); |
472 | BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); | 466 | BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); |
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 762d6eedd944..5cc7dc51de3d 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
@@ -1,59 +1,22 @@ | |||
1 | /* sun4m_smp.c: Sparc SUN4M SMP support. | 1 | /* |
2 | * sun4m SMP support. | ||
2 | * | 3 | * |
3 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | 4 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) |
4 | */ | 5 | */ |
5 | 6 | ||
6 | #include <asm/head.h> | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/threads.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/interrupt.h> | 7 | #include <linux/interrupt.h> |
13 | #include <linux/kernel_stat.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/swap.h> | ||
18 | #include <linux/profile.h> | 8 | #include <linux/profile.h> |
19 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
20 | #include <linux/cpu.h> | 10 | #include <linux/cpu.h> |
21 | 11 | ||
22 | #include <asm/cacheflush.h> | 12 | #include <asm/cacheflush.h> |
23 | #include <asm/tlbflush.h> | 13 | #include <asm/tlbflush.h> |
24 | #include <asm/irq_regs.h> | ||
25 | |||
26 | #include <asm/ptrace.h> | ||
27 | #include <asm/atomic.h> | ||
28 | |||
29 | #include <asm/irq.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/pgalloc.h> | ||
32 | #include <asm/pgtable.h> | ||
33 | #include <asm/oplib.h> | ||
34 | #include <asm/cpudata.h> | ||
35 | 14 | ||
36 | #include "irq.h" | 15 | #include "irq.h" |
16 | #include "kernel.h" | ||
37 | 17 | ||
38 | #define IRQ_CROSS_CALL 15 | 18 | #define IRQ_CROSS_CALL 15 |
39 | 19 | ||
40 | extern ctxd_t *srmmu_ctx_table_phys; | ||
41 | |||
42 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | ||
43 | extern unsigned char boot_cpu_id; | ||
44 | |||
45 | extern cpumask_t smp_commenced_mask; | ||
46 | |||
47 | extern int __smp4m_processor_id(void); | ||
48 | |||
49 | /*#define SMP_DEBUG*/ | ||
50 | |||
51 | #ifdef SMP_DEBUG | ||
52 | #define SMP_PRINTK(x) printk x | ||
53 | #else | ||
54 | #define SMP_PRINTK(x) | ||
55 | #endif | ||
56 | |||
57 | static inline unsigned long | 20 | static inline unsigned long |
58 | swap_ulong(volatile unsigned long *ptr, unsigned long val) | 21 | swap_ulong(volatile unsigned long *ptr, unsigned long val) |
59 | { | 22 | { |
@@ -64,7 +27,6 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) | |||
64 | } | 27 | } |
65 | 28 | ||
66 | static void smp_setup_percpu_timer(void); | 29 | static void smp_setup_percpu_timer(void); |
67 | extern void cpu_probe(void); | ||
68 | 30 | ||
69 | void __cpuinit smp4m_callin(void) | 31 | void __cpuinit smp4m_callin(void) |
70 | { | 32 | { |
@@ -96,7 +58,7 @@ void __cpuinit smp4m_callin(void) | |||
96 | /* XXX: What's up with all the flushes? */ | 58 | /* XXX: What's up with all the flushes? */ |
97 | local_flush_cache_all(); | 59 | local_flush_cache_all(); |
98 | local_flush_tlb_all(); | 60 | local_flush_tlb_all(); |
99 | 61 | ||
100 | cpu_probe(); | 62 | cpu_probe(); |
101 | 63 | ||
102 | /* Fix idle thread fields. */ | 64 | /* Fix idle thread fields. */ |
@@ -119,9 +81,6 @@ void __cpuinit smp4m_callin(void) | |||
119 | /* | 81 | /* |
120 | * Cycle through the processors asking the PROM to start each one. | 82 | * Cycle through the processors asking the PROM to start each one. |
121 | */ | 83 | */ |
122 | |||
123 | extern struct linux_prom_registers smp_penguin_ctable; | ||
124 | |||
125 | void __init smp4m_boot_cpus(void) | 84 | void __init smp4m_boot_cpus(void) |
126 | { | 85 | { |
127 | smp_setup_percpu_timer(); | 86 | smp_setup_percpu_timer(); |
@@ -130,7 +89,6 @@ void __init smp4m_boot_cpus(void) | |||
130 | 89 | ||
131 | int __cpuinit smp4m_boot_one_cpu(int i) | 90 | int __cpuinit smp4m_boot_one_cpu(int i) |
132 | { | 91 | { |
133 | extern unsigned long sun4m_cpu_startup; | ||
134 | unsigned long *entry = &sun4m_cpu_startup; | 92 | unsigned long *entry = &sun4m_cpu_startup; |
135 | struct task_struct *p; | 93 | struct task_struct *p; |
136 | int timeout; | 94 | int timeout; |
@@ -142,7 +100,7 @@ int __cpuinit smp4m_boot_one_cpu(int i) | |||
142 | p = fork_idle(i); | 100 | p = fork_idle(i); |
143 | current_set[i] = task_thread_info(p); | 101 | current_set[i] = task_thread_info(p); |
144 | /* See trampoline.S for details... */ | 102 | /* See trampoline.S for details... */ |
145 | entry += ((i-1) * 3); | 103 | entry += ((i - 1) * 3); |
146 | 104 | ||
147 | /* | 105 | /* |
148 | * Initialize the contexts table | 106 | * Initialize the contexts table |
@@ -154,20 +112,19 @@ int __cpuinit smp4m_boot_one_cpu(int i) | |||
154 | smp_penguin_ctable.reg_size = 0; | 112 | smp_penguin_ctable.reg_size = 0; |
155 | 113 | ||
156 | /* whirrr, whirrr, whirrrrrrrrr... */ | 114 | /* whirrr, whirrr, whirrrrrrrrr... */ |
157 | printk("Starting CPU %d at %p\n", i, entry); | 115 | printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); |
158 | local_flush_cache_all(); | 116 | local_flush_cache_all(); |
159 | prom_startcpu(cpu_node, | 117 | prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); |
160 | &smp_penguin_ctable, 0, (char *)entry); | ||
161 | 118 | ||
162 | /* wheee... it's going... */ | 119 | /* wheee... it's going... */ |
163 | for(timeout = 0; timeout < 10000; timeout++) { | 120 | for (timeout = 0; timeout < 10000; timeout++) { |
164 | if(cpu_callin_map[i]) | 121 | if (cpu_callin_map[i]) |
165 | break; | 122 | break; |
166 | udelay(200); | 123 | udelay(200); |
167 | } | 124 | } |
168 | 125 | ||
169 | if (!(cpu_callin_map[i])) { | 126 | if (!(cpu_callin_map[i])) { |
170 | printk("Processor %d is stuck.\n", i); | 127 | printk(KERN_ERR "Processor %d is stuck.\n", i); |
171 | return -ENODEV; | 128 | return -ENODEV; |
172 | } | 129 | } |
173 | 130 | ||
@@ -202,6 +159,7 @@ void __init smp4m_smp_done(void) | |||
202 | void smp4m_irq_rotate(int cpu) | 159 | void smp4m_irq_rotate(int cpu) |
203 | { | 160 | { |
204 | int next = cpu_data(cpu).next; | 161 | int next = cpu_data(cpu).next; |
162 | |||
205 | if (next != cpu) | 163 | if (next != cpu) |
206 | set_irq_udt(next); | 164 | set_irq_udt(next); |
207 | } | 165 | } |
@@ -243,7 +201,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
243 | 201 | ||
244 | cpu_clear(smp_processor_id(), mask); | 202 | cpu_clear(smp_processor_id(), mask); |
245 | cpus_and(mask, cpu_online_map, mask); | 203 | cpus_and(mask, cpu_online_map, mask); |
246 | for(i = 0; i < ncpus; i++) { | 204 | for (i = 0; i < ncpus; i++) { |
247 | if (cpu_isset(i, mask)) { | 205 | if (cpu_isset(i, mask)) { |
248 | ccall_info.processors_in[i] = 0; | 206 | ccall_info.processors_in[i] = 0; |
249 | ccall_info.processors_out[i] = 0; | 207 | ccall_info.processors_out[i] = 0; |
@@ -262,19 +220,18 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
262 | do { | 220 | do { |
263 | if (!cpu_isset(i, mask)) | 221 | if (!cpu_isset(i, mask)) |
264 | continue; | 222 | continue; |
265 | while(!ccall_info.processors_in[i]) | 223 | while (!ccall_info.processors_in[i]) |
266 | barrier(); | 224 | barrier(); |
267 | } while(++i < ncpus); | 225 | } while (++i < ncpus); |
268 | 226 | ||
269 | i = 0; | 227 | i = 0; |
270 | do { | 228 | do { |
271 | if (!cpu_isset(i, mask)) | 229 | if (!cpu_isset(i, mask)) |
272 | continue; | 230 | continue; |
273 | while(!ccall_info.processors_out[i]) | 231 | while (!ccall_info.processors_out[i]) |
274 | barrier(); | 232 | barrier(); |
275 | } while(++i < ncpus); | 233 | } while (++i < ncpus); |
276 | } | 234 | } |
277 | |||
278 | spin_unlock_irqrestore(&cross_call_lock, flags); | 235 | spin_unlock_irqrestore(&cross_call_lock, flags); |
279 | } | 236 | } |
280 | 237 | ||
@@ -289,8 +246,6 @@ void smp4m_cross_call_irq(void) | |||
289 | ccall_info.processors_out[i] = 1; | 246 | ccall_info.processors_out[i] = 1; |
290 | } | 247 | } |
291 | 248 | ||
292 | extern void sun4m_clear_profile_irq(int cpu); | ||
293 | |||
294 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | 249 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) |
295 | { | 250 | { |
296 | struct pt_regs *old_regs; | 251 | struct pt_regs *old_regs; |
@@ -302,7 +257,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
302 | 257 | ||
303 | profile_tick(CPU_PROFILING); | 258 | profile_tick(CPU_PROFILING); |
304 | 259 | ||
305 | if(!--prof_counter(cpu)) { | 260 | if (!--prof_counter(cpu)) { |
306 | int user = user_mode(regs); | 261 | int user = user_mode(regs); |
307 | 262 | ||
308 | irq_enter(); | 263 | irq_enter(); |
@@ -314,8 +269,6 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
314 | set_irq_regs(old_regs); | 269 | set_irq_regs(old_regs); |
315 | } | 270 | } |
316 | 271 | ||
317 | extern unsigned int lvl14_resolution; | ||
318 | |||
319 | static void __cpuinit smp_setup_percpu_timer(void) | 272 | static void __cpuinit smp_setup_percpu_timer(void) |
320 | { | 273 | { |
321 | int cpu = smp_processor_id(); | 274 | int cpu = smp_processor_id(); |
@@ -323,7 +276,7 @@ static void __cpuinit smp_setup_percpu_timer(void) | |||
323 | prof_counter(cpu) = prof_multiplier(cpu) = 1; | 276 | prof_counter(cpu) = prof_multiplier(cpu) = 1; |
324 | load_profile_irq(cpu, lvl14_resolution); | 277 | load_profile_irq(cpu, lvl14_resolution); |
325 | 278 | ||
326 | if(cpu == boot_cpu_id) | 279 | if (cpu == boot_cpu_id) |
327 | enable_pil_irq(14); | 280 | enable_pil_irq(14); |
328 | } | 281 | } |
329 | 282 | ||
@@ -331,9 +284,9 @@ static void __init smp4m_blackbox_id(unsigned *addr) | |||
331 | { | 284 | { |
332 | int rd = *addr & 0x3e000000; | 285 | int rd = *addr & 0x3e000000; |
333 | int rs1 = rd >> 11; | 286 | int rs1 = rd >> 11; |
334 | 287 | ||
335 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ | 288 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ |
336 | addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */ | 289 | addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */ |
337 | addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */ | 290 | addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */ |
338 | } | 291 | } |
339 | 292 | ||
@@ -341,9 +294,9 @@ static void __init smp4m_blackbox_current(unsigned *addr) | |||
341 | { | 294 | { |
342 | int rd = *addr & 0x3e000000; | 295 | int rd = *addr & 0x3e000000; |
343 | int rs1 = rd >> 11; | 296 | int rs1 = rd >> 11; |
344 | 297 | ||
345 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ | 298 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ |
346 | addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */ | 299 | addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */ |
347 | addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */ | 300 | addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */ |
348 | } | 301 | } |
349 | 302 | ||
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index f836f4e93afe..96082d30def0 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -360,20 +360,25 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u | |||
360 | } | 360 | } |
361 | EXPORT_SYMBOL(get_fb_unmapped_area); | 361 | EXPORT_SYMBOL(get_fb_unmapped_area); |
362 | 362 | ||
363 | /* Essentially the same as PowerPC... */ | 363 | /* Essentially the same as PowerPC. */ |
364 | void arch_pick_mmap_layout(struct mm_struct *mm) | 364 | static unsigned long mmap_rnd(void) |
365 | { | 365 | { |
366 | unsigned long random_factor = 0UL; | 366 | unsigned long rnd = 0UL; |
367 | unsigned long gap; | ||
368 | 367 | ||
369 | if (current->flags & PF_RANDOMIZE) { | 368 | if (current->flags & PF_RANDOMIZE) { |
370 | random_factor = get_random_int(); | 369 | unsigned long val = get_random_int(); |
371 | if (test_thread_flag(TIF_32BIT)) | 370 | if (test_thread_flag(TIF_32BIT)) |
372 | random_factor &= ((1 * 1024 * 1024) - 1); | 371 | rnd = (val % (1UL << (22UL-PAGE_SHIFT))); |
373 | else | 372 | else |
374 | random_factor = ((random_factor << PAGE_SHIFT) & | 373 | rnd = (val % (1UL << (29UL-PAGE_SHIFT))); |
375 | 0xffffffffUL); | ||
376 | } | 374 | } |
375 | return (rnd << PAGE_SHIFT) * 2; | ||
376 | } | ||
377 | |||
378 | void arch_pick_mmap_layout(struct mm_struct *mm) | ||
379 | { | ||
380 | unsigned long random_factor = mmap_rnd(); | ||
381 | unsigned long gap; | ||
377 | 382 | ||
378 | /* | 383 | /* |
379 | * Fall back to the standard layout if the personality | 384 | * Fall back to the standard layout if the personality |
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c deleted file mode 100644 index 138bbf5f8724..000000000000 --- a/arch/sparc/kernel/tick14.c +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | /* tick14.c | ||
2 | * | ||
3 | * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) | ||
4 | * | ||
5 | * This file handles the Sparc specific level14 ticker | ||
6 | * This is really useful for profiling OBP uses it for keyboard | ||
7 | * aborts and other stuff. | ||
8 | */ | ||
9 | #include <linux/kernel.h> | ||
10 | |||
11 | extern unsigned long lvl14_save[5]; | ||
12 | static unsigned long *linux_lvl14 = NULL; | ||
13 | static unsigned long obp_lvl14[4]; | ||
14 | |||
15 | /* | ||
16 | * Call with timer IRQ closed. | ||
17 | * First time we do it with disable_irq, later prom code uses spin_lock_irq(). | ||
18 | */ | ||
19 | void install_linux_ticker(void) | ||
20 | { | ||
21 | |||
22 | if (!linux_lvl14) | ||
23 | return; | ||
24 | linux_lvl14[0] = lvl14_save[0]; | ||
25 | linux_lvl14[1] = lvl14_save[1]; | ||
26 | linux_lvl14[2] = lvl14_save[2]; | ||
27 | linux_lvl14[3] = lvl14_save[3]; | ||
28 | } | ||
29 | |||
30 | void install_obp_ticker(void) | ||
31 | { | ||
32 | |||
33 | if (!linux_lvl14) | ||
34 | return; | ||
35 | linux_lvl14[0] = obp_lvl14[0]; | ||
36 | linux_lvl14[1] = obp_lvl14[1]; | ||
37 | linux_lvl14[2] = obp_lvl14[2]; | ||
38 | linux_lvl14[3] = obp_lvl14[3]; | ||
39 | } | ||
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 19ab42a932db..8237dd4dfeb4 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c | |||
@@ -219,7 +219,7 @@ static void __init sbus_time_init(void) | |||
219 | 219 | ||
220 | btfixup(); | 220 | btfixup(); |
221 | 221 | ||
222 | sparc_init_timers(timer_interrupt); | 222 | sparc_irq_config.init_timers(timer_interrupt); |
223 | } | 223 | } |
224 | 224 | ||
225 | void __init time_init(void) | 225 | void __init time_init(void) |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index e1862793a61d..95ec25faba39 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -816,14 +816,12 @@ void __init time_init(void) | |||
816 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); | 816 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); |
817 | 817 | ||
818 | clocksource_tick.name = tick_ops->name; | 818 | clocksource_tick.name = tick_ops->name; |
819 | clocksource_calc_mult_shift(&clocksource_tick, freq, 4); | ||
820 | clocksource_tick.read = clocksource_tick_read; | 819 | clocksource_tick.read = clocksource_tick_read; |
821 | 820 | ||
821 | clocksource_register_hz(&clocksource_tick, freq); | ||
822 | printk("clocksource: mult[%x] shift[%d]\n", | 822 | printk("clocksource: mult[%x] shift[%d]\n", |
823 | clocksource_tick.mult, clocksource_tick.shift); | 823 | clocksource_tick.mult, clocksource_tick.shift); |
824 | 824 | ||
825 | clocksource_register(&clocksource_tick); | ||
826 | |||
827 | sparc64_clockevent.name = tick_ops->name; | 825 | sparc64_clockevent.name = tick_ops->name; |
828 | clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4); | 826 | clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4); |
829 | 827 | ||
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 1e9770936c3b..1ed547bd850f 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -2152,7 +2152,7 @@ static void user_instruction_dump(unsigned int __user *pc) | |||
2152 | 2152 | ||
2153 | void show_stack(struct task_struct *tsk, unsigned long *_ksp) | 2153 | void show_stack(struct task_struct *tsk, unsigned long *_ksp) |
2154 | { | 2154 | { |
2155 | unsigned long fp, thread_base, ksp; | 2155 | unsigned long fp, ksp; |
2156 | struct thread_info *tp; | 2156 | struct thread_info *tp; |
2157 | int count = 0; | 2157 | int count = 0; |
2158 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 2158 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
@@ -2173,7 +2173,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
2173 | flushw_all(); | 2173 | flushw_all(); |
2174 | 2174 | ||
2175 | fp = ksp + STACK_BIAS; | 2175 | fp = ksp + STACK_BIAS; |
2176 | thread_base = (unsigned long) tp; | ||
2177 | 2176 | ||
2178 | printk("Call Trace:\n"); | 2177 | printk("Call Trace:\n"); |
2179 | do { | 2178 | do { |
diff --git a/arch/sparc/kernel/una_asm_64.S b/arch/sparc/kernel/una_asm_64.S index be183fe41443..1c8d33228b2a 100644 --- a/arch/sparc/kernel/una_asm_64.S +++ b/arch/sparc/kernel/una_asm_64.S | |||
@@ -127,7 +127,7 @@ do_int_load: | |||
127 | wr %o5, 0x0, %asi | 127 | wr %o5, 0x0, %asi |
128 | retl | 128 | retl |
129 | mov 0, %o0 | 129 | mov 0, %o0 |
130 | .size __do_int_load, .-__do_int_load | 130 | .size do_int_load, .-do_int_load |
131 | 131 | ||
132 | .section __ex_table,"a" | 132 | .section __ex_table,"a" |
133 | .word 4b, __retl_efault | 133 | .word 4b, __retl_efault |
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 5b836f5aea90..b10ac4d62378 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -240,11 +240,10 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
240 | * only copy the information from the master page table, | 240 | * only copy the information from the master page table, |
241 | * nothing more. | 241 | * nothing more. |
242 | */ | 242 | */ |
243 | code = SEGV_MAPERR; | ||
243 | if (!ARCH_SUN4C && address >= TASK_SIZE) | 244 | if (!ARCH_SUN4C && address >= TASK_SIZE) |
244 | goto vmalloc_fault; | 245 | goto vmalloc_fault; |
245 | 246 | ||
246 | code = SEGV_MAPERR; | ||
247 | |||
248 | /* | 247 | /* |
249 | * If we're in an interrupt or have no user | 248 | * If we're in an interrupt or have no user |
250 | * context, we must not take the fault.. | 249 | * context, we must not take the fault.. |
diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c index 8c278c311ba4..677b6a10fbde 100644 --- a/arch/sparc/prom/misc_32.c +++ b/arch/sparc/prom/misc_32.c | |||
@@ -54,15 +54,11 @@ EXPORT_SYMBOL(prom_feval); | |||
54 | void | 54 | void |
55 | prom_cmdline(void) | 55 | prom_cmdline(void) |
56 | { | 56 | { |
57 | extern void install_obp_ticker(void); | ||
58 | extern void install_linux_ticker(void); | ||
59 | unsigned long flags; | 57 | unsigned long flags; |
60 | 58 | ||
61 | spin_lock_irqsave(&prom_lock, flags); | 59 | spin_lock_irqsave(&prom_lock, flags); |
62 | install_obp_ticker(); | ||
63 | (*(romvec->pv_abort))(); | 60 | (*(romvec->pv_abort))(); |
64 | restore_current(); | 61 | restore_current(); |
65 | install_linux_ticker(); | ||
66 | spin_unlock_irqrestore(&prom_lock, flags); | 62 | spin_unlock_irqrestore(&prom_lock, flags); |
67 | set_auxio(AUXIO_LED, 0); | 63 | set_auxio(AUXIO_LED, 0); |
68 | } | 64 | } |