diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/sparc | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/sparc')
191 files changed, 5206 insertions, 4665 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 491e9d6de191..253986bd6bb6 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -1,9 +1,3 @@ | |||
1 | # For a description of the syntax of this configuration file, | ||
2 | # see Documentation/kbuild/kconfig-language.txt. | ||
3 | # | ||
4 | |||
5 | mainmenu "Linux/SPARC Kernel Configuration" | ||
6 | |||
7 | config 64BIT | 1 | config 64BIT |
8 | bool "64-bit kernel" if ARCH = "sparc" | 2 | bool "64-bit kernel" if ARCH = "sparc" |
9 | default ARCH = "sparc64" | 3 | default ARCH = "sparc64" |
@@ -19,6 +13,7 @@ config SPARC | |||
19 | bool | 13 | bool |
20 | default y | 14 | default y |
21 | select OF | 15 | select OF |
16 | select OF_PROMTREE | ||
22 | select HAVE_IDE | 17 | select HAVE_IDE |
23 | select HAVE_OPROFILE | 18 | select HAVE_OPROFILE |
24 | select HAVE_ARCH_KGDB if !SMP || SPARC64 | 19 | select HAVE_ARCH_KGDB if !SMP || SPARC64 |
@@ -26,10 +21,13 @@ config SPARC | |||
26 | select ARCH_WANT_OPTIONAL_GPIOLIB | 21 | select ARCH_WANT_OPTIONAL_GPIOLIB |
27 | select RTC_CLASS | 22 | select RTC_CLASS |
28 | select RTC_DRV_M48T59 | 23 | select RTC_DRV_M48T59 |
29 | select HAVE_PERF_EVENTS | 24 | select HAVE_IRQ_WORK |
30 | select PERF_USE_VMALLOC | ||
31 | select HAVE_DMA_ATTRS | 25 | select HAVE_DMA_ATTRS |
32 | select HAVE_DMA_API_DEBUG | 26 | select HAVE_DMA_API_DEBUG |
27 | select HAVE_ARCH_JUMP_LABEL | ||
28 | select HAVE_GENERIC_HARDIRQS | ||
29 | select GENERIC_IRQ_SHOW | ||
30 | select USE_GENERIC_SMP_HELPERS if SMP | ||
33 | 31 | ||
34 | config SPARC32 | 32 | config SPARC32 |
35 | def_bool !64BIT | 33 | def_bool !64BIT |
@@ -48,13 +46,13 @@ config SPARC64 | |||
48 | select HAVE_DYNAMIC_FTRACE | 46 | select HAVE_DYNAMIC_FTRACE |
49 | select HAVE_FTRACE_MCOUNT_RECORD | 47 | select HAVE_FTRACE_MCOUNT_RECORD |
50 | select HAVE_SYSCALL_TRACEPOINTS | 48 | select HAVE_SYSCALL_TRACEPOINTS |
51 | select USE_GENERIC_SMP_HELPERS if SMP | ||
52 | select RTC_DRV_CMOS | 49 | select RTC_DRV_CMOS |
53 | select RTC_DRV_BQ4802 | 50 | select RTC_DRV_BQ4802 |
54 | select RTC_DRV_SUN4V | 51 | select RTC_DRV_SUN4V |
55 | select RTC_DRV_STARFIRE | 52 | select RTC_DRV_STARFIRE |
56 | select HAVE_PERF_EVENTS | 53 | select HAVE_PERF_EVENTS |
57 | select PERF_USE_VMALLOC | 54 | select PERF_USE_VMALLOC |
55 | select IRQ_PREFLOW_FASTEOI | ||
58 | 56 | ||
59 | config ARCH_DEFCONFIG | 57 | config ARCH_DEFCONFIG |
60 | string | 58 | string |
@@ -112,10 +110,6 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK | |||
112 | config NEED_PER_CPU_PAGE_FIRST_CHUNK | 110 | config NEED_PER_CPU_PAGE_FIRST_CHUNK |
113 | def_bool y if SPARC64 | 111 | def_bool y if SPARC64 |
114 | 112 | ||
115 | config GENERIC_HARDIRQS_NO__DO_IRQ | ||
116 | bool | ||
117 | def_bool y if SPARC64 | ||
118 | |||
119 | config MMU | 113 | config MMU |
120 | bool | 114 | bool |
121 | default y | 115 | default y |
@@ -195,10 +189,6 @@ config RWSEM_XCHGADD_ALGORITHM | |||
195 | bool | 189 | bool |
196 | default y if SPARC64 | 190 | default y if SPARC64 |
197 | 191 | ||
198 | config GENERIC_FIND_NEXT_BIT | ||
199 | bool | ||
200 | default y | ||
201 | |||
202 | config GENERIC_HWEIGHT | 192 | config GENERIC_HWEIGHT |
203 | bool | 193 | bool |
204 | default y if !ULTRA_HAS_POPULATION_COUNT | 194 | default y if !ULTRA_HAS_POPULATION_COUNT |
@@ -281,10 +271,6 @@ config HOTPLUG_CPU | |||
281 | can be controlled through /sys/devices/system/cpu/cpu#. | 271 | can be controlled through /sys/devices/system/cpu/cpu#. |
282 | Say N if you want to disable CPU hotplug. | 272 | Say N if you want to disable CPU hotplug. |
283 | 273 | ||
284 | config GENERIC_HARDIRQS | ||
285 | bool | ||
286 | default y if SPARC64 | ||
287 | |||
288 | source "kernel/time/Kconfig" | 274 | source "kernel/time/Kconfig" |
289 | 275 | ||
290 | if SPARC64 | 276 | if SPARC64 |
@@ -472,6 +458,39 @@ config SPARC_LEON | |||
472 | from www.gaisler.com. You can download a sparc-linux cross-compilation | 458 | from www.gaisler.com. You can download a sparc-linux cross-compilation |
473 | toolchain at www.gaisler.com. | 459 | toolchain at www.gaisler.com. |
474 | 460 | ||
461 | if SPARC_LEON | ||
462 | menu "U-Boot options" | ||
463 | |||
464 | config UBOOT_LOAD_ADDR | ||
465 | hex "uImage Load Address" | ||
466 | default 0x40004000 | ||
467 | ---help--- | ||
468 | U-Boot kernel load address, the address in physical address space | ||
469 | where u-boot will place the Linux kernel before booting it. | ||
470 | This address is normally the base address of main memory + 0x4000. | ||
471 | |||
472 | config UBOOT_FLASH_ADDR | ||
473 | hex "uImage.o Load Address" | ||
474 | default 0x00080000 | ||
475 | ---help--- | ||
476 | Optional setting only affecting the uImage.o ELF-image used to | ||
477 | download the uImage file to the target using a ELF-loader other than | ||
478 | U-Boot. It may for example be used to download an uImage to FLASH with | ||
479 | the GRMON utility before even starting u-boot. | ||
480 | |||
481 | config UBOOT_ENTRY_ADDR | ||
482 | hex "uImage Entry Address" | ||
483 | default 0xf0004000 | ||
484 | ---help--- | ||
485 | Do not change this unless you know what you're doing. This is | ||
486 | hardcoded by the SPARC32 and LEON port. | ||
487 | |||
488 | This is the virtual address u-boot jumps to when booting the Linux | ||
489 | Kernel. | ||
490 | |||
491 | endmenu | ||
492 | endif | ||
493 | |||
475 | endmenu | 494 | endmenu |
476 | 495 | ||
477 | menu "Bus options (PCI etc.)" | 496 | menu "Bus options (PCI etc.)" |
@@ -508,6 +527,23 @@ config PCI_DOMAINS | |||
508 | config PCI_SYSCALL | 527 | config PCI_SYSCALL |
509 | def_bool PCI | 528 | def_bool PCI |
510 | 529 | ||
530 | config PCIC_PCI | ||
531 | bool | ||
532 | depends on PCI && SPARC32 && !SPARC_LEON | ||
533 | default y | ||
534 | |||
535 | config LEON_PCI | ||
536 | bool | ||
537 | depends on PCI && SPARC_LEON | ||
538 | default y | ||
539 | |||
540 | config GRPCI2 | ||
541 | bool "GRPCI2 Host Bridge Support" | ||
542 | depends on LEON_PCI | ||
543 | default y | ||
544 | help | ||
545 | Say Y here to include the GRPCI2 Host Bridge Driver. | ||
546 | |||
511 | source "drivers/pci/Kconfig" | 547 | source "drivers/pci/Kconfig" |
512 | 548 | ||
513 | source "drivers/pcmcia/Kconfig" | 549 | source "drivers/pcmcia/Kconfig" |
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index d9a795efbc04..6db35fba79fd 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug | |||
@@ -6,15 +6,6 @@ config TRACE_IRQFLAGS_SUPPORT | |||
6 | 6 | ||
7 | source "lib/Kconfig.debug" | 7 | source "lib/Kconfig.debug" |
8 | 8 | ||
9 | config DEBUG_STACK_USAGE | ||
10 | bool "Enable stack utilization instrumentation" | ||
11 | depends on DEBUG_KERNEL | ||
12 | help | ||
13 | Enables the display of the minimum amount of free stack which each | ||
14 | task has ever had available in the sysrq-T and sysrq-P debug output. | ||
15 | |||
16 | This option will slow down process creation somewhat. | ||
17 | |||
18 | config DEBUG_DCFLUSH | 9 | config DEBUG_DCFLUSH |
19 | bool "D-cache flush debugging" | 10 | bool "D-cache flush debugging" |
20 | depends on SPARC64 && DEBUG_KERNEL | 11 | depends on SPARC64 && DEBUG_KERNEL |
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 97e3feb9ff1b..9205416b1e67 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile | |||
@@ -5,26 +5,26 @@ | |||
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_32 piggyback_64 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 |
11 | clean-files := System.map | 12 | clean-files := System.map |
12 | 13 | ||
13 | quiet_cmd_elftoaout = ELFTOAOUT $@ | 14 | quiet_cmd_elftoaout = ELFTOAOUT $@ |
14 | cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ | 15 | cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ |
16 | quiet_cmd_piggy = PIGGY $@ | ||
17 | cmd_piggy = $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG) | ||
18 | quiet_cmd_strip = STRIP $@ | ||
19 | cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@ | ||
15 | 20 | ||
16 | ifeq ($(CONFIG_SPARC32),y) | 21 | ifeq ($(CONFIG_SPARC32),y) |
17 | quiet_cmd_piggy = PIGGY $@ | ||
18 | cmd_piggy = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG) | ||
19 | quiet_cmd_btfix = BTFIX $@ | 22 | quiet_cmd_btfix = BTFIX $@ |
20 | cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ | 23 | cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ |
21 | quiet_cmd_sysmap = SYSMAP $(obj)/System.map | 24 | quiet_cmd_sysmap = SYSMAP $(obj)/System.map |
22 | cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap | 25 | cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap |
23 | quiet_cmd_image = LD $@ | 26 | quiet_cmd_image = LD $@ |
24 | cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@ | 27 | cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@ |
25 | quiet_cmd_strip = STRIP $@ | ||
26 | cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $(obj)/image -o $@ | ||
27 | |||
28 | 28 | ||
29 | define rule_image | 29 | define rule_image |
30 | $(if $($(quiet)cmd_image), \ | 30 | $(if $($(quiet)cmd_image), \ |
@@ -57,10 +57,7 @@ $(obj)/image: $(obj)/btfix.o FORCE | |||
57 | 57 | ||
58 | $(obj)/zImage: $(obj)/image | 58 | $(obj)/zImage: $(obj)/image |
59 | $(call if_changed,strip) | 59 | $(call if_changed,strip) |
60 | 60 | @echo ' kernel: $@ is ready' | |
61 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE | ||
62 | $(call if_changed,elftoaout) | ||
63 | $(call if_changed,piggy) | ||
64 | 61 | ||
65 | $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE | 62 | $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE |
66 | $(call if_changed,btfix) | 63 | $(call if_changed,btfix) |
@@ -68,11 +65,6 @@ $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE | |||
68 | endif | 65 | endif |
69 | 66 | ||
70 | ifeq ($(CONFIG_SPARC64),y) | 67 | ifeq ($(CONFIG_SPARC64),y) |
71 | quiet_cmd_piggy = PIGGY $@ | ||
72 | cmd_piggy = $(obj)/piggyback_64 $@ System.map $(ROOT_IMG) | ||
73 | quiet_cmd_strip = STRIP $@ | ||
74 | cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ | ||
75 | |||
76 | 68 | ||
77 | # Actual linking | 69 | # Actual linking |
78 | $(obj)/image: vmlinux FORCE | 70 | $(obj)/image: vmlinux FORCE |
@@ -81,14 +73,43 @@ $(obj)/image: vmlinux FORCE | |||
81 | 73 | ||
82 | $(obj)/zImage: $(obj)/image | 74 | $(obj)/zImage: $(obj)/image |
83 | $(call if_changed,gzip) | 75 | $(call if_changed,gzip) |
84 | |||
85 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE | ||
86 | $(call if_changed,elftoaout) | ||
87 | $(call if_changed,piggy) | ||
88 | @echo ' kernel: $@ is ready' | 76 | @echo ' kernel: $@ is ready' |
89 | 77 | ||
90 | $(obj)/vmlinux.aout: vmlinux FORCE | 78 | $(obj)/vmlinux.aout: vmlinux FORCE |
91 | $(call if_changed,elftoaout) | 79 | $(call if_changed,elftoaout) |
92 | @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 | |||
93 | endif | 111 | endif |
94 | 112 | ||
113 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE | ||
114 | $(call if_changed,elftoaout) | ||
115 | $(call if_changed,piggy) | ||
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c new file mode 100644 index 000000000000..c0a798fcf030 --- /dev/null +++ b/arch/sparc/boot/piggyback.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* | ||
2 | Simple utility to make a single-image install kernel with initial ramdisk | ||
3 | for Sparc tftpbooting without need to set up nfs. | ||
4 | |||
5 | Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000. | ||
7 | Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org> | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
22 | |||
23 | #include <dirent.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | #include <unistd.h> | ||
27 | #include <ctype.h> | ||
28 | #include <errno.h> | ||
29 | #include <fcntl.h> | ||
30 | #include <stdio.h> | ||
31 | |||
32 | #include <sys/types.h> | ||
33 | #include <sys/stat.h> | ||
34 | |||
35 | /* | ||
36 | * Note: run this on an a.out kernel (use elftoaout for it), | ||
37 | * as PROM looks for a.out image only. | ||
38 | */ | ||
39 | |||
40 | #define AOUT_TEXT_OFFSET 32 | ||
41 | |||
42 | static int is64bit = 0; | ||
43 | |||
44 | /* align to power-of-two size */ | ||
45 | static int align(int n) | ||
46 | { | ||
47 | if (is64bit) | ||
48 | return (n + 0x1fff) & ~0x1fff; | ||
49 | else | ||
50 | return (n + 0xfff) & ~0xfff; | ||
51 | } | ||
52 | |||
53 | /* read two bytes as big endian */ | ||
54 | static unsigned short ld2(char *p) | ||
55 | { | ||
56 | return (p[0] << 8) | p[1]; | ||
57 | } | ||
58 | |||
59 | /* save 4 bytes as big endian */ | ||
60 | static void st4(char *p, unsigned int x) | ||
61 | { | ||
62 | p[0] = x >> 24; | ||
63 | p[1] = x >> 16; | ||
64 | p[2] = x >> 8; | ||
65 | p[3] = x; | ||
66 | } | ||
67 | |||
68 | static void die(const char *str) | ||
69 | { | ||
70 | perror(str); | ||
71 | exit(1); | ||
72 | } | ||
73 | |||
74 | static void usage(void) | ||
75 | { | ||
76 | /* fs_img.gz is an image of initial ramdisk. */ | ||
77 | fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n"); | ||
78 | fprintf(stderr, "\tKernel image will be modified in place.\n"); | ||
79 | exit(1); | ||
80 | } | ||
81 | |||
82 | static int start_line(const char *line) | ||
83 | { | ||
84 | if (strcmp(line + 8, " T _start\n") == 0) | ||
85 | return 1; | ||
86 | else if (strcmp(line + 16, " T _start\n") == 0) | ||
87 | return 1; | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int end_line(const char *line) | ||
92 | { | ||
93 | if (strcmp(line + 8, " A _end\n") == 0) | ||
94 | return 1; | ||
95 | else if (strcmp (line + 16, " A _end\n") == 0) | ||
96 | return 1; | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Find address for start and end in System.map. | ||
102 | * The file looks like this: | ||
103 | * f0004000 T _start | ||
104 | * f0379f79 A _end | ||
105 | * 1234567890123456 | ||
106 | * ^coloumn 1 | ||
107 | * There is support for 64 bit addresses too. | ||
108 | * | ||
109 | * Return 0 if either start or end is not found | ||
110 | */ | ||
111 | static int get_start_end(const char *filename, unsigned int *start, | ||
112 | unsigned int *end) | ||
113 | { | ||
114 | FILE *map; | ||
115 | char buffer[1024]; | ||
116 | |||
117 | *start = 0; | ||
118 | *end = 0; | ||
119 | map = fopen(filename, "r"); | ||
120 | if (!map) | ||
121 | die(filename); | ||
122 | while (fgets(buffer, 1024, map)) { | ||
123 | if (start_line(buffer)) | ||
124 | *start = strtoul(buffer, NULL, 16); | ||
125 | else if (end_line(buffer)) | ||
126 | *end = strtoul(buffer, NULL, 16); | ||
127 | } | ||
128 | fclose (map); | ||
129 | |||
130 | if (*start == 0 || *end == 0) | ||
131 | return 0; | ||
132 | |||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | #define LOOKBACK (128 * 4) | ||
137 | #define BUFSIZE 1024 | ||
138 | /* | ||
139 | * Find the HdrS entry from head_32/head_64. | ||
140 | * We check if it is at the beginning of the file (sparc64 case) | ||
141 | * and if not we search for it. | ||
142 | * When we search do so in steps of 4 as HdrS is on a 4-byte aligned | ||
143 | * address (it is on same alignment as sparc instructions) | ||
144 | * Return the offset to the HdrS entry (as off_t) | ||
145 | */ | ||
146 | static off_t get_hdrs_offset(int kernelfd, const char *filename) | ||
147 | { | ||
148 | char buffer[BUFSIZE]; | ||
149 | off_t offset; | ||
150 | int i; | ||
151 | |||
152 | if (lseek(kernelfd, 0, SEEK_SET) < 0) | ||
153 | die("lseek"); | ||
154 | if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) | ||
155 | die(filename); | ||
156 | |||
157 | if (buffer[40] == 'H' && buffer[41] == 'd' && | ||
158 | buffer[42] == 'r' && buffer[43] == 'S') { | ||
159 | return 40; | ||
160 | } else { | ||
161 | /* Find the gokernel label */ | ||
162 | /* Decode offset from branch instruction */ | ||
163 | offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; | ||
164 | /* Go back 512 bytes so we do not miss HdrS */ | ||
165 | offset -= LOOKBACK; | ||
166 | /* skip a.out header */ | ||
167 | offset += AOUT_TEXT_OFFSET; | ||
168 | if (lseek(kernelfd, offset, SEEK_SET) < 0) | ||
169 | die("lseek"); | ||
170 | if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) | ||
171 | die(filename); | ||
172 | |||
173 | for (i = 0; i < LOOKBACK; i += 4) { | ||
174 | if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && | ||
175 | buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { | ||
176 | return offset + i; | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | fprintf (stderr, "Couldn't find headers signature in %s\n", filename); | ||
181 | exit(1); | ||
182 | } | ||
183 | |||
184 | int main(int argc,char **argv) | ||
185 | { | ||
186 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; | ||
187 | char buffer[1024]; | ||
188 | unsigned int i, start, end; | ||
189 | off_t offset; | ||
190 | struct stat s; | ||
191 | int image, tail; | ||
192 | |||
193 | if (argc != 5) | ||
194 | usage(); | ||
195 | if (strcmp(argv[1], "64") == 0) | ||
196 | is64bit = 1; | ||
197 | if (stat (argv[4], &s) < 0) | ||
198 | die(argv[4]); | ||
199 | |||
200 | if (!get_start_end(argv[3], &start, &end)) { | ||
201 | fprintf(stderr, "Could not determine start and end from %s\n", | ||
202 | argv[3]); | ||
203 | exit(1); | ||
204 | } | ||
205 | if ((image = open(argv[2], O_RDWR)) < 0) | ||
206 | die(argv[2]); | ||
207 | if (read(image, buffer, 512) != 512) | ||
208 | die(argv[2]); | ||
209 | if (memcmp(buffer, aout_magic, 4) != 0) { | ||
210 | fprintf (stderr, "Not a.out. Don't blame me.\n"); | ||
211 | exit(1); | ||
212 | } | ||
213 | /* | ||
214 | * We need to fill in values for | ||
215 | * sparc_ramdisk_image + sparc_ramdisk_size | ||
216 | * To locate these symbols search for the "HdrS" text which appear | ||
217 | * in the image a little before the gokernel symbol. | ||
218 | * See definition of these in init_32.S | ||
219 | */ | ||
220 | |||
221 | offset = get_hdrs_offset(image, argv[2]); | ||
222 | /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ | ||
223 | offset += 10; | ||
224 | |||
225 | if (lseek(image, offset, 0) < 0) | ||
226 | die("lseek"); | ||
227 | |||
228 | /* | ||
229 | * root_flags = 0 | ||
230 | * root_dev = 1 (RAMDISK_MAJOR) | ||
231 | * ram_flags = 0 | ||
232 | * sparc_ramdisk_image = "PAGE aligned address after _end") | ||
233 | * sparc_ramdisk_size = size of image | ||
234 | */ | ||
235 | st4(buffer, 0); | ||
236 | st4(buffer + 4, 0x01000000); | ||
237 | st4(buffer + 8, align(end + 32)); | ||
238 | st4(buffer + 12, s.st_size); | ||
239 | |||
240 | if (write(image, buffer + 2, 14) != 14) | ||
241 | die(argv[2]); | ||
242 | |||
243 | /* For sparc64 update a_text and clear a_data + a_bss */ | ||
244 | if (is64bit) | ||
245 | { | ||
246 | if (lseek(image, 4, 0) < 0) | ||
247 | die("lseek"); | ||
248 | /* a_text */ | ||
249 | st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + | ||
250 | s.st_size); | ||
251 | /* a_data */ | ||
252 | st4(buffer + 4, 0); | ||
253 | /* a_bss */ | ||
254 | st4(buffer + 8, 0); | ||
255 | if (write(image, buffer, 12) != 12) | ||
256 | die(argv[2]); | ||
257 | } | ||
258 | |||
259 | /* seek page aligned boundary in the image file and add boot image */ | ||
260 | if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) | ||
261 | die("lseek"); | ||
262 | if ((tail = open(argv[4], O_RDONLY)) < 0) | ||
263 | die(argv[4]); | ||
264 | while ((i = read(tail, buffer, 1024)) > 0) | ||
265 | if (write(image, buffer, i) != i) | ||
266 | die(argv[2]); | ||
267 | if (close(image) < 0) | ||
268 | die("close"); | ||
269 | if (close(tail) < 0) | ||
270 | die("close"); | ||
271 | return 0; | ||
272 | } | ||
diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c deleted file mode 100644 index ac944aec7301..000000000000 --- a/arch/sparc/boot/piggyback_32.c +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | /* | ||
2 | Simple utility to make a single-image install kernel with initial ramdisk | ||
3 | for Sparc tftpbooting without need to set up nfs. | ||
4 | |||
5 | Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000. | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | #include <ctype.h> | ||
25 | #include <errno.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <dirent.h> | ||
28 | #include <unistd.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <sys/types.h> | ||
31 | #include <sys/stat.h> | ||
32 | |||
33 | /* | ||
34 | * Note: run this on an a.out kernel (use elftoaout for it), | ||
35 | * as PROM looks for a.out image only. | ||
36 | */ | ||
37 | |||
38 | static unsigned short ld2(char *p) | ||
39 | { | ||
40 | return (p[0] << 8) | p[1]; | ||
41 | } | ||
42 | |||
43 | static unsigned int ld4(char *p) | ||
44 | { | ||
45 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | ||
46 | } | ||
47 | |||
48 | static void st4(char *p, unsigned int x) | ||
49 | { | ||
50 | p[0] = x >> 24; | ||
51 | p[1] = x >> 16; | ||
52 | p[2] = x >> 8; | ||
53 | p[3] = x; | ||
54 | } | ||
55 | |||
56 | static void usage(void) | ||
57 | { | ||
58 | /* fs_img.gz is an image of initial ramdisk. */ | ||
59 | fprintf(stderr, "Usage: piggyback vmlinux.aout System.map fs_img.gz\n"); | ||
60 | fprintf(stderr, "\tKernel image will be modified in place.\n"); | ||
61 | exit(1); | ||
62 | } | ||
63 | |||
64 | static void die(char *str) | ||
65 | { | ||
66 | perror (str); | ||
67 | exit(1); | ||
68 | } | ||
69 | |||
70 | int main(int argc,char **argv) | ||
71 | { | ||
72 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; | ||
73 | char buffer[1024], *q, *r; | ||
74 | unsigned int i, j, k, start, end, offset; | ||
75 | FILE *map; | ||
76 | struct stat s; | ||
77 | int image, tail; | ||
78 | |||
79 | if (argc != 4) usage(); | ||
80 | start = end = 0; | ||
81 | if (stat (argv[3], &s) < 0) die (argv[3]); | ||
82 | map = fopen (argv[2], "r"); | ||
83 | if (!map) die(argv[2]); | ||
84 | while (fgets (buffer, 1024, map)) { | ||
85 | if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) | ||
86 | start = strtoul (buffer, NULL, 16); | ||
87 | else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n")) | ||
88 | end = strtoul (buffer, NULL, 16); | ||
89 | } | ||
90 | fclose (map); | ||
91 | if (!start || !end) { | ||
92 | fprintf (stderr, "Could not determine start and end from System.map\n"); | ||
93 | exit(1); | ||
94 | } | ||
95 | if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); | ||
96 | if (read(image,buffer,512) != 512) die(argv[1]); | ||
97 | if (memcmp (buffer, "\177ELF", 4) == 0) { | ||
98 | q = buffer + ld4(buffer + 28); | ||
99 | i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); | ||
100 | if (lseek(image,i,0) < 0) die("lseek"); | ||
101 | if (read(image,buffer,512) != 512) die(argv[1]); | ||
102 | j = 0; | ||
103 | } else if (memcmp(buffer, aout_magic, 4) == 0) { | ||
104 | i = j = 32; | ||
105 | } else { | ||
106 | fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); | ||
107 | exit(1); | ||
108 | } | ||
109 | k = i; | ||
110 | i += (ld2(buffer + j + 2)<<2) - 512; | ||
111 | if (lseek(image,i,0) < 0) die("lseek"); | ||
112 | if (read(image,buffer,1024) != 1024) die(argv[1]); | ||
113 | for (q = buffer, r = q + 512; q < r; q += 4) { | ||
114 | if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') | ||
115 | break; | ||
116 | } | ||
117 | if (q == r) { | ||
118 | fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); | ||
119 | exit(1); | ||
120 | } | ||
121 | offset = i + (q - buffer) + 10; | ||
122 | if (lseek(image, offset, 0) < 0) die ("lseek"); | ||
123 | |||
124 | st4(buffer, 0); | ||
125 | st4(buffer + 4, 0x01000000); | ||
126 | st4(buffer + 8, (end + 32 + 4095) & ~4095); | ||
127 | st4(buffer + 12, s.st_size); | ||
128 | |||
129 | if (write(image,buffer+2,14) != 14) die (argv[1]); | ||
130 | if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek"); | ||
131 | if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); | ||
132 | while ((i = read (tail,buffer,1024)) > 0) | ||
133 | if (write(image,buffer,i) != i) die (argv[1]); | ||
134 | if (close(image) < 0) die("close"); | ||
135 | if (close(tail) < 0) die("close"); | ||
136 | return 0; | ||
137 | } | ||
diff --git a/arch/sparc/boot/piggyback_64.c b/arch/sparc/boot/piggyback_64.c deleted file mode 100644 index a26a686cb5aa..000000000000 --- a/arch/sparc/boot/piggyback_64.c +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /* | ||
2 | Simple utility to make a single-image install kernel with initial ramdisk | ||
3 | for Sparc64 tftpbooting without need to set up nfs. | ||
4 | |||
5 | Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
20 | |||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <ctype.h> | ||
24 | #include <errno.h> | ||
25 | #include <fcntl.h> | ||
26 | #include <dirent.h> | ||
27 | #include <unistd.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <sys/stat.h> | ||
31 | |||
32 | /* Note: run this on an a.out kernel (use elftoaout for it), as PROM looks for a.out image onlly | ||
33 | usage: piggyback vmlinux System.map tail, where tail is gzipped fs of the initial ramdisk */ | ||
34 | |||
35 | static void die(char *str) | ||
36 | { | ||
37 | perror (str); | ||
38 | exit(1); | ||
39 | } | ||
40 | |||
41 | int main(int argc,char **argv) | ||
42 | { | ||
43 | char buffer [1024], *q, *r; | ||
44 | unsigned int i, j, k, start, end, offset; | ||
45 | FILE *map; | ||
46 | struct stat s; | ||
47 | int image, tail; | ||
48 | |||
49 | start = end = 0; | ||
50 | if (stat (argv[3], &s) < 0) die (argv[3]); | ||
51 | map = fopen (argv[2], "r"); | ||
52 | if (!map) die(argv[2]); | ||
53 | while (fgets (buffer, 1024, map)) { | ||
54 | if (!strcmp (buffer + 19, "_start\n")) | ||
55 | start = strtoul (buffer + 8, NULL, 16); | ||
56 | else if (!strcmp (buffer + 19, "_end\n")) | ||
57 | end = strtoul (buffer + 8, NULL, 16); | ||
58 | } | ||
59 | fclose (map); | ||
60 | if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); | ||
61 | if (read(image,buffer,512) != 512) die(argv[1]); | ||
62 | if (!memcmp (buffer, "\177ELF", 4)) { | ||
63 | unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28)); | ||
64 | |||
65 | i = p[1] + *(unsigned int *)(buffer + 24) - p[2]; | ||
66 | if (lseek(image,i,0) < 0) die("lseek"); | ||
67 | if (read(image,buffer,512) != 512) die(argv[1]); | ||
68 | j = 0; | ||
69 | } else if (*(unsigned int *)buffer == 0x01030107) { | ||
70 | i = j = 32; | ||
71 | } else { | ||
72 | fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); | ||
73 | exit(1); | ||
74 | } | ||
75 | k = i; | ||
76 | if (j == 32 && buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') { | ||
77 | offset = 40 + 10; | ||
78 | } else { | ||
79 | i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512; | ||
80 | if (lseek(image,i,0) < 0) die("lseek"); | ||
81 | if (read(image,buffer,1024) != 1024) die(argv[1]); | ||
82 | for (q = buffer, r = q + 512; q < r; q += 4) { | ||
83 | if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') | ||
84 | break; | ||
85 | } | ||
86 | if (q == r) { | ||
87 | fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); | ||
88 | exit(1); | ||
89 | } | ||
90 | offset = i + (q - buffer) + 10; | ||
91 | } | ||
92 | if (lseek(image, offset, 0) < 0) die ("lseek"); | ||
93 | *(unsigned *)buffer = 0; | ||
94 | *(unsigned *)(buffer + 4) = 0x01000000; | ||
95 | *(unsigned *)(buffer + 8) = ((end + 32 + 8191) & ~8191); | ||
96 | *(unsigned *)(buffer + 12) = s.st_size; | ||
97 | if (write(image,buffer+2,14) != 14) die (argv[1]); | ||
98 | if (lseek(image, 4, 0) < 0) die ("lseek"); | ||
99 | *(unsigned *)buffer = ((end + 32 + 8191) & ~8191) - (start & ~0x3fffffUL) + s.st_size; | ||
100 | *(unsigned *)(buffer + 4) = 0; | ||
101 | *(unsigned *)(buffer + 8) = 0; | ||
102 | if (write(image,buffer,12) != 12) die (argv[1]); | ||
103 | if (lseek(image, k - start + ((end + 32 + 8191) & ~8191), 0) < 0) die ("lseek"); | ||
104 | if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); | ||
105 | while ((i = read (tail,buffer,1024)) > 0) | ||
106 | if (write(image,buffer,i) != i) die (argv[1]); | ||
107 | if (close(image) < 0) die("close"); | ||
108 | if (close(tail) < 0) die("close"); | ||
109 | return 0; | ||
110 | } | ||
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index deeb0fba8029..3c93f08ce187 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -7,7 +7,6 @@ header-y += display7seg.h | |||
7 | header-y += envctrl.h | 7 | header-y += envctrl.h |
8 | header-y += fbio.h | 8 | header-y += fbio.h |
9 | header-y += jsflash.h | 9 | header-y += jsflash.h |
10 | header-y += openprom.h | ||
11 | header-y += openpromio.h | 10 | header-y += openpromio.h |
12 | header-y += perfctr.h | 11 | header-y += perfctr.h |
13 | header-y += psrcompat.h | 12 | header-y += psrcompat.h |
diff --git a/arch/sparc/include/asm/bitops_32.h b/arch/sparc/include/asm/bitops_32.h index 9cf4ae0cd7ba..25a676653d45 100644 --- a/arch/sparc/include/asm/bitops_32.h +++ b/arch/sparc/include/asm/bitops_32.h | |||
@@ -103,9 +103,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) | |||
103 | #include <asm-generic/bitops/hweight.h> | 103 | #include <asm-generic/bitops/hweight.h> |
104 | #include <asm-generic/bitops/lock.h> | 104 | #include <asm-generic/bitops/lock.h> |
105 | #include <asm-generic/bitops/find.h> | 105 | #include <asm-generic/bitops/find.h> |
106 | #include <asm-generic/bitops/ext2-non-atomic.h> | 106 | #include <asm-generic/bitops/le.h> |
107 | #include <asm-generic/bitops/ext2-atomic.h> | 107 | #include <asm-generic/bitops/ext2-atomic.h> |
108 | #include <asm-generic/bitops/minix.h> | ||
109 | 108 | ||
110 | #endif /* __KERNEL__ */ | 109 | #endif /* __KERNEL__ */ |
111 | 110 | ||
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h index 766121a67a24..38e9aa1b2cea 100644 --- a/arch/sparc/include/asm/bitops_64.h +++ b/arch/sparc/include/asm/bitops_64.h | |||
@@ -89,15 +89,13 @@ static inline unsigned int __arch_hweight8(unsigned int w) | |||
89 | 89 | ||
90 | #ifdef __KERNEL__ | 90 | #ifdef __KERNEL__ |
91 | 91 | ||
92 | #include <asm-generic/bitops/ext2-non-atomic.h> | 92 | #include <asm-generic/bitops/le.h> |
93 | 93 | ||
94 | #define ext2_set_bit_atomic(lock,nr,addr) \ | 94 | #define ext2_set_bit_atomic(lock,nr,addr) \ |
95 | test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr)) | 95 | test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr)) |
96 | #define ext2_clear_bit_atomic(lock,nr,addr) \ | 96 | #define ext2_clear_bit_atomic(lock,nr,addr) \ |
97 | test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr)) | 97 | test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr)) |
98 | 98 | ||
99 | #include <asm-generic/bitops/minix.h> | ||
100 | |||
101 | #endif /* __KERNEL__ */ | 99 | #endif /* __KERNEL__ */ |
102 | 100 | ||
103 | #endif /* defined(_SPARC64_BITOPS_H) */ | 101 | #endif /* defined(_SPARC64_BITOPS_H) */ |
diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h index 31d48a0e32c7..a4c5a938b936 100644 --- a/arch/sparc/include/asm/cpudata_32.h +++ b/arch/sparc/include/asm/cpudata_32.h | |||
@@ -16,6 +16,10 @@ typedef struct { | |||
16 | unsigned long clock_tick; | 16 | unsigned long clock_tick; |
17 | unsigned int multiplier; | 17 | unsigned int multiplier; |
18 | unsigned int counter; | 18 | unsigned int counter; |
19 | #ifdef CONFIG_SMP | ||
20 | unsigned int irq_resched_count; | ||
21 | unsigned int irq_call_count; | ||
22 | #endif | ||
19 | int prom_node; | 23 | int prom_node; |
20 | int mid; | 24 | int mid; |
21 | int next; | 25 | int next; |
@@ -23,5 +27,6 @@ typedef struct { | |||
23 | 27 | ||
24 | DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data); | 28 | DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data); |
25 | #define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu)) | 29 | #define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu)) |
30 | #define local_cpu_data() __get_cpu_var(__cpu_data) | ||
26 | 31 | ||
27 | #endif /* _SPARC_CPUDATA_H */ | 32 | #endif /* _SPARC_CPUDATA_H */ |
diff --git a/arch/sparc/include/asm/errno.h b/arch/sparc/include/asm/errno.h index 4e2bc490d714..c351aba997b7 100644 --- a/arch/sparc/include/asm/errno.h +++ b/arch/sparc/include/asm/errno.h | |||
@@ -112,4 +112,6 @@ | |||
112 | 112 | ||
113 | #define ERFKILL 134 /* Operation not possible due to RF-kill */ | 113 | #define ERFKILL 134 /* Operation not possible due to RF-kill */ |
114 | 114 | ||
115 | #define EHWPOISON 135 /* Memory page has hardware error */ | ||
116 | |||
115 | #endif | 117 | #endif |
diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h index 38f37b333cc7..d0b83f66f356 100644 --- a/arch/sparc/include/asm/fcntl.h +++ b/arch/sparc/include/asm/fcntl.h | |||
@@ -34,6 +34,8 @@ | |||
34 | #define __O_SYNC 0x800000 | 34 | #define __O_SYNC 0x800000 |
35 | #define O_SYNC (__O_SYNC|O_DSYNC) | 35 | #define O_SYNC (__O_SYNC|O_DSYNC) |
36 | 36 | ||
37 | #define O_PATH 0x1000000 | ||
38 | |||
37 | #define F_GETOWN 5 /* for sockets. */ | 39 | #define F_GETOWN 5 /* for sockets. */ |
38 | #define F_SETOWN 6 /* for sockets. */ | 40 | #define F_SETOWN 6 /* for sockets. */ |
39 | #define F_GETLK 7 | 41 | #define F_GETLK 7 |
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index c792830636de..7440915e86d8 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h | |||
@@ -138,7 +138,7 @@ static unsigned char sun_82072_fd_inb(int port) | |||
138 | return sun_fdc->data_82072; | 138 | return sun_fdc->data_82072; |
139 | case 7: /* FD_DIR */ | 139 | case 7: /* FD_DIR */ |
140 | return sun_read_dir(); | 140 | return sun_read_dir(); |
141 | }; | 141 | } |
142 | panic("sun_82072_fd_inb: How did I get here?"); | 142 | panic("sun_82072_fd_inb: How did I get here?"); |
143 | } | 143 | } |
144 | 144 | ||
@@ -161,7 +161,7 @@ static void sun_82072_fd_outb(unsigned char value, int port) | |||
161 | case 4: /* FD_STATUS */ | 161 | case 4: /* FD_STATUS */ |
162 | sun_fdc->status_82072 = value; | 162 | sun_fdc->status_82072 = value; |
163 | break; | 163 | break; |
164 | }; | 164 | } |
165 | return; | 165 | return; |
166 | } | 166 | } |
167 | 167 | ||
@@ -186,7 +186,7 @@ static unsigned char sun_82077_fd_inb(int port) | |||
186 | return sun_fdc->data_82077; | 186 | return sun_fdc->data_82077; |
187 | case 7: /* FD_DIR */ | 187 | case 7: /* FD_DIR */ |
188 | return sun_read_dir(); | 188 | return sun_read_dir(); |
189 | }; | 189 | } |
190 | panic("sun_82077_fd_inb: How did I get here?"); | 190 | panic("sun_82077_fd_inb: How did I get here?"); |
191 | } | 191 | } |
192 | 192 | ||
@@ -212,7 +212,7 @@ static void sun_82077_fd_outb(unsigned char value, int port) | |||
212 | case 3: /* FD_TDR */ | 212 | case 3: /* FD_TDR */ |
213 | sun_fdc->tapectl_82077 = value; | 213 | sun_fdc->tapectl_82077 = value; |
214 | break; | 214 | break; |
215 | }; | 215 | } |
216 | return; | 216 | return; |
217 | } | 217 | } |
218 | 218 | ||
@@ -281,35 +281,34 @@ static inline void sun_fd_enable_dma(void) | |||
281 | pdma_areasize = pdma_size; | 281 | pdma_areasize = pdma_size; |
282 | } | 282 | } |
283 | 283 | ||
284 | /* Our low-level entry point in arch/sparc/kernel/entry.S */ | 284 | extern int sparc_floppy_request_irq(unsigned int irq, |
285 | extern int sparc_floppy_request_irq(int irq, unsigned long flags, | 285 | irq_handler_t irq_handler); |
286 | irq_handler_t irq_handler); | ||
287 | 286 | ||
288 | static int sun_fd_request_irq(void) | 287 | static int sun_fd_request_irq(void) |
289 | { | 288 | { |
290 | static int once = 0; | 289 | static int once = 0; |
291 | int error; | ||
292 | 290 | ||
293 | if(!once) { | 291 | if (!once) { |
294 | once = 1; | 292 | once = 1; |
295 | error = sparc_floppy_request_irq(FLOPPY_IRQ, | 293 | return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt); |
296 | IRQF_DISABLED, | 294 | } else { |
297 | floppy_interrupt); | 295 | return 0; |
298 | return ((error == 0) ? 0 : -1); | 296 | } |
299 | } else return 0; | ||
300 | } | 297 | } |
301 | 298 | ||
302 | static struct linux_prom_registers fd_regs[2]; | 299 | static struct linux_prom_registers fd_regs[2]; |
303 | 300 | ||
304 | static int sun_floppy_init(void) | 301 | static int sun_floppy_init(void) |
305 | { | 302 | { |
303 | struct platform_device *op; | ||
304 | struct device_node *dp; | ||
306 | char state[128]; | 305 | char state[128]; |
307 | int tnode, fd_node, num_regs; | 306 | phandle tnode, fd_node; |
307 | int num_regs; | ||
308 | struct resource r; | 308 | struct resource r; |
309 | 309 | ||
310 | use_virtual_dma = 1; | 310 | use_virtual_dma = 1; |
311 | 311 | ||
312 | FLOPPY_IRQ = 11; | ||
313 | /* Forget it if we aren't on a machine that could possibly | 312 | /* Forget it if we aren't on a machine that could possibly |
314 | * ever have a floppy drive. | 313 | * ever have a floppy drive. |
315 | */ | 314 | */ |
@@ -348,6 +347,26 @@ static int sun_floppy_init(void) | |||
348 | sun_fdc = (struct sun_flpy_controller *) | 347 | sun_fdc = (struct sun_flpy_controller *) |
349 | of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); | 348 | of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); |
350 | 349 | ||
350 | /* Look up irq in platform_device. | ||
351 | * We try "SUNW,fdtwo" and "fd" | ||
352 | */ | ||
353 | for_each_node_by_name(dp, "SUNW,fdtwo") { | ||
354 | op = of_find_device_by_node(dp); | ||
355 | if (op) | ||
356 | break; | ||
357 | } | ||
358 | if (!op) { | ||
359 | for_each_node_by_name(dp, "fd") { | ||
360 | op = of_find_device_by_node(dp); | ||
361 | if (op) | ||
362 | break; | ||
363 | } | ||
364 | } | ||
365 | if (!op) | ||
366 | goto no_sun_fdc; | ||
367 | |||
368 | FLOPPY_IRQ = op->archdata.irqs[0]; | ||
369 | |||
351 | /* Last minute sanity check... */ | 370 | /* Last minute sanity check... */ |
352 | if(sun_fdc->status_82072 == 0xff) { | 371 | if(sun_fdc->status_82072 == 0xff) { |
353 | sun_fdc = NULL; | 372 | sun_fdc = NULL; |
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index 6597ce874d78..bcef1f5a2a6d 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h | |||
@@ -111,7 +111,7 @@ static unsigned char sun_82077_fd_inb(unsigned long port) | |||
111 | case 7: /* FD_DIR */ | 111 | case 7: /* FD_DIR */ |
112 | /* XXX: Is DCL on 0x80 in sun4m? */ | 112 | /* XXX: Is DCL on 0x80 in sun4m? */ |
113 | return sbus_readb(&sun_fdc->dir_82077); | 113 | return sbus_readb(&sun_fdc->dir_82077); |
114 | }; | 114 | } |
115 | panic("sun_82072_fd_inb: How did I get here?"); | 115 | panic("sun_82072_fd_inb: How did I get here?"); |
116 | } | 116 | } |
117 | 117 | ||
@@ -135,7 +135,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port) | |||
135 | case 4: /* FD_STATUS */ | 135 | case 4: /* FD_STATUS */ |
136 | sbus_writeb(value, &sun_fdc->status_82077); | 136 | sbus_writeb(value, &sun_fdc->status_82077); |
137 | break; | 137 | break; |
138 | }; | 138 | } |
139 | return; | 139 | return; |
140 | } | 140 | } |
141 | 141 | ||
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h index 47f95839dc69..444e7bea23bc 100644 --- a/arch/sparc/include/asm/futex_64.h +++ b/arch/sparc/include/asm/futex_64.h | |||
@@ -30,7 +30,7 @@ | |||
30 | : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ | 30 | : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ |
31 | : "memory") | 31 | : "memory") |
32 | 32 | ||
33 | static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | 33 | static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) |
34 | { | 34 | { |
35 | int op = (encoded_op >> 28) & 7; | 35 | int op = (encoded_op >> 28) & 7; |
36 | int cmp = (encoded_op >> 24) & 15; | 36 | int cmp = (encoded_op >> 24) & 15; |
@@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | |||
38 | int cmparg = (encoded_op << 20) >> 20; | 38 | int cmparg = (encoded_op << 20) >> 20; |
39 | int oldval = 0, ret, tem; | 39 | int oldval = 0, ret, tem; |
40 | 40 | ||
41 | if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))) | 41 | if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) |
42 | return -EFAULT; | 42 | return -EFAULT; |
43 | if (unlikely((((unsigned long) uaddr) & 0x3UL))) | 43 | if (unlikely((((unsigned long) uaddr) & 0x3UL))) |
44 | return -EINVAL; | 44 | return -EINVAL; |
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | static inline int | 87 | static inline int |
88 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | 88 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
89 | u32 oldval, u32 newval) | ||
89 | { | 90 | { |
91 | int ret = 0; | ||
92 | |||
90 | __asm__ __volatile__( | 93 | __asm__ __volatile__( |
91 | "\n1: casa [%3] %%asi, %2, %0\n" | 94 | "\n1: casa [%4] %%asi, %3, %1\n" |
92 | "2:\n" | 95 | "2:\n" |
93 | " .section .fixup,#alloc,#execinstr\n" | 96 | " .section .fixup,#alloc,#execinstr\n" |
94 | " .align 4\n" | 97 | " .align 4\n" |
95 | "3: sethi %%hi(2b), %0\n" | 98 | "3: sethi %%hi(2b), %0\n" |
96 | " jmpl %0 + %%lo(2b), %%g0\n" | 99 | " jmpl %0 + %%lo(2b), %%g0\n" |
97 | " mov %4, %0\n" | 100 | " mov %5, %0\n" |
98 | " .previous\n" | 101 | " .previous\n" |
99 | " .section __ex_table,\"a\"\n" | 102 | " .section __ex_table,\"a\"\n" |
100 | " .align 4\n" | 103 | " .align 4\n" |
101 | " .word 1b, 3b\n" | 104 | " .word 1b, 3b\n" |
102 | " .previous\n" | 105 | " .previous\n" |
103 | : "=r" (newval) | 106 | : "+r" (ret), "=r" (newval) |
104 | : "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT) | 107 | : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT) |
105 | : "memory"); | 108 | : "memory"); |
106 | 109 | ||
107 | return newval; | 110 | *uval = newval; |
111 | return ret; | ||
108 | } | 112 | } |
109 | 113 | ||
110 | #endif /* !(_SPARC64_FUTEX_H) */ | 114 | #endif /* !(_SPARC64_FUTEX_H) */ |
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h index ec23b0a87b98..3d7afbb7f4bb 100644 --- a/arch/sparc/include/asm/highmem.h +++ b/arch/sparc/include/asm/highmem.h | |||
@@ -70,8 +70,8 @@ static inline void kunmap(struct page *page) | |||
70 | kunmap_high(page); | 70 | kunmap_high(page); |
71 | } | 71 | } |
72 | 72 | ||
73 | extern void *kmap_atomic(struct page *page, enum km_type type); | 73 | extern void *__kmap_atomic(struct page *page); |
74 | extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 74 | extern void __kunmap_atomic(void *kvaddr); |
75 | extern struct page *kmap_atomic_to_page(void *vaddr); | 75 | extern struct page *kmap_atomic_to_page(void *vaddr); |
76 | 76 | ||
77 | #define flush_cache_kmaps() flush_cache_all() | 77 | #define flush_cache_kmaps() flush_cache_all() |
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h index bafe5a631b6d..75686409be24 100644 --- a/arch/sparc/include/asm/hypervisor.h +++ b/arch/sparc/include/asm/hypervisor.h | |||
@@ -654,7 +654,7 @@ extern unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions, | |||
654 | * ARG3: mmu context | 654 | * ARG3: mmu context |
655 | * ARG4: flags (HV_MMU_{IMMU,DMMU}) | 655 | * ARG4: flags (HV_MMU_{IMMU,DMMU}) |
656 | * RET0: status | 656 | * RET0: status |
657 | * ERRORS: EINVAL Invalid virutal address, context, or | 657 | * ERRORS: EINVAL Invalid virtual address, context, or |
658 | * flags value | 658 | * flags value |
659 | * ENOTSUPPORTED ARG0 or ARG1 is non-zero | 659 | * ENOTSUPPORTED ARG0 or ARG1 is non-zero |
660 | * | 660 | * |
@@ -721,7 +721,7 @@ extern void sun4v_mmu_demap_all(void); | |||
721 | * ARG2: TTE | 721 | * ARG2: TTE |
722 | * ARG3: flags (HV_MMU_{IMMU,DMMU}) | 722 | * ARG3: flags (HV_MMU_{IMMU,DMMU}) |
723 | * RET0: status | 723 | * RET0: status |
724 | * ERRORS: EINVAL Invalid virutal address or flags value | 724 | * ERRORS: EINVAL Invalid virtual address or flags value |
725 | * EBADPGSZ Invalid page size value | 725 | * EBADPGSZ Invalid page size value |
726 | * ENORADDR Invalid real address in TTE | 726 | * ENORADDR Invalid real address in TTE |
727 | * ETOOMANY Too many mappings (max of 8 reached) | 727 | * ETOOMANY Too many mappings (max of 8 reached) |
@@ -800,7 +800,7 @@ extern unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr, | |||
800 | * ARG1: reserved, must be zero | 800 | * ARG1: reserved, must be zero |
801 | * ARG2: flags (HV_MMU_{IMMU,DMMU}) | 801 | * ARG2: flags (HV_MMU_{IMMU,DMMU}) |
802 | * RET0: status | 802 | * RET0: status |
803 | * ERRORS: EINVAL Invalid virutal address or flags value | 803 | * ERRORS: EINVAL Invalid virtual address or flags value |
804 | * ENOMAP Specified mapping was not found | 804 | * ENOMAP Specified mapping was not found |
805 | * | 805 | * |
806 | * Demaps any permanent page mapping (established via | 806 | * Demaps any permanent page mapping (established via |
@@ -1205,7 +1205,7 @@ struct hv_trap_trace_control { | |||
1205 | * structure contents. Attempts to do so will result in undefined | 1205 | * structure contents. Attempts to do so will result in undefined |
1206 | * behavior for the guest. | 1206 | * behavior for the guest. |
1207 | * | 1207 | * |
1208 | * Each trap trace buffer entry is layed out as follows: | 1208 | * Each trap trace buffer entry is laid out as follows: |
1209 | */ | 1209 | */ |
1210 | #ifndef __ASSEMBLY__ | 1210 | #ifndef __ASSEMBLY__ |
1211 | struct hv_trap_trace_entry { | 1211 | struct hv_trap_trace_entry { |
@@ -1300,7 +1300,7 @@ struct hv_trap_trace_entry { | |||
1300 | * state in RET1. Future systems may define various flags for the | 1300 | * state in RET1. Future systems may define various flags for the |
1301 | * enable argument (ARG0), for the moment a guest should pass | 1301 | * enable argument (ARG0), for the moment a guest should pass |
1302 | * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all | 1302 | * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all |
1303 | * tracing - which will ensure future compatability. | 1303 | * tracing - which will ensure future compatibility. |
1304 | */ | 1304 | */ |
1305 | #define HV_FAST_TTRACE_ENABLE 0x92 | 1305 | #define HV_FAST_TTRACE_ENABLE 0x92 |
1306 | 1306 | ||
@@ -1880,7 +1880,7 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, | |||
1880 | * pci_device, at pci_config_offset from the beginning of the device's | 1880 | * pci_device, at pci_config_offset from the beginning of the device's |
1881 | * configuration space. If there was no error, RET1 is set to zero and | 1881 | * configuration space. If there was no error, RET1 is set to zero and |
1882 | * RET2 is set to the data read. Insignificant bits in RET2 are not | 1882 | * RET2 is set to the data read. Insignificant bits in RET2 are not |
1883 | * guarenteed to have any specific value and therefore must be ignored. | 1883 | * guaranteed to have any specific value and therefore must be ignored. |
1884 | * | 1884 | * |
1885 | * The data returned in RET2 is size based byte swapped. | 1885 | * The data returned in RET2 is size based byte swapped. |
1886 | * | 1886 | * |
@@ -1941,9 +1941,9 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, | |||
1941 | * and return the actual data read in RET2. The data returned is size based | 1941 | * and return the actual data read in RET2. The data returned is size based |
1942 | * byte swapped. | 1942 | * byte swapped. |
1943 | * | 1943 | * |
1944 | * Non-significant bits in RET2 are not guarenteed to have any specific value | 1944 | * Non-significant bits in RET2 are not guaranteed to have any specific value |
1945 | * and therefore must be ignored. If RET1 is returned as non-zero, the data | 1945 | * and therefore must be ignored. If RET1 is returned as non-zero, the data |
1946 | * value is not guarenteed to have any specific value and should be ignored. | 1946 | * value is not guaranteed to have any specific value and should be ignored. |
1947 | * | 1947 | * |
1948 | * The caller must have permission to read from the given devhandle, real | 1948 | * The caller must have permission to read from the given devhandle, real |
1949 | * address, which must be an IO address. The argument real address must be a | 1949 | * address, which must be an IO address. The argument real address must be a |
@@ -2456,9 +2456,9 @@ extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle, | |||
2456 | * | 2456 | * |
2457 | * As receive queue configuration causes a reset of the queue's head and | 2457 | * As receive queue configuration causes a reset of the queue's head and |
2458 | * tail pointers there is no way for a gues to determine how many entries | 2458 | * tail pointers there is no way for a gues to determine how many entries |
2459 | * have been received between a preceeding ldc_get_rx_state() API call | 2459 | * have been received between a preceding ldc_get_rx_state() API call |
2460 | * and the completion of the configuration operation. It should be noted | 2460 | * and the completion of the configuration operation. It should be noted |
2461 | * that datagram delivery is not guarenteed via domain channels anyway, | 2461 | * that datagram delivery is not guaranteed via domain channels anyway, |
2462 | * and therefore any higher protocol should be resilient to datagram | 2462 | * and therefore any higher protocol should be resilient to datagram |
2463 | * loss if necessary. However, to overcome this specific race potential | 2463 | * loss if necessary. However, to overcome this specific race potential |
2464 | * it is recommended, for example, that a higher level protocol be employed | 2464 | * it is recommended, for example, that a higher level protocol be employed |
diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h index a34b2994937a..f6902cf3cbe9 100644 --- a/arch/sparc/include/asm/io.h +++ b/arch/sparc/include/asm/io.h | |||
@@ -5,4 +5,17 @@ | |||
5 | #else | 5 | #else |
6 | #include <asm/io_32.h> | 6 | #include <asm/io_32.h> |
7 | #endif | 7 | #endif |
8 | |||
9 | /* | ||
10 | * Defines used for both SPARC32 and SPARC64 | ||
11 | */ | ||
12 | |||
13 | /* Big endian versions of memory read/write routines */ | ||
14 | #define readb_be(__addr) __raw_readb(__addr) | ||
15 | #define readw_be(__addr) __raw_readw(__addr) | ||
16 | #define readl_be(__addr) __raw_readl(__addr) | ||
17 | #define writeb_be(__b, __addr) __raw_writeb(__b, __addr) | ||
18 | #define writel_be(__w, __addr) __raw_writel(__w, __addr) | ||
19 | #define writew_be(__l, __addr) __raw_writew(__l, __addr) | ||
20 | |||
8 | #endif | 21 | #endif |
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 2889574608db..c2ced21c9dc1 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h | |||
@@ -208,6 +208,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n) | |||
208 | #define memset_io(d,c,sz) _memset_io(d,c,sz) | 208 | #define memset_io(d,c,sz) _memset_io(d,c,sz) |
209 | 209 | ||
210 | static inline void | 210 | static inline void |
211 | _sbus_memcpy_fromio(void *dst, const volatile void __iomem *src, | ||
212 | __kernel_size_t n) | ||
213 | { | ||
214 | char *d = dst; | ||
215 | |||
216 | while (n--) { | ||
217 | char tmp = sbus_readb(src); | ||
218 | *d++ = tmp; | ||
219 | src++; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | #define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz) | ||
224 | |||
225 | static inline void | ||
211 | _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) | 226 | _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) |
212 | { | 227 | { |
213 | char *d = dst; | 228 | char *d = dst; |
@@ -222,6 +237,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) | |||
222 | #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) | 237 | #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) |
223 | 238 | ||
224 | static inline void | 239 | static inline void |
240 | _sbus_memcpy_toio(volatile void __iomem *dst, const void *src, | ||
241 | __kernel_size_t n) | ||
242 | { | ||
243 | const char *s = src; | ||
244 | volatile void __iomem *d = dst; | ||
245 | |||
246 | while (n--) { | ||
247 | char tmp = *s++; | ||
248 | sbus_writeb(tmp, d); | ||
249 | d++; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | #define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz) | ||
254 | |||
255 | static inline void | ||
225 | _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) | 256 | _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) |
226 | { | 257 | { |
227 | const char *s = src; | 258 | const char *s = src; |
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h index 9517d063c79c..9c8965415f0a 100644 --- a/arch/sparc/include/asm/io_64.h +++ b/arch/sparc/include/asm/io_64.h | |||
@@ -419,6 +419,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n) | |||
419 | #define memset_io(d,c,sz) _memset_io(d,c,sz) | 419 | #define memset_io(d,c,sz) _memset_io(d,c,sz) |
420 | 420 | ||
421 | static inline void | 421 | static inline void |
422 | _sbus_memcpy_fromio(void *dst, const volatile void __iomem *src, | ||
423 | __kernel_size_t n) | ||
424 | { | ||
425 | char *d = dst; | ||
426 | |||
427 | while (n--) { | ||
428 | char tmp = sbus_readb(src); | ||
429 | *d++ = tmp; | ||
430 | src++; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | #define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz) | ||
435 | |||
436 | static inline void | ||
422 | _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) | 437 | _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) |
423 | { | 438 | { |
424 | char *d = dst; | 439 | char *d = dst; |
@@ -433,6 +448,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) | |||
433 | #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) | 448 | #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) |
434 | 449 | ||
435 | static inline void | 450 | static inline void |
451 | _sbus_memcpy_toio(volatile void __iomem *dst, const void *src, | ||
452 | __kernel_size_t n) | ||
453 | { | ||
454 | const char *s = src; | ||
455 | volatile void __iomem *d = dst; | ||
456 | |||
457 | while (n--) { | ||
458 | char tmp = *s++; | ||
459 | sbus_writeb(tmp, d); | ||
460 | d++; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | #define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz) | ||
465 | |||
466 | static inline void | ||
436 | _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) | 467 | _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) |
437 | { | 468 | { |
438 | const char *s = src; | 469 | const char *s = src; |
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h index 53f4ee009bdd..28d0c8b02cc3 100644 --- a/arch/sparc/include/asm/ioctls.h +++ b/arch/sparc/include/asm/ioctls.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #define TCSETS2 _IOW('T', 13, struct termios2) | 19 | #define TCSETS2 _IOW('T', 13, struct termios2) |
20 | #define TCSETSW2 _IOW('T', 14, struct termios2) | 20 | #define TCSETSW2 _IOW('T', 14, struct termios2) |
21 | #define TCSETSF2 _IOW('T', 15, struct termios2) | 21 | #define TCSETSF2 _IOW('T', 15, struct termios2) |
22 | #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ | ||
23 | #define TIOCVHANGUP _IO('T', 0x37) | ||
22 | 24 | ||
23 | /* Note that all the ioctls that are not available in Linux have a | 25 | /* Note that all the ioctls that are not available in Linux have a |
24 | * double underscore on the front to: a) avoid some programs to | 26 | * double underscore on the front to: a) avoid some programs to |
diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h index cbf4801deaaf..2ae3acaeb1b3 100644 --- a/arch/sparc/include/asm/irq_32.h +++ b/arch/sparc/include/asm/irq_32.h | |||
@@ -6,11 +6,18 @@ | |||
6 | #ifndef _SPARC_IRQ_H | 6 | #ifndef _SPARC_IRQ_H |
7 | #define _SPARC_IRQ_H | 7 | #define _SPARC_IRQ_H |
8 | 8 | ||
9 | #define NR_IRQS 16 | 9 | /* Allocated number of logical irq numbers. |
10 | * sun4d boxes (ss2000e) should be OK with ~32. | ||
11 | * Be on the safe side and make room for 64 | ||
12 | */ | ||
13 | #define NR_IRQS 64 | ||
10 | 14 | ||
11 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
12 | 16 | ||
13 | #define irq_canonicalize(irq) (irq) | 17 | #define irq_canonicalize(irq) (irq) |
14 | 18 | ||
15 | extern void __init init_IRQ(void); | 19 | extern void __init init_IRQ(void); |
20 | |||
21 | #define NO_IRQ 0xffffffff | ||
22 | |||
16 | #endif | 23 | #endif |
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index a0b443cb3c1f..16dcae6d56e7 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); |
@@ -97,4 +97,6 @@ extern void *softirq_stack[NR_CPUS]; | |||
97 | #define __ARCH_HAS_DO_SOFTIRQ | 97 | #define __ARCH_HAS_DO_SOFTIRQ |
98 | #define ARCH_HAS_NMI_WATCHDOG | 98 | #define ARCH_HAS_NMI_WATCHDOG |
99 | 99 | ||
100 | #define NO_IRQ 0xffffffff | ||
101 | |||
100 | #endif | 102 | #endif |
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h index 0fca9d97d44f..14848909e0de 100644 --- a/arch/sparc/include/asm/irqflags_32.h +++ b/arch/sparc/include/asm/irqflags_32.h | |||
@@ -5,33 +5,40 @@ | |||
5 | * | 5 | * |
6 | * This file gets included from lowlevel asm headers too, to provide | 6 | * This file gets included from lowlevel asm headers too, to provide |
7 | * wrapped versions of the local_irq_*() APIs, based on the | 7 | * wrapped versions of the local_irq_*() APIs, based on the |
8 | * raw_local_irq_*() functions from the lowlevel headers. | 8 | * arch_local_irq_*() functions from the lowlevel headers. |
9 | */ | 9 | */ |
10 | #ifndef _ASM_IRQFLAGS_H | 10 | #ifndef _ASM_IRQFLAGS_H |
11 | #define _ASM_IRQFLAGS_H | 11 | #define _ASM_IRQFLAGS_H |
12 | 12 | ||
13 | #ifndef __ASSEMBLY__ | 13 | #ifndef __ASSEMBLY__ |
14 | 14 | ||
15 | extern void raw_local_irq_restore(unsigned long); | 15 | #include <linux/types.h> |
16 | extern unsigned long __raw_local_irq_save(void); | ||
17 | extern void raw_local_irq_enable(void); | ||
18 | 16 | ||
19 | static inline unsigned long getipl(void) | 17 | extern void arch_local_irq_restore(unsigned long); |
18 | extern unsigned long arch_local_irq_save(void); | ||
19 | extern void arch_local_irq_enable(void); | ||
20 | |||
21 | static inline notrace unsigned long arch_local_save_flags(void) | ||
20 | { | 22 | { |
21 | unsigned long retval; | 23 | unsigned long flags; |
24 | |||
25 | asm volatile("rd %%psr, %0" : "=r" (flags)); | ||
26 | return flags; | ||
27 | } | ||
22 | 28 | ||
23 | __asm__ __volatile__("rd %%psr, %0" : "=r" (retval)); | 29 | static inline notrace void arch_local_irq_disable(void) |
24 | return retval; | 30 | { |
31 | arch_local_irq_save(); | ||
25 | } | 32 | } |
26 | 33 | ||
27 | #define raw_local_save_flags(flags) ((flags) = getipl()) | 34 | static inline notrace bool arch_irqs_disabled_flags(unsigned long flags) |
28 | #define raw_local_irq_save(flags) ((flags) = __raw_local_irq_save()) | 35 | { |
29 | #define raw_local_irq_disable() ((void) __raw_local_irq_save()) | 36 | return (flags & PSR_PIL) != 0; |
30 | #define raw_irqs_disabled() ((getipl() & PSR_PIL) != 0) | 37 | } |
31 | 38 | ||
32 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 39 | static inline notrace bool arch_irqs_disabled(void) |
33 | { | 40 | { |
34 | return ((flags & PSR_PIL) != 0); | 41 | return arch_irqs_disabled_flags(arch_local_save_flags()); |
35 | } | 42 | } |
36 | 43 | ||
37 | #endif /* (__ASSEMBLY__) */ | 44 | #endif /* (__ASSEMBLY__) */ |
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h index bfa1ea45b4cd..23cd27f6beb4 100644 --- a/arch/sparc/include/asm/irqflags_64.h +++ b/arch/sparc/include/asm/irqflags_64.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * This file gets included from lowlevel asm headers too, to provide | 6 | * This file gets included from lowlevel asm headers too, to provide |
7 | * wrapped versions of the local_irq_*() APIs, based on the | 7 | * wrapped versions of the local_irq_*() APIs, based on the |
8 | * raw_local_irq_*() functions from the lowlevel headers. | 8 | * arch_local_irq_*() functions from the lowlevel headers. |
9 | */ | 9 | */ |
10 | #ifndef _ASM_IRQFLAGS_H | 10 | #ifndef _ASM_IRQFLAGS_H |
11 | #define _ASM_IRQFLAGS_H | 11 | #define _ASM_IRQFLAGS_H |
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ |
16 | 16 | ||
17 | static inline unsigned long __raw_local_save_flags(void) | 17 | static inline notrace unsigned long arch_local_save_flags(void) |
18 | { | 18 | { |
19 | unsigned long flags; | 19 | unsigned long flags; |
20 | 20 | ||
@@ -26,10 +26,7 @@ static inline unsigned long __raw_local_save_flags(void) | |||
26 | return flags; | 26 | return flags; |
27 | } | 27 | } |
28 | 28 | ||
29 | #define raw_local_save_flags(flags) \ | 29 | static inline notrace void arch_local_irq_restore(unsigned long flags) |
30 | do { (flags) = __raw_local_save_flags(); } while (0) | ||
31 | |||
32 | static inline void raw_local_irq_restore(unsigned long flags) | ||
33 | { | 30 | { |
34 | __asm__ __volatile__( | 31 | __asm__ __volatile__( |
35 | "wrpr %0, %%pil" | 32 | "wrpr %0, %%pil" |
@@ -39,7 +36,7 @@ static inline void raw_local_irq_restore(unsigned long flags) | |||
39 | ); | 36 | ); |
40 | } | 37 | } |
41 | 38 | ||
42 | static inline void raw_local_irq_disable(void) | 39 | static inline notrace void arch_local_irq_disable(void) |
43 | { | 40 | { |
44 | __asm__ __volatile__( | 41 | __asm__ __volatile__( |
45 | "wrpr %0, %%pil" | 42 | "wrpr %0, %%pil" |
@@ -49,7 +46,7 @@ static inline void raw_local_irq_disable(void) | |||
49 | ); | 46 | ); |
50 | } | 47 | } |
51 | 48 | ||
52 | static inline void raw_local_irq_enable(void) | 49 | static inline notrace void arch_local_irq_enable(void) |
53 | { | 50 | { |
54 | __asm__ __volatile__( | 51 | __asm__ __volatile__( |
55 | "wrpr 0, %%pil" | 52 | "wrpr 0, %%pil" |
@@ -59,22 +56,17 @@ static inline void raw_local_irq_enable(void) | |||
59 | ); | 56 | ); |
60 | } | 57 | } |
61 | 58 | ||
62 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 59 | static inline notrace int arch_irqs_disabled_flags(unsigned long flags) |
63 | { | 60 | { |
64 | return (flags > 0); | 61 | return (flags > 0); |
65 | } | 62 | } |
66 | 63 | ||
67 | static inline int raw_irqs_disabled(void) | 64 | static inline notrace int arch_irqs_disabled(void) |
68 | { | 65 | { |
69 | unsigned long flags = __raw_local_save_flags(); | 66 | return arch_irqs_disabled_flags(arch_local_save_flags()); |
70 | |||
71 | return raw_irqs_disabled_flags(flags); | ||
72 | } | 67 | } |
73 | 68 | ||
74 | /* | 69 | static inline notrace unsigned long arch_local_irq_save(void) |
75 | * For spinlocks, etc: | ||
76 | */ | ||
77 | static inline unsigned long __raw_local_irq_save(void) | ||
78 | { | 70 | { |
79 | unsigned long flags, tmp; | 71 | unsigned long flags, tmp; |
80 | 72 | ||
@@ -100,9 +92,6 @@ static inline unsigned long __raw_local_irq_save(void) | |||
100 | return flags; | 92 | return flags; |
101 | } | 93 | } |
102 | 94 | ||
103 | #define raw_local_irq_save(flags) \ | ||
104 | do { (flags) = __raw_local_irq_save(); } while (0) | ||
105 | |||
106 | #endif /* (__ASSEMBLY__) */ | 95 | #endif /* (__ASSEMBLY__) */ |
107 | 96 | ||
108 | #endif /* !(_ASM_IRQFLAGS_H) */ | 97 | #endif /* !(_ASM_IRQFLAGS_H) */ |
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h new file mode 100644 index 000000000000..fc73a82366f8 --- /dev/null +++ b/arch/sparc/include/asm/jump_label.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef _ASM_SPARC_JUMP_LABEL_H | ||
2 | #define _ASM_SPARC_JUMP_LABEL_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | |||
6 | #include <linux/types.h> | ||
7 | |||
8 | #define JUMP_LABEL_NOP_SIZE 4 | ||
9 | |||
10 | static __always_inline bool arch_static_branch(struct jump_label_key *key) | ||
11 | { | ||
12 | asm goto("1:\n\t" | ||
13 | "nop\n\t" | ||
14 | "nop\n\t" | ||
15 | ".pushsection __jump_table, \"aw\"\n\t" | ||
16 | ".align 4\n\t" | ||
17 | ".word 1b, %l[l_yes], %c0\n\t" | ||
18 | ".popsection \n\t" | ||
19 | : : "i" (key) : : l_yes); | ||
20 | return false; | ||
21 | l_yes: | ||
22 | return true; | ||
23 | } | ||
24 | |||
25 | #endif /* __KERNEL__ */ | ||
26 | |||
27 | typedef u32 jump_label_t; | ||
28 | |||
29 | struct jump_entry { | ||
30 | jump_label_t code; | ||
31 | jump_label_t target; | ||
32 | jump_label_t key; | ||
33 | }; | ||
34 | |||
35 | #endif | ||
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 3ea5964c43b4..a4e457f003ed 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h | |||
@@ -52,29 +52,6 @@ | |||
52 | #define LEON_DIAGF_VALID 0x2000 | 52 | #define LEON_DIAGF_VALID 0x2000 |
53 | #define LEON_DIAGF_VALID_SHIFT 13 | 53 | #define LEON_DIAGF_VALID_SHIFT 13 |
54 | 54 | ||
55 | /* | ||
56 | * Interrupt Sources | ||
57 | * | ||
58 | * The interrupt source numbers directly map to the trap type and to | ||
59 | * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask, | ||
60 | * and the Interrupt Pending Registers. | ||
61 | */ | ||
62 | #define LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR 1 | ||
63 | #define LEON_INTERRUPT_UART_1_RX_TX 2 | ||
64 | #define LEON_INTERRUPT_UART_0_RX_TX 3 | ||
65 | #define LEON_INTERRUPT_EXTERNAL_0 4 | ||
66 | #define LEON_INTERRUPT_EXTERNAL_1 5 | ||
67 | #define LEON_INTERRUPT_EXTERNAL_2 6 | ||
68 | #define LEON_INTERRUPT_EXTERNAL_3 7 | ||
69 | #define LEON_INTERRUPT_TIMER1 8 | ||
70 | #define LEON_INTERRUPT_TIMER2 9 | ||
71 | #define LEON_INTERRUPT_EMPTY1 10 | ||
72 | #define LEON_INTERRUPT_EMPTY2 11 | ||
73 | #define LEON_INTERRUPT_OPEN_ETH 12 | ||
74 | #define LEON_INTERRUPT_EMPTY4 13 | ||
75 | #define LEON_INTERRUPT_EMPTY5 14 | ||
76 | #define LEON_INTERRUPT_EMPTY6 15 | ||
77 | |||
78 | /* irq masks */ | 55 | /* irq masks */ |
79 | #define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */ | 56 | #define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */ |
80 | #define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */ | 57 | #define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */ |
@@ -183,7 +160,6 @@ static inline void leon_srmmu_enabletlb(void) | |||
183 | /* macro access for leon_readnobuffer_reg() */ | 160 | /* macro access for leon_readnobuffer_reg() */ |
184 | #define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x)) | 161 | #define LEON_BYPASSCACHE_LOAD_VA(x) leon_readnobuffer_reg((unsigned long)(x)) |
185 | 162 | ||
186 | extern void sparc_leon_eirq_register(int eirq); | ||
187 | extern void leon_init(void); | 163 | extern void leon_init(void); |
188 | extern void leon_switch_mm(void); | 164 | extern void leon_switch_mm(void); |
189 | extern void leon_init_IRQ(void); | 165 | extern void leon_init_IRQ(void); |
@@ -224,11 +200,23 @@ static inline void sparc_leon3_disable_cache(void) | |||
224 | "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); | 200 | "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); |
225 | }; | 201 | }; |
226 | 202 | ||
203 | static inline unsigned long sparc_leon3_asr17(void) | ||
204 | { | ||
205 | u32 asr17; | ||
206 | __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17)); | ||
207 | return asr17; | ||
208 | }; | ||
209 | |||
210 | static inline int sparc_leon3_cpuid(void) | ||
211 | { | ||
212 | return sparc_leon3_asr17() >> 28; | ||
213 | } | ||
214 | |||
227 | #endif /*!__ASSEMBLY__*/ | 215 | #endif /*!__ASSEMBLY__*/ |
228 | 216 | ||
229 | #ifdef CONFIG_SMP | 217 | #ifdef CONFIG_SMP |
230 | # define LEON3_IRQ_RESCHEDULE 13 | 218 | # define LEON3_IRQ_IPI_DEFAULT 13 |
231 | # define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) | 219 | # define LEON3_IRQ_TICKER (leon3_ticker_irq) |
232 | # define LEON3_IRQ_CROSS_CALL 15 | 220 | # define LEON3_IRQ_CROSS_CALL 15 |
233 | #endif | 221 | #endif |
234 | 222 | ||
@@ -327,9 +315,12 @@ struct leon2_cacheregs { | |||
327 | #include <linux/interrupt.h> | 315 | #include <linux/interrupt.h> |
328 | 316 | ||
329 | struct device_node; | 317 | struct device_node; |
330 | extern int sparc_leon_eirq_get(int eirq, int cpu); | 318 | extern unsigned int leon_build_device_irq(unsigned int real_irq, |
331 | extern irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id); | 319 | irq_flow_handler_t flow_handler, |
332 | extern void sparc_leon_eirq_register(int eirq); | 320 | const char *name, int do_ack); |
321 | extern void leon_update_virq_handling(unsigned int virq, | ||
322 | irq_flow_handler_t flow_handler, | ||
323 | const char *name, int do_ack); | ||
333 | extern void leon_clear_clock_irq(void); | 324 | extern void leon_clear_clock_irq(void); |
334 | extern void leon_load_profile_irq(int cpu, unsigned int limit); | 325 | extern void leon_load_profile_irq(int cpu, unsigned int limit); |
335 | extern void leon_init_timers(irq_handler_t counter_fn); | 326 | extern void leon_init_timers(irq_handler_t counter_fn); |
@@ -346,6 +337,7 @@ extern void leon3_getCacheRegs(struct leon3_cacheregs *regs); | |||
346 | extern int leon_flush_needed(void); | 337 | extern int leon_flush_needed(void); |
347 | extern void leon_switch_mm(void); | 338 | extern void leon_switch_mm(void); |
348 | extern int srmmu_swprobe_trace; | 339 | extern int srmmu_swprobe_trace; |
340 | extern int leon3_ticker_irq; | ||
349 | 341 | ||
350 | #ifdef CONFIG_SMP | 342 | #ifdef CONFIG_SMP |
351 | extern int leon_smp_nrcpus(void); | 343 | extern int leon_smp_nrcpus(void); |
@@ -354,20 +346,19 @@ extern void leon_smp_done(void); | |||
354 | extern void leon_boot_cpus(void); | 346 | extern void leon_boot_cpus(void); |
355 | extern int leon_boot_one_cpu(int i); | 347 | extern int leon_boot_one_cpu(int i); |
356 | void leon_init_smp(void); | 348 | void leon_init_smp(void); |
357 | extern void cpu_probe(void); | ||
358 | extern void cpu_idle(void); | 349 | extern void cpu_idle(void); |
359 | extern void init_IRQ(void); | 350 | extern void init_IRQ(void); |
360 | extern void cpu_panic(void); | 351 | extern void cpu_panic(void); |
361 | extern int __leon_processor_id(void); | 352 | extern int __leon_processor_id(void); |
362 | void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); | 353 | void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu); |
354 | extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused); | ||
363 | 355 | ||
364 | extern unsigned int real_irq_entry[], smpleon_ticker[]; | 356 | extern unsigned int real_irq_entry[]; |
357 | extern unsigned int smpleon_ipi[]; | ||
365 | extern unsigned int patchme_maybe_smp_msg[]; | 358 | extern unsigned int patchme_maybe_smp_msg[]; |
366 | extern unsigned long trapbase_cpu1[]; | ||
367 | extern unsigned long trapbase_cpu2[]; | ||
368 | extern unsigned long trapbase_cpu3[]; | ||
369 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; | 359 | extern unsigned int t_nmi[], linux_trap_ipi15_leon[]; |
370 | extern unsigned int linux_trap_ipi15_sun4m[]; | 360 | extern unsigned int linux_trap_ipi15_sun4m[]; |
361 | extern int leon_ipi_irq; | ||
371 | 362 | ||
372 | #endif /* CONFIG_SMP */ | 363 | #endif /* CONFIG_SMP */ |
373 | 364 | ||
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h index 618e88821795..e50f326e71bd 100644 --- a/arch/sparc/include/asm/leon_amba.h +++ b/arch/sparc/include/asm/leon_amba.h | |||
@@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map { | |||
100 | u32 mpbroadcast; | 100 | u32 mpbroadcast; |
101 | u32 notused02; | 101 | u32 notused02; |
102 | u32 notused03; | 102 | u32 notused03; |
103 | u32 notused10; | 103 | u32 ampctrl; |
104 | u32 notused11; | 104 | u32 icsel[2]; |
105 | u32 notused12; | ||
106 | u32 notused13; | 105 | u32 notused13; |
107 | u32 notused20; | 106 | u32 notused20; |
108 | u32 notused21; | 107 | u32 notused21; |
@@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map { | |||
112 | u32 force[16]; | 111 | u32 force[16]; |
113 | /* Extended IRQ registers */ | 112 | /* Extended IRQ registers */ |
114 | u32 intid[16]; /* 0xc0 */ | 113 | u32 intid[16]; /* 0xc0 */ |
114 | u32 unused[(0x1000-0x100)/4]; | ||
115 | }; | 115 | }; |
116 | 116 | ||
117 | struct leon3_apbuart_regs_map { | 117 | struct leon3_apbuart_regs_map { |
@@ -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/leon_pci.h b/arch/sparc/include/asm/leon_pci.h new file mode 100644 index 000000000000..42b4b31a82fe --- /dev/null +++ b/arch/sparc/include/asm/leon_pci.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * asm/leon_pci.h | ||
3 | * | ||
4 | * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom | ||
5 | */ | ||
6 | |||
7 | #ifndef _ASM_LEON_PCI_H_ | ||
8 | #define _ASM_LEON_PCI_H_ | ||
9 | |||
10 | /* PCI related definitions */ | ||
11 | struct leon_pci_info { | ||
12 | struct pci_ops *ops; | ||
13 | struct resource io_space; | ||
14 | struct resource mem_space; | ||
15 | int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin); | ||
16 | }; | ||
17 | |||
18 | extern void leon_pci_init(struct platform_device *ofdev, | ||
19 | struct leon_pci_info *info); | ||
20 | |||
21 | #endif /* _ASM_LEON_PCI_H_ */ | ||
diff --git a/arch/sparc/include/asm/memblock.h b/arch/sparc/include/asm/memblock.h index f12af880649b..c67b047ef85e 100644 --- a/arch/sparc/include/asm/memblock.h +++ b/arch/sparc/include/asm/memblock.h | |||
@@ -5,6 +5,4 @@ | |||
5 | 5 | ||
6 | #define MEMBLOCK_DBG(fmt...) prom_printf(fmt) | 6 | #define MEMBLOCK_DBG(fmt...) prom_printf(fmt) |
7 | 7 | ||
8 | #define MEMBLOCK_REAL_LIMIT 0 | ||
9 | |||
10 | #endif /* !(_SPARC64_MEMBLOCK_H) */ | 8 | #endif /* !(_SPARC64_MEMBLOCK_H) */ |
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/mmzone.h b/arch/sparc/include/asm/mmzone.h index e8c648741ed4..99d9b9f577bf 100644 --- a/arch/sparc/include/asm/mmzone.h +++ b/arch/sparc/include/asm/mmzone.h | |||
@@ -8,8 +8,6 @@ | |||
8 | extern struct pglist_data *node_data[]; | 8 | extern struct pglist_data *node_data[]; |
9 | 9 | ||
10 | #define NODE_DATA(nid) (node_data[nid]) | 10 | #define NODE_DATA(nid) (node_data[nid]) |
11 | #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) | ||
12 | #define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) | ||
13 | 11 | ||
14 | extern int numa_cpu_lookup_table[]; | 12 | extern int numa_cpu_lookup_table[]; |
15 | extern cpumask_t numa_cpumask_lookup_table[]; | 13 | extern cpumask_t numa_cpumask_lookup_table[]; |
diff --git a/arch/sparc/include/asm/ns87303.h b/arch/sparc/include/asm/ns87303.h index 686defe6aaa0..af755483e17d 100644 --- a/arch/sparc/include/asm/ns87303.h +++ b/arch/sparc/include/asm/ns87303.h | |||
@@ -37,7 +37,7 @@ | |||
37 | /* Power and Test Register (PTR) bits */ | 37 | /* Power and Test Register (PTR) bits */ |
38 | #define PTR_LPTB_IRQ7 0x08 | 38 | #define PTR_LPTB_IRQ7 0x08 |
39 | #define PTR_LEVEL_IRQ 0x80 /* When not ECP/EPP: Use level IRQ */ | 39 | #define PTR_LEVEL_IRQ 0x80 /* When not ECP/EPP: Use level IRQ */ |
40 | #define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controlls direction */ | 40 | #define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controls direction */ |
41 | /* of the parallel port */ | 41 | /* of the parallel port */ |
42 | 42 | ||
43 | /* Function Control Register (FCR) bits */ | 43 | /* Function Control Register (FCR) bits */ |
diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h index 963e1a45c35f..47eaafad15ce 100644 --- a/arch/sparc/include/asm/openprom.h +++ b/arch/sparc/include/asm/openprom.h | |||
@@ -11,6 +11,8 @@ | |||
11 | #define LINUX_OPPROM_MAGIC 0x10010407 | 11 | #define LINUX_OPPROM_MAGIC 0x10010407 |
12 | 12 | ||
13 | #ifndef __ASSEMBLY__ | 13 | #ifndef __ASSEMBLY__ |
14 | #include <linux/of.h> | ||
15 | |||
14 | /* V0 prom device operations. */ | 16 | /* V0 prom device operations. */ |
15 | struct linux_dev_v0_funcs { | 17 | struct linux_dev_v0_funcs { |
16 | int (*v0_devopen)(char *device_str); | 18 | int (*v0_devopen)(char *device_str); |
@@ -26,7 +28,7 @@ struct linux_dev_v0_funcs { | |||
26 | 28 | ||
27 | /* V2 and later prom device operations. */ | 29 | /* V2 and later prom device operations. */ |
28 | struct linux_dev_v2_funcs { | 30 | struct linux_dev_v2_funcs { |
29 | int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */ | 31 | phandle (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */ |
30 | char * (*v2_dumb_mem_alloc)(char *va, unsigned sz); | 32 | char * (*v2_dumb_mem_alloc)(char *va, unsigned sz); |
31 | void (*v2_dumb_mem_free)(char *va, unsigned sz); | 33 | void (*v2_dumb_mem_free)(char *va, unsigned sz); |
32 | 34 | ||
@@ -37,7 +39,7 @@ struct linux_dev_v2_funcs { | |||
37 | int (*v2_dev_open)(char *devpath); | 39 | int (*v2_dev_open)(char *devpath); |
38 | void (*v2_dev_close)(int d); | 40 | void (*v2_dev_close)(int d); |
39 | int (*v2_dev_read)(int d, char *buf, int nbytes); | 41 | int (*v2_dev_read)(int d, char *buf, int nbytes); |
40 | int (*v2_dev_write)(int d, char *buf, int nbytes); | 42 | int (*v2_dev_write)(int d, const char *buf, int nbytes); |
41 | int (*v2_dev_seek)(int d, int hi, int lo); | 43 | int (*v2_dev_seek)(int d, int hi, int lo); |
42 | 44 | ||
43 | /* Never issued (multistage load support) */ | 45 | /* Never issued (multistage load support) */ |
@@ -168,12 +170,12 @@ struct linux_romvec { | |||
168 | 170 | ||
169 | /* Routines for traversing the prom device tree. */ | 171 | /* Routines for traversing the prom device tree. */ |
170 | struct linux_nodeops { | 172 | struct linux_nodeops { |
171 | int (*no_nextnode)(int node); | 173 | phandle (*no_nextnode)(phandle node); |
172 | int (*no_child)(int node); | 174 | phandle (*no_child)(phandle node); |
173 | int (*no_proplen)(int node, const char *name); | 175 | int (*no_proplen)(phandle node, const char *name); |
174 | int (*no_getprop)(int node, const char *name, char *val); | 176 | int (*no_getprop)(phandle node, const char *name, char *val); |
175 | int (*no_setprop)(int node, const char *name, char *val, int len); | 177 | int (*no_setprop)(phandle node, const char *name, char *val, int len); |
176 | char * (*no_nextprop)(int node, char *name); | 178 | char * (*no_nextprop)(phandle node, char *name); |
177 | }; | 179 | }; |
178 | 180 | ||
179 | /* More fun PROM structures for device probing. */ | 181 | /* More fun PROM structures for device probing. */ |
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 33e31ce6b31f..71e5e9aeb67e 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h | |||
@@ -30,7 +30,7 @@ extern unsigned int prom_rev, prom_prev; | |||
30 | /* Root node of the prom device tree, this stays constant after | 30 | /* Root node of the prom device tree, this stays constant after |
31 | * initialization is complete. | 31 | * initialization is complete. |
32 | */ | 32 | */ |
33 | extern int prom_root_node; | 33 | extern phandle prom_root_node; |
34 | 34 | ||
35 | /* Pointer to prom structure containing the device tree traversal | 35 | /* Pointer to prom structure containing the device tree traversal |
36 | * and usage utility functions. Only prom-lib should use these, | 36 | * and usage utility functions. Only prom-lib should use these, |
@@ -48,37 +48,6 @@ extern void prom_init(struct linux_romvec *rom_ptr); | |||
48 | /* Boot argument acquisition, returns the boot command line string. */ | 48 | /* Boot argument acquisition, returns the boot command line string. */ |
49 | extern char *prom_getbootargs(void); | 49 | extern char *prom_getbootargs(void); |
50 | 50 | ||
51 | /* Device utilities. */ | ||
52 | |||
53 | /* Map and unmap devices in IO space at virtual addresses. Note that the | ||
54 | * virtual address you pass is a request and the prom may put your mappings | ||
55 | * somewhere else, so check your return value as that is where your new | ||
56 | * mappings really are! | ||
57 | * | ||
58 | * Another note, these are only available on V2 or higher proms! | ||
59 | */ | ||
60 | extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes); | ||
61 | extern void prom_unmapio(char *virt_addr, unsigned int num_bytes); | ||
62 | |||
63 | /* Device operations. */ | ||
64 | |||
65 | /* Open the device described by the passed string. Note, that the format | ||
66 | * of the string is different on V0 vs. V2->higher proms. The caller must | ||
67 | * know what he/she is doing! Returns the device descriptor, an int. | ||
68 | */ | ||
69 | extern int prom_devopen(char *device_string); | ||
70 | |||
71 | /* Close a previously opened device described by the passed integer | ||
72 | * descriptor. | ||
73 | */ | ||
74 | extern int prom_devclose(int device_handle); | ||
75 | |||
76 | /* Do a seek operation on the device described by the passed integer | ||
77 | * descriptor. | ||
78 | */ | ||
79 | extern void prom_seek(int device_handle, unsigned int seek_hival, | ||
80 | unsigned int seek_lowval); | ||
81 | |||
82 | /* Miscellaneous routines, don't really fit in any category per se. */ | 51 | /* Miscellaneous routines, don't really fit in any category per se. */ |
83 | 52 | ||
84 | /* Reboot the machine with the command line passed. */ | 53 | /* Reboot the machine with the command line passed. */ |
@@ -95,7 +64,7 @@ extern void prom_cmdline(void); | |||
95 | /* Enter the prom, with no chance of continuation for the stand-alone | 64 | /* Enter the prom, with no chance of continuation for the stand-alone |
96 | * which calls this. | 65 | * which calls this. |
97 | */ | 66 | */ |
98 | extern void prom_halt(void) __attribute__ ((noreturn)); | 67 | extern void __noreturn prom_halt(void); |
99 | 68 | ||
100 | /* Set the PROM 'sync' callback function to the passed function pointer. | 69 | /* Set the PROM 'sync' callback function to the passed function pointer. |
101 | * When the user gives the 'sync' command at the prom prompt while the | 70 | * When the user gives the 'sync' command at the prom prompt while the |
@@ -121,19 +90,8 @@ extern int prom_getrev(void); | |||
121 | /* Get the prom firmware revision. */ | 90 | /* Get the prom firmware revision. */ |
122 | extern int prom_getprev(void); | 91 | extern int prom_getprev(void); |
123 | 92 | ||
124 | /* Character operations to/from the console.... */ | 93 | /* Write a buffer of characters to the console. */ |
125 | 94 | extern void prom_console_write_buf(const char *buf, int len); | |
126 | /* Non-blocking get character from console. */ | ||
127 | extern int prom_nbgetchar(void); | ||
128 | |||
129 | /* Non-blocking put character to console. */ | ||
130 | extern int prom_nbputchar(char character); | ||
131 | |||
132 | /* Blocking get character from console. */ | ||
133 | extern char prom_getchar(void); | ||
134 | |||
135 | /* Blocking put character to console. */ | ||
136 | extern void prom_putchar(char character); | ||
137 | 95 | ||
138 | /* Prom's internal routines, don't use in kernel/boot code. */ | 96 | /* Prom's internal routines, don't use in kernel/boot code. */ |
139 | extern void prom_printf(const char *fmt, ...); | 97 | extern void prom_printf(const char *fmt, ...); |
@@ -147,25 +105,6 @@ extern void prom_write(const char *buf, unsigned int len); | |||
147 | extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table, | 105 | extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table, |
148 | int context, char *program_counter); | 106 | int context, char *program_counter); |
149 | 107 | ||
150 | /* Stop the CPU with the passed device tree node. */ | ||
151 | extern int prom_stopcpu(int cpunode); | ||
152 | |||
153 | /* Idle the CPU with the passed device tree node. */ | ||
154 | extern int prom_idlecpu(int cpunode); | ||
155 | |||
156 | /* Re-Start the CPU with the passed device tree node. */ | ||
157 | extern int prom_restartcpu(int cpunode); | ||
158 | |||
159 | /* PROM memory allocation facilities... */ | ||
160 | |||
161 | /* Allocated at possibly the given virtual address a chunk of the | ||
162 | * indicated size. | ||
163 | */ | ||
164 | extern char *prom_alloc(char *virt_hint, unsigned int size); | ||
165 | |||
166 | /* Free a previously allocated chunk. */ | ||
167 | extern void prom_free(char *virt_addr, unsigned int size); | ||
168 | |||
169 | /* Sun4/sun4c specific memory-management startup hook. */ | 108 | /* Sun4/sun4c specific memory-management startup hook. */ |
170 | 109 | ||
171 | /* Map the passed segment in the given context at the passed | 110 | /* Map the passed segment in the given context at the passed |
@@ -174,72 +113,62 @@ extern void prom_free(char *virt_addr, unsigned int size); | |||
174 | extern void prom_putsegment(int context, unsigned long virt_addr, | 113 | extern void prom_putsegment(int context, unsigned long virt_addr, |
175 | int physical_segment); | 114 | int physical_segment); |
176 | 115 | ||
116 | /* Initialize the memory lists based upon the prom version. */ | ||
117 | void prom_meminit(void); | ||
177 | 118 | ||
178 | /* PROM device tree traversal functions... */ | 119 | /* PROM device tree traversal functions... */ |
179 | 120 | ||
180 | /* Get the child node of the given node, or zero if no child exists. */ | 121 | /* Get the child node of the given node, or zero if no child exists. */ |
181 | extern int prom_getchild(int parent_node); | 122 | extern phandle prom_getchild(phandle parent_node); |
182 | 123 | ||
183 | /* Get the next sibling node of the given node, or zero if no further | 124 | /* Get the next sibling node of the given node, or zero if no further |
184 | * siblings exist. | 125 | * siblings exist. |
185 | */ | 126 | */ |
186 | extern int prom_getsibling(int node); | 127 | extern phandle prom_getsibling(phandle node); |
187 | 128 | ||
188 | /* Get the length, at the passed node, of the given property type. | 129 | /* Get the length, at the passed node, of the given property type. |
189 | * Returns -1 on error (ie. no such property at this node). | 130 | * Returns -1 on error (ie. no such property at this node). |
190 | */ | 131 | */ |
191 | extern int prom_getproplen(int thisnode, const char *property); | 132 | extern int prom_getproplen(phandle thisnode, const char *property); |
192 | 133 | ||
193 | /* Fetch the requested property using the given buffer. Returns | 134 | /* Fetch the requested property using the given buffer. Returns |
194 | * the number of bytes the prom put into your buffer or -1 on error. | 135 | * the number of bytes the prom put into your buffer or -1 on error. |
195 | */ | 136 | */ |
196 | extern int __must_check prom_getproperty(int thisnode, const char *property, | 137 | extern int __must_check prom_getproperty(phandle thisnode, const char *property, |
197 | char *prop_buffer, int propbuf_size); | 138 | char *prop_buffer, int propbuf_size); |
198 | 139 | ||
199 | /* Acquire an integer property. */ | 140 | /* Acquire an integer property. */ |
200 | extern int prom_getint(int node, char *property); | 141 | extern int prom_getint(phandle node, char *property); |
201 | 142 | ||
202 | /* Acquire an integer property, with a default value. */ | 143 | /* Acquire an integer property, with a default value. */ |
203 | extern int prom_getintdefault(int node, char *property, int defval); | 144 | extern int prom_getintdefault(phandle node, char *property, int defval); |
204 | 145 | ||
205 | /* Acquire a boolean property, 0=FALSE 1=TRUE. */ | 146 | /* Acquire a boolean property, 0=FALSE 1=TRUE. */ |
206 | extern int prom_getbool(int node, char *prop); | 147 | extern int prom_getbool(phandle node, char *prop); |
207 | 148 | ||
208 | /* Acquire a string property, null string on error. */ | 149 | /* Acquire a string property, null string on error. */ |
209 | extern void prom_getstring(int node, char *prop, char *buf, int bufsize); | 150 | extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize); |
210 | |||
211 | /* Does the passed node have the given "name"? YES=1 NO=0 */ | ||
212 | extern int prom_nodematch(int thisnode, char *name); | ||
213 | 151 | ||
214 | /* Search all siblings starting at the passed node for "name" matching | 152 | /* Search all siblings starting at the passed node for "name" matching |
215 | * the given string. Returns the node on success, zero on failure. | 153 | * the given string. Returns the node on success, zero on failure. |
216 | */ | 154 | */ |
217 | extern int prom_searchsiblings(int node_start, char *name); | 155 | extern phandle prom_searchsiblings(phandle node_start, char *name); |
218 | |||
219 | /* Return the first property type, as a string, for the given node. | ||
220 | * Returns a null string on error. | ||
221 | */ | ||
222 | extern char *prom_firstprop(int node, char *buffer); | ||
223 | 156 | ||
224 | /* Returns the next property after the passed property for the given | 157 | /* Returns the next property after the passed property for the given |
225 | * node. Returns null string on failure. | 158 | * node. Returns null string on failure. |
226 | */ | 159 | */ |
227 | extern char *prom_nextprop(int node, char *prev_property, char *buffer); | 160 | extern char *prom_nextprop(phandle node, char *prev_property, char *buffer); |
228 | 161 | ||
229 | /* Returns phandle of the path specified */ | 162 | /* Returns phandle of the path specified */ |
230 | extern int prom_finddevice(char *name); | 163 | extern phandle prom_finddevice(char *name); |
231 | |||
232 | /* Returns 1 if the specified node has given property. */ | ||
233 | extern int prom_node_has_property(int node, char *property); | ||
234 | 164 | ||
235 | /* Set the indicated property at the given node with the passed value. | 165 | /* Set the indicated property at the given node with the passed value. |
236 | * Returns the number of bytes of your value that the prom took. | 166 | * Returns the number of bytes of your value that the prom took. |
237 | */ | 167 | */ |
238 | extern int prom_setprop(int node, const char *prop_name, char *prop_value, | 168 | extern int prom_setprop(phandle node, const char *prop_name, char *prop_value, |
239 | int value_size); | 169 | int value_size); |
240 | 170 | ||
241 | extern int prom_pathtoinode(char *path); | 171 | extern phandle prom_inst2pkg(int); |
242 | extern int prom_inst2pkg(int); | ||
243 | 172 | ||
244 | /* Dorking with Bus ranges... */ | 173 | /* Dorking with Bus ranges... */ |
245 | 174 | ||
@@ -247,13 +176,15 @@ extern int prom_inst2pkg(int); | |||
247 | extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs); | 176 | extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs); |
248 | 177 | ||
249 | /* Apply ranges of any prom node (and optionally parent node as well) to registers. */ | 178 | /* Apply ranges of any prom node (and optionally parent node as well) to registers. */ |
250 | extern void prom_apply_generic_ranges(int node, int parent, | 179 | extern void prom_apply_generic_ranges(phandle node, phandle parent, |
251 | struct linux_prom_registers *sbusregs, int nregs); | 180 | struct linux_prom_registers *sbusregs, int nregs); |
252 | 181 | ||
182 | void prom_ranges_init(void); | ||
183 | |||
253 | /* CPU probing helpers. */ | 184 | /* CPU probing helpers. */ |
254 | int cpu_find_by_instance(int instance, int *prom_node, int *mid); | 185 | int cpu_find_by_instance(int instance, phandle *prom_node, int *mid); |
255 | int cpu_find_by_mid(int mid, int *prom_node); | 186 | int cpu_find_by_mid(int mid, phandle *prom_node); |
256 | int cpu_get_hwmid(int prom_node); | 187 | int cpu_get_hwmid(phandle prom_node); |
257 | 188 | ||
258 | extern spinlock_t prom_lock; | 189 | extern spinlock_t prom_lock; |
259 | 190 | ||
diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 3e0b2d62303d..97a90475c314 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h | |||
@@ -16,15 +16,15 @@ extern char prom_version[]; | |||
16 | /* Root node of the prom device tree, this stays constant after | 16 | /* Root node of the prom device tree, this stays constant after |
17 | * initialization is complete. | 17 | * initialization is complete. |
18 | */ | 18 | */ |
19 | extern int prom_root_node; | 19 | extern phandle prom_root_node; |
20 | 20 | ||
21 | /* PROM stdin and stdout */ | 21 | /* PROM stdout */ |
22 | extern int prom_stdin, prom_stdout; | 22 | extern int prom_stdout; |
23 | 23 | ||
24 | /* /chosen node of the prom device tree, this stays constant after | 24 | /* /chosen node of the prom device tree, this stays constant after |
25 | * initialization is complete. | 25 | * initialization is complete. |
26 | */ | 26 | */ |
27 | extern int prom_chosen_node; | 27 | extern phandle prom_chosen_node; |
28 | 28 | ||
29 | /* Helper values and strings in arch/sparc64/kernel/head.S */ | 29 | /* Helper values and strings in arch/sparc64/kernel/head.S */ |
30 | extern const char prom_peer_name[]; | 30 | extern const char prom_peer_name[]; |
@@ -67,27 +67,6 @@ extern void prom_init(void *cif_handler, void *cif_stack); | |||
67 | /* Boot argument acquisition, returns the boot command line string. */ | 67 | /* Boot argument acquisition, returns the boot command line string. */ |
68 | extern char *prom_getbootargs(void); | 68 | extern char *prom_getbootargs(void); |
69 | 69 | ||
70 | /* Device utilities. */ | ||
71 | |||
72 | /* Device operations. */ | ||
73 | |||
74 | /* Open the device described by the passed string. Note, that the format | ||
75 | * of the string is different on V0 vs. V2->higher proms. The caller must | ||
76 | * know what he/she is doing! Returns the device descriptor, an int. | ||
77 | */ | ||
78 | extern int prom_devopen(const char *device_string); | ||
79 | |||
80 | /* Close a previously opened device described by the passed integer | ||
81 | * descriptor. | ||
82 | */ | ||
83 | extern int prom_devclose(int device_handle); | ||
84 | |||
85 | /* Do a seek operation on the device described by the passed integer | ||
86 | * descriptor. | ||
87 | */ | ||
88 | extern void prom_seek(int device_handle, unsigned int seek_hival, | ||
89 | unsigned int seek_lowval); | ||
90 | |||
91 | /* Miscellaneous routines, don't really fit in any category per se. */ | 70 | /* Miscellaneous routines, don't really fit in any category per se. */ |
92 | 71 | ||
93 | /* Reboot the machine with the command line passed. */ | 72 | /* Reboot the machine with the command line passed. */ |
@@ -109,33 +88,14 @@ extern void prom_halt(void) __attribute__ ((noreturn)); | |||
109 | /* Halt and power-off the machine. */ | 88 | /* Halt and power-off the machine. */ |
110 | extern void prom_halt_power_off(void) __attribute__ ((noreturn)); | 89 | extern void prom_halt_power_off(void) __attribute__ ((noreturn)); |
111 | 90 | ||
112 | /* Set the PROM 'sync' callback function to the passed function pointer. | ||
113 | * When the user gives the 'sync' command at the prom prompt while the | ||
114 | * kernel is still active, the prom will call this routine. | ||
115 | * | ||
116 | */ | ||
117 | typedef int (*callback_func_t)(long *cmd); | ||
118 | extern void prom_setcallback(callback_func_t func_ptr); | ||
119 | |||
120 | /* Acquire the IDPROM of the root node in the prom device tree. This | 91 | /* Acquire the IDPROM of the root node in the prom device tree. This |
121 | * gets passed a buffer where you would like it stuffed. The return value | 92 | * gets passed a buffer where you would like it stuffed. The return value |
122 | * is the format type of this idprom or 0xff on error. | 93 | * is the format type of this idprom or 0xff on error. |
123 | */ | 94 | */ |
124 | extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); | 95 | extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size); |
125 | 96 | ||
126 | /* Character operations to/from the console.... */ | 97 | /* Write a buffer of characters to the console. */ |
127 | 98 | extern void prom_console_write_buf(const char *buf, int len); | |
128 | /* Non-blocking get character from console. */ | ||
129 | extern int prom_nbgetchar(void); | ||
130 | |||
131 | /* Non-blocking put character to console. */ | ||
132 | extern int prom_nbputchar(char character); | ||
133 | |||
134 | /* Blocking get character from console. */ | ||
135 | extern char prom_getchar(void); | ||
136 | |||
137 | /* Blocking put character to console. */ | ||
138 | extern void prom_putchar(char character); | ||
139 | 99 | ||
140 | /* Prom's internal routines, don't use in kernel/boot code. */ | 100 | /* Prom's internal routines, don't use in kernel/boot code. */ |
141 | extern void prom_printf(const char *fmt, ...); | 101 | extern void prom_printf(const char *fmt, ...); |
@@ -218,69 +178,68 @@ extern void prom_unmap(unsigned long size, unsigned long vaddr); | |||
218 | /* PROM device tree traversal functions... */ | 178 | /* PROM device tree traversal functions... */ |
219 | 179 | ||
220 | /* Get the child node of the given node, or zero if no child exists. */ | 180 | /* Get the child node of the given node, or zero if no child exists. */ |
221 | extern int prom_getchild(int parent_node); | 181 | extern phandle prom_getchild(phandle parent_node); |
222 | 182 | ||
223 | /* Get the next sibling node of the given node, or zero if no further | 183 | /* Get the next sibling node of the given node, or zero if no further |
224 | * siblings exist. | 184 | * siblings exist. |
225 | */ | 185 | */ |
226 | extern int prom_getsibling(int node); | 186 | extern phandle prom_getsibling(phandle node); |
227 | 187 | ||
228 | /* Get the length, at the passed node, of the given property type. | 188 | /* Get the length, at the passed node, of the given property type. |
229 | * Returns -1 on error (ie. no such property at this node). | 189 | * Returns -1 on error (ie. no such property at this node). |
230 | */ | 190 | */ |
231 | extern int prom_getproplen(int thisnode, const char *property); | 191 | extern int prom_getproplen(phandle thisnode, const char *property); |
232 | 192 | ||
233 | /* Fetch the requested property using the given buffer. Returns | 193 | /* Fetch the requested property using the given buffer. Returns |
234 | * the number of bytes the prom put into your buffer or -1 on error. | 194 | * the number of bytes the prom put into your buffer or -1 on error. |
235 | */ | 195 | */ |
236 | extern int prom_getproperty(int thisnode, const char *property, | 196 | extern int prom_getproperty(phandle thisnode, const char *property, |
237 | char *prop_buffer, int propbuf_size); | 197 | char *prop_buffer, int propbuf_size); |
238 | 198 | ||
239 | /* Acquire an integer property. */ | 199 | /* Acquire an integer property. */ |
240 | extern int prom_getint(int node, const char *property); | 200 | extern int prom_getint(phandle node, const char *property); |
241 | 201 | ||
242 | /* Acquire an integer property, with a default value. */ | 202 | /* Acquire an integer property, with a default value. */ |
243 | extern int prom_getintdefault(int node, const char *property, int defval); | 203 | extern int prom_getintdefault(phandle node, const char *property, int defval); |
244 | 204 | ||
245 | /* Acquire a boolean property, 0=FALSE 1=TRUE. */ | 205 | /* Acquire a boolean property, 0=FALSE 1=TRUE. */ |
246 | extern int prom_getbool(int node, const char *prop); | 206 | extern int prom_getbool(phandle node, const char *prop); |
247 | 207 | ||
248 | /* Acquire a string property, null string on error. */ | 208 | /* Acquire a string property, null string on error. */ |
249 | extern void prom_getstring(int node, const char *prop, char *buf, int bufsize); | 209 | extern void prom_getstring(phandle node, const char *prop, char *buf, |
210 | int bufsize); | ||
250 | 211 | ||
251 | /* Does the passed node have the given "name"? YES=1 NO=0 */ | 212 | /* Does the passed node have the given "name"? YES=1 NO=0 */ |
252 | extern int prom_nodematch(int thisnode, const char *name); | 213 | extern int prom_nodematch(phandle thisnode, const char *name); |
253 | 214 | ||
254 | /* Search all siblings starting at the passed node for "name" matching | 215 | /* Search all siblings starting at the passed node for "name" matching |
255 | * the given string. Returns the node on success, zero on failure. | 216 | * the given string. Returns the node on success, zero on failure. |
256 | */ | 217 | */ |
257 | extern int prom_searchsiblings(int node_start, const char *name); | 218 | extern phandle prom_searchsiblings(phandle node_start, const char *name); |
258 | 219 | ||
259 | /* Return the first property type, as a string, for the given node. | 220 | /* Return the first property type, as a string, for the given node. |
260 | * Returns a null string on error. Buffer should be at least 32B long. | 221 | * Returns a null string on error. Buffer should be at least 32B long. |
261 | */ | 222 | */ |
262 | extern char *prom_firstprop(int node, char *buffer); | 223 | extern char *prom_firstprop(phandle node, char *buffer); |
263 | 224 | ||
264 | /* Returns the next property after the passed property for the given | 225 | /* Returns the next property after the passed property for the given |
265 | * node. Returns null string on failure. Buffer should be at least 32B long. | 226 | * node. Returns null string on failure. Buffer should be at least 32B long. |
266 | */ | 227 | */ |
267 | extern char *prom_nextprop(int node, const char *prev_property, char *buffer); | 228 | extern char *prom_nextprop(phandle node, const char *prev_property, char *buf); |
268 | 229 | ||
269 | /* Returns 1 if the specified node has given property. */ | 230 | /* Returns 1 if the specified node has given property. */ |
270 | extern int prom_node_has_property(int node, const char *property); | 231 | extern int prom_node_has_property(phandle node, const char *property); |
271 | 232 | ||
272 | /* Returns phandle of the path specified */ | 233 | /* Returns phandle of the path specified */ |
273 | extern int prom_finddevice(const char *name); | 234 | extern phandle prom_finddevice(const char *name); |
274 | 235 | ||
275 | /* Set the indicated property at the given node with the passed value. | 236 | /* Set the indicated property at the given node with the passed value. |
276 | * Returns the number of bytes of your value that the prom took. | 237 | * Returns the number of bytes of your value that the prom took. |
277 | */ | 238 | */ |
278 | extern int prom_setprop(int node, const char *prop_name, char *prop_value, | 239 | extern int prom_setprop(phandle node, const char *prop_name, char *prop_value, |
279 | int value_size); | 240 | int value_size); |
280 | 241 | ||
281 | extern int prom_pathtoinode(const char *path); | 242 | extern phandle prom_inst2pkg(int); |
282 | extern int prom_inst2pkg(int); | ||
283 | extern int prom_service_exists(const char *service_name); | ||
284 | extern void prom_sun4v_guest_soft_state(void); | 243 | extern void prom_sun4v_guest_soft_state(void); |
285 | 244 | ||
286 | extern int prom_ihandle2path(int handle, char *buffer, int bufsize); | 245 | extern int prom_ihandle2path(int handle, char *buffer, int bufsize); |
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index aa4c82648d88..cb33608cc68f 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h | |||
@@ -103,7 +103,7 @@ static inline unsigned int get_dma_residue(unsigned int dmanr) | |||
103 | return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); | 103 | return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); |
104 | } | 104 | } |
105 | 105 | ||
106 | static int __devinit ecpp_probe(struct platform_device *op, const struct of_device_id *match) | 106 | static int __devinit ecpp_probe(struct platform_device *op) |
107 | { | 107 | { |
108 | unsigned long base = op->resource[0].start; | 108 | unsigned long base = op->resource[0].start; |
109 | unsigned long config = op->resource[1].start; | 109 | unsigned long config = op->resource[1].start; |
@@ -235,7 +235,7 @@ static const struct of_device_id ecpp_match[] = { | |||
235 | {}, | 235 | {}, |
236 | }; | 236 | }; |
237 | 237 | ||
238 | static struct of_platform_driver ecpp_driver = { | 238 | static struct platform_driver ecpp_driver = { |
239 | .driver = { | 239 | .driver = { |
240 | .name = "ecpp", | 240 | .name = "ecpp", |
241 | .owner = THIS_MODULE, | 241 | .owner = THIS_MODULE, |
@@ -247,7 +247,7 @@ static struct of_platform_driver ecpp_driver = { | |||
247 | 247 | ||
248 | static int parport_pc_find_nonpci_ports(int autoirq, int autodma) | 248 | static int parport_pc_find_nonpci_ports(int autoirq, int autodma) |
249 | { | 249 | { |
250 | return of_register_platform_driver(&ecpp_driver); | 250 | return platform_driver_register(&ecpp_driver); |
251 | } | 251 | } |
252 | 252 | ||
253 | #endif /* !(_ASM_SPARC64_PARPORT_H */ | 253 | #endif /* !(_ASM_SPARC64_PARPORT_H */ |
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index 332ac9ab36bc..862e3ce92b15 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h | |||
@@ -47,7 +47,31 @@ extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev); | |||
47 | 47 | ||
48 | #endif /* __KERNEL__ */ | 48 | #endif /* __KERNEL__ */ |
49 | 49 | ||
50 | #ifndef CONFIG_LEON_PCI | ||
50 | /* generic pci stuff */ | 51 | /* generic pci stuff */ |
51 | #include <asm-generic/pci.h> | 52 | #include <asm-generic/pci.h> |
53 | #else | ||
54 | /* | ||
55 | * On LEON PCI Memory space is mapped 1:1 with physical address space. | ||
56 | * | ||
57 | * I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses | ||
58 | * are converted into CPU addresses to virtual addresses that are mapped with | ||
59 | * MMU to the PCI Host PCI I/O space window which are translated to the low | ||
60 | * 64Kbytes by the Host controller. | ||
61 | */ | ||
62 | |||
63 | extern void | ||
64 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
65 | struct resource *res); | ||
66 | |||
67 | extern void | ||
68 | pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
69 | struct pci_bus_region *region); | ||
70 | |||
71 | static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) | ||
72 | { | ||
73 | return PCI_IRQ_NONE; | ||
74 | } | ||
75 | #endif | ||
52 | 76 | ||
53 | #endif /* __SPARC_PCI_H */ | 77 | #endif /* __SPARC_PCI_H */ |
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h index 5312782f0b5e..948b686ec089 100644 --- a/arch/sparc/include/asm/pci_64.h +++ b/arch/sparc/include/asm/pci_64.h | |||
@@ -38,7 +38,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) | |||
38 | * types on sparc64. However, it requires that the device | 38 | * types on sparc64. However, it requires that the device |
39 | * can drive enough of the 64 bits. | 39 | * can drive enough of the 64 bits. |
40 | */ | 40 | */ |
41 | #define PCI64_REQUIRED_MASK (~(dma64_addr_t)0) | 41 | #define PCI64_REQUIRED_MASK (~(u64)0) |
42 | #define PCI64_ADDR_BASE 0xfffc000000000000UL | 42 | #define PCI64_ADDR_BASE 0xfffc000000000000UL |
43 | 43 | ||
44 | #ifdef CONFIG_PCI | 44 | #ifdef CONFIG_PCI |
diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h index f20ef562b265..6676cbcc8b6a 100644 --- a/arch/sparc/include/asm/pcic.h +++ b/arch/sparc/include/asm/pcic.h | |||
@@ -29,11 +29,17 @@ struct linux_pcic { | |||
29 | int pcic_imdim; | 29 | int pcic_imdim; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | extern int pcic_probe(void); | 32 | #ifdef CONFIG_PCIC_PCI |
33 | /* Erm... MJ redefined pcibios_present() so that it does not work early. */ | ||
34 | extern int pcic_present(void); | 33 | extern int pcic_present(void); |
34 | extern int pcic_probe(void); | ||
35 | extern void pci_time_init(void); | ||
35 | extern void sun4m_pci_init_IRQ(void); | 36 | extern void sun4m_pci_init_IRQ(void); |
36 | 37 | #else | |
38 | static inline int pcic_present(void) { return 0; } | ||
39 | static inline int pcic_probe(void) { return 0; } | ||
40 | static inline void pci_time_init(void) {} | ||
41 | static inline void sun4m_pci_init_IRQ(void) {} | ||
42 | #endif | ||
37 | #endif | 43 | #endif |
38 | 44 | ||
39 | /* Size of PCI I/O space which we relocate. */ | 45 | /* Size of PCI I/O space which we relocate. */ |
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h index a2f5c61f924e..288d7beba051 100644 --- a/arch/sparc/include/asm/pcr.h +++ b/arch/sparc/include/asm/pcr.h | |||
@@ -31,7 +31,7 @@ extern unsigned int picl_shift; | |||
31 | 31 | ||
32 | /* In order to commonize as much of the implementation as | 32 | /* In order to commonize as much of the implementation as |
33 | * possible, we use PICH as our counter. Mostly this is | 33 | * possible, we use PICH as our counter. Mostly this is |
34 | * to accomodate Niagara-1 which can only count insn cycles | 34 | * to accommodate Niagara-1 which can only count insn cycles |
35 | * in PICH. | 35 | * in PICH. |
36 | */ | 36 | */ |
37 | static inline u64 picl_value(unsigned int nmi_hz) | 37 | static inline u64 picl_value(unsigned int nmi_hz) |
@@ -43,4 +43,6 @@ static inline u64 picl_value(unsigned int nmi_hz) | |||
43 | 43 | ||
44 | extern u64 pcr_enable; | 44 | extern u64 pcr_enable; |
45 | 45 | ||
46 | extern int pcr_arch_init(void); | ||
47 | |||
46 | #endif /* __PCR_H */ | 48 | #endif /* __PCR_H */ |
diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h index 727af70646cb..4d3dbe3703e9 100644 --- a/arch/sparc/include/asm/perf_event.h +++ b/arch/sparc/include/asm/perf_event.h | |||
@@ -1,15 +1,9 @@ | |||
1 | #ifndef __ASM_SPARC_PERF_EVENT_H | 1 | #ifndef __ASM_SPARC_PERF_EVENT_H |
2 | #define __ASM_SPARC_PERF_EVENT_H | 2 | #define __ASM_SPARC_PERF_EVENT_H |
3 | 3 | ||
4 | extern void set_perf_event_pending(void); | ||
5 | |||
6 | #define PERF_EVENT_INDEX_OFFSET 0 | ||
7 | |||
8 | #ifdef CONFIG_PERF_EVENTS | 4 | #ifdef CONFIG_PERF_EVENTS |
9 | #include <asm/ptrace.h> | 5 | #include <asm/ptrace.h> |
10 | 6 | ||
11 | extern void init_hw_perf_events(void); | ||
12 | |||
13 | #define perf_arch_fetch_caller_regs(regs, ip) \ | 7 | #define perf_arch_fetch_caller_regs(regs, ip) \ |
14 | do { \ | 8 | do { \ |
15 | unsigned long _pstate, _asi, _pil, _i7, _fp; \ | 9 | unsigned long _pstate, _asi, _pil, _i7, _fp; \ |
@@ -30,8 +24,6 @@ do { \ | |||
30 | (regs)->u_regs[UREG_I6] = _fp; \ | 24 | (regs)->u_regs[UREG_I6] = _fp; \ |
31 | (regs)->u_regs[UREG_I7] = _i7; \ | 25 | (regs)->u_regs[UREG_I7] = _i7; \ |
32 | } while (0) | 26 | } while (0) |
33 | #else | ||
34 | static inline void init_hw_perf_events(void) { } | ||
35 | #endif | 27 | #endif |
36 | 28 | ||
37 | #endif | 29 | #endif |
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h index 5bdfa2c6e400..4e5e0878144f 100644 --- a/arch/sparc/include/asm/pgalloc_64.h +++ b/arch/sparc/include/asm/pgalloc_64.h | |||
@@ -78,4 +78,7 @@ static inline void check_pgt_cache(void) | |||
78 | quicklist_trim(0, NULL, 25, 16); | 78 | quicklist_trim(0, NULL, 25, 16); |
79 | } | 79 | } |
80 | 80 | ||
81 | #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) | ||
82 | #define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) | ||
83 | |||
81 | #endif /* _SPARC64_PGALLOC_H */ | 84 | #endif /* _SPARC64_PGALLOC_H */ |
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 0ece77f47753..5b31a8e89823 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h | |||
@@ -8,6 +8,8 @@ | |||
8 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | 8 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/const.h> | ||
12 | |||
11 | #ifndef __ASSEMBLY__ | 13 | #ifndef __ASSEMBLY__ |
12 | #include <asm-generic/4level-fixup.h> | 14 | #include <asm-generic/4level-fixup.h> |
13 | 15 | ||
@@ -304,10 +306,7 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long) | |||
304 | * and sun4c is guaranteed to have no highmem anyway. | 306 | * and sun4c is guaranteed to have no highmem anyway. |
305 | */ | 307 | */ |
306 | #define pte_offset_map(d, a) pte_offset_kernel(d,a) | 308 | #define pte_offset_map(d, a) pte_offset_kernel(d,a) |
307 | #define pte_offset_map_nested(d, a) pte_offset_kernel(d,a) | ||
308 | |||
309 | #define pte_unmap(pte) do{}while(0) | 309 | #define pte_unmap(pte) do{}while(0) |
310 | #define pte_unmap_nested(pte) do{}while(0) | ||
311 | 310 | ||
312 | /* Certain architectures need to do special things when pte's | 311 | /* Certain architectures need to do special things when pte's |
313 | * within a page table are directly modified. Thus, the following | 312 | * within a page table are directly modified. Thus, the following |
@@ -459,9 +458,9 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, | |||
459 | 458 | ||
460 | #endif /* !(__ASSEMBLY__) */ | 459 | #endif /* !(__ASSEMBLY__) */ |
461 | 460 | ||
462 | #define VMALLOC_START 0xfe600000 | 461 | #define VMALLOC_START _AC(0xfe600000,UL) |
463 | /* XXX Alter this when I get around to fixing sun4c - Anton */ | 462 | /* XXX Alter this when I get around to fixing sun4c - Anton */ |
464 | #define VMALLOC_END 0xffc00000 | 463 | #define VMALLOC_END _AC(0xffc00000,UL) |
465 | 464 | ||
466 | 465 | ||
467 | /* We provide our own get_unmapped_area to cope with VA holes for userland */ | 466 | /* We provide our own get_unmapped_area to cope with VA holes for userland */ |
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index f5b5fa76c02d..1e03c5a6b4f7 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -652,14 +652,14 @@ static inline int pte_special(pte_t pte) | |||
652 | ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) | 652 | ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) |
653 | #define pte_offset_kernel pte_index | 653 | #define pte_offset_kernel pte_index |
654 | #define pte_offset_map pte_index | 654 | #define pte_offset_map pte_index |
655 | #define pte_offset_map_nested pte_index | ||
656 | #define pte_unmap(pte) do { } while (0) | 655 | #define pte_unmap(pte) do { } while (0) |
657 | #define pte_unmap_nested(pte) do { } while (0) | ||
658 | 656 | ||
659 | /* Actual page table PTE updates. */ | 657 | /* Actual page table PTE updates. */ |
660 | extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig); | 658 | extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, |
659 | pte_t *ptep, pte_t orig, int fullmm); | ||
661 | 660 | ||
662 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) | 661 | static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, |
662 | pte_t *ptep, pte_t pte, int fullmm) | ||
663 | { | 663 | { |
664 | pte_t orig = *ptep; | 664 | pte_t orig = *ptep; |
665 | 665 | ||
@@ -672,12 +672,19 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p | |||
672 | * and SUN4V pte layout, so this inline test is fine. | 672 | * and SUN4V pte layout, so this inline test is fine. |
673 | */ | 673 | */ |
674 | if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID)) | 674 | if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID)) |
675 | tlb_batch_add(mm, addr, ptep, orig); | 675 | tlb_batch_add(mm, addr, ptep, orig, fullmm); |
676 | } | 676 | } |
677 | 677 | ||
678 | #define set_pte_at(mm,addr,ptep,pte) \ | ||
679 | __set_pte_at((mm), (addr), (ptep), (pte), 0) | ||
680 | |||
678 | #define pte_clear(mm,addr,ptep) \ | 681 | #define pte_clear(mm,addr,ptep) \ |
679 | set_pte_at((mm), (addr), (ptep), __pte(0UL)) | 682 | set_pte_at((mm), (addr), (ptep), __pte(0UL)) |
680 | 683 | ||
684 | #define __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL | ||
685 | #define pte_clear_not_present_full(mm,addr,ptep,fullmm) \ | ||
686 | __set_pte_at((mm), (addr), (ptep), __pte(0UL), (fullmm)) | ||
687 | |||
681 | #ifdef DCACHE_ALIASING_POSSIBLE | 688 | #ifdef DCACHE_ALIASING_POSSIBLE |
682 | #define __HAVE_ARCH_MOVE_PTE | 689 | #define __HAVE_ARCH_MOVE_PTE |
683 | #define move_pte(pte, prot, old_addr, new_addr) \ | 690 | #define move_pte(pte, prot, old_addr, new_addr) \ |
@@ -701,6 +708,9 @@ extern pmd_t swapper_low_pmd_dir[2048]; | |||
701 | extern void paging_init(void); | 708 | extern void paging_init(void); |
702 | extern unsigned long find_ecache_flush_span(unsigned long size); | 709 | extern unsigned long find_ecache_flush_span(unsigned long size); |
703 | 710 | ||
711 | struct seq_file; | ||
712 | extern void mmu_info(struct seq_file *); | ||
713 | |||
704 | /* These do nothing with the way I have things setup. */ | 714 | /* These do nothing with the way I have things setup. */ |
705 | #define mmu_lockarea(vaddr, len) (vaddr) | 715 | #define mmu_lockarea(vaddr, len) (vaddr) |
706 | #define mmu_unlockarea(vaddr, len) do { } while(0) | 716 | #define mmu_unlockarea(vaddr, len) do { } while(0) |
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index 291f12575edd..56bbaadef646 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h | |||
@@ -18,6 +18,7 @@ | |||
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | */ | 19 | */ |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/of_pdt.h> | ||
21 | #include <linux/proc_fs.h> | 22 | #include <linux/proc_fs.h> |
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
23 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
@@ -67,8 +68,8 @@ extern struct device_node *of_console_device; | |||
67 | extern char *of_console_path; | 68 | extern char *of_console_path; |
68 | extern char *of_console_options; | 69 | extern char *of_console_options; |
69 | 70 | ||
70 | extern void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp); | 71 | extern void irq_trans_init(struct device_node *dp); |
71 | extern char *build_full_name(struct device_node *dp); | 72 | extern char *build_path_component(struct device_node *dp); |
72 | 73 | ||
73 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
74 | #endif /* _SPARC_PROM_H */ | 75 | #endif /* _SPARC_PROM_H */ |
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index 30b0b797dc0c..b928b31424b1 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h | |||
@@ -33,7 +33,7 @@ struct pt_regs { | |||
33 | * things like "in a system call" etc. for an arbitray | 33 | * things like "in a system call" etc. for an arbitray |
34 | * process. | 34 | * process. |
35 | * | 35 | * |
36 | * The PT_REGS_MAGIC is choosen such that it can be | 36 | * The PT_REGS_MAGIC is chosen such that it can be |
37 | * loaded completely using just a sethi instruction. | 37 | * loaded completely using just a sethi instruction. |
38 | */ | 38 | */ |
39 | unsigned int magic; | 39 | unsigned int magic; |
@@ -205,6 +205,7 @@ do { current_thread_info()->syscall_noerror = 1; \ | |||
205 | } while (0) | 205 | } while (0) |
206 | #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) | 206 | #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) |
207 | #define instruction_pointer(regs) ((regs)->tpc) | 207 | #define instruction_pointer(regs) ((regs)->tpc) |
208 | #define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) | ||
208 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) | 209 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) |
209 | #define regs_return_value(regs) ((regs)->u_regs[UREG_I0]) | 210 | #define regs_return_value(regs) ((regs)->u_regs[UREG_I0]) |
210 | #ifdef CONFIG_SMP | 211 | #ifdef CONFIG_SMP |
diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h index a2b4302869bc..069bf4d663a1 100644 --- a/arch/sparc/include/asm/rwsem.h +++ b/arch/sparc/include/asm/rwsem.h | |||
@@ -13,53 +13,12 @@ | |||
13 | 13 | ||
14 | #ifdef __KERNEL__ | 14 | #ifdef __KERNEL__ |
15 | 15 | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | |||
19 | struct rwsem_waiter; | ||
20 | |||
21 | struct rw_semaphore { | ||
22 | signed long count; | ||
23 | #define RWSEM_UNLOCKED_VALUE 0x00000000L | 16 | #define RWSEM_UNLOCKED_VALUE 0x00000000L |
24 | #define RWSEM_ACTIVE_BIAS 0x00000001L | 17 | #define RWSEM_ACTIVE_BIAS 0x00000001L |
25 | #define RWSEM_ACTIVE_MASK 0xffffffffL | 18 | #define RWSEM_ACTIVE_MASK 0xffffffffL |
26 | #define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) | 19 | #define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) |
27 | #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS | 20 | #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS |
28 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) | 21 | #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) |
29 | spinlock_t wait_lock; | ||
30 | struct list_head wait_list; | ||
31 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
32 | struct lockdep_map dep_map; | ||
33 | #endif | ||
34 | }; | ||
35 | |||
36 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
37 | # define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } | ||
38 | #else | ||
39 | # define __RWSEM_DEP_MAP_INIT(lockname) | ||
40 | #endif | ||
41 | |||
42 | #define __RWSEM_INITIALIZER(name) \ | ||
43 | { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \ | ||
44 | LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) } | ||
45 | |||
46 | #define DECLARE_RWSEM(name) \ | ||
47 | struct rw_semaphore name = __RWSEM_INITIALIZER(name) | ||
48 | |||
49 | extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); | ||
50 | extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); | ||
51 | extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); | ||
52 | extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); | ||
53 | |||
54 | extern void __init_rwsem(struct rw_semaphore *sem, const char *name, | ||
55 | struct lock_class_key *key); | ||
56 | |||
57 | #define init_rwsem(sem) \ | ||
58 | do { \ | ||
59 | static struct lock_class_key __key; \ | ||
60 | \ | ||
61 | __init_rwsem((sem), #sem, &__key); \ | ||
62 | } while (0) | ||
63 | 22 | ||
64 | /* | 23 | /* |
65 | * lock for reading | 24 | * lock for reading |
@@ -160,11 +119,6 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) | |||
160 | return atomic64_add_return(delta, (atomic64_t *)(&sem->count)); | 119 | return atomic64_add_return(delta, (atomic64_t *)(&sem->count)); |
161 | } | 120 | } |
162 | 121 | ||
163 | static inline int rwsem_is_locked(struct rw_semaphore *sem) | ||
164 | { | ||
165 | return (sem->count != 0); | ||
166 | } | ||
167 | |||
168 | #endif /* __KERNEL__ */ | 122 | #endif /* __KERNEL__ */ |
169 | 123 | ||
170 | #endif /* _SPARC64_RWSEM_H */ | 124 | #endif /* _SPARC64_RWSEM_H */ |
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h index 2643c62f4ac0..64718ba26434 100644 --- a/arch/sparc/include/asm/setup.h +++ b/arch/sparc/include/asm/setup.h | |||
@@ -11,4 +11,16 @@ | |||
11 | # define COMMAND_LINE_SIZE 256 | 11 | # define COMMAND_LINE_SIZE 256 |
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #ifdef __KERNEL__ | ||
15 | |||
16 | #ifdef CONFIG_SPARC32 | ||
17 | /* The CPU that was used for booting | ||
18 | * Only sun4d + leon may have boot_cpu_id != 0 | ||
19 | */ | ||
20 | extern unsigned char boot_cpu_id; | ||
21 | extern unsigned char boot_cpu_id4; | ||
22 | #endif | ||
23 | |||
24 | #endif /* __KERNEL__ */ | ||
25 | |||
14 | #endif /* _SPARC_SETUP_H */ | 26 | #endif /* _SPARC_SETUP_H */ |
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h index 841905c10215..093f10843ff2 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 | */ |
@@ -44,42 +50,38 @@ void smp_callin(void); | |||
44 | void smp_boot_cpus(void); | 50 | void smp_boot_cpus(void); |
45 | void smp_store_cpu_info(int); | 51 | void smp_store_cpu_info(int); |
46 | 52 | ||
53 | void smp_resched_interrupt(void); | ||
54 | void smp_call_function_single_interrupt(void); | ||
55 | void smp_call_function_interrupt(void); | ||
56 | |||
47 | struct seq_file; | 57 | struct seq_file; |
48 | void smp_bogo(struct seq_file *); | 58 | void smp_bogo(struct seq_file *); |
49 | void smp_info(struct seq_file *); | 59 | void smp_info(struct seq_file *); |
50 | 60 | ||
51 | BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long) | 61 | BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, cpumask_t, unsigned long, unsigned long, unsigned long, unsigned long) |
52 | BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void) | 62 | BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void) |
63 | BTFIXUPDEF_CALL(void, smp_ipi_resched, int); | ||
64 | BTFIXUPDEF_CALL(void, smp_ipi_single, int); | ||
65 | BTFIXUPDEF_CALL(void, smp_ipi_mask_one, int); | ||
53 | BTFIXUPDEF_BLACKBOX(hard_smp_processor_id) | 66 | BTFIXUPDEF_BLACKBOX(hard_smp_processor_id) |
54 | BTFIXUPDEF_BLACKBOX(load_current) | 67 | BTFIXUPDEF_BLACKBOX(load_current) |
55 | 68 | ||
56 | #define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4) | 69 | #define smp_cross_call(func,mask,arg1,arg2,arg3,arg4) BTFIXUP_CALL(smp_cross_call)(func,mask,arg1,arg2,arg3,arg4) |
57 | 70 | ||
58 | static inline void xc0(smpfunc_t func) { smp_cross_call(func, cpu_online_map, 0, 0, 0, 0); } | 71 | static inline void xc0(smpfunc_t func) { smp_cross_call(func, *cpu_online_mask, 0, 0, 0, 0); } |
59 | static inline void xc1(smpfunc_t func, unsigned long arg1) | 72 | static inline void xc1(smpfunc_t func, unsigned long arg1) |
60 | { smp_cross_call(func, cpu_online_map, arg1, 0, 0, 0); } | 73 | { smp_cross_call(func, *cpu_online_mask, arg1, 0, 0, 0); } |
61 | static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) | 74 | static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) |
62 | { smp_cross_call(func, cpu_online_map, arg1, arg2, 0, 0); } | 75 | { smp_cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0); } |
63 | static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, | 76 | static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, |
64 | unsigned long arg3) | 77 | unsigned long arg3) |
65 | { smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, 0); } | 78 | { smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, 0); } |
66 | static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, | 79 | static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, |
67 | unsigned long arg3, unsigned long arg4) | 80 | unsigned long arg3, unsigned long arg4) |
68 | { smp_cross_call(func, cpu_online_map, arg1, arg2, arg3, arg4); } | 81 | { smp_cross_call(func, *cpu_online_mask, arg1, arg2, arg3, arg4); } |
69 | 82 | ||
70 | static inline int smp_call_function(void (*func)(void *info), void *info, int wait) | 83 | extern void arch_send_call_function_single_ipi(int cpu); |
71 | { | 84 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
72 | xc1((smpfunc_t)func, (unsigned long)info); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static inline int smp_call_function_single(int cpuid, void (*func) (void *info), | ||
77 | void *info, int wait) | ||
78 | { | ||
79 | smp_cross_call((smpfunc_t)func, cpumask_of_cpu(cpuid), | ||
80 | (unsigned long) info, 0, 0, 0); | ||
81 | return 0; | ||
82 | } | ||
83 | 85 | ||
84 | static inline int cpu_logical_map(int cpu) | 86 | static inline int cpu_logical_map(int cpu) |
85 | { | 87 | { |
@@ -129,6 +131,11 @@ static inline int hard_smp_processor_id(void) | |||
129 | __asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t" | 131 | __asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t" |
130 | "nop; nop" : | 132 | "nop; nop" : |
131 | "=&r" (cpuid)); | 133 | "=&r" (cpuid)); |
134 | - leon | ||
135 | __asm__ __volatile__( "rd %asr17, %0\n\t" | ||
136 | "srl %0, 0x1c, %0\n\t" | ||
137 | "nop\n\t" : | ||
138 | "=&r" (cpuid)); | ||
132 | See btfixup.h and btfixupprep.c to understand how a blackbox works. | 139 | See btfixup.h and btfixupprep.c to understand how a blackbox works. |
133 | */ | 140 | */ |
134 | __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t" | 141 | __asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t" |
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h index f49e11cd4ded..20bca8950710 100644 --- a/arch/sparc/include/asm/smp_64.h +++ b/arch/sparc/include/asm/smp_64.h | |||
@@ -49,6 +49,10 @@ extern void cpu_play_dead(void); | |||
49 | 49 | ||
50 | extern void smp_fetch_global_regs(void); | 50 | extern void smp_fetch_global_regs(void); |
51 | 51 | ||
52 | struct seq_file; | ||
53 | void smp_bogo(struct seq_file *); | ||
54 | void smp_info(struct seq_file *); | ||
55 | |||
52 | #ifdef CONFIG_HOTPLUG_CPU | 56 | #ifdef CONFIG_HOTPLUG_CPU |
53 | extern int __cpu_disable(void); | 57 | extern int __cpu_disable(void); |
54 | extern void __cpu_die(unsigned int cpu); | 58 | extern void __cpu_die(unsigned int cpu); |
diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h index 7f9b9dba38a6..5f5b8bf3f50d 100644 --- a/arch/sparc/include/asm/spinlock_32.h +++ b/arch/sparc/include/asm/spinlock_32.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #ifndef __ASSEMBLY__ | 9 | #ifndef __ASSEMBLY__ |
10 | 10 | ||
11 | #include <asm/psr.h> | 11 | #include <asm/psr.h> |
12 | #include <asm/processor.h> /* for cpu_relax */ | ||
12 | 13 | ||
13 | #define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0) | 14 | #define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0) |
14 | 15 | ||
diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index 890036b3689a..aba16092a81b 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h | |||
@@ -15,11 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/irqflags.h> | 16 | #include <linux/irqflags.h> |
17 | 17 | ||
18 | static inline unsigned int probe_irq_mask(unsigned long val) | ||
19 | { | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | /* | 18 | /* |
24 | * Sparc (general) CPU types | 19 | * Sparc (general) CPU types |
25 | */ | 20 | */ |
@@ -225,7 +220,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int | |||
225 | switch (size) { | 220 | switch (size) { |
226 | case 4: | 221 | case 4: |
227 | return xchg_u32(ptr, x); | 222 | return xchg_u32(ptr, x); |
228 | }; | 223 | } |
229 | __xchg_called_with_bad_pointer(); | 224 | __xchg_called_with_bad_pointer(); |
230 | return x; | 225 | return x; |
231 | } | 226 | } |
diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index e3b65d8cf41b..10bcabce97b2 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h | |||
@@ -29,10 +29,6 @@ enum sparc_cpu { | |||
29 | /* This cannot ever be a sun4c :) That's just history. */ | 29 | /* This cannot ever be a sun4c :) That's just history. */ |
30 | #define ARCH_SUN4C 0 | 30 | #define ARCH_SUN4C 0 |
31 | 31 | ||
32 | extern const char *sparc_cpu_type; | ||
33 | extern const char *sparc_fpu_type; | ||
34 | extern const char *sparc_pmu_type; | ||
35 | |||
36 | extern char reboot_command[]; | 32 | extern char reboot_command[]; |
37 | 33 | ||
38 | /* These are here in an effort to more fully work around Spitfire Errata | 34 | /* These are here in an effort to more fully work around Spitfire Errata |
@@ -238,7 +234,7 @@ static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, | |||
238 | return xchg32(ptr, x); | 234 | return xchg32(ptr, x); |
239 | case 8: | 235 | case 8: |
240 | return xchg64(ptr, x); | 236 | return xchg64(ptr, x); |
241 | }; | 237 | } |
242 | __xchg_called_with_bad_pointer(); | 238 | __xchg_called_with_bad_pointer(); |
243 | return x; | 239 | return x; |
244 | } | 240 | } |
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index 9dd0318d3ddf..fa5753233410 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h | |||
@@ -82,8 +82,8 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
82 | 82 | ||
83 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | 83 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR |
84 | 84 | ||
85 | BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void) | 85 | BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int) |
86 | #define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)() | 86 | #define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node) |
87 | 87 | ||
88 | BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) | 88 | BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) |
89 | #define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti) | 89 | #define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti) |
@@ -92,7 +92,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *) | |||
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Size of kernel stack for each process. | 94 | * Size of kernel stack for each process. |
95 | * Observe the order of get_free_pages() in alloc_thread_info(). | 95 | * Observe the order of get_free_pages() in alloc_thread_info_node(). |
96 | * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste. | 96 | * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste. |
97 | */ | 97 | */ |
98 | #define THREAD_SIZE 8192 | 98 | #define THREAD_SIZE 8192 |
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index fb2ea7705a46..60d86be1a533 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h | |||
@@ -146,21 +146,21 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
146 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | 146 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR |
147 | 147 | ||
148 | #ifdef CONFIG_DEBUG_STACK_USAGE | 148 | #ifdef CONFIG_DEBUG_STACK_USAGE |
149 | #define alloc_thread_info(tsk) \ | 149 | #define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO) |
150 | ({ \ | ||
151 | struct thread_info *ret; \ | ||
152 | \ | ||
153 | ret = (struct thread_info *) \ | ||
154 | __get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER); \ | ||
155 | if (ret) \ | ||
156 | memset(ret, 0, PAGE_SIZE<<__THREAD_INFO_ORDER); \ | ||
157 | ret; \ | ||
158 | }) | ||
159 | #else | 150 | #else |
160 | #define alloc_thread_info(tsk) \ | 151 | #define THREAD_FLAGS (GFP_KERNEL) |
161 | ((struct thread_info *)__get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER)) | ||
162 | #endif | 152 | #endif |
163 | 153 | ||
154 | #define alloc_thread_info_node(tsk, node) \ | ||
155 | ({ \ | ||
156 | struct page *page = alloc_pages_node(node, THREAD_FLAGS, \ | ||
157 | __THREAD_INFO_ORDER); \ | ||
158 | struct thread_info *ret; \ | ||
159 | \ | ||
160 | ret = page ? page_address(page) : NULL; \ | ||
161 | ret; \ | ||
162 | }) | ||
163 | |||
164 | #define free_thread_info(ti) \ | 164 | #define free_thread_info(ti) \ |
165 | free_pages((unsigned long)(ti),__THREAD_INFO_ORDER) | 165 | free_pages((unsigned long)(ti),__THREAD_INFO_ORDER) |
166 | 166 | ||
diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h index dca406b9b6fc..190e18913cc6 100644 --- a/arch/sparc/include/asm/tlb_64.h +++ b/arch/sparc/include/asm/tlb_64.h | |||
@@ -7,66 +7,11 @@ | |||
7 | #include <asm/tlbflush.h> | 7 | #include <asm/tlbflush.h> |
8 | #include <asm/mmu_context.h> | 8 | #include <asm/mmu_context.h> |
9 | 9 | ||
10 | #define TLB_BATCH_NR 192 | ||
11 | |||
12 | /* | ||
13 | * For UP we don't need to worry about TLB flush | ||
14 | * and page free order so much.. | ||
15 | */ | ||
16 | #ifdef CONFIG_SMP | ||
17 | #define FREE_PTE_NR 506 | ||
18 | #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U) | ||
19 | #else | ||
20 | #define FREE_PTE_NR 1 | ||
21 | #define tlb_fast_mode(bp) 1 | ||
22 | #endif | ||
23 | |||
24 | struct mmu_gather { | ||
25 | struct mm_struct *mm; | ||
26 | unsigned int pages_nr; | ||
27 | unsigned int need_flush; | ||
28 | unsigned int fullmm; | ||
29 | unsigned int tlb_nr; | ||
30 | unsigned long vaddrs[TLB_BATCH_NR]; | ||
31 | struct page *pages[FREE_PTE_NR]; | ||
32 | }; | ||
33 | |||
34 | DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
35 | |||
36 | #ifdef CONFIG_SMP | 10 | #ifdef CONFIG_SMP |
37 | extern void smp_flush_tlb_pending(struct mm_struct *, | 11 | extern void smp_flush_tlb_pending(struct mm_struct *, |
38 | unsigned long, unsigned long *); | 12 | unsigned long, unsigned long *); |
39 | #endif | 13 | #endif |
40 | 14 | ||
41 | extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *); | ||
42 | extern void flush_tlb_pending(void); | ||
43 | |||
44 | static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) | ||
45 | { | ||
46 | struct mmu_gather *mp = &get_cpu_var(mmu_gathers); | ||
47 | |||
48 | BUG_ON(mp->tlb_nr); | ||
49 | |||
50 | mp->mm = mm; | ||
51 | mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U; | ||
52 | mp->fullmm = full_mm_flush; | ||
53 | |||
54 | return mp; | ||
55 | } | ||
56 | |||
57 | |||
58 | static inline void tlb_flush_mmu(struct mmu_gather *mp) | ||
59 | { | ||
60 | if (!mp->fullmm) | ||
61 | flush_tlb_pending(); | ||
62 | if (mp->need_flush) { | ||
63 | free_pages_and_swap_cache(mp->pages, mp->pages_nr); | ||
64 | mp->pages_nr = 0; | ||
65 | mp->need_flush = 0; | ||
66 | } | ||
67 | |||
68 | } | ||
69 | |||
70 | #ifdef CONFIG_SMP | 15 | #ifdef CONFIG_SMP |
71 | extern void smp_flush_tlb_mm(struct mm_struct *mm); | 16 | extern void smp_flush_tlb_mm(struct mm_struct *mm); |
72 | #define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm) | 17 | #define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm) |
@@ -74,38 +19,14 @@ extern void smp_flush_tlb_mm(struct mm_struct *mm); | |||
74 | #define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT) | 19 | #define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT) |
75 | #endif | 20 | #endif |
76 | 21 | ||
77 | static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end) | 22 | extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *); |
78 | { | 23 | extern void flush_tlb_pending(void); |
79 | tlb_flush_mmu(mp); | ||
80 | |||
81 | if (mp->fullmm) | ||
82 | mp->fullmm = 0; | ||
83 | |||
84 | /* keep the page table cache within bounds */ | ||
85 | check_pgt_cache(); | ||
86 | |||
87 | put_cpu_var(mmu_gathers); | ||
88 | } | ||
89 | |||
90 | static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page) | ||
91 | { | ||
92 | if (tlb_fast_mode(mp)) { | ||
93 | free_page_and_swap_cache(page); | ||
94 | return; | ||
95 | } | ||
96 | mp->need_flush = 1; | ||
97 | mp->pages[mp->pages_nr++] = page; | ||
98 | if (mp->pages_nr >= FREE_PTE_NR) | ||
99 | tlb_flush_mmu(mp); | ||
100 | } | ||
101 | |||
102 | #define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0) | ||
103 | #define pte_free_tlb(mp, ptepage, addr) pte_free((mp)->mm, ptepage) | ||
104 | #define pmd_free_tlb(mp, pmdp, addr) pmd_free((mp)->mm, pmdp) | ||
105 | #define pud_free_tlb(tlb,pudp, addr) __pud_free_tlb(tlb,pudp,addr) | ||
106 | 24 | ||
107 | #define tlb_migrate_finish(mm) do { } while (0) | ||
108 | #define tlb_start_vma(tlb, vma) do { } while (0) | 25 | #define tlb_start_vma(tlb, vma) do { } while (0) |
109 | #define tlb_end_vma(tlb, vma) do { } while (0) | 26 | #define tlb_end_vma(tlb, vma) do { } while (0) |
27 | #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) | ||
28 | #define tlb_flush(tlb) flush_tlb_pending() | ||
29 | |||
30 | #include <asm-generic/tlb.h> | ||
110 | 31 | ||
111 | #endif /* _SPARC64_TLB_H */ | 32 | #endif /* _SPARC64_TLB_H */ |
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h index fbb675dbe0c9..2ef463494153 100644 --- a/arch/sparc/include/asm/tlbflush_64.h +++ b/arch/sparc/include/asm/tlbflush_64.h | |||
@@ -5,9 +5,17 @@ | |||
5 | #include <asm/mmu_context.h> | 5 | #include <asm/mmu_context.h> |
6 | 6 | ||
7 | /* TSB flush operations. */ | 7 | /* TSB flush operations. */ |
8 | struct mmu_gather; | 8 | |
9 | #define TLB_BATCH_NR 192 | ||
10 | |||
11 | struct tlb_batch { | ||
12 | struct mm_struct *mm; | ||
13 | unsigned long tlb_nr; | ||
14 | unsigned long vaddrs[TLB_BATCH_NR]; | ||
15 | }; | ||
16 | |||
9 | extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); | 17 | extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); |
10 | extern void flush_tsb_user(struct mmu_gather *mp); | 18 | extern void flush_tsb_user(struct tlb_batch *tb); |
11 | 19 | ||
12 | /* TLB flush operations. */ | 20 | /* TLB flush operations. */ |
13 | 21 | ||
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h index 1c79f32734a0..8b9c556d630b 100644 --- a/arch/sparc/include/asm/topology_64.h +++ b/arch/sparc/include/asm/topology_64.h | |||
@@ -65,6 +65,10 @@ static inline int pcibus_to_node(struct pci_bus *pbus) | |||
65 | #define smt_capable() (sparc64_multi_core) | 65 | #define smt_capable() (sparc64_multi_core) |
66 | #endif /* CONFIG_SMP */ | 66 | #endif /* CONFIG_SMP */ |
67 | 67 | ||
68 | #define cpu_coregroup_mask(cpu) (&cpu_core_map[cpu]) | 68 | extern cpumask_t cpu_core_map[NR_CPUS]; |
69 | static inline const struct cpumask *cpu_coregroup_mask(int cpu) | ||
70 | { | ||
71 | return &cpu_core_map[cpu]; | ||
72 | } | ||
69 | 73 | ||
70 | #endif /* _ASM_SPARC64_TOPOLOGY_H */ | 74 | #endif /* _ASM_SPARC64_TOPOLOGY_H */ |
diff --git a/arch/sparc/include/asm/types.h b/arch/sparc/include/asm/types.h index 09c79a9c8516..91e5a034f987 100644 --- a/arch/sparc/include/asm/types.h +++ b/arch/sparc/include/asm/types.h | |||
@@ -18,28 +18,6 @@ typedef unsigned short umode_t; | |||
18 | 18 | ||
19 | #endif /* __ASSEMBLY__ */ | 19 | #endif /* __ASSEMBLY__ */ |
20 | 20 | ||
21 | #ifdef __KERNEL__ | ||
22 | |||
23 | #ifndef __ASSEMBLY__ | ||
24 | |||
25 | /* Dma addresses come in generic and 64-bit flavours. */ | ||
26 | |||
27 | typedef u32 dma_addr_t; | ||
28 | |||
29 | #if defined(__arch64__) | ||
30 | |||
31 | /*** SPARC 64 bit ***/ | ||
32 | typedef u64 dma64_addr_t; | ||
33 | #else | ||
34 | /*** SPARC 32 bit ***/ | ||
35 | typedef u32 dma64_addr_t; | ||
36 | |||
37 | #endif /* defined(__arch64__) */ | ||
38 | |||
39 | #endif /* __ASSEMBLY__ */ | ||
40 | |||
41 | #endif /* __KERNEL__ */ | ||
42 | |||
43 | #endif /* defined(__sparc__) */ | 21 | #endif /* defined(__sparc__) */ |
44 | 22 | ||
45 | #endif /* defined(_SPARC_TYPES_H) */ | 23 | #endif /* defined(_SPARC_TYPES_H) */ |
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 03eb5a8f6f93..6260d5deeabc 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h | |||
@@ -400,8 +400,14 @@ | |||
400 | #define __NR_fanotify_init 329 | 400 | #define __NR_fanotify_init 329 |
401 | #define __NR_fanotify_mark 330 | 401 | #define __NR_fanotify_mark 330 |
402 | #define __NR_prlimit64 331 | 402 | #define __NR_prlimit64 331 |
403 | #define __NR_name_to_handle_at 332 | ||
404 | #define __NR_open_by_handle_at 333 | ||
405 | #define __NR_clock_adjtime 334 | ||
406 | #define __NR_syncfs 335 | ||
407 | #define __NR_sendmmsg 336 | ||
408 | #define __NR_setns 337 | ||
403 | 409 | ||
404 | #define NR_syscalls 332 | 410 | #define NR_syscalls 338 |
405 | 411 | ||
406 | #ifdef __32bit_syscall_numbers__ | 412 | #ifdef __32bit_syscall_numbers__ |
407 | /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, | 413 | /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, |
diff --git a/arch/sparc/include/asm/winmacro.h b/arch/sparc/include/asm/winmacro.h index 5b0a06dc3bcb..a9be04b0d049 100644 --- a/arch/sparc/include/asm/winmacro.h +++ b/arch/sparc/include/asm/winmacro.h | |||
@@ -103,6 +103,7 @@ | |||
103 | st %scratch, [%cur_reg + TI_W_SAVED]; | 103 | st %scratch, [%cur_reg + TI_W_SAVED]; |
104 | 104 | ||
105 | #ifdef CONFIG_SMP | 105 | #ifdef CONFIG_SMP |
106 | /* Results of LOAD_CURRENT() after BTFIXUP for SUN4M, SUN4D & LEON (comments) */ | ||
106 | #define LOAD_CURRENT4M(dest_reg, idreg) \ | 107 | #define LOAD_CURRENT4M(dest_reg, idreg) \ |
107 | rd %tbr, %idreg; \ | 108 | rd %tbr, %idreg; \ |
108 | sethi %hi(current_set), %dest_reg; \ | 109 | sethi %hi(current_set), %dest_reg; \ |
@@ -118,6 +119,14 @@ | |||
118 | or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ | 119 | or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ |
119 | ld [%idreg + %dest_reg], %dest_reg; | 120 | ld [%idreg + %dest_reg], %dest_reg; |
120 | 121 | ||
122 | #define LOAD_CURRENT_LEON(dest_reg, idreg) \ | ||
123 | rd %asr17, %idreg; \ | ||
124 | sethi %hi(current_set), %dest_reg; \ | ||
125 | srl %idreg, 0x1c, %idreg; \ | ||
126 | or %dest_reg, %lo(current_set), %dest_reg; \ | ||
127 | sll %idreg, 0x2, %idreg; \ | ||
128 | ld [%idreg + %dest_reg], %dest_reg; | ||
129 | |||
121 | /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */ | 130 | /* Blackbox - take care with this... - check smp4m and smp4d before changing this. */ |
122 | #define LOAD_CURRENT(dest_reg, idreg) \ | 131 | #define LOAD_CURRENT(dest_reg, idreg) \ |
123 | sethi %hi(___b_load_current), %idreg; \ | 132 | sethi %hi(___b_load_current), %idreg; \ |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 0c2dc1f24a9a..b90b4a1d070a 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 |
@@ -71,13 +71,11 @@ obj-$(CONFIG_SPARC64) += pcr.o | |||
71 | obj-$(CONFIG_SPARC64) += nmi.o | 71 | obj-$(CONFIG_SPARC64) += nmi.o |
72 | obj-$(CONFIG_SPARC64_SMP) += cpumap.o | 72 | obj-$(CONFIG_SPARC64_SMP) += cpumap.o |
73 | 73 | ||
74 | # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation | ||
75 | obj-$(CONFIG_SPARC32) += devres.o | ||
76 | devres-y := ../../../kernel/irq/devres.o | ||
77 | |||
78 | obj-y += dma.o | 74 | obj-y += dma.o |
79 | 75 | ||
80 | obj-$(CONFIG_SPARC32_PCI) += pcic.o | 76 | obj-$(CONFIG_PCIC_PCI) += pcic.o |
77 | obj-$(CONFIG_LEON_PCI) += leon_pci.o | ||
78 | obj-$(CONFIG_GRPCI2) += leon_pci_grpci2.o | ||
81 | 79 | ||
82 | obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o | 80 | obj-$(CONFIG_SMP) += trampoline_$(BITS).o smp_$(BITS).o |
83 | obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o | 81 | obj-$(CONFIG_SPARC32_SMP) += sun4m_smp.o sun4d_smp.o leon_smp.o |
@@ -119,3 +117,5 @@ obj-$(CONFIG_COMPAT) += $(audit--y) | |||
119 | 117 | ||
120 | pc--$(CONFIG_PERF_EVENTS) := perf_event.o | 118 | pc--$(CONFIG_PERF_EVENTS) := perf_event.o |
121 | obj-$(CONFIG_SPARC64) += $(pc--y) | 119 | obj-$(CONFIG_SPARC64) += $(pc--y) |
120 | |||
121 | obj-$(CONFIG_SPARC64) += jump_label.o | ||
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 2c0046ecc715..caef9deb5866 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c | |||
@@ -123,7 +123,7 @@ static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) | |||
123 | 123 | ||
124 | default: | 124 | default: |
125 | return -EINVAL; | 125 | return -EINVAL; |
126 | }; | 126 | } |
127 | 127 | ||
128 | return 0; | 128 | return 0; |
129 | } | 129 | } |
@@ -132,12 +132,12 @@ static const struct file_operations apc_fops = { | |||
132 | .unlocked_ioctl = apc_ioctl, | 132 | .unlocked_ioctl = apc_ioctl, |
133 | .open = apc_open, | 133 | .open = apc_open, |
134 | .release = apc_release, | 134 | .release = apc_release, |
135 | .llseek = noop_llseek, | ||
135 | }; | 136 | }; |
136 | 137 | ||
137 | static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; | 138 | static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; |
138 | 139 | ||
139 | static int __devinit apc_probe(struct platform_device *op, | 140 | static int __devinit apc_probe(struct platform_device *op) |
140 | const struct of_device_id *match) | ||
141 | { | 141 | { |
142 | int err; | 142 | int err; |
143 | 143 | ||
@@ -165,7 +165,7 @@ static int __devinit apc_probe(struct platform_device *op, | |||
165 | return 0; | 165 | return 0; |
166 | } | 166 | } |
167 | 167 | ||
168 | static struct of_device_id __initdata apc_match[] = { | 168 | static struct of_device_id apc_match[] = { |
169 | { | 169 | { |
170 | .name = APC_OBPNAME, | 170 | .name = APC_OBPNAME, |
171 | }, | 171 | }, |
@@ -173,7 +173,7 @@ static struct of_device_id __initdata apc_match[] = { | |||
173 | }; | 173 | }; |
174 | MODULE_DEVICE_TABLE(of, apc_match); | 174 | MODULE_DEVICE_TABLE(of, apc_match); |
175 | 175 | ||
176 | static struct of_platform_driver apc_driver = { | 176 | static struct platform_driver apc_driver = { |
177 | .driver = { | 177 | .driver = { |
178 | .name = "apc", | 178 | .name = "apc", |
179 | .owner = THIS_MODULE, | 179 | .owner = THIS_MODULE, |
@@ -184,7 +184,7 @@ static struct of_platform_driver apc_driver = { | |||
184 | 184 | ||
185 | static int __init apc_init(void) | 185 | static int __init apc_init(void) |
186 | { | 186 | { |
187 | return of_register_platform_driver(&apc_driver); | 187 | return platform_driver_register(&apc_driver); |
188 | } | 188 | } |
189 | 189 | ||
190 | /* This driver is not critical to the boot process | 190 | /* This driver is not critical to the boot process |
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c index ee8d214cae1e..acf5151f3c1d 100644 --- a/arch/sparc/kernel/auxio_32.c +++ b/arch/sparc/kernel/auxio_32.c | |||
@@ -23,7 +23,7 @@ static DEFINE_SPINLOCK(auxio_lock); | |||
23 | 23 | ||
24 | void __init auxio_probe(void) | 24 | void __init auxio_probe(void) |
25 | { | 25 | { |
26 | int node, auxio_nd; | 26 | phandle node, auxio_nd; |
27 | struct linux_prom_registers auxregs[1]; | 27 | struct linux_prom_registers auxregs[1]; |
28 | struct resource r; | 28 | struct resource r; |
29 | 29 | ||
@@ -101,7 +101,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off) | |||
101 | break; | 101 | break; |
102 | default: | 102 | default: |
103 | panic("Can't set AUXIO register on this machine."); | 103 | panic("Can't set AUXIO register on this machine."); |
104 | }; | 104 | } |
105 | spin_unlock_irqrestore(&auxio_lock, flags); | 105 | spin_unlock_irqrestore(&auxio_lock, flags); |
106 | } | 106 | } |
107 | EXPORT_SYMBOL(set_auxio); | 107 | EXPORT_SYMBOL(set_auxio); |
@@ -113,7 +113,7 @@ volatile unsigned char * auxio_power_register = NULL; | |||
113 | void __init auxio_power_probe(void) | 113 | void __init auxio_power_probe(void) |
114 | { | 114 | { |
115 | struct linux_prom_registers regs; | 115 | struct linux_prom_registers regs; |
116 | int node; | 116 | phandle node; |
117 | struct resource r; | 117 | struct resource r; |
118 | 118 | ||
119 | /* Attempt to find the sun4m power control node. */ | 119 | /* Attempt to find the sun4m power control node. */ |
@@ -121,7 +121,7 @@ void __init auxio_power_probe(void) | |||
121 | node = prom_searchsiblings(node, "obio"); | 121 | node = prom_searchsiblings(node, "obio"); |
122 | node = prom_getchild(node); | 122 | node = prom_getchild(node); |
123 | node = prom_searchsiblings(node, "power"); | 123 | node = prom_searchsiblings(node, "power"); |
124 | if (node == 0 || node == -1) | 124 | if (node == 0 || (s32)node == -1) |
125 | return; | 125 | return; |
126 | 126 | ||
127 | /* Map the power control register. */ | 127 | /* Map the power control register. */ |
diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c index 3efd3c5af6a9..773091ac71a3 100644 --- a/arch/sparc/kernel/auxio_64.c +++ b/arch/sparc/kernel/auxio_64.c | |||
@@ -93,7 +93,7 @@ void auxio_set_lte(int on) | |||
93 | } | 93 | } |
94 | EXPORT_SYMBOL(auxio_set_lte); | 94 | EXPORT_SYMBOL(auxio_set_lte); |
95 | 95 | ||
96 | static struct of_device_id __initdata auxio_match[] = { | 96 | static const struct of_device_id auxio_match[] = { |
97 | { | 97 | { |
98 | .name = "auxio", | 98 | .name = "auxio", |
99 | }, | 99 | }, |
@@ -102,8 +102,7 @@ static struct of_device_id __initdata auxio_match[] = { | |||
102 | 102 | ||
103 | MODULE_DEVICE_TABLE(of, auxio_match); | 103 | MODULE_DEVICE_TABLE(of, auxio_match); |
104 | 104 | ||
105 | static int __devinit auxio_probe(struct platform_device *dev, | 105 | static int __devinit auxio_probe(struct platform_device *dev) |
106 | const struct of_device_id *match) | ||
107 | { | 106 | { |
108 | struct device_node *dp = dev->dev.of_node; | 107 | struct device_node *dp = dev->dev.of_node; |
109 | unsigned long size; | 108 | unsigned long size; |
@@ -132,7 +131,7 @@ static int __devinit auxio_probe(struct platform_device *dev, | |||
132 | return 0; | 131 | return 0; |
133 | } | 132 | } |
134 | 133 | ||
135 | static struct of_platform_driver auxio_driver = { | 134 | static struct platform_driver auxio_driver = { |
136 | .probe = auxio_probe, | 135 | .probe = auxio_probe, |
137 | .driver = { | 136 | .driver = { |
138 | .name = "auxio", | 137 | .name = "auxio", |
@@ -143,7 +142,7 @@ static struct of_platform_driver auxio_driver = { | |||
143 | 142 | ||
144 | static int __init auxio_init(void) | 143 | static int __init auxio_init(void) |
145 | { | 144 | { |
146 | return of_register_platform_driver(&auxio_driver); | 145 | return platform_driver_register(&auxio_driver); |
147 | } | 146 | } |
148 | 147 | ||
149 | /* Must be after subsys_initcall() so that busses are probed. Must | 148 | /* Must be after subsys_initcall() so that busses are probed. Must |
diff --git a/arch/sparc/kernel/btext.c b/arch/sparc/kernel/btext.c index 8cc2d56ffe9a..89aa4eb20cf5 100644 --- a/arch/sparc/kernel/btext.c +++ b/arch/sparc/kernel/btext.c | |||
@@ -40,7 +40,7 @@ static unsigned char *dispDeviceBase __force_data; | |||
40 | 40 | ||
41 | static unsigned char vga_font[cmapsz]; | 41 | static unsigned char vga_font[cmapsz]; |
42 | 42 | ||
43 | static int __init btext_initialize(unsigned int node) | 43 | static int __init btext_initialize(phandle node) |
44 | { | 44 | { |
45 | unsigned int width, height, depth, pitch; | 45 | unsigned int width, height, depth, pitch; |
46 | unsigned long address = 0; | 46 | unsigned long address = 0; |
@@ -309,7 +309,7 @@ static struct console btext_console = { | |||
309 | 309 | ||
310 | int __init btext_find_display(void) | 310 | int __init btext_find_display(void) |
311 | { | 311 | { |
312 | unsigned int node; | 312 | phandle node; |
313 | char type[32]; | 313 | char type[32]; |
314 | int ret; | 314 | int ret; |
315 | 315 | ||
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index cfa2624c5332..7eef3f741963 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c | |||
@@ -59,8 +59,7 @@ static int __devinit clock_board_calc_nslots(struct clock_board *p) | |||
59 | } | 59 | } |
60 | } | 60 | } |
61 | 61 | ||
62 | static int __devinit clock_board_probe(struct platform_device *op, | 62 | static int __devinit clock_board_probe(struct platform_device *op) |
63 | const struct of_device_id *match) | ||
64 | { | 63 | { |
65 | struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); | 64 | struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); |
66 | int err = -ENOMEM; | 65 | int err = -ENOMEM; |
@@ -141,14 +140,14 @@ out_free: | |||
141 | goto out; | 140 | goto out; |
142 | } | 141 | } |
143 | 142 | ||
144 | static struct of_device_id __initdata clock_board_match[] = { | 143 | static const struct of_device_id clock_board_match[] = { |
145 | { | 144 | { |
146 | .name = "clock-board", | 145 | .name = "clock-board", |
147 | }, | 146 | }, |
148 | {}, | 147 | {}, |
149 | }; | 148 | }; |
150 | 149 | ||
151 | static struct of_platform_driver clock_board_driver = { | 150 | static struct platform_driver clock_board_driver = { |
152 | .probe = clock_board_probe, | 151 | .probe = clock_board_probe, |
153 | .driver = { | 152 | .driver = { |
154 | .name = "clock_board", | 153 | .name = "clock_board", |
@@ -157,8 +156,7 @@ static struct of_platform_driver clock_board_driver = { | |||
157 | }, | 156 | }, |
158 | }; | 157 | }; |
159 | 158 | ||
160 | static int __devinit fhc_probe(struct platform_device *op, | 159 | static int __devinit fhc_probe(struct platform_device *op) |
161 | const struct of_device_id *match) | ||
162 | { | 160 | { |
163 | struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); | 161 | struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); |
164 | int err = -ENOMEM; | 162 | int err = -ENOMEM; |
@@ -247,14 +245,14 @@ out_free: | |||
247 | goto out; | 245 | goto out; |
248 | } | 246 | } |
249 | 247 | ||
250 | static struct of_device_id __initdata fhc_match[] = { | 248 | static const struct of_device_id fhc_match[] = { |
251 | { | 249 | { |
252 | .name = "fhc", | 250 | .name = "fhc", |
253 | }, | 251 | }, |
254 | {}, | 252 | {}, |
255 | }; | 253 | }; |
256 | 254 | ||
257 | static struct of_platform_driver fhc_driver = { | 255 | static struct platform_driver fhc_driver = { |
258 | .probe = fhc_probe, | 256 | .probe = fhc_probe, |
259 | .driver = { | 257 | .driver = { |
260 | .name = "fhc", | 258 | .name = "fhc", |
@@ -265,8 +263,8 @@ static struct of_platform_driver fhc_driver = { | |||
265 | 263 | ||
266 | static int __init sunfire_init(void) | 264 | static int __init sunfire_init(void) |
267 | { | 265 | { |
268 | (void) of_register_platform_driver(&fhc_driver); | 266 | (void) platform_driver_register(&fhc_driver); |
269 | (void) of_register_platform_driver(&clock_board_driver); | 267 | (void) platform_driver_register(&clock_board_driver); |
270 | return 0; | 268 | return 0; |
271 | } | 269 | } |
272 | 270 | ||
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 08c466ebb32b..5f450260981d 100644 --- a/arch/sparc/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c | |||
@@ -392,8 +392,7 @@ static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, | |||
392 | } | 392 | } |
393 | } | 393 | } |
394 | 394 | ||
395 | static int __devinit jbusmc_probe(struct platform_device *op, | 395 | static int __devinit jbusmc_probe(struct platform_device *op) |
396 | const struct of_device_id *match) | ||
397 | { | 396 | { |
398 | const struct linux_prom64_registers *mem_regs; | 397 | const struct linux_prom64_registers *mem_regs; |
399 | struct device_node *mem_node; | 398 | struct device_node *mem_node; |
@@ -665,7 +664,7 @@ static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 va | |||
665 | case 0x0: | 664 | case 0x0: |
666 | bp->interleave = 16; | 665 | bp->interleave = 16; |
667 | break; | 666 | break; |
668 | }; | 667 | } |
669 | 668 | ||
670 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM | 669 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM |
671 | * bank size definition. | 670 | * bank size definition. |
@@ -690,8 +689,7 @@ static void chmc_fetch_decode_regs(struct chmc *p) | |||
690 | chmc_read_mcreg(p, CHMCTRL_DECODE4)); | 689 | chmc_read_mcreg(p, CHMCTRL_DECODE4)); |
691 | } | 690 | } |
692 | 691 | ||
693 | static int __devinit chmc_probe(struct platform_device *op, | 692 | static int __devinit chmc_probe(struct platform_device *op) |
694 | const struct of_device_id *match) | ||
695 | { | 693 | { |
696 | struct device_node *dp = op->dev.of_node; | 694 | struct device_node *dp = op->dev.of_node; |
697 | unsigned long ver; | 695 | unsigned long ver; |
@@ -765,13 +763,12 @@ out_free: | |||
765 | goto out; | 763 | goto out; |
766 | } | 764 | } |
767 | 765 | ||
768 | static int __devinit us3mc_probe(struct platform_device *op, | 766 | static int __devinit us3mc_probe(struct platform_device *op) |
769 | const struct of_device_id *match) | ||
770 | { | 767 | { |
771 | if (mc_type == MC_TYPE_SAFARI) | 768 | if (mc_type == MC_TYPE_SAFARI) |
772 | return chmc_probe(op, match); | 769 | return chmc_probe(op); |
773 | else if (mc_type == MC_TYPE_JBUS) | 770 | else if (mc_type == MC_TYPE_JBUS) |
774 | return jbusmc_probe(op, match); | 771 | return jbusmc_probe(op); |
775 | return -ENODEV; | 772 | return -ENODEV; |
776 | } | 773 | } |
777 | 774 | ||
@@ -810,7 +807,7 @@ static const struct of_device_id us3mc_match[] = { | |||
810 | }; | 807 | }; |
811 | MODULE_DEVICE_TABLE(of, us3mc_match); | 808 | MODULE_DEVICE_TABLE(of, us3mc_match); |
812 | 809 | ||
813 | static struct of_platform_driver us3mc_driver = { | 810 | static struct platform_driver us3mc_driver = { |
814 | .driver = { | 811 | .driver = { |
815 | .name = "us3mc", | 812 | .name = "us3mc", |
816 | .owner = THIS_MODULE, | 813 | .owner = THIS_MODULE, |
@@ -848,7 +845,7 @@ static int __init us3mc_init(void) | |||
848 | ret = register_dimm_printer(us3mc_dimm_printer); | 845 | ret = register_dimm_printer(us3mc_dimm_printer); |
849 | 846 | ||
850 | if (!ret) { | 847 | if (!ret) { |
851 | ret = of_register_platform_driver(&us3mc_driver); | 848 | ret = platform_driver_register(&us3mc_driver); |
852 | if (ret) | 849 | if (ret) |
853 | unregister_dimm_printer(us3mc_dimm_printer); | 850 | unregister_dimm_printer(us3mc_dimm_printer); |
854 | } | 851 | } |
@@ -859,7 +856,7 @@ static void __exit us3mc_cleanup(void) | |||
859 | { | 856 | { |
860 | if (us3mc_platform()) { | 857 | if (us3mc_platform()) { |
861 | unregister_dimm_printer(us3mc_dimm_printer); | 858 | unregister_dimm_printer(us3mc_dimm_printer); |
862 | of_unregister_platform_driver(&us3mc_driver); | 859 | platform_driver_unregister(&us3mc_driver); |
863 | } | 860 | } |
864 | } | 861 | } |
865 | 862 | ||
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index e447938d39cf..138dbbc8dc84 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | 4 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/seq_file.h> | ||
7 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
@@ -11,7 +12,9 @@ | |||
11 | #include <linux/threads.h> | 12 | #include <linux/threads.h> |
12 | 13 | ||
13 | #include <asm/spitfire.h> | 14 | #include <asm/spitfire.h> |
15 | #include <asm/pgtable.h> | ||
14 | #include <asm/oplib.h> | 16 | #include <asm/oplib.h> |
17 | #include <asm/setup.h> | ||
15 | #include <asm/page.h> | 18 | #include <asm/page.h> |
16 | #include <asm/head.h> | 19 | #include <asm/head.h> |
17 | #include <asm/psr.h> | 20 | #include <asm/psr.h> |
@@ -23,6 +26,9 @@ | |||
23 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; | 26 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; |
24 | EXPORT_PER_CPU_SYMBOL(__cpu_data); | 27 | EXPORT_PER_CPU_SYMBOL(__cpu_data); |
25 | 28 | ||
29 | int ncpus_probed; | ||
30 | unsigned int fsr_storage; | ||
31 | |||
26 | struct cpu_info { | 32 | struct cpu_info { |
27 | int psr_vers; | 33 | int psr_vers; |
28 | const char *name; | 34 | const char *name; |
@@ -247,13 +253,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { | |||
247 | * machine type value into consideration too. I will fix this. | 253 | * machine type value into consideration too. I will fix this. |
248 | */ | 254 | */ |
249 | 255 | ||
250 | const char *sparc_cpu_type; | 256 | static const char *sparc_cpu_type; |
251 | const char *sparc_fpu_type; | 257 | static const char *sparc_fpu_type; |
252 | const char *sparc_pmu_type; | 258 | const char *sparc_pmu_type; |
253 | 259 | ||
254 | unsigned int fsr_storage; | ||
255 | 260 | ||
256 | static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) | 261 | static void __init set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) |
257 | { | 262 | { |
258 | const struct manufacturer_info *manuf; | 263 | const struct manufacturer_info *manuf; |
259 | int i; | 264 | int i; |
@@ -313,7 +318,123 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) | |||
313 | } | 318 | } |
314 | 319 | ||
315 | #ifdef CONFIG_SPARC32 | 320 | #ifdef CONFIG_SPARC32 |
316 | void __cpuinit cpu_probe(void) | 321 | static int show_cpuinfo(struct seq_file *m, void *__unused) |
322 | { | ||
323 | seq_printf(m, | ||
324 | "cpu\t\t: %s\n" | ||
325 | "fpu\t\t: %s\n" | ||
326 | "promlib\t\t: Version %d Revision %d\n" | ||
327 | "prom\t\t: %d.%d\n" | ||
328 | "type\t\t: %s\n" | ||
329 | "ncpus probed\t: %d\n" | ||
330 | "ncpus active\t: %d\n" | ||
331 | #ifndef CONFIG_SMP | ||
332 | "CPU0Bogo\t: %lu.%02lu\n" | ||
333 | "CPU0ClkTck\t: %ld\n" | ||
334 | #endif | ||
335 | , | ||
336 | sparc_cpu_type, | ||
337 | sparc_fpu_type , | ||
338 | romvec->pv_romvers, | ||
339 | prom_rev, | ||
340 | romvec->pv_printrev >> 16, | ||
341 | romvec->pv_printrev & 0xffff, | ||
342 | &cputypval[0], | ||
343 | ncpus_probed, | ||
344 | num_online_cpus() | ||
345 | #ifndef CONFIG_SMP | ||
346 | , cpu_data(0).udelay_val/(500000/HZ), | ||
347 | (cpu_data(0).udelay_val/(5000/HZ)) % 100, | ||
348 | cpu_data(0).clock_tick | ||
349 | #endif | ||
350 | ); | ||
351 | |||
352 | #ifdef CONFIG_SMP | ||
353 | smp_bogo(m); | ||
354 | #endif | ||
355 | mmu_info(m); | ||
356 | #ifdef CONFIG_SMP | ||
357 | smp_info(m); | ||
358 | #endif | ||
359 | return 0; | ||
360 | } | ||
361 | #endif /* CONFIG_SPARC32 */ | ||
362 | |||
363 | #ifdef CONFIG_SPARC64 | ||
364 | unsigned int dcache_parity_tl1_occurred; | ||
365 | unsigned int icache_parity_tl1_occurred; | ||
366 | |||
367 | |||
368 | static int show_cpuinfo(struct seq_file *m, void *__unused) | ||
369 | { | ||
370 | seq_printf(m, | ||
371 | "cpu\t\t: %s\n" | ||
372 | "fpu\t\t: %s\n" | ||
373 | "pmu\t\t: %s\n" | ||
374 | "prom\t\t: %s\n" | ||
375 | "type\t\t: %s\n" | ||
376 | "ncpus probed\t: %d\n" | ||
377 | "ncpus active\t: %d\n" | ||
378 | "D$ parity tl1\t: %u\n" | ||
379 | "I$ parity tl1\t: %u\n" | ||
380 | #ifndef CONFIG_SMP | ||
381 | "Cpu0ClkTck\t: %016lx\n" | ||
382 | #endif | ||
383 | , | ||
384 | sparc_cpu_type, | ||
385 | sparc_fpu_type, | ||
386 | sparc_pmu_type, | ||
387 | prom_version, | ||
388 | ((tlb_type == hypervisor) ? | ||
389 | "sun4v" : | ||
390 | "sun4u"), | ||
391 | ncpus_probed, | ||
392 | num_online_cpus(), | ||
393 | dcache_parity_tl1_occurred, | ||
394 | icache_parity_tl1_occurred | ||
395 | #ifndef CONFIG_SMP | ||
396 | , cpu_data(0).clock_tick | ||
397 | #endif | ||
398 | ); | ||
399 | #ifdef CONFIG_SMP | ||
400 | smp_bogo(m); | ||
401 | #endif | ||
402 | mmu_info(m); | ||
403 | #ifdef CONFIG_SMP | ||
404 | smp_info(m); | ||
405 | #endif | ||
406 | return 0; | ||
407 | } | ||
408 | #endif /* CONFIG_SPARC64 */ | ||
409 | |||
410 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
411 | { | ||
412 | /* The pointer we are returning is arbitrary, | ||
413 | * it just has to be non-NULL and not IS_ERR | ||
414 | * in the success case. | ||
415 | */ | ||
416 | return *pos == 0 ? &c_start : NULL; | ||
417 | } | ||
418 | |||
419 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
420 | { | ||
421 | ++*pos; | ||
422 | return c_start(m, pos); | ||
423 | } | ||
424 | |||
425 | static void c_stop(struct seq_file *m, void *v) | ||
426 | { | ||
427 | } | ||
428 | |||
429 | const struct seq_operations cpuinfo_op = { | ||
430 | .start =c_start, | ||
431 | .next = c_next, | ||
432 | .stop = c_stop, | ||
433 | .show = show_cpuinfo, | ||
434 | }; | ||
435 | |||
436 | #ifdef CONFIG_SPARC32 | ||
437 | static int __init cpu_type_probe(void) | ||
317 | { | 438 | { |
318 | int psr_impl, psr_vers, fpu_vers; | 439 | int psr_impl, psr_vers, fpu_vers; |
319 | int psr; | 440 | int psr; |
@@ -324,7 +445,7 @@ void __cpuinit cpu_probe(void) | |||
324 | psr = get_psr(); | 445 | psr = get_psr(); |
325 | put_psr(psr | PSR_EF); | 446 | put_psr(psr | PSR_EF); |
326 | #ifdef CONFIG_SPARC_LEON | 447 | #ifdef CONFIG_SPARC_LEON |
327 | fpu_vers = 7; | 448 | fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7; |
328 | #else | 449 | #else |
329 | fpu_vers = ((get_fsr() >> 17) & 0x7); | 450 | fpu_vers = ((get_fsr() >> 17) & 0x7); |
330 | #endif | 451 | #endif |
@@ -332,8 +453,12 @@ void __cpuinit cpu_probe(void) | |||
332 | put_psr(psr); | 453 | put_psr(psr); |
333 | 454 | ||
334 | set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); | 455 | set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); |
456 | |||
457 | return 0; | ||
335 | } | 458 | } |
336 | #else | 459 | #endif /* CONFIG_SPARC32 */ |
460 | |||
461 | #ifdef CONFIG_SPARC64 | ||
337 | static void __init sun4v_cpu_probe(void) | 462 | static void __init sun4v_cpu_probe(void) |
338 | { | 463 | { |
339 | switch (sun4v_chip_type) { | 464 | switch (sun4v_chip_type) { |
@@ -374,6 +499,6 @@ static int __init cpu_type_probe(void) | |||
374 | } | 499 | } |
375 | return 0; | 500 | return 0; |
376 | } | 501 | } |
502 | #endif /* CONFIG_SPARC64 */ | ||
377 | 503 | ||
378 | arch_initcall(cpu_type_probe); | 504 | early_initcall(cpu_type_probe); |
379 | #endif | ||
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c index 8de64c8126bc..d91fd782743a 100644 --- a/arch/sparc/kernel/cpumap.c +++ b/arch/sparc/kernel/cpumap.c | |||
@@ -202,7 +202,7 @@ static struct cpuinfo_tree *build_cpuinfo_tree(void) | |||
202 | new_tree->total_nodes = n; | 202 | new_tree->total_nodes = n; |
203 | memcpy(&new_tree->level, tmp_level, sizeof(tmp_level)); | 203 | memcpy(&new_tree->level, tmp_level, sizeof(tmp_level)); |
204 | 204 | ||
205 | prev_cpu = cpu = first_cpu(cpu_online_map); | 205 | prev_cpu = cpu = cpumask_first(cpu_online_mask); |
206 | 206 | ||
207 | /* Initialize all levels in the tree with the first CPU */ | 207 | /* Initialize all levels in the tree with the first CPU */ |
208 | for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT; level--) { | 208 | for (level = CPUINFO_LVL_PROC; level >= CPUINFO_LVL_ROOT; level--) { |
@@ -381,7 +381,7 @@ static int simple_map_to_cpu(unsigned int index) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* Impossible, since num_online_cpus() <= num_possible_cpus() */ | 383 | /* Impossible, since num_online_cpus() <= num_possible_cpus() */ |
384 | return first_cpu(cpu_online_map); | 384 | return cpumask_first(cpu_online_mask); |
385 | } | 385 | } |
386 | 386 | ||
387 | static int _map_to_cpu(unsigned int index) | 387 | static int _map_to_cpu(unsigned int index) |
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index 62dc7a021413..113c052c3043 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | #include <asm/cpudata.h> | 21 | #include <asm/cpudata.h> |
22 | 22 | ||
23 | extern void cpu_probe(void); | ||
24 | extern void clock_stop_probe(void); /* tadpole.c */ | 23 | extern void clock_stop_probe(void); /* tadpole.c */ |
25 | extern void sun4c_probe_memerr_reg(void); | 24 | extern void sun4c_probe_memerr_reg(void); |
26 | 25 | ||
@@ -31,9 +30,9 @@ static char *cpu_mid_prop(void) | |||
31 | return "mid"; | 30 | return "mid"; |
32 | } | 31 | } |
33 | 32 | ||
34 | static int check_cpu_node(int nd, int *cur_inst, | 33 | static int check_cpu_node(phandle nd, int *cur_inst, |
35 | int (*compare)(int, int, void *), void *compare_arg, | 34 | int (*compare)(phandle, int, void *), void *compare_arg, |
36 | int *prom_node, int *mid) | 35 | phandle *prom_node, int *mid) |
37 | { | 36 | { |
38 | if (!compare(nd, *cur_inst, compare_arg)) { | 37 | if (!compare(nd, *cur_inst, compare_arg)) { |
39 | if (prom_node) | 38 | if (prom_node) |
@@ -51,8 +50,8 @@ static int check_cpu_node(int nd, int *cur_inst, | |||
51 | return -ENODEV; | 50 | return -ENODEV; |
52 | } | 51 | } |
53 | 52 | ||
54 | static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, | 53 | static int __cpu_find_by(int (*compare)(phandle, int, void *), |
55 | int *prom_node, int *mid) | 54 | void *compare_arg, phandle *prom_node, int *mid) |
56 | { | 55 | { |
57 | struct device_node *dp; | 56 | struct device_node *dp; |
58 | int cur_inst; | 57 | int cur_inst; |
@@ -71,7 +70,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, | |||
71 | return -ENODEV; | 70 | return -ENODEV; |
72 | } | 71 | } |
73 | 72 | ||
74 | static int cpu_instance_compare(int nd, int instance, void *_arg) | 73 | static int cpu_instance_compare(phandle nd, int instance, void *_arg) |
75 | { | 74 | { |
76 | int desired_instance = (int) _arg; | 75 | int desired_instance = (int) _arg; |
77 | 76 | ||
@@ -80,13 +79,13 @@ static int cpu_instance_compare(int nd, int instance, void *_arg) | |||
80 | return -ENODEV; | 79 | return -ENODEV; |
81 | } | 80 | } |
82 | 81 | ||
83 | int cpu_find_by_instance(int instance, int *prom_node, int *mid) | 82 | int cpu_find_by_instance(int instance, phandle *prom_node, int *mid) |
84 | { | 83 | { |
85 | return __cpu_find_by(cpu_instance_compare, (void *)instance, | 84 | return __cpu_find_by(cpu_instance_compare, (void *)instance, |
86 | prom_node, mid); | 85 | prom_node, mid); |
87 | } | 86 | } |
88 | 87 | ||
89 | static int cpu_mid_compare(int nd, int instance, void *_arg) | 88 | static int cpu_mid_compare(phandle nd, int instance, void *_arg) |
90 | { | 89 | { |
91 | int desired_mid = (int) _arg; | 90 | int desired_mid = (int) _arg; |
92 | int this_mid; | 91 | int this_mid; |
@@ -98,7 +97,7 @@ static int cpu_mid_compare(int nd, int instance, void *_arg) | |||
98 | return -ENODEV; | 97 | return -ENODEV; |
99 | } | 98 | } |
100 | 99 | ||
101 | int cpu_find_by_mid(int mid, int *prom_node) | 100 | int cpu_find_by_mid(int mid, phandle *prom_node) |
102 | { | 101 | { |
103 | return __cpu_find_by(cpu_mid_compare, (void *)mid, | 102 | return __cpu_find_by(cpu_mid_compare, (void *)mid, |
104 | prom_node, NULL); | 103 | prom_node, NULL); |
@@ -108,18 +107,19 @@ int cpu_find_by_mid(int mid, int *prom_node) | |||
108 | * address (0-3). This gives us the true hardware mid, which might have | 107 | * address (0-3). This gives us the true hardware mid, which might have |
109 | * some other bits set. On 4d hardware and software mids are the same. | 108 | * some other bits set. On 4d hardware and software mids are the same. |
110 | */ | 109 | */ |
111 | int cpu_get_hwmid(int prom_node) | 110 | int cpu_get_hwmid(phandle prom_node) |
112 | { | 111 | { |
113 | return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV); | 112 | return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV); |
114 | } | 113 | } |
115 | 114 | ||
116 | void __init device_scan(void) | 115 | void __init device_scan(void) |
117 | { | 116 | { |
118 | prom_printf("Booting Linux...\n"); | 117 | printk(KERN_NOTICE "Booting Linux...\n"); |
119 | 118 | ||
120 | #ifndef CONFIG_SMP | 119 | #ifndef CONFIG_SMP |
121 | { | 120 | { |
122 | int err, cpu_node; | 121 | phandle cpu_node; |
122 | int err; | ||
123 | err = cpu_find_by_instance(0, &cpu_node, NULL); | 123 | err = cpu_find_by_instance(0, &cpu_node, NULL); |
124 | if (err) { | 124 | if (err) { |
125 | /* Probably a sun4e, Sun is trying to trick us ;-) */ | 125 | /* Probably a sun4e, Sun is trying to trick us ;-) */ |
@@ -132,7 +132,6 @@ void __init device_scan(void) | |||
132 | } | 132 | } |
133 | #endif /* !CONFIG_SMP */ | 133 | #endif /* !CONFIG_SMP */ |
134 | 134 | ||
135 | cpu_probe(); | ||
136 | { | 135 | { |
137 | extern void auxio_probe(void); | 136 | extern void auxio_probe(void); |
138 | extern void auxio_power_probe(void); | 137 | extern void auxio_power_probe(void); |
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 4a700f4b79ce..dd1342c0a3be 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c | |||
@@ -497,7 +497,7 @@ static void dr_cpu_init_response(struct ds_data *resp, u64 req_num, | |||
497 | tag->num_records = ncpus; | 497 | tag->num_records = ncpus; |
498 | 498 | ||
499 | i = 0; | 499 | i = 0; |
500 | for_each_cpu_mask(cpu, *mask) { | 500 | for_each_cpu(cpu, mask) { |
501 | ent[i].cpu = cpu; | 501 | ent[i].cpu = cpu; |
502 | ent[i].result = DR_CPU_RES_OK; | 502 | ent[i].result = DR_CPU_RES_OK; |
503 | ent[i].stat = default_stat; | 503 | ent[i].stat = default_stat; |
@@ -534,7 +534,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp, | |||
534 | int resp_len, ncpus, cpu; | 534 | int resp_len, ncpus, cpu; |
535 | unsigned long flags; | 535 | unsigned long flags; |
536 | 536 | ||
537 | ncpus = cpus_weight(*mask); | 537 | ncpus = cpumask_weight(mask); |
538 | resp_len = dr_cpu_size_response(ncpus); | 538 | resp_len = dr_cpu_size_response(ncpus); |
539 | resp = kzalloc(resp_len, GFP_KERNEL); | 539 | resp = kzalloc(resp_len, GFP_KERNEL); |
540 | if (!resp) | 540 | if (!resp) |
@@ -547,7 +547,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp, | |||
547 | mdesc_populate_present_mask(mask); | 547 | mdesc_populate_present_mask(mask); |
548 | mdesc_fill_in_cpu_data(mask); | 548 | mdesc_fill_in_cpu_data(mask); |
549 | 549 | ||
550 | for_each_cpu_mask(cpu, *mask) { | 550 | for_each_cpu(cpu, mask) { |
551 | int err; | 551 | int err; |
552 | 552 | ||
553 | printk(KERN_INFO "ds-%llu: Starting cpu %d...\n", | 553 | printk(KERN_INFO "ds-%llu: Starting cpu %d...\n", |
@@ -593,7 +593,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp, | |||
593 | int resp_len, ncpus, cpu; | 593 | int resp_len, ncpus, cpu; |
594 | unsigned long flags; | 594 | unsigned long flags; |
595 | 595 | ||
596 | ncpus = cpus_weight(*mask); | 596 | ncpus = cpumask_weight(mask); |
597 | resp_len = dr_cpu_size_response(ncpus); | 597 | resp_len = dr_cpu_size_response(ncpus); |
598 | resp = kzalloc(resp_len, GFP_KERNEL); | 598 | resp = kzalloc(resp_len, GFP_KERNEL); |
599 | if (!resp) | 599 | if (!resp) |
@@ -603,7 +603,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp, | |||
603 | resp_len, ncpus, mask, | 603 | resp_len, ncpus, mask, |
604 | DR_CPU_STAT_UNCONFIGURED); | 604 | DR_CPU_STAT_UNCONFIGURED); |
605 | 605 | ||
606 | for_each_cpu_mask(cpu, *mask) { | 606 | for_each_cpu(cpu, mask) { |
607 | int err; | 607 | int err; |
608 | 608 | ||
609 | printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n", | 609 | printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n", |
@@ -649,13 +649,13 @@ static void __cpuinit dr_cpu_data(struct ds_info *dp, | |||
649 | 649 | ||
650 | purge_dups(cpu_list, tag->num_records); | 650 | purge_dups(cpu_list, tag->num_records); |
651 | 651 | ||
652 | cpus_clear(mask); | 652 | cpumask_clear(&mask); |
653 | for (i = 0; i < tag->num_records; i++) { | 653 | for (i = 0; i < tag->num_records; i++) { |
654 | if (cpu_list[i] == CPU_SENTINEL) | 654 | if (cpu_list[i] == CPU_SENTINEL) |
655 | continue; | 655 | continue; |
656 | 656 | ||
657 | if (cpu_list[i] < nr_cpu_ids) | 657 | if (cpu_list[i] < nr_cpu_ids) |
658 | cpu_set(cpu_list[i], mask); | 658 | cpumask_set_cpu(cpu_list[i], &mask); |
659 | } | 659 | } |
660 | 660 | ||
661 | if (tag->type == DR_CPU_CONFIGURE) | 661 | if (tag->type == DR_CPU_CONFIGURE) |
@@ -1218,7 +1218,7 @@ static int ds_remove(struct vio_dev *vdev) | |||
1218 | return 0; | 1218 | return 0; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | static struct vio_device_id __initdata ds_match[] = { | 1221 | static const struct vio_device_id ds_match[] = { |
1222 | { | 1222 | { |
1223 | .type = "domain-services-port", | 1223 | .type = "domain-services-port", |
1224 | }, | 1224 | }, |
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 1504df8ddf70..f445e98463e6 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -229,7 +229,7 @@ real_irq_entry: | |||
229 | #ifdef CONFIG_SMP | 229 | #ifdef CONFIG_SMP |
230 | .globl patchme_maybe_smp_msg | 230 | .globl patchme_maybe_smp_msg |
231 | 231 | ||
232 | cmp %l7, 12 | 232 | cmp %l7, 11 |
233 | patchme_maybe_smp_msg: | 233 | patchme_maybe_smp_msg: |
234 | bgu maybe_smp4m_msg | 234 | bgu maybe_smp4m_msg |
235 | nop | 235 | nop |
@@ -269,19 +269,22 @@ smp4m_ticker: | |||
269 | /* Here is where we check for possible SMP IPI passed to us | 269 | /* Here is where we check for possible SMP IPI passed to us |
270 | * on some level other than 15 which is the NMI and only used | 270 | * on some level other than 15 which is the NMI and only used |
271 | * for cross calls. That has a separate entry point below. | 271 | * for cross calls. That has a separate entry point below. |
272 | * | ||
273 | * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*. | ||
272 | */ | 274 | */ |
273 | maybe_smp4m_msg: | 275 | maybe_smp4m_msg: |
274 | GET_PROCESSOR4M_ID(o3) | 276 | GET_PROCESSOR4M_ID(o3) |
275 | sethi %hi(sun4m_irq_percpu), %l5 | 277 | sethi %hi(sun4m_irq_percpu), %l5 |
276 | sll %o3, 2, %o3 | 278 | sll %o3, 2, %o3 |
277 | or %l5, %lo(sun4m_irq_percpu), %o5 | 279 | or %l5, %lo(sun4m_irq_percpu), %o5 |
278 | sethi %hi(0x40000000), %o2 | 280 | sethi %hi(0x70000000), %o2 ! Check all soft-IRQs |
279 | ld [%o5 + %o3], %o1 | 281 | ld [%o5 + %o3], %o1 |
280 | ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending | 282 | ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending |
281 | andcc %o3, %o2, %g0 | 283 | andcc %o3, %o2, %g0 |
282 | be,a smp4m_ticker | 284 | be,a smp4m_ticker |
283 | cmp %l7, 14 | 285 | cmp %l7, 14 |
284 | st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 | 286 | /* Soft-IRQ IPI */ |
287 | st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x70000000 | ||
285 | WRITE_PAUSE | 288 | WRITE_PAUSE |
286 | ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending | 289 | ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending |
287 | WRITE_PAUSE | 290 | WRITE_PAUSE |
@@ -290,9 +293,27 @@ maybe_smp4m_msg: | |||
290 | WRITE_PAUSE | 293 | WRITE_PAUSE |
291 | wr %l4, PSR_ET, %psr | 294 | wr %l4, PSR_ET, %psr |
292 | WRITE_PAUSE | 295 | WRITE_PAUSE |
293 | call smp_reschedule_irq | 296 | srl %o3, 28, %o2 ! shift for simpler checks below |
297 | maybe_smp4m_msg_check_single: | ||
298 | andcc %o2, 0x1, %g0 | ||
299 | beq,a maybe_smp4m_msg_check_mask | ||
300 | andcc %o2, 0x2, %g0 | ||
301 | call smp_call_function_single_interrupt | ||
294 | nop | 302 | nop |
295 | 303 | andcc %o2, 0x2, %g0 | |
304 | maybe_smp4m_msg_check_mask: | ||
305 | beq,a maybe_smp4m_msg_check_resched | ||
306 | andcc %o2, 0x4, %g0 | ||
307 | call smp_call_function_interrupt | ||
308 | nop | ||
309 | andcc %o2, 0x4, %g0 | ||
310 | maybe_smp4m_msg_check_resched: | ||
311 | /* rescheduling is done in RESTORE_ALL regardless, but incr stats */ | ||
312 | beq,a maybe_smp4m_msg_out | ||
313 | nop | ||
314 | call smp_resched_interrupt | ||
315 | nop | ||
316 | maybe_smp4m_msg_out: | ||
296 | RESTORE_ALL | 317 | RESTORE_ALL |
297 | 318 | ||
298 | .align 4 | 319 | .align 4 |
@@ -401,18 +422,18 @@ linux_trap_ipi15_sun4d: | |||
401 | 1: b,a 1b | 422 | 1: b,a 1b |
402 | 423 | ||
403 | #ifdef CONFIG_SPARC_LEON | 424 | #ifdef CONFIG_SPARC_LEON |
404 | 425 | .globl smpleon_ipi | |
405 | .globl smpleon_ticker | 426 | .extern leon_ipi_interrupt |
406 | /* SMP per-cpu ticker interrupts are handled specially. */ | 427 | /* SMP per-cpu IPI interrupts are handled specially. */ |
407 | smpleon_ticker: | 428 | smpleon_ipi: |
408 | SAVE_ALL | 429 | SAVE_ALL |
409 | or %l0, PSR_PIL, %g2 | 430 | or %l0, PSR_PIL, %g2 |
410 | wr %g2, 0x0, %psr | 431 | wr %g2, 0x0, %psr |
411 | WRITE_PAUSE | 432 | WRITE_PAUSE |
412 | wr %g2, PSR_ET, %psr | 433 | wr %g2, PSR_ET, %psr |
413 | WRITE_PAUSE | 434 | WRITE_PAUSE |
414 | call leon_percpu_timer_interrupt | 435 | call leonsmp_ipi_interrupt |
415 | add %sp, STACKFRAME_SZ, %o0 | 436 | add %sp, STACKFRAME_SZ, %o1 ! pt_regs |
416 | wr %l0, PSR_ET, %psr | 437 | wr %l0, PSR_ET, %psr |
417 | WRITE_PAUSE | 438 | WRITE_PAUSE |
418 | RESTORE_ALL | 439 | RESTORE_ALL |
@@ -801,7 +822,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 | |||
801 | .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on | 822 | .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on |
802 | 823 | ||
803 | /* | 824 | /* |
804 | * Ugly, but we cant use hardware flushing on the sun4 and we'd require | 825 | * Ugly, but we can't use hardware flushing on the sun4 and we'd require |
805 | * two instructions (Anton) | 826 | * two instructions (Anton) |
806 | */ | 827 | */ |
807 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 | 828 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 |
@@ -851,7 +872,7 @@ sun4c_fault: | |||
851 | sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 | 872 | sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 |
852 | 873 | ||
853 | /* If the kernel references a bum kernel pointer, or a pte which | 874 | /* If the kernel references a bum kernel pointer, or a pte which |
854 | * points to a non existant page in ram, we will run this code | 875 | * points to a non existent page in ram, we will run this code |
855 | * _forever_ and lock up the machine!!!!! So we must check for | 876 | * _forever_ and lock up the machine!!!!! So we must check for |
856 | * this condition, the AC_SYNC_ERR bits are what we must examine. | 877 | * this condition, the AC_SYNC_ERR bits are what we must examine. |
857 | * Also a parity error would make this happen as well. So we just | 878 | * Also a parity error would make this happen as well. So we just |
@@ -1283,7 +1304,7 @@ linux_syscall_trace: | |||
1283 | .globl ret_from_fork | 1304 | .globl ret_from_fork |
1284 | ret_from_fork: | 1305 | ret_from_fork: |
1285 | call schedule_tail | 1306 | call schedule_tail |
1286 | mov %g3, %o0 | 1307 | ld [%g3 + TI_TASK], %o0 |
1287 | b ret_sys_call | 1308 | b ret_sys_call |
1288 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 | 1309 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 |
1289 | 1310 | ||
@@ -1583,7 +1604,7 @@ restore_current: | |||
1583 | retl | 1604 | retl |
1584 | nop | 1605 | nop |
1585 | 1606 | ||
1586 | #ifdef CONFIG_PCI | 1607 | #ifdef CONFIG_PCIC_PCI |
1587 | #include <asm/pcic.h> | 1608 | #include <asm/pcic.h> |
1588 | 1609 | ||
1589 | .align 4 | 1610 | .align 4 |
@@ -1629,7 +1650,7 @@ pcic_nmi_trap_patch: | |||
1629 | rd %psr, %l0 | 1650 | rd %psr, %l0 |
1630 | .word 0 | 1651 | .word 0 |
1631 | 1652 | ||
1632 | #endif /* CONFIG_PCI */ | 1653 | #endif /* CONFIG_PCIC_PCI */ |
1633 | 1654 | ||
1634 | .globl flushw_all | 1655 | .globl flushw_all |
1635 | flushw_all: | 1656 | flushw_all: |
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/head_32.S b/arch/sparc/kernel/head_32.S index 21bb2590d4ae..587785759838 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S | |||
@@ -73,12 +73,11 @@ sun4e_notsup: | |||
73 | 73 | ||
74 | /* The Sparc trap table, bootloader gives us control at _start. */ | 74 | /* The Sparc trap table, bootloader gives us control at _start. */ |
75 | __HEAD | 75 | __HEAD |
76 | .globl start, _stext, _start, __stext | 76 | .globl _stext, _start, __stext |
77 | .globl trapbase | 77 | .globl trapbase |
78 | _start: /* danger danger */ | 78 | _start: /* danger danger */ |
79 | __stext: | 79 | __stext: |
80 | _stext: | 80 | _stext: |
81 | start: | ||
82 | trapbase: | 81 | trapbase: |
83 | #ifdef CONFIG_SMP | 82 | #ifdef CONFIG_SMP |
84 | trapbase_cpu0: | 83 | trapbase_cpu0: |
@@ -811,31 +810,25 @@ found_version: | |||
811 | got_prop: | 810 | got_prop: |
812 | #ifdef CONFIG_SPARC_LEON | 811 | #ifdef CONFIG_SPARC_LEON |
813 | /* no cpu-type check is needed, it is a SPARC-LEON */ | 812 | /* no cpu-type check is needed, it is a SPARC-LEON */ |
814 | #ifdef CONFIG_SMP | ||
815 | ba leon_smp_init | ||
816 | nop | ||
817 | 813 | ||
818 | .global leon_smp_init | 814 | sethi %hi(boot_cpu_id), %g2 ! boot-cpu index |
819 | leon_smp_init: | ||
820 | sethi %hi(boot_cpu_id), %g1 ! master always 0 | ||
821 | stb %g0, [%g1 + %lo(boot_cpu_id)] | ||
822 | sethi %hi(boot_cpu_id4), %g1 ! master always 0 | ||
823 | stb %g0, [%g1 + %lo(boot_cpu_id4)] | ||
824 | 815 | ||
825 | rd %asr17,%g1 | 816 | #ifdef CONFIG_SMP |
826 | srl %g1,28,%g1 | 817 | ldub [%g2 + %lo(boot_cpu_id)], %g1 |
818 | cmp %g1, 0xff ! unset means first CPU | ||
819 | bne leon_smp_cpu_startup ! continue only with master | ||
820 | nop | ||
821 | #endif | ||
822 | /* Get CPU-ID from most significant 4-bit of ASR17 */ | ||
823 | rd %asr17, %g1 | ||
824 | srl %g1, 28, %g1 | ||
827 | 825 | ||
828 | cmp %g0,%g1 | 826 | /* Update boot_cpu_id only on boot cpu */ |
829 | beq sun4c_continue_boot !continue with master | 827 | stub %g1, [%g2 + %lo(boot_cpu_id)] |
830 | nop | ||
831 | 828 | ||
832 | ba leon_smp_cpu_startup | ||
833 | nop | ||
834 | #else | ||
835 | ba sun4c_continue_boot | 829 | ba sun4c_continue_boot |
836 | nop | 830 | nop |
837 | #endif | 831 | #endif |
838 | #endif | ||
839 | set cputypval, %o2 | 832 | set cputypval, %o2 |
840 | ldub [%o2 + 0x4], %l1 | 833 | ldub [%o2 + 0x4], %l1 |
841 | 834 | ||
@@ -894,9 +887,6 @@ sun4d_init: | |||
894 | sta %g4, [%g0] ASI_M_VIKING_TMP1 | 887 | sta %g4, [%g0] ASI_M_VIKING_TMP1 |
895 | sethi %hi(boot_cpu_id), %g5 | 888 | sethi %hi(boot_cpu_id), %g5 |
896 | stb %g4, [%g5 + %lo(boot_cpu_id)] | 889 | stb %g4, [%g5 + %lo(boot_cpu_id)] |
897 | sll %g4, 2, %g4 | ||
898 | sethi %hi(boot_cpu_id4), %g5 | ||
899 | stb %g4, [%g5 + %lo(boot_cpu_id4)] | ||
900 | #endif | 890 | #endif |
901 | 891 | ||
902 | /* Fall through to sun4m_init */ | 892 | /* Fall through to sun4m_init */ |
@@ -1025,14 +1015,28 @@ sun4c_continue_boot: | |||
1025 | bl 1b | 1015 | bl 1b |
1026 | add %o0, 0x1, %o0 | 1016 | add %o0, 0x1, %o0 |
1027 | 1017 | ||
1018 | /* If boot_cpu_id has not been setup by machine specific | ||
1019 | * init-code above we default it to zero. | ||
1020 | */ | ||
1021 | sethi %hi(boot_cpu_id), %g2 | ||
1022 | ldub [%g2 + %lo(boot_cpu_id)], %g3 | ||
1023 | cmp %g3, 0xff | ||
1024 | bne 1f | ||
1025 | nop | ||
1026 | mov %g0, %g3 | ||
1027 | stub %g3, [%g2 + %lo(boot_cpu_id)] | ||
1028 | |||
1029 | 1: /* boot_cpu_id set. calculate boot_cpu_id4 = boot_cpu_id*4 */ | ||
1030 | sll %g3, 2, %g3 | ||
1031 | sethi %hi(boot_cpu_id4), %g2 | ||
1032 | stub %g3, [%g2 + %lo(boot_cpu_id4)] | ||
1033 | |||
1028 | /* Initialize the uwinmask value for init task just in case. | 1034 | /* Initialize the uwinmask value for init task just in case. |
1029 | * But first make current_set[boot_cpu_id] point to something useful. | 1035 | * But first make current_set[boot_cpu_id] point to something useful. |
1030 | */ | 1036 | */ |
1031 | set init_thread_union, %g6 | 1037 | set init_thread_union, %g6 |
1032 | set current_set, %g2 | 1038 | set current_set, %g2 |
1033 | #ifdef CONFIG_SMP | 1039 | #ifdef CONFIG_SMP |
1034 | sethi %hi(boot_cpu_id4), %g3 | ||
1035 | ldub [%g3 + %lo(boot_cpu_id4)], %g3 | ||
1036 | st %g6, [%g2] | 1040 | st %g6, [%g2] |
1037 | add %g2, %g3, %g2 | 1041 | add %g2, %g3, %g2 |
1038 | #endif | 1042 | #endif |
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index f8f21050448b..aa594c792d19 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S | |||
@@ -85,7 +85,7 @@ sparc_ramdisk_image64: | |||
85 | sparc64_boot: | 85 | sparc64_boot: |
86 | mov %o4, %l7 | 86 | mov %o4, %l7 |
87 | 87 | ||
88 | /* We need to remap the kernel. Use position independant | 88 | /* We need to remap the kernel. Use position independent |
89 | * code to remap us to KERNBASE. | 89 | * code to remap us to KERNBASE. |
90 | * | 90 | * |
91 | * SILO can invoke us with 32-bit address masking enabled, | 91 | * SILO can invoke us with 32-bit address masking enabled, |
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index 5fe3d65581f7..35f141a9f506 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c | |||
@@ -15,7 +15,7 @@ EXPORT_SYMBOL(init_task); | |||
15 | 15 | ||
16 | /* .text section in head.S is aligned at 8k boundary and this gets linked | 16 | /* .text section in head.S is aligned at 8k boundary and this gets linked |
17 | * right after that so that the init_thread_union is aligned properly as well. | 17 | * right after that so that the init_thread_union is aligned properly as well. |
18 | * If this is not aligned on a 8k boundry, then you should change code | 18 | * If this is not aligned on a 8k boundary, then you should change code |
19 | * in etrap.S which assumes it. | 19 | * in etrap.S which assumes it. |
20 | */ | 20 | */ |
21 | union thread_union init_thread_union __init_task_data = | 21 | union thread_union init_thread_union __init_task_data = |
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c index 47977a77f6c6..6f01e8c83197 100644 --- a/arch/sparc/kernel/iommu.c +++ b/arch/sparc/kernel/iommu.c | |||
@@ -255,10 +255,9 @@ static inline iopte_t *alloc_npages(struct device *dev, struct iommu *iommu, | |||
255 | static int iommu_alloc_ctx(struct iommu *iommu) | 255 | static int iommu_alloc_ctx(struct iommu *iommu) |
256 | { | 256 | { |
257 | int lowest = iommu->ctx_lowest_free; | 257 | int lowest = iommu->ctx_lowest_free; |
258 | int sz = IOMMU_NUM_CTXS - lowest; | 258 | int n = find_next_zero_bit(iommu->ctx_bitmap, IOMMU_NUM_CTXS, lowest); |
259 | int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest); | ||
260 | 259 | ||
261 | if (unlikely(n == sz)) { | 260 | if (unlikely(n == IOMMU_NUM_CTXS)) { |
262 | n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); | 261 | n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1); |
263 | if (unlikely(n == lowest)) { | 262 | if (unlikely(n == lowest)) { |
264 | printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); | 263 | printk(KERN_WARNING "IOMMU: Ran out of contexts.\n"); |
@@ -334,13 +333,10 @@ static void dma_4u_free_coherent(struct device *dev, size_t size, | |||
334 | void *cpu, dma_addr_t dvma) | 333 | void *cpu, dma_addr_t dvma) |
335 | { | 334 | { |
336 | struct iommu *iommu; | 335 | struct iommu *iommu; |
337 | iopte_t *iopte; | ||
338 | unsigned long flags, order, npages; | 336 | unsigned long flags, order, npages; |
339 | 337 | ||
340 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; | 338 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; |
341 | iommu = dev->archdata.iommu; | 339 | iommu = dev->archdata.iommu; |
342 | iopte = iommu->page_table + | ||
343 | ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); | ||
344 | 340 | ||
345 | spin_lock_irqsave(&iommu->lock, flags); | 341 | spin_lock_irqsave(&iommu->lock, flags); |
346 | 342 | ||
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 41f7e4e0f72a..1c9c80a1a86a 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -50,10 +50,19 @@ | |||
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 | /* This function must make sure that caches and memory are coherent after DMA |
54 | #define mmu_inval_dma_area(p, l) leon_flush_dcache_all() | 54 | * On LEON systems without cache snooping it flushes the entire D-CACHE. |
55 | */ | ||
56 | #ifndef CONFIG_SPARC_LEON | ||
57 | static inline void dma_make_coherent(unsigned long pa, unsigned long len) | ||
58 | { | ||
59 | } | ||
55 | #else | 60 | #else |
56 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ | 61 | static inline void dma_make_coherent(unsigned long pa, unsigned long len) |
62 | { | ||
63 | if (!sparc_leon3_snooping_enabled()) | ||
64 | leon_flush_dcache_all(); | ||
65 | } | ||
57 | #endif | 66 | #endif |
58 | 67 | ||
59 | static struct resource *_sparc_find_resource(struct resource *r, | 68 | static struct resource *_sparc_find_resource(struct resource *r, |
@@ -254,7 +263,7 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
254 | dma_addr_t *dma_addrp, gfp_t gfp) | 263 | dma_addr_t *dma_addrp, gfp_t gfp) |
255 | { | 264 | { |
256 | struct platform_device *op = to_platform_device(dev); | 265 | struct platform_device *op = to_platform_device(dev); |
257 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; | 266 | unsigned long len_total = PAGE_ALIGN(len); |
258 | unsigned long va; | 267 | unsigned long va; |
259 | struct resource *res; | 268 | struct resource *res; |
260 | int order; | 269 | int order; |
@@ -280,7 +289,7 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
280 | printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total); | 289 | printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total); |
281 | goto err_nova; | 290 | goto err_nova; |
282 | } | 291 | } |
283 | mmu_inval_dma_area(va, len_total); | 292 | |
284 | // XXX The mmu_map_dma_area does this for us below, see comments. | 293 | // 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); | 294 | // sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); |
286 | /* | 295 | /* |
@@ -297,9 +306,9 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, | |||
297 | err_noiommu: | 306 | err_noiommu: |
298 | release_resource(res); | 307 | release_resource(res); |
299 | err_nova: | 308 | err_nova: |
300 | free_pages(va, order); | ||
301 | err_nomem: | ||
302 | kfree(res); | 309 | kfree(res); |
310 | err_nomem: | ||
311 | free_pages(va, order); | ||
303 | err_nopages: | 312 | err_nopages: |
304 | return NULL; | 313 | return NULL; |
305 | } | 314 | } |
@@ -321,7 +330,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p, | |||
321 | return; | 330 | return; |
322 | } | 331 | } |
323 | 332 | ||
324 | n = (n + PAGE_SIZE-1) & PAGE_MASK; | 333 | n = PAGE_ALIGN(n); |
325 | if ((res->end-res->start)+1 != n) { | 334 | if ((res->end-res->start)+1 != n) { |
326 | printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", | 335 | printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n", |
327 | (long)((res->end-res->start)+1), n); | 336 | (long)((res->end-res->start)+1), n); |
@@ -331,7 +340,6 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p, | |||
331 | release_resource(res); | 340 | release_resource(res); |
332 | kfree(res); | 341 | kfree(res); |
333 | 342 | ||
334 | /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ | ||
335 | pgv = virt_to_page(p); | 343 | pgv = virt_to_page(p); |
336 | mmu_unmap_dma_area(dev, ba, n); | 344 | mmu_unmap_dma_area(dev, ba, n); |
337 | 345 | ||
@@ -408,9 +416,6 @@ struct dma_map_ops sbus_dma_ops = { | |||
408 | .sync_sg_for_device = sbus_sync_sg_for_device, | 416 | .sync_sg_for_device = sbus_sync_sg_for_device, |
409 | }; | 417 | }; |
410 | 418 | ||
411 | struct dma_map_ops *dma_ops = &sbus_dma_ops; | ||
412 | EXPORT_SYMBOL(dma_ops); | ||
413 | |||
414 | static int __init sparc_register_ioport(void) | 419 | static int __init sparc_register_ioport(void) |
415 | { | 420 | { |
416 | register_proc_sparc_ioport(); | 421 | register_proc_sparc_ioport(); |
@@ -422,7 +427,9 @@ arch_initcall(sparc_register_ioport); | |||
422 | 427 | ||
423 | #endif /* CONFIG_SBUS */ | 428 | #endif /* CONFIG_SBUS */ |
424 | 429 | ||
425 | #ifdef CONFIG_PCI | 430 | |
431 | /* LEON reuses PCI DMA ops */ | ||
432 | #if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON) | ||
426 | 433 | ||
427 | /* Allocate and map kernel buffer using consistent mode DMA for a device. | 434 | /* Allocate and map kernel buffer using consistent mode DMA for a device. |
428 | * hwdev should be valid struct pci_dev pointer for PCI devices. | 435 | * hwdev should be valid struct pci_dev pointer for PCI devices. |
@@ -430,8 +437,8 @@ arch_initcall(sparc_register_ioport); | |||
430 | static void *pci32_alloc_coherent(struct device *dev, size_t len, | 437 | static void *pci32_alloc_coherent(struct device *dev, size_t len, |
431 | dma_addr_t *pba, gfp_t gfp) | 438 | dma_addr_t *pba, gfp_t gfp) |
432 | { | 439 | { |
433 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; | 440 | unsigned long len_total = PAGE_ALIGN(len); |
434 | unsigned long va; | 441 | void *va; |
435 | struct resource *res; | 442 | struct resource *res; |
436 | int order; | 443 | int order; |
437 | 444 | ||
@@ -443,34 +450,33 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len, | |||
443 | } | 450 | } |
444 | 451 | ||
445 | order = get_order(len_total); | 452 | order = get_order(len_total); |
446 | va = __get_free_pages(GFP_KERNEL, order); | 453 | va = (void *) __get_free_pages(GFP_KERNEL, order); |
447 | if (va == 0) { | 454 | if (va == NULL) { |
448 | printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); | 455 | printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); |
449 | return NULL; | 456 | goto err_nopages; |
450 | } | 457 | } |
451 | 458 | ||
452 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { | 459 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { |
453 | free_pages(va, order); | ||
454 | printk("pci_alloc_consistent: no core\n"); | 460 | printk("pci_alloc_consistent: no core\n"); |
455 | return NULL; | 461 | goto err_nomem; |
456 | } | 462 | } |
457 | 463 | ||
458 | if (allocate_resource(&_sparc_dvma, res, len_total, | 464 | if (allocate_resource(&_sparc_dvma, res, len_total, |
459 | _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { | 465 | _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { |
460 | printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); | 466 | printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total); |
461 | free_pages(va, order); | 467 | goto err_nova; |
462 | kfree(res); | ||
463 | return NULL; | ||
464 | } | 468 | } |
465 | 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); | 469 | sparc_mapiorange(0, virt_to_phys(va), res->start, len_total); |
471 | 470 | ||
472 | *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ | 471 | *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */ |
473 | return (void *) res->start; | 472 | return (void *) res->start; |
473 | |||
474 | err_nova: | ||
475 | kfree(res); | ||
476 | err_nomem: | ||
477 | free_pages((unsigned long)va, order); | ||
478 | err_nopages: | ||
479 | return NULL; | ||
474 | } | 480 | } |
475 | 481 | ||
476 | /* Free and unmap a consistent DMA buffer. | 482 | /* Free and unmap a consistent DMA buffer. |
@@ -485,7 +491,6 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, | |||
485 | dma_addr_t ba) | 491 | dma_addr_t ba) |
486 | { | 492 | { |
487 | struct resource *res; | 493 | struct resource *res; |
488 | unsigned long pgp; | ||
489 | 494 | ||
490 | if ((res = _sparc_find_resource(&_sparc_dvma, | 495 | if ((res = _sparc_find_resource(&_sparc_dvma, |
491 | (unsigned long)p)) == NULL) { | 496 | (unsigned long)p)) == NULL) { |
@@ -498,21 +503,19 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p, | |||
498 | return; | 503 | return; |
499 | } | 504 | } |
500 | 505 | ||
501 | n = (n + PAGE_SIZE-1) & PAGE_MASK; | 506 | n = PAGE_ALIGN(n); |
502 | if ((res->end-res->start)+1 != n) { | 507 | if ((res->end-res->start)+1 != n) { |
503 | printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", | 508 | printk("pci_free_consistent: region 0x%lx asked 0x%lx\n", |
504 | (long)((res->end-res->start)+1), (long)n); | 509 | (long)((res->end-res->start)+1), (long)n); |
505 | return; | 510 | return; |
506 | } | 511 | } |
507 | 512 | ||
508 | pgp = (unsigned long) phys_to_virt(ba); /* bus_to_virt actually */ | 513 | dma_make_coherent(ba, n); |
509 | 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 | free_pages((unsigned long)phys_to_virt(ba), get_order(n)); | |
515 | free_pages(pgp, get_order(n)); | ||
516 | } | 519 | } |
517 | 520 | ||
518 | /* | 521 | /* |
@@ -527,6 +530,13 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page, | |||
527 | return page_to_phys(page) + offset; | 530 | return page_to_phys(page) + offset; |
528 | } | 531 | } |
529 | 532 | ||
533 | static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size, | ||
534 | enum dma_data_direction dir, struct dma_attrs *attrs) | ||
535 | { | ||
536 | if (dir != PCI_DMA_TODEVICE) | ||
537 | dma_make_coherent(ba, PAGE_ALIGN(size)); | ||
538 | } | ||
539 | |||
530 | /* Map a set of buffers described by scatterlist in streaming | 540 | /* Map a set of buffers described by scatterlist in streaming |
531 | * mode for DMA. This is the scather-gather version of the | 541 | * mode for DMA. This is the scather-gather version of the |
532 | * above pci_map_single interface. Here the scatter gather list | 542 | * above pci_map_single interface. Here the scatter gather list |
@@ -551,8 +561,7 @@ static int pci32_map_sg(struct device *device, struct scatterlist *sgl, | |||
551 | 561 | ||
552 | /* IIep is write-through, not flushing. */ | 562 | /* IIep is write-through, not flushing. */ |
553 | for_each_sg(sgl, sg, nents, n) { | 563 | for_each_sg(sgl, sg, nents, n) { |
554 | BUG_ON(page_address(sg_page(sg)) == NULL); | 564 | sg->dma_address = sg_phys(sg); |
555 | sg->dma_address = virt_to_phys(sg_virt(sg)); | ||
556 | sg->dma_length = sg->length; | 565 | sg->dma_length = sg->length; |
557 | } | 566 | } |
558 | return nents; | 567 | return nents; |
@@ -571,10 +580,7 @@ static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl, | |||
571 | 580 | ||
572 | if (dir != PCI_DMA_TODEVICE) { | 581 | if (dir != PCI_DMA_TODEVICE) { |
573 | for_each_sg(sgl, sg, nents, n) { | 582 | for_each_sg(sgl, sg, nents, n) { |
574 | BUG_ON(page_address(sg_page(sg)) == NULL); | 583 | dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); |
575 | mmu_inval_dma_area( | ||
576 | (unsigned long) page_address(sg_page(sg)), | ||
577 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
578 | } | 584 | } |
579 | } | 585 | } |
580 | } | 586 | } |
@@ -593,8 +599,7 @@ static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba, | |||
593 | size_t size, enum dma_data_direction dir) | 599 | size_t size, enum dma_data_direction dir) |
594 | { | 600 | { |
595 | if (dir != PCI_DMA_TODEVICE) { | 601 | if (dir != PCI_DMA_TODEVICE) { |
596 | mmu_inval_dma_area((unsigned long)phys_to_virt(ba), | 602 | dma_make_coherent(ba, PAGE_ALIGN(size)); |
597 | (size + PAGE_SIZE-1) & PAGE_MASK); | ||
598 | } | 603 | } |
599 | } | 604 | } |
600 | 605 | ||
@@ -602,8 +607,7 @@ static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba, | |||
602 | size_t size, enum dma_data_direction dir) | 607 | size_t size, enum dma_data_direction dir) |
603 | { | 608 | { |
604 | if (dir != PCI_DMA_TODEVICE) { | 609 | if (dir != PCI_DMA_TODEVICE) { |
605 | mmu_inval_dma_area((unsigned long)phys_to_virt(ba), | 610 | dma_make_coherent(ba, PAGE_ALIGN(size)); |
606 | (size + PAGE_SIZE-1) & PAGE_MASK); | ||
607 | } | 611 | } |
608 | } | 612 | } |
609 | 613 | ||
@@ -621,10 +625,7 @@ static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl, | |||
621 | 625 | ||
622 | if (dir != PCI_DMA_TODEVICE) { | 626 | if (dir != PCI_DMA_TODEVICE) { |
623 | for_each_sg(sgl, sg, nents, n) { | 627 | for_each_sg(sgl, sg, nents, n) { |
624 | BUG_ON(page_address(sg_page(sg)) == NULL); | 628 | dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); |
625 | mmu_inval_dma_area( | ||
626 | (unsigned long) page_address(sg_page(sg)), | ||
627 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
628 | } | 629 | } |
629 | } | 630 | } |
630 | } | 631 | } |
@@ -637,10 +638,7 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist * | |||
637 | 638 | ||
638 | if (dir != PCI_DMA_TODEVICE) { | 639 | if (dir != PCI_DMA_TODEVICE) { |
639 | for_each_sg(sgl, sg, nents, n) { | 640 | for_each_sg(sgl, sg, nents, n) { |
640 | BUG_ON(page_address(sg_page(sg)) == NULL); | 641 | dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length)); |
641 | mmu_inval_dma_area( | ||
642 | (unsigned long) page_address(sg_page(sg)), | ||
643 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | ||
644 | } | 642 | } |
645 | } | 643 | } |
646 | } | 644 | } |
@@ -649,6 +647,7 @@ struct dma_map_ops pci32_dma_ops = { | |||
649 | .alloc_coherent = pci32_alloc_coherent, | 647 | .alloc_coherent = pci32_alloc_coherent, |
650 | .free_coherent = pci32_free_coherent, | 648 | .free_coherent = pci32_free_coherent, |
651 | .map_page = pci32_map_page, | 649 | .map_page = pci32_map_page, |
650 | .unmap_page = pci32_unmap_page, | ||
652 | .map_sg = pci32_map_sg, | 651 | .map_sg = pci32_map_sg, |
653 | .unmap_sg = pci32_unmap_sg, | 652 | .unmap_sg = pci32_unmap_sg, |
654 | .sync_single_for_cpu = pci32_sync_single_for_cpu, | 653 | .sync_single_for_cpu = pci32_sync_single_for_cpu, |
@@ -658,7 +657,16 @@ struct dma_map_ops pci32_dma_ops = { | |||
658 | }; | 657 | }; |
659 | EXPORT_SYMBOL(pci32_dma_ops); | 658 | EXPORT_SYMBOL(pci32_dma_ops); |
660 | 659 | ||
661 | #endif /* CONFIG_PCI */ | 660 | #endif /* CONFIG_PCI || CONFIG_SPARC_LEON */ |
661 | |||
662 | #ifdef CONFIG_SPARC_LEON | ||
663 | struct dma_map_ops *dma_ops = &pci32_dma_ops; | ||
664 | #elif defined(CONFIG_SBUS) | ||
665 | struct dma_map_ops *dma_ops = &sbus_dma_ops; | ||
666 | #endif | ||
667 | |||
668 | EXPORT_SYMBOL(dma_ops); | ||
669 | |||
662 | 670 | ||
663 | /* | 671 | /* |
664 | * Return whether the given PCI device DMA address mask can be | 672 | * Return whether the given PCI device DMA address mask can be |
@@ -717,7 +725,7 @@ static const struct file_operations sparc_io_proc_fops = { | |||
717 | static struct resource *_sparc_find_resource(struct resource *root, | 725 | static struct resource *_sparc_find_resource(struct resource *root, |
718 | unsigned long hit) | 726 | unsigned long hit) |
719 | { | 727 | { |
720 | struct resource *tmp; | 728 | struct resource *tmp; |
721 | 729 | ||
722 | for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { | 730 | for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { |
723 | if (tmp->start <= hit && tmp->end >= hit) | 731 | if (tmp->start <= hit && tmp->end >= hit) |
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index db7513881530..100b9c204e78 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h | |||
@@ -1,5 +1,62 @@ | |||
1 | #include <linux/platform_device.h> | ||
2 | |||
1 | #include <asm/btfixup.h> | 3 | #include <asm/btfixup.h> |
2 | 4 | ||
5 | struct irq_bucket { | ||
6 | struct irq_bucket *next; | ||
7 | unsigned int real_irq; | ||
8 | unsigned int irq; | ||
9 | unsigned int pil; | ||
10 | }; | ||
11 | |||
12 | #define SUN4D_MAX_BOARD 10 | ||
13 | #define SUN4D_MAX_IRQ ((SUN4D_MAX_BOARD + 2) << 5) | ||
14 | |||
15 | /* Map between the irq identifier used in hw to the | ||
16 | * irq_bucket. The map is sufficient large to hold | ||
17 | * the sun4d hw identifiers. | ||
18 | */ | ||
19 | extern struct irq_bucket *irq_map[SUN4D_MAX_IRQ]; | ||
20 | |||
21 | |||
22 | /* sun4m specific type definitions */ | ||
23 | |||
24 | /* This maps direct to CPU specific interrupt registers */ | ||
25 | struct sun4m_irq_percpu { | ||
26 | u32 pending; | ||
27 | u32 clear; | ||
28 | u32 set; | ||
29 | }; | ||
30 | |||
31 | /* This maps direct to global interrupt registers */ | ||
32 | struct sun4m_irq_global { | ||
33 | u32 pending; | ||
34 | u32 mask; | ||
35 | u32 mask_clear; | ||
36 | u32 mask_set; | ||
37 | u32 interrupt_target; | ||
38 | }; | ||
39 | |||
40 | extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | ||
41 | extern struct sun4m_irq_global __iomem *sun4m_irq_global; | ||
42 | |||
43 | /* | ||
44 | * Platform specific irq configuration | ||
45 | * The individual platforms assign their platform | ||
46 | * specifics in their init functions. | ||
47 | */ | ||
48 | struct sparc_irq_config { | ||
49 | void (*init_timers)(irq_handler_t); | ||
50 | unsigned int (*build_device_irq)(struct platform_device *op, | ||
51 | unsigned int real_irq); | ||
52 | }; | ||
53 | extern struct sparc_irq_config sparc_irq_config; | ||
54 | |||
55 | unsigned int irq_alloc(unsigned int real_irq, unsigned int pil); | ||
56 | void irq_link(unsigned int irq); | ||
57 | void irq_unlink(unsigned int irq); | ||
58 | void handler_irq(unsigned int pil, struct pt_regs *regs); | ||
59 | |||
3 | /* Dave Redman (djhr@tadpole.co.uk) | 60 | /* Dave Redman (djhr@tadpole.co.uk) |
4 | * changed these to function pointers.. it saves cycles and will allow | 61 | * 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 | 62 | * the irq dependencies to be split into different files at a later date |
@@ -8,33 +65,9 @@ | |||
8 | * Changed these to btfixup entities... It saves cycles :) | 65 | * Changed these to btfixup entities... It saves cycles :) |
9 | */ | 66 | */ |
10 | 67 | ||
11 | BTFIXUPDEF_CALL(void, disable_irq, unsigned int) | ||
12 | BTFIXUPDEF_CALL(void, enable_irq, unsigned int) | ||
13 | BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) | ||
14 | BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) | ||
15 | BTFIXUPDEF_CALL(void, clear_clock_irq, void) | 68 | BTFIXUPDEF_CALL(void, clear_clock_irq, void) |
16 | BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) | 69 | BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) |
17 | 70 | ||
18 | static inline void __disable_irq(unsigned int irq) | ||
19 | { | ||
20 | BTFIXUP_CALL(disable_irq)(irq); | ||
21 | } | ||
22 | |||
23 | static inline void __enable_irq(unsigned int irq) | ||
24 | { | ||
25 | BTFIXUP_CALL(enable_irq)(irq); | ||
26 | } | ||
27 | |||
28 | static inline void disable_pil_irq(unsigned int irq) | ||
29 | { | ||
30 | BTFIXUP_CALL(disable_pil_irq)(irq); | ||
31 | } | ||
32 | |||
33 | static inline void enable_pil_irq(unsigned int irq) | ||
34 | { | ||
35 | BTFIXUP_CALL(enable_pil_irq)(irq); | ||
36 | } | ||
37 | |||
38 | static inline void clear_clock_irq(void) | 71 | static inline void clear_clock_irq(void) |
39 | { | 72 | { |
40 | BTFIXUP_CALL(clear_clock_irq)(); | 73 | BTFIXUP_CALL(clear_clock_irq)(); |
@@ -45,12 +78,6 @@ static inline void load_profile_irq(int cpu, int limit) | |||
45 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); | 78 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); |
46 | } | 79 | } |
47 | 80 | ||
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 | 81 | #ifdef CONFIG_SMP |
55 | BTFIXUPDEF_CALL(void, set_cpu_int, int, int) | 82 | BTFIXUPDEF_CALL(void, set_cpu_int, int, int) |
56 | BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) | 83 | BTFIXUPDEF_CALL(void, clear_cpu_int, int, int) |
@@ -59,4 +86,10 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int) | |||
59 | #define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) | 86 | #define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level) |
60 | #define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level) | 87 | #define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level) |
61 | #define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) | 88 | #define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu) |
89 | |||
90 | /* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */ | ||
91 | #define SUN4D_IPI_IRQ 14 | ||
92 | |||
93 | extern void sun4d_ipi_interrupt(void); | ||
94 | |||
62 | #endif | 95 | #endif |
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c index e1af43728329..9b89d842913c 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,12 @@ | |||
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/cpudata.h> |
19 | #include <asm/pcic.h> | ||
48 | #include <asm/leon.h> | 20 | #include <asm/leon.h> |
49 | 21 | ||
50 | #include "kernel.h" | 22 | #include "kernel.h" |
@@ -57,7 +29,11 @@ | |||
57 | #define SMP_NOP2 | 29 | #define SMP_NOP2 |
58 | #define SMP_NOP3 | 30 | #define SMP_NOP3 |
59 | #endif /* SMP */ | 31 | #endif /* SMP */ |
60 | unsigned long __raw_local_irq_save(void) | 32 | |
33 | /* platform specific irq setup */ | ||
34 | struct sparc_irq_config sparc_irq_config; | ||
35 | |||
36 | unsigned long arch_local_irq_save(void) | ||
61 | { | 37 | { |
62 | unsigned long retval; | 38 | unsigned long retval; |
63 | unsigned long tmp; | 39 | unsigned long tmp; |
@@ -74,8 +50,9 @@ unsigned long __raw_local_irq_save(void) | |||
74 | 50 | ||
75 | return retval; | 51 | return retval; |
76 | } | 52 | } |
53 | EXPORT_SYMBOL(arch_local_irq_save); | ||
77 | 54 | ||
78 | void raw_local_irq_enable(void) | 55 | void arch_local_irq_enable(void) |
79 | { | 56 | { |
80 | unsigned long tmp; | 57 | unsigned long tmp; |
81 | 58 | ||
@@ -89,8 +66,9 @@ void raw_local_irq_enable(void) | |||
89 | : "i" (PSR_PIL) | 66 | : "i" (PSR_PIL) |
90 | : "memory"); | 67 | : "memory"); |
91 | } | 68 | } |
69 | EXPORT_SYMBOL(arch_local_irq_enable); | ||
92 | 70 | ||
93 | void raw_local_irq_restore(unsigned long old_psr) | 71 | void arch_local_irq_restore(unsigned long old_psr) |
94 | { | 72 | { |
95 | unsigned long tmp; | 73 | unsigned long tmp; |
96 | 74 | ||
@@ -105,10 +83,7 @@ void raw_local_irq_restore(unsigned long old_psr) | |||
105 | : "i" (PSR_PIL), "r" (old_psr) | 83 | : "i" (PSR_PIL), "r" (old_psr) |
106 | : "memory"); | 84 | : "memory"); |
107 | } | 85 | } |
108 | 86 | EXPORT_SYMBOL(arch_local_irq_restore); | |
109 | EXPORT_SYMBOL(__raw_local_irq_save); | ||
110 | EXPORT_SYMBOL(raw_local_irq_enable); | ||
111 | EXPORT_SYMBOL(raw_local_irq_restore); | ||
112 | 87 | ||
113 | /* | 88 | /* |
114 | * Dave Redman (djhr@tadpole.co.uk) | 89 | * Dave Redman (djhr@tadpole.co.uk) |
@@ -127,309 +102,185 @@ EXPORT_SYMBOL(raw_local_irq_restore); | |||
127 | * directed CPU interrupts using the existing enable/disable irq code | 102 | * directed CPU interrupts using the existing enable/disable irq code |
128 | * with tweaks. | 103 | * with tweaks. |
129 | * | 104 | * |
105 | * Sun4d complicates things even further. IRQ numbers are arbitrary | ||
106 | * 32-bit values in that case. Since this is similar to sparc64, | ||
107 | * we adopt a virtual IRQ numbering scheme as is done there. | ||
108 | * Virutal interrupt numbers are allocated by build_irq(). So NR_IRQS | ||
109 | * just becomes a limit of how many interrupt sources we can handle in | ||
110 | * a single system. Even fully loaded SS2000 machines top off at | ||
111 | * about 32 interrupt sources or so, therefore a NR_IRQS value of 64 | ||
112 | * is more than enough. | ||
113 | * | ||
114 | * We keep a map of per-PIL enable interrupts. These get wired | ||
115 | * up via the irq_chip->startup() method which gets invoked by | ||
116 | * the generic IRQ layer during request_irq(). | ||
130 | */ | 117 | */ |
131 | 118 | ||
132 | static void irq_panic(void) | ||
133 | { | ||
134 | extern char *cputypval; | ||
135 | prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval); | ||
136 | prom_halt(); | ||
137 | } | ||
138 | 119 | ||
139 | void (*sparc_init_timers)(irq_handler_t ) = | 120 | /* Table of allocated irqs. Unused entries has irq == 0 */ |
140 | (void (*)(irq_handler_t )) irq_panic; | 121 | static struct irq_bucket irq_table[NR_IRQS]; |
122 | /* Protect access to irq_table */ | ||
123 | static DEFINE_SPINLOCK(irq_table_lock); | ||
141 | 124 | ||
142 | /* | 125 | /* Map between the irq identifier used in hw to the irq_bucket. */ |
143 | * Dave Redman (djhr@tadpole.co.uk) | 126 | struct irq_bucket *irq_map[SUN4D_MAX_IRQ]; |
144 | * | 127 | /* Protect access to irq_map */ |
145 | * There used to be extern calls and hard coded values here.. very sucky! | 128 | static DEFINE_SPINLOCK(irq_map_lock); |
146 | * instead, because some of the devices attach very early, I do something | ||
147 | * equally sucky but at least we'll never try to free statically allocated | ||
148 | * space or call kmalloc before kmalloc_init :(. | ||
149 | * | ||
150 | * In fact it's the timer10 that attaches first.. then timer14 | ||
151 | * then kmalloc_init is called.. then the tty interrupts attach. | ||
152 | * hmmm.... | ||
153 | * | ||
154 | */ | ||
155 | #define MAX_STATIC_ALLOC 4 | ||
156 | struct irqaction static_irqaction[MAX_STATIC_ALLOC]; | ||
157 | int static_irq_count; | ||
158 | |||
159 | static struct { | ||
160 | struct irqaction *action; | ||
161 | int flags; | ||
162 | } sparc_irq[NR_IRQS]; | ||
163 | #define SPARC_IRQ_INPROGRESS 1 | ||
164 | 129 | ||
165 | /* Used to protect the IRQ action lists */ | 130 | /* Allocate a new irq from the irq_table */ |
166 | DEFINE_SPINLOCK(irq_action_lock); | 131 | unsigned int irq_alloc(unsigned int real_irq, unsigned int pil) |
167 | |||
168 | int show_interrupts(struct seq_file *p, void *v) | ||
169 | { | 132 | { |
170 | int i = *(loff_t *) v; | ||
171 | struct irqaction * action; | ||
172 | unsigned long flags; | 133 | unsigned long flags; |
173 | #ifdef CONFIG_SMP | 134 | unsigned int i; |
174 | int j; | ||
175 | #endif | ||
176 | 135 | ||
177 | if (sparc_cpu_model == sun4d) { | 136 | spin_lock_irqsave(&irq_table_lock, flags); |
178 | extern int show_sun4d_interrupts(struct seq_file *, void *); | 137 | for (i = 1; i < NR_IRQS; i++) { |
179 | 138 | if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil) | |
180 | return show_sun4d_interrupts(p, v); | 139 | goto found; |
181 | } | 140 | } |
182 | spin_lock_irqsave(&irq_action_lock, flags); | 141 | |
142 | for (i = 1; i < NR_IRQS; i++) { | ||
143 | if (!irq_table[i].irq) | ||
144 | break; | ||
145 | } | ||
146 | |||
183 | if (i < NR_IRQS) { | 147 | if (i < NR_IRQS) { |
184 | action = sparc_irq[i].action; | 148 | irq_table[i].real_irq = real_irq; |
185 | if (!action) | 149 | irq_table[i].irq = i; |
186 | goto out_unlock; | 150 | irq_table[i].pil = pil; |
187 | seq_printf(p, "%3d: ", i); | 151 | } else { |
188 | #ifndef CONFIG_SMP | 152 | printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); |
189 | seq_printf(p, "%10u ", kstat_irqs(i)); | 153 | i = 0; |
190 | #else | ||
191 | for_each_online_cpu(j) { | ||
192 | seq_printf(p, "%10u ", | ||
193 | kstat_cpu(j).irqs[i]); | ||
194 | } | ||
195 | #endif | ||
196 | seq_printf(p, " %c %s", | ||
197 | (action->flags & IRQF_DISABLED) ? '+' : ' ', | ||
198 | action->name); | ||
199 | for (action=action->next; action; action = action->next) { | ||
200 | seq_printf(p, ",%s %s", | ||
201 | (action->flags & IRQF_DISABLED) ? " +" : "", | ||
202 | action->name); | ||
203 | } | ||
204 | seq_putc(p, '\n'); | ||
205 | } | 154 | } |
206 | out_unlock: | 155 | found: |
207 | spin_unlock_irqrestore(&irq_action_lock, flags); | 156 | spin_unlock_irqrestore(&irq_table_lock, flags); |
208 | return 0; | 157 | |
158 | return i; | ||
209 | } | 159 | } |
210 | 160 | ||
211 | void free_irq(unsigned int irq, void *dev_id) | 161 | /* Based on a single pil handler_irq may need to call several |
162 | * interrupt handlers. Use irq_map as entry to irq_table, | ||
163 | * and let each entry in irq_table point to the next entry. | ||
164 | */ | ||
165 | void irq_link(unsigned int irq) | ||
212 | { | 166 | { |
213 | struct irqaction * action; | 167 | struct irq_bucket *p; |
214 | struct irqaction **actionp; | 168 | unsigned long flags; |
215 | unsigned long flags; | 169 | unsigned int pil; |
216 | unsigned int cpu_irq; | ||
217 | |||
218 | if (sparc_cpu_model == sun4d) { | ||
219 | extern void sun4d_free_irq(unsigned int, void *); | ||
220 | |||
221 | sun4d_free_irq(irq, dev_id); | ||
222 | return; | ||
223 | } | ||
224 | cpu_irq = irq & (NR_IRQS - 1); | ||
225 | if (cpu_irq > 14) { /* 14 irq levels on the sparc */ | ||
226 | printk("Trying to free bogus IRQ %d\n", irq); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | spin_lock_irqsave(&irq_action_lock, flags); | ||
231 | 170 | ||
232 | actionp = &sparc_irq[cpu_irq].action; | 171 | BUG_ON(irq >= NR_IRQS); |
233 | action = *actionp; | ||
234 | 172 | ||
235 | if (!action->handler) { | 173 | spin_lock_irqsave(&irq_map_lock, flags); |
236 | printk("Trying to free free IRQ%d\n",irq); | ||
237 | goto out_unlock; | ||
238 | } | ||
239 | if (dev_id) { | ||
240 | for (; action; action = action->next) { | ||
241 | if (action->dev_id == dev_id) | ||
242 | break; | ||
243 | actionp = &action->next; | ||
244 | } | ||
245 | if (!action) { | ||
246 | printk("Trying to free free shared IRQ%d\n",irq); | ||
247 | goto out_unlock; | ||
248 | } | ||
249 | } else if (action->flags & IRQF_SHARED) { | ||
250 | printk("Trying to free shared IRQ%d with NULL device ID\n", irq); | ||
251 | goto out_unlock; | ||
252 | } | ||
253 | if (action->flags & SA_STATIC_ALLOC) | ||
254 | { | ||
255 | /* This interrupt is marked as specially allocated | ||
256 | * so it is a bad idea to free it. | ||
257 | */ | ||
258 | printk("Attempt to free statically allocated IRQ%d (%s)\n", | ||
259 | irq, action->name); | ||
260 | goto out_unlock; | ||
261 | } | ||
262 | 174 | ||
263 | *actionp = action->next; | 175 | p = &irq_table[irq]; |
176 | pil = p->pil; | ||
177 | BUG_ON(pil > SUN4D_MAX_IRQ); | ||
178 | p->next = irq_map[pil]; | ||
179 | irq_map[pil] = p; | ||
264 | 180 | ||
265 | spin_unlock_irqrestore(&irq_action_lock, flags); | 181 | spin_unlock_irqrestore(&irq_map_lock, flags); |
182 | } | ||
266 | 183 | ||
267 | synchronize_irq(irq); | 184 | void irq_unlink(unsigned int irq) |
185 | { | ||
186 | struct irq_bucket *p, **pnext; | ||
187 | unsigned long flags; | ||
268 | 188 | ||
269 | spin_lock_irqsave(&irq_action_lock, flags); | 189 | BUG_ON(irq >= NR_IRQS); |
270 | 190 | ||
271 | kfree(action); | 191 | spin_lock_irqsave(&irq_map_lock, flags); |
272 | 192 | ||
273 | if (!sparc_irq[cpu_irq].action) | 193 | p = &irq_table[irq]; |
274 | __disable_irq(irq); | 194 | BUG_ON(p->pil > SUN4D_MAX_IRQ); |
195 | pnext = &irq_map[p->pil]; | ||
196 | while (*pnext != p) | ||
197 | pnext = &(*pnext)->next; | ||
198 | *pnext = p->next; | ||
275 | 199 | ||
276 | out_unlock: | 200 | spin_unlock_irqrestore(&irq_map_lock, flags); |
277 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
278 | } | 201 | } |
279 | 202 | ||
280 | EXPORT_SYMBOL(free_irq); | ||
281 | 203 | ||
282 | /* | 204 | /* /proc/interrupts printing */ |
283 | * This is called when we want to synchronize with | 205 | int arch_show_interrupts(struct seq_file *p, int prec) |
284 | * interrupts. We may for example tell a device to | ||
285 | * stop sending interrupts: but to make sure there | ||
286 | * are no interrupts that are executing on another | ||
287 | * CPU we need to call this function. | ||
288 | */ | ||
289 | #ifdef CONFIG_SMP | ||
290 | void synchronize_irq(unsigned int irq) | ||
291 | { | 206 | { |
292 | unsigned int cpu_irq; | 207 | int j; |
293 | |||
294 | cpu_irq = irq & (NR_IRQS - 1); | ||
295 | while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS) | ||
296 | cpu_relax(); | ||
297 | } | ||
298 | EXPORT_SYMBOL(synchronize_irq); | ||
299 | #endif /* SMP */ | ||
300 | 208 | ||
301 | void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) | 209 | #ifdef CONFIG_SMP |
302 | { | 210 | seq_printf(p, "RES: "); |
303 | int i; | 211 | for_each_online_cpu(j) |
304 | struct irqaction * action; | 212 | seq_printf(p, "%10u ", cpu_data(j).irq_resched_count); |
305 | unsigned int cpu_irq; | 213 | seq_printf(p, " IPI rescheduling interrupts\n"); |
306 | 214 | seq_printf(p, "CAL: "); | |
307 | cpu_irq = irq & (NR_IRQS - 1); | 215 | for_each_online_cpu(j) |
308 | action = sparc_irq[cpu_irq].action; | 216 | seq_printf(p, "%10u ", cpu_data(j).irq_call_count); |
309 | 217 | seq_printf(p, " IPI function call interrupts\n"); | |
310 | printk("IO device interrupt, irq = %d\n", irq); | 218 | #endif |
311 | printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, | 219 | seq_printf(p, "NMI: "); |
312 | regs->npc, regs->u_regs[14]); | 220 | for_each_online_cpu(j) |
313 | if (action) { | 221 | seq_printf(p, "%10u ", cpu_data(j).counter); |
314 | printk("Expecting: "); | 222 | seq_printf(p, " Non-maskable interrupts\n"); |
315 | for (i = 0; i < 16; i++) | 223 | return 0; |
316 | if (action->handler) | ||
317 | printk("[%s:%d:0x%x] ", action->name, | ||
318 | (int) i, (unsigned int) action->handler); | ||
319 | } | ||
320 | printk("AIEEE\n"); | ||
321 | panic("bogus interrupt received"); | ||
322 | } | 224 | } |
323 | 225 | ||
324 | void handler_irq(int irq, struct pt_regs * regs) | 226 | void handler_irq(unsigned int pil, struct pt_regs *regs) |
325 | { | 227 | { |
326 | struct pt_regs *old_regs; | 228 | struct pt_regs *old_regs; |
327 | struct irqaction * action; | 229 | struct irq_bucket *p; |
328 | int cpu = smp_processor_id(); | ||
329 | #ifdef CONFIG_SMP | ||
330 | extern void smp4m_irq_rotate(int cpu); | ||
331 | #endif | ||
332 | 230 | ||
231 | BUG_ON(pil > 15); | ||
333 | old_regs = set_irq_regs(regs); | 232 | old_regs = set_irq_regs(regs); |
334 | irq_enter(); | 233 | irq_enter(); |
335 | disable_pil_irq(irq); | 234 | |
336 | #ifdef CONFIG_SMP | 235 | p = irq_map[pil]; |
337 | /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ | 236 | while (p) { |
338 | if((sparc_cpu_model==sun4m) && (irq < 10)) | 237 | struct irq_bucket *next = p->next; |
339 | smp4m_irq_rotate(cpu); | 238 | |
340 | #endif | 239 | generic_handle_irq(p->irq); |
341 | action = sparc_irq[irq].action; | 240 | p = next; |
342 | sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS; | 241 | } |
343 | kstat_cpu(cpu).irqs[irq]++; | ||
344 | do { | ||
345 | if (!action || !action->handler) | ||
346 | unexpected_irq(irq, NULL, regs); | ||
347 | action->handler(irq, action->dev_id); | ||
348 | action = action->next; | ||
349 | } while (action); | ||
350 | sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS; | ||
351 | enable_pil_irq(irq); | ||
352 | irq_exit(); | 242 | irq_exit(); |
353 | set_irq_regs(old_regs); | 243 | set_irq_regs(old_regs); |
354 | } | 244 | } |
355 | 245 | ||
356 | #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) | 246 | #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) |
247 | static unsigned int floppy_irq; | ||
357 | 248 | ||
358 | /* Fast IRQs on the Sparc can only have one routine attached to them, | 249 | int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler) |
359 | * thus no sharing possible. | ||
360 | */ | ||
361 | static int request_fast_irq(unsigned int irq, | ||
362 | void (*handler)(void), | ||
363 | unsigned long irqflags, const char *devname) | ||
364 | { | 250 | { |
365 | struct irqaction *action; | ||
366 | unsigned long flags; | ||
367 | unsigned int cpu_irq; | 251 | unsigned int cpu_irq; |
368 | int ret; | 252 | int err; |
369 | #ifdef CONFIG_SMP | 253 | |
254 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON | ||
370 | struct tt_entry *trap_table; | 255 | struct tt_entry *trap_table; |
371 | extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3; | ||
372 | #endif | 256 | #endif |
373 | |||
374 | cpu_irq = irq & (NR_IRQS - 1); | ||
375 | if(cpu_irq > 14) { | ||
376 | ret = -EINVAL; | ||
377 | goto out; | ||
378 | } | ||
379 | if(!handler) { | ||
380 | ret = -EINVAL; | ||
381 | goto out; | ||
382 | } | ||
383 | 257 | ||
384 | spin_lock_irqsave(&irq_action_lock, flags); | 258 | err = request_irq(irq, irq_handler, 0, "floppy", NULL); |
259 | if (err) | ||
260 | return -1; | ||
385 | 261 | ||
386 | action = sparc_irq[cpu_irq].action; | 262 | /* Save for later use in floppy interrupt handler */ |
387 | if(action) { | 263 | floppy_irq = irq; |
388 | if(action->flags & IRQF_SHARED) | ||
389 | panic("Trying to register fast irq when already shared.\n"); | ||
390 | if(irqflags & IRQF_SHARED) | ||
391 | panic("Trying to register fast irq as shared.\n"); | ||
392 | 264 | ||
393 | /* Anyway, someone already owns it so cannot be made fast. */ | 265 | cpu_irq = (irq & (NR_IRQS - 1)); |
394 | printk("request_fast_irq: Trying to register yet already owned.\n"); | ||
395 | ret = -EBUSY; | ||
396 | goto out_unlock; | ||
397 | } | ||
398 | |||
399 | /* If this is flagged as statically allocated then we use our | ||
400 | * private struct which is never freed. | ||
401 | */ | ||
402 | if (irqflags & SA_STATIC_ALLOC) { | ||
403 | if (static_irq_count < MAX_STATIC_ALLOC) | ||
404 | action = &static_irqaction[static_irq_count++]; | ||
405 | else | ||
406 | printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", | ||
407 | irq, devname); | ||
408 | } | ||
409 | |||
410 | if (action == NULL) | ||
411 | action = kmalloc(sizeof(struct irqaction), | ||
412 | GFP_ATOMIC); | ||
413 | |||
414 | if (!action) { | ||
415 | ret = -ENOMEM; | ||
416 | goto out_unlock; | ||
417 | } | ||
418 | 266 | ||
419 | /* Dork with trap table if we get this far. */ | 267 | /* Dork with trap table if we get this far. */ |
420 | #define INSTANTIATE(table) \ | 268 | #define INSTANTIATE(table) \ |
421 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \ | 269 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \ |
422 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \ | 270 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \ |
423 | SPARC_BRANCH((unsigned long) handler, \ | 271 | SPARC_BRANCH((unsigned long) floppy_hardint, \ |
424 | (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\ | 272 | (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\ |
425 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \ | 273 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \ |
426 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP; | 274 | table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP; |
427 | 275 | ||
428 | INSTANTIATE(sparc_ttable) | 276 | INSTANTIATE(sparc_ttable) |
429 | #ifdef CONFIG_SMP | 277 | #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON |
430 | trap_table = &trapbase_cpu1; INSTANTIATE(trap_table) | 278 | trap_table = &trapbase_cpu1; |
431 | trap_table = &trapbase_cpu2; INSTANTIATE(trap_table) | 279 | INSTANTIATE(trap_table) |
432 | trap_table = &trapbase_cpu3; INSTANTIATE(trap_table) | 280 | trap_table = &trapbase_cpu2; |
281 | INSTANTIATE(trap_table) | ||
282 | trap_table = &trapbase_cpu3; | ||
283 | INSTANTIATE(trap_table) | ||
433 | #endif | 284 | #endif |
434 | #undef INSTANTIATE | 285 | #undef INSTANTIATE |
435 | /* | 286 | /* |
@@ -438,24 +289,12 @@ static int request_fast_irq(unsigned int irq, | |||
438 | * writing we have no CPU-neutral interface to fine-grained flushes. | 289 | * writing we have no CPU-neutral interface to fine-grained flushes. |
439 | */ | 290 | */ |
440 | flush_cache_all(); | 291 | flush_cache_all(); |
441 | 292 | return 0; | |
442 | action->flags = irqflags; | ||
443 | action->name = devname; | ||
444 | action->dev_id = NULL; | ||
445 | action->next = NULL; | ||
446 | |||
447 | sparc_irq[cpu_irq].action = action; | ||
448 | |||
449 | __enable_irq(irq); | ||
450 | |||
451 | ret = 0; | ||
452 | out_unlock: | ||
453 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
454 | out: | ||
455 | return ret; | ||
456 | } | 293 | } |
294 | EXPORT_SYMBOL(sparc_floppy_request_irq); | ||
457 | 295 | ||
458 | /* These variables are used to access state from the assembler | 296 | /* |
297 | * These variables are used to access state from the assembler | ||
459 | * interrupt handler, floppy_hardint, so we cannot put these in | 298 | * interrupt handler, floppy_hardint, so we cannot put these in |
460 | * the floppy driver image because that would not work in the | 299 | * the floppy driver image because that would not work in the |
461 | * modular case. | 300 | * modular case. |
@@ -478,155 +317,23 @@ EXPORT_SYMBOL(pdma_base); | |||
478 | unsigned long pdma_areasize; | 317 | unsigned long pdma_areasize; |
479 | EXPORT_SYMBOL(pdma_areasize); | 318 | EXPORT_SYMBOL(pdma_areasize); |
480 | 319 | ||
481 | extern void floppy_hardint(void); | 320 | /* Use the generic irq support to call floppy_interrupt |
482 | 321 | * which was setup using request_irq() in sparc_floppy_request_irq(). | |
483 | static irq_handler_t floppy_irq_handler; | 322 | * We only have one floppy interrupt so we do not need to check |
484 | 323 | * for additional handlers being wired up by irq_link() | |
324 | */ | ||
485 | void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) | 325 | void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) |
486 | { | 326 | { |
487 | struct pt_regs *old_regs; | 327 | struct pt_regs *old_regs; |
488 | int cpu = smp_processor_id(); | ||
489 | 328 | ||
490 | old_regs = set_irq_regs(regs); | 329 | old_regs = set_irq_regs(regs); |
491 | disable_pil_irq(irq); | ||
492 | irq_enter(); | 330 | irq_enter(); |
493 | kstat_cpu(cpu).irqs[irq]++; | 331 | generic_handle_irq(floppy_irq); |
494 | floppy_irq_handler(irq, dev_id); | ||
495 | irq_exit(); | 332 | irq_exit(); |
496 | enable_pil_irq(irq); | ||
497 | set_irq_regs(old_regs); | 333 | set_irq_regs(old_regs); |
498 | // XXX Eek, it's totally changed with preempt_count() and such | ||
499 | // if (softirq_pending(cpu)) | ||
500 | // do_softirq(); | ||
501 | } | 334 | } |
502 | |||
503 | int sparc_floppy_request_irq(int irq, unsigned long flags, | ||
504 | irq_handler_t irq_handler) | ||
505 | { | ||
506 | floppy_irq_handler = irq_handler; | ||
507 | return request_fast_irq(irq, floppy_hardint, flags, "floppy"); | ||
508 | } | ||
509 | EXPORT_SYMBOL(sparc_floppy_request_irq); | ||
510 | |||
511 | #endif | 335 | #endif |
512 | 336 | ||
513 | int request_irq(unsigned int irq, | ||
514 | irq_handler_t handler, | ||
515 | unsigned long irqflags, const char * devname, void *dev_id) | ||
516 | { | ||
517 | struct irqaction * action, **actionp; | ||
518 | unsigned long flags; | ||
519 | unsigned int cpu_irq; | ||
520 | int ret; | ||
521 | |||
522 | if (sparc_cpu_model == sun4d) { | ||
523 | extern int sun4d_request_irq(unsigned int, | ||
524 | irq_handler_t , | ||
525 | unsigned long, const char *, void *); | ||
526 | return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); | ||
527 | } | ||
528 | cpu_irq = irq & (NR_IRQS - 1); | ||
529 | if(cpu_irq > 14) { | ||
530 | ret = -EINVAL; | ||
531 | goto out; | ||
532 | } | ||
533 | if (!handler) { | ||
534 | ret = -EINVAL; | ||
535 | goto out; | ||
536 | } | ||
537 | |||
538 | spin_lock_irqsave(&irq_action_lock, flags); | ||
539 | |||
540 | actionp = &sparc_irq[cpu_irq].action; | ||
541 | action = *actionp; | ||
542 | if (action) { | ||
543 | if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) { | ||
544 | ret = -EBUSY; | ||
545 | goto out_unlock; | ||
546 | } | ||
547 | if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { | ||
548 | printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); | ||
549 | ret = -EBUSY; | ||
550 | goto out_unlock; | ||
551 | } | ||
552 | for ( ; action; action = *actionp) | ||
553 | actionp = &action->next; | ||
554 | } | ||
555 | |||
556 | /* If this is flagged as statically allocated then we use our | ||
557 | * private struct which is never freed. | ||
558 | */ | ||
559 | if (irqflags & SA_STATIC_ALLOC) { | ||
560 | if (static_irq_count < MAX_STATIC_ALLOC) | ||
561 | action = &static_irqaction[static_irq_count++]; | ||
562 | else | ||
563 | printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); | ||
564 | } | ||
565 | |||
566 | if (action == NULL) | ||
567 | action = kmalloc(sizeof(struct irqaction), | ||
568 | GFP_ATOMIC); | ||
569 | |||
570 | if (!action) { | ||
571 | ret = -ENOMEM; | ||
572 | goto out_unlock; | ||
573 | } | ||
574 | |||
575 | action->handler = handler; | ||
576 | action->flags = irqflags; | ||
577 | action->name = devname; | ||
578 | action->next = NULL; | ||
579 | action->dev_id = dev_id; | ||
580 | |||
581 | *actionp = action; | ||
582 | |||
583 | __enable_irq(irq); | ||
584 | |||
585 | ret = 0; | ||
586 | out_unlock: | ||
587 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
588 | out: | ||
589 | return ret; | ||
590 | } | ||
591 | |||
592 | EXPORT_SYMBOL(request_irq); | ||
593 | |||
594 | void disable_irq_nosync(unsigned int irq) | ||
595 | { | ||
596 | __disable_irq(irq); | ||
597 | } | ||
598 | EXPORT_SYMBOL(disable_irq_nosync); | ||
599 | |||
600 | void disable_irq(unsigned int irq) | ||
601 | { | ||
602 | __disable_irq(irq); | ||
603 | } | ||
604 | EXPORT_SYMBOL(disable_irq); | ||
605 | |||
606 | void enable_irq(unsigned int irq) | ||
607 | { | ||
608 | __enable_irq(irq); | ||
609 | } | ||
610 | |||
611 | EXPORT_SYMBOL(enable_irq); | ||
612 | |||
613 | /* We really don't need these at all on the Sparc. We only have | ||
614 | * stubs here because they are exported to modules. | ||
615 | */ | ||
616 | unsigned long probe_irq_on(void) | ||
617 | { | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | EXPORT_SYMBOL(probe_irq_on); | ||
622 | |||
623 | int probe_irq_off(unsigned long mask) | ||
624 | { | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | EXPORT_SYMBOL(probe_irq_off); | ||
629 | |||
630 | /* djhr | 337 | /* djhr |
631 | * This could probably be made indirect too and assigned in the CPU | 338 | * This could probably be made indirect too and assigned in the CPU |
632 | * bits of the code. That would be much nicer I think and would also | 339 | * bits of the code. That would be much nicer I think and would also |
@@ -637,27 +344,20 @@ EXPORT_SYMBOL(probe_irq_off); | |||
637 | 344 | ||
638 | void __init init_IRQ(void) | 345 | void __init init_IRQ(void) |
639 | { | 346 | { |
640 | extern void sun4c_init_IRQ( void ); | 347 | switch (sparc_cpu_model) { |
641 | extern void sun4m_init_IRQ( void ); | ||
642 | extern void sun4d_init_IRQ( void ); | ||
643 | |||
644 | switch(sparc_cpu_model) { | ||
645 | case sun4c: | 348 | case sun4c: |
646 | case sun4: | 349 | case sun4: |
647 | sun4c_init_IRQ(); | 350 | sun4c_init_IRQ(); |
648 | break; | 351 | break; |
649 | 352 | ||
650 | case sun4m: | 353 | case sun4m: |
651 | #ifdef CONFIG_PCI | ||
652 | pcic_probe(); | 354 | pcic_probe(); |
653 | if (pcic_present()) { | 355 | if (pcic_present()) |
654 | sun4m_pci_init_IRQ(); | 356 | sun4m_pci_init_IRQ(); |
655 | break; | 357 | else |
656 | } | 358 | sun4m_init_IRQ(); |
657 | #endif | ||
658 | sun4m_init_IRQ(); | ||
659 | break; | 359 | break; |
660 | 360 | ||
661 | case sun4d: | 361 | case sun4d: |
662 | sun4d_init_IRQ(); | 362 | sun4d_init_IRQ(); |
663 | break; | 363 | break; |
@@ -673,9 +373,3 @@ void __init init_IRQ(void) | |||
673 | btfixup(); | 373 | btfixup(); |
674 | } | 374 | } |
675 | 375 | ||
676 | #ifdef CONFIG_PROC_FS | ||
677 | void init_irq_proc(void) | ||
678 | { | ||
679 | /* For now, nothing... */ | ||
680 | } | ||
681 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 830d70a3e20b..4e78862d12fd 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,97 +113,63 @@ 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 | ||
164 | /* | 162 | /* |
165 | * /proc/interrupts printing: | 163 | * /proc/interrupts printing: |
166 | */ | 164 | */ |
167 | 165 | int arch_show_interrupts(struct seq_file *p, int prec) | |
168 | int show_interrupts(struct seq_file *p, void *v) | ||
169 | { | 166 | { |
170 | int i = *(loff_t *) v, j; | 167 | int j; |
171 | struct irqaction * action; | ||
172 | unsigned long flags; | ||
173 | 168 | ||
174 | if (i == 0) { | 169 | seq_printf(p, "NMI: "); |
175 | seq_printf(p, " "); | 170 | for_each_online_cpu(j) |
176 | for_each_online_cpu(j) | 171 | seq_printf(p, "%10u ", cpu_data(j).__nmi_count); |
177 | seq_printf(p, "CPU%d ",j); | 172 | seq_printf(p, " Non-maskable interrupts\n"); |
178 | seq_putc(p, '\n'); | ||
179 | } | ||
180 | |||
181 | if (i < NR_IRQS) { | ||
182 | raw_spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
183 | action = irq_desc[i].action; | ||
184 | if (!action) | ||
185 | goto skip; | ||
186 | seq_printf(p, "%3d: ",i); | ||
187 | #ifndef CONFIG_SMP | ||
188 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
189 | #else | ||
190 | for_each_online_cpu(j) | ||
191 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
192 | #endif | ||
193 | seq_printf(p, " %9s", irq_desc[i].chip->name); | ||
194 | seq_printf(p, " %s", action->name); | ||
195 | |||
196 | for (action=action->next; action; action = action->next) | ||
197 | seq_printf(p, ", %s", action->name); | ||
198 | |||
199 | seq_putc(p, '\n'); | ||
200 | skip: | ||
201 | raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
202 | } else if (i == NR_IRQS) { | ||
203 | seq_printf(p, "NMI: "); | ||
204 | for_each_online_cpu(j) | ||
205 | seq_printf(p, "%10u ", cpu_data(j).__nmi_count); | ||
206 | seq_printf(p, " Non-maskable interrupts\n"); | ||
207 | } | ||
208 | return 0; | 173 | return 0; |
209 | } | 174 | } |
210 | 175 | ||
@@ -253,39 +218,38 @@ struct irq_handler_data { | |||
253 | }; | 218 | }; |
254 | 219 | ||
255 | #ifdef CONFIG_SMP | 220 | #ifdef CONFIG_SMP |
256 | static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity) | 221 | static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity) |
257 | { | 222 | { |
258 | cpumask_t mask; | 223 | cpumask_t mask; |
259 | int cpuid; | 224 | int cpuid; |
260 | 225 | ||
261 | cpumask_copy(&mask, affinity); | 226 | cpumask_copy(&mask, affinity); |
262 | if (cpus_equal(mask, cpu_online_map)) { | 227 | if (cpumask_equal(&mask, cpu_online_mask)) { |
263 | cpuid = map_to_cpu(virt_irq); | 228 | cpuid = map_to_cpu(irq); |
264 | } else { | 229 | } else { |
265 | cpumask_t tmp; | 230 | cpumask_t tmp; |
266 | 231 | ||
267 | cpus_and(tmp, cpu_online_map, mask); | 232 | cpumask_and(&tmp, cpu_online_mask, &mask); |
268 | cpuid = cpus_empty(tmp) ? map_to_cpu(virt_irq) : first_cpu(tmp); | 233 | cpuid = cpumask_empty(&tmp) ? map_to_cpu(irq) : cpumask_first(&tmp); |
269 | } | 234 | } |
270 | 235 | ||
271 | return cpuid; | 236 | return cpuid; |
272 | } | 237 | } |
273 | #else | 238 | #else |
274 | #define irq_choose_cpu(virt_irq, affinity) \ | 239 | #define irq_choose_cpu(irq, affinity) \ |
275 | real_hard_smp_processor_id() | 240 | real_hard_smp_processor_id() |
276 | #endif | 241 | #endif |
277 | 242 | ||
278 | static void sun4u_irq_enable(unsigned int virt_irq) | 243 | static void sun4u_irq_enable(struct irq_data *data) |
279 | { | 244 | { |
280 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 245 | struct irq_handler_data *handler_data = data->handler_data; |
281 | 246 | ||
282 | if (likely(data)) { | 247 | if (likely(handler_data)) { |
283 | unsigned long cpuid, imap, val; | 248 | unsigned long cpuid, imap, val; |
284 | unsigned int tid; | 249 | unsigned int tid; |
285 | 250 | ||
286 | cpuid = irq_choose_cpu(virt_irq, | 251 | cpuid = irq_choose_cpu(data->irq, data->affinity); |
287 | irq_desc[virt_irq].affinity); | 252 | imap = handler_data->imap; |
288 | imap = data->imap; | ||
289 | 253 | ||
290 | tid = sun4u_compute_tid(imap, cpuid); | 254 | tid = sun4u_compute_tid(imap, cpuid); |
291 | 255 | ||
@@ -294,21 +258,21 @@ static void sun4u_irq_enable(unsigned int virt_irq) | |||
294 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); | 258 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); |
295 | val |= tid | IMAP_VALID; | 259 | val |= tid | IMAP_VALID; |
296 | upa_writeq(val, imap); | 260 | upa_writeq(val, imap); |
297 | upa_writeq(ICLR_IDLE, data->iclr); | 261 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
298 | } | 262 | } |
299 | } | 263 | } |
300 | 264 | ||
301 | static int sun4u_set_affinity(unsigned int virt_irq, | 265 | static int sun4u_set_affinity(struct irq_data *data, |
302 | const struct cpumask *mask) | 266 | const struct cpumask *mask, bool force) |
303 | { | 267 | { |
304 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 268 | struct irq_handler_data *handler_data = data->handler_data; |
305 | 269 | ||
306 | if (likely(data)) { | 270 | if (likely(handler_data)) { |
307 | unsigned long cpuid, imap, val; | 271 | unsigned long cpuid, imap, val; |
308 | unsigned int tid; | 272 | unsigned int tid; |
309 | 273 | ||
310 | cpuid = irq_choose_cpu(virt_irq, mask); | 274 | cpuid = irq_choose_cpu(data->irq, mask); |
311 | imap = data->imap; | 275 | imap = handler_data->imap; |
312 | 276 | ||
313 | tid = sun4u_compute_tid(imap, cpuid); | 277 | tid = sun4u_compute_tid(imap, cpuid); |
314 | 278 | ||
@@ -317,7 +281,7 @@ static int sun4u_set_affinity(unsigned int virt_irq, | |||
317 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); | 281 | IMAP_AID_SAFARI | IMAP_NID_SAFARI); |
318 | val |= tid | IMAP_VALID; | 282 | val |= tid | IMAP_VALID; |
319 | upa_writeq(val, imap); | 283 | upa_writeq(val, imap); |
320 | upa_writeq(ICLR_IDLE, data->iclr); | 284 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
321 | } | 285 | } |
322 | 286 | ||
323 | return 0; | 287 | return 0; |
@@ -340,27 +304,22 @@ static int sun4u_set_affinity(unsigned int virt_irq, | |||
340 | * sees that, it also hooks up a default ->shutdown method which | 304 | * sees that, it also hooks up a default ->shutdown method which |
341 | * invokes ->mask() which we do not want. See irq_chip_set_defaults(). | 305 | * invokes ->mask() which we do not want. See irq_chip_set_defaults(). |
342 | */ | 306 | */ |
343 | static void sun4u_irq_disable(unsigned int virt_irq) | 307 | static void sun4u_irq_disable(struct irq_data *data) |
344 | { | 308 | { |
345 | } | 309 | } |
346 | 310 | ||
347 | static void sun4u_irq_eoi(unsigned int virt_irq) | 311 | static void sun4u_irq_eoi(struct irq_data *data) |
348 | { | 312 | { |
349 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 313 | struct irq_handler_data *handler_data = data->handler_data; |
350 | struct irq_desc *desc = irq_desc + virt_irq; | ||
351 | 314 | ||
352 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 315 | if (likely(handler_data)) |
353 | return; | 316 | upa_writeq(ICLR_IDLE, handler_data->iclr); |
354 | |||
355 | if (likely(data)) | ||
356 | upa_writeq(ICLR_IDLE, data->iclr); | ||
357 | } | 317 | } |
358 | 318 | ||
359 | static void sun4v_irq_enable(unsigned int virt_irq) | 319 | static void sun4v_irq_enable(struct irq_data *data) |
360 | { | 320 | { |
361 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 321 | unsigned int ino = irq_table[data->irq].dev_ino; |
362 | unsigned long cpuid = irq_choose_cpu(virt_irq, | 322 | unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity); |
363 | irq_desc[virt_irq].affinity); | ||
364 | int err; | 323 | int err; |
365 | 324 | ||
366 | err = sun4v_intr_settarget(ino, cpuid); | 325 | err = sun4v_intr_settarget(ino, cpuid); |
@@ -377,11 +336,11 @@ static void sun4v_irq_enable(unsigned int virt_irq) | |||
377 | ino, err); | 336 | ino, err); |
378 | } | 337 | } |
379 | 338 | ||
380 | static int sun4v_set_affinity(unsigned int virt_irq, | 339 | static int sun4v_set_affinity(struct irq_data *data, |
381 | const struct cpumask *mask) | 340 | const struct cpumask *mask, bool force) |
382 | { | 341 | { |
383 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 342 | unsigned int ino = irq_table[data->irq].dev_ino; |
384 | unsigned long cpuid = irq_choose_cpu(virt_irq, mask); | 343 | unsigned long cpuid = irq_choose_cpu(data->irq, mask); |
385 | int err; | 344 | int err; |
386 | 345 | ||
387 | err = sun4v_intr_settarget(ino, cpuid); | 346 | err = sun4v_intr_settarget(ino, cpuid); |
@@ -392,9 +351,9 @@ static int sun4v_set_affinity(unsigned int virt_irq, | |||
392 | return 0; | 351 | return 0; |
393 | } | 352 | } |
394 | 353 | ||
395 | static void sun4v_irq_disable(unsigned int virt_irq) | 354 | static void sun4v_irq_disable(struct irq_data *data) |
396 | { | 355 | { |
397 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 356 | unsigned int ino = irq_table[data->irq].dev_ino; |
398 | int err; | 357 | int err; |
399 | 358 | ||
400 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); | 359 | err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); |
@@ -403,30 +362,26 @@ static void sun4v_irq_disable(unsigned int virt_irq) | |||
403 | "err(%d)\n", ino, err); | 362 | "err(%d)\n", ino, err); |
404 | } | 363 | } |
405 | 364 | ||
406 | static void sun4v_irq_eoi(unsigned int virt_irq) | 365 | static void sun4v_irq_eoi(struct irq_data *data) |
407 | { | 366 | { |
408 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 367 | unsigned int ino = irq_table[data->irq].dev_ino; |
409 | struct irq_desc *desc = irq_desc + virt_irq; | ||
410 | int err; | 368 | int err; |
411 | 369 | ||
412 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
413 | return; | ||
414 | |||
415 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); | 370 | err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); |
416 | if (err != HV_EOK) | 371 | if (err != HV_EOK) |
417 | printk(KERN_ERR "sun4v_intr_setstate(%x): " | 372 | printk(KERN_ERR "sun4v_intr_setstate(%x): " |
418 | "err(%d)\n", ino, err); | 373 | "err(%d)\n", ino, err); |
419 | } | 374 | } |
420 | 375 | ||
421 | static void sun4v_virq_enable(unsigned int virt_irq) | 376 | static void sun4v_virq_enable(struct irq_data *data) |
422 | { | 377 | { |
423 | unsigned long cpuid, dev_handle, dev_ino; | 378 | unsigned long cpuid, dev_handle, dev_ino; |
424 | int err; | 379 | int err; |
425 | 380 | ||
426 | cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity); | 381 | cpuid = irq_choose_cpu(data->irq, data->affinity); |
427 | 382 | ||
428 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 383 | dev_handle = irq_table[data->irq].dev_handle; |
429 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 384 | dev_ino = irq_table[data->irq].dev_ino; |
430 | 385 | ||
431 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 386 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
432 | if (err != HV_EOK) | 387 | if (err != HV_EOK) |
@@ -447,16 +402,16 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
447 | dev_handle, dev_ino, err); | 402 | dev_handle, dev_ino, err); |
448 | } | 403 | } |
449 | 404 | ||
450 | static int sun4v_virt_set_affinity(unsigned int virt_irq, | 405 | static int sun4v_virt_set_affinity(struct irq_data *data, |
451 | const struct cpumask *mask) | 406 | const struct cpumask *mask, bool force) |
452 | { | 407 | { |
453 | unsigned long cpuid, dev_handle, dev_ino; | 408 | unsigned long cpuid, dev_handle, dev_ino; |
454 | int err; | 409 | int err; |
455 | 410 | ||
456 | cpuid = irq_choose_cpu(virt_irq, mask); | 411 | cpuid = irq_choose_cpu(data->irq, mask); |
457 | 412 | ||
458 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 413 | dev_handle = irq_table[data->irq].dev_handle; |
459 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 414 | dev_ino = irq_table[data->irq].dev_ino; |
460 | 415 | ||
461 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 416 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
462 | if (err != HV_EOK) | 417 | if (err != HV_EOK) |
@@ -467,13 +422,13 @@ static int sun4v_virt_set_affinity(unsigned int virt_irq, | |||
467 | return 0; | 422 | return 0; |
468 | } | 423 | } |
469 | 424 | ||
470 | static void sun4v_virq_disable(unsigned int virt_irq) | 425 | static void sun4v_virq_disable(struct irq_data *data) |
471 | { | 426 | { |
472 | unsigned long dev_handle, dev_ino; | 427 | unsigned long dev_handle, dev_ino; |
473 | int err; | 428 | int err; |
474 | 429 | ||
475 | dev_handle = virt_irq_table[virt_irq].dev_handle; | 430 | dev_handle = irq_table[data->irq].dev_handle; |
476 | dev_ino = virt_irq_table[virt_irq].dev_ino; | 431 | dev_ino = irq_table[data->irq].dev_ino; |
477 | 432 | ||
478 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 433 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
479 | HV_INTR_DISABLED); | 434 | HV_INTR_DISABLED); |
@@ -483,17 +438,13 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
483 | dev_handle, dev_ino, err); | 438 | dev_handle, dev_ino, err); |
484 | } | 439 | } |
485 | 440 | ||
486 | static void sun4v_virq_eoi(unsigned int virt_irq) | 441 | static void sun4v_virq_eoi(struct irq_data *data) |
487 | { | 442 | { |
488 | struct irq_desc *desc = irq_desc + virt_irq; | ||
489 | unsigned long dev_handle, dev_ino; | 443 | unsigned long dev_handle, dev_ino; |
490 | int err; | 444 | int err; |
491 | 445 | ||
492 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 446 | dev_handle = irq_table[data->irq].dev_handle; |
493 | return; | 447 | dev_ino = irq_table[data->irq].dev_ino; |
494 | |||
495 | dev_handle = virt_irq_table[virt_irq].dev_handle; | ||
496 | dev_ino = virt_irq_table[virt_irq].dev_ino; | ||
497 | 448 | ||
498 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 449 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
499 | HV_INTR_STATE_IDLE); | 450 | HV_INTR_STATE_IDLE); |
@@ -504,132 +455,128 @@ static void sun4v_virq_eoi(unsigned int virt_irq) | |||
504 | } | 455 | } |
505 | 456 | ||
506 | static struct irq_chip sun4u_irq = { | 457 | static struct irq_chip sun4u_irq = { |
507 | .name = "sun4u", | 458 | .name = "sun4u", |
508 | .enable = sun4u_irq_enable, | 459 | .irq_enable = sun4u_irq_enable, |
509 | .disable = sun4u_irq_disable, | 460 | .irq_disable = sun4u_irq_disable, |
510 | .eoi = sun4u_irq_eoi, | 461 | .irq_eoi = sun4u_irq_eoi, |
511 | .set_affinity = sun4u_set_affinity, | 462 | .irq_set_affinity = sun4u_set_affinity, |
463 | .flags = IRQCHIP_EOI_IF_HANDLED, | ||
512 | }; | 464 | }; |
513 | 465 | ||
514 | static struct irq_chip sun4v_irq = { | 466 | static struct irq_chip sun4v_irq = { |
515 | .name = "sun4v", | 467 | .name = "sun4v", |
516 | .enable = sun4v_irq_enable, | 468 | .irq_enable = sun4v_irq_enable, |
517 | .disable = sun4v_irq_disable, | 469 | .irq_disable = sun4v_irq_disable, |
518 | .eoi = sun4v_irq_eoi, | 470 | .irq_eoi = sun4v_irq_eoi, |
519 | .set_affinity = sun4v_set_affinity, | 471 | .irq_set_affinity = sun4v_set_affinity, |
472 | .flags = IRQCHIP_EOI_IF_HANDLED, | ||
520 | }; | 473 | }; |
521 | 474 | ||
522 | static struct irq_chip sun4v_virq = { | 475 | static struct irq_chip sun4v_virq = { |
523 | .name = "vsun4v", | 476 | .name = "vsun4v", |
524 | .enable = sun4v_virq_enable, | 477 | .irq_enable = sun4v_virq_enable, |
525 | .disable = sun4v_virq_disable, | 478 | .irq_disable = sun4v_virq_disable, |
526 | .eoi = sun4v_virq_eoi, | 479 | .irq_eoi = sun4v_virq_eoi, |
527 | .set_affinity = sun4v_virt_set_affinity, | 480 | .irq_set_affinity = sun4v_virt_set_affinity, |
481 | .flags = IRQCHIP_EOI_IF_HANDLED, | ||
528 | }; | 482 | }; |
529 | 483 | ||
530 | static void pre_flow_handler(unsigned int virt_irq, | 484 | static void pre_flow_handler(struct irq_data *d) |
531 | struct irq_desc *desc) | ||
532 | { | 485 | { |
533 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 486 | struct irq_handler_data *handler_data = irq_data_get_irq_handler_data(d); |
534 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 487 | unsigned int ino = irq_table[d->irq].dev_ino; |
535 | 488 | ||
536 | data->pre_handler(ino, data->arg1, data->arg2); | 489 | handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2); |
537 | |||
538 | handle_fasteoi_irq(virt_irq, desc); | ||
539 | } | 490 | } |
540 | 491 | ||
541 | void irq_install_pre_handler(int virt_irq, | 492 | void irq_install_pre_handler(int irq, |
542 | void (*func)(unsigned int, void *, void *), | 493 | void (*func)(unsigned int, void *, void *), |
543 | void *arg1, void *arg2) | 494 | void *arg1, void *arg2) |
544 | { | 495 | { |
545 | struct irq_handler_data *data = get_irq_chip_data(virt_irq); | 496 | struct irq_handler_data *handler_data = irq_get_handler_data(irq); |
546 | struct irq_desc *desc = irq_desc + virt_irq; | ||
547 | 497 | ||
548 | data->pre_handler = func; | 498 | handler_data->pre_handler = func; |
549 | data->arg1 = arg1; | 499 | handler_data->arg1 = arg1; |
550 | data->arg2 = arg2; | 500 | handler_data->arg2 = arg2; |
551 | 501 | ||
552 | desc->handle_irq = pre_flow_handler; | 502 | __irq_set_preflow_handler(irq, pre_flow_handler); |
553 | } | 503 | } |
554 | 504 | ||
555 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) | 505 | unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) |
556 | { | 506 | { |
557 | struct ino_bucket *bucket; | 507 | struct ino_bucket *bucket; |
558 | struct irq_handler_data *data; | 508 | struct irq_handler_data *handler_data; |
559 | unsigned int virt_irq; | 509 | unsigned int irq; |
560 | int ino; | 510 | int ino; |
561 | 511 | ||
562 | BUG_ON(tlb_type == hypervisor); | 512 | BUG_ON(tlb_type == hypervisor); |
563 | 513 | ||
564 | ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; | 514 | ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; |
565 | bucket = &ivector_table[ino]; | 515 | bucket = &ivector_table[ino]; |
566 | virt_irq = bucket_get_virt_irq(__pa(bucket)); | 516 | irq = bucket_get_irq(__pa(bucket)); |
567 | if (!virt_irq) { | 517 | if (!irq) { |
568 | virt_irq = virt_irq_alloc(0, ino); | 518 | irq = irq_alloc(0, ino); |
569 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 519 | bucket_set_irq(__pa(bucket), irq); |
570 | set_irq_chip_and_handler_name(virt_irq, | 520 | irq_set_chip_and_handler_name(irq, &sun4u_irq, |
571 | &sun4u_irq, | 521 | handle_fasteoi_irq, "IVEC"); |
572 | handle_fasteoi_irq, | ||
573 | "IVEC"); | ||
574 | } | 522 | } |
575 | 523 | ||
576 | data = get_irq_chip_data(virt_irq); | 524 | handler_data = irq_get_handler_data(irq); |
577 | if (unlikely(data)) | 525 | if (unlikely(handler_data)) |
578 | goto out; | 526 | goto out; |
579 | 527 | ||
580 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 528 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
581 | if (unlikely(!data)) { | 529 | if (unlikely(!handler_data)) { |
582 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); | 530 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
583 | prom_halt(); | 531 | prom_halt(); |
584 | } | 532 | } |
585 | set_irq_chip_data(virt_irq, data); | 533 | irq_set_handler_data(irq, handler_data); |
586 | 534 | ||
587 | data->imap = imap; | 535 | handler_data->imap = imap; |
588 | data->iclr = iclr; | 536 | handler_data->iclr = iclr; |
589 | 537 | ||
590 | out: | 538 | out: |
591 | return virt_irq; | 539 | return irq; |
592 | } | 540 | } |
593 | 541 | ||
594 | static unsigned int sun4v_build_common(unsigned long sysino, | 542 | static unsigned int sun4v_build_common(unsigned long sysino, |
595 | struct irq_chip *chip) | 543 | struct irq_chip *chip) |
596 | { | 544 | { |
597 | struct ino_bucket *bucket; | 545 | struct ino_bucket *bucket; |
598 | struct irq_handler_data *data; | 546 | struct irq_handler_data *handler_data; |
599 | unsigned int virt_irq; | 547 | unsigned int irq; |
600 | 548 | ||
601 | BUG_ON(tlb_type != hypervisor); | 549 | BUG_ON(tlb_type != hypervisor); |
602 | 550 | ||
603 | bucket = &ivector_table[sysino]; | 551 | bucket = &ivector_table[sysino]; |
604 | virt_irq = bucket_get_virt_irq(__pa(bucket)); | 552 | irq = bucket_get_irq(__pa(bucket)); |
605 | if (!virt_irq) { | 553 | if (!irq) { |
606 | virt_irq = virt_irq_alloc(0, sysino); | 554 | irq = irq_alloc(0, sysino); |
607 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 555 | bucket_set_irq(__pa(bucket), irq); |
608 | set_irq_chip_and_handler_name(virt_irq, chip, | 556 | irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq, |
609 | handle_fasteoi_irq, | ||
610 | "IVEC"); | 557 | "IVEC"); |
611 | } | 558 | } |
612 | 559 | ||
613 | data = get_irq_chip_data(virt_irq); | 560 | handler_data = irq_get_handler_data(irq); |
614 | if (unlikely(data)) | 561 | if (unlikely(handler_data)) |
615 | goto out; | 562 | goto out; |
616 | 563 | ||
617 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 564 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
618 | if (unlikely(!data)) { | 565 | if (unlikely(!handler_data)) { |
619 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); | 566 | prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); |
620 | prom_halt(); | 567 | prom_halt(); |
621 | } | 568 | } |
622 | set_irq_chip_data(virt_irq, data); | 569 | irq_set_handler_data(irq, handler_data); |
623 | 570 | ||
624 | /* Catch accidental accesses to these things. IMAP/ICLR handling | 571 | /* Catch accidental accesses to these things. IMAP/ICLR handling |
625 | * is done by hypervisor calls on sun4v platforms, not by direct | 572 | * is done by hypervisor calls on sun4v platforms, not by direct |
626 | * register accesses. | 573 | * register accesses. |
627 | */ | 574 | */ |
628 | data->imap = ~0UL; | 575 | handler_data->imap = ~0UL; |
629 | data->iclr = ~0UL; | 576 | handler_data->iclr = ~0UL; |
630 | 577 | ||
631 | out: | 578 | out: |
632 | return virt_irq; | 579 | return irq; |
633 | } | 580 | } |
634 | 581 | ||
635 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | 582 | unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) |
@@ -641,11 +588,10 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | |||
641 | 588 | ||
642 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 589 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) |
643 | { | 590 | { |
644 | struct irq_handler_data *data; | 591 | struct irq_handler_data *handler_data; |
645 | unsigned long hv_err, cookie; | 592 | unsigned long hv_err, cookie; |
646 | struct ino_bucket *bucket; | 593 | struct ino_bucket *bucket; |
647 | struct irq_desc *desc; | 594 | unsigned int irq; |
648 | unsigned int virt_irq; | ||
649 | 595 | ||
650 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); | 596 | bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); |
651 | if (unlikely(!bucket)) | 597 | if (unlikely(!bucket)) |
@@ -662,32 +608,29 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
662 | ((unsigned long) bucket + | 608 | ((unsigned long) bucket + |
663 | sizeof(struct ino_bucket))); | 609 | sizeof(struct ino_bucket))); |
664 | 610 | ||
665 | virt_irq = virt_irq_alloc(devhandle, devino); | 611 | irq = irq_alloc(devhandle, devino); |
666 | bucket_set_virt_irq(__pa(bucket), virt_irq); | 612 | bucket_set_irq(__pa(bucket), irq); |
667 | 613 | ||
668 | set_irq_chip_and_handler_name(virt_irq, &sun4v_virq, | 614 | irq_set_chip_and_handler_name(irq, &sun4v_virq, handle_fasteoi_irq, |
669 | handle_fasteoi_irq, | ||
670 | "IVEC"); | 615 | "IVEC"); |
671 | 616 | ||
672 | data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); | 617 | handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); |
673 | if (unlikely(!data)) | 618 | if (unlikely(!handler_data)) |
674 | return 0; | 619 | return 0; |
675 | 620 | ||
676 | /* In order to make the LDC channel startup sequence easier, | 621 | /* In order to make the LDC channel startup sequence easier, |
677 | * especially wrt. locking, we do not let request_irq() enable | 622 | * especially wrt. locking, we do not let request_irq() enable |
678 | * the interrupt. | 623 | * the interrupt. |
679 | */ | 624 | */ |
680 | desc = irq_desc + virt_irq; | 625 | irq_set_status_flags(irq, IRQ_NOAUTOEN); |
681 | desc->status |= IRQ_NOAUTOEN; | 626 | irq_set_handler_data(irq, handler_data); |
682 | |||
683 | set_irq_chip_data(virt_irq, data); | ||
684 | 627 | ||
685 | /* Catch accidental accesses to these things. IMAP/ICLR handling | 628 | /* Catch accidental accesses to these things. IMAP/ICLR handling |
686 | * is done by hypervisor calls on sun4v platforms, not by direct | 629 | * is done by hypervisor calls on sun4v platforms, not by direct |
687 | * register accesses. | 630 | * register accesses. |
688 | */ | 631 | */ |
689 | data->imap = ~0UL; | 632 | handler_data->imap = ~0UL; |
690 | data->iclr = ~0UL; | 633 | handler_data->iclr = ~0UL; |
691 | 634 | ||
692 | cookie = ~__pa(bucket); | 635 | cookie = ~__pa(bucket); |
693 | hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); | 636 | hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); |
@@ -697,30 +640,30 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
697 | prom_halt(); | 640 | prom_halt(); |
698 | } | 641 | } |
699 | 642 | ||
700 | return virt_irq; | 643 | return irq; |
701 | } | 644 | } |
702 | 645 | ||
703 | void ack_bad_irq(unsigned int virt_irq) | 646 | void ack_bad_irq(unsigned int irq) |
704 | { | 647 | { |
705 | unsigned int ino = virt_irq_table[virt_irq].dev_ino; | 648 | unsigned int ino = irq_table[irq].dev_ino; |
706 | 649 | ||
707 | if (!ino) | 650 | if (!ino) |
708 | ino = 0xdeadbeef; | 651 | ino = 0xdeadbeef; |
709 | 652 | ||
710 | printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n", | 653 | printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n", |
711 | ino, virt_irq); | 654 | ino, irq); |
712 | } | 655 | } |
713 | 656 | ||
714 | void *hardirq_stack[NR_CPUS]; | 657 | void *hardirq_stack[NR_CPUS]; |
715 | void *softirq_stack[NR_CPUS]; | 658 | void *softirq_stack[NR_CPUS]; |
716 | 659 | ||
717 | void __irq_entry handler_irq(int irq, struct pt_regs *regs) | 660 | void __irq_entry handler_irq(int pil, struct pt_regs *regs) |
718 | { | 661 | { |
719 | unsigned long pstate, bucket_pa; | 662 | unsigned long pstate, bucket_pa; |
720 | struct pt_regs *old_regs; | 663 | struct pt_regs *old_regs; |
721 | void *orig_sp; | 664 | void *orig_sp; |
722 | 665 | ||
723 | clear_softint(1 << irq); | 666 | clear_softint(1 << pil); |
724 | 667 | ||
725 | old_regs = set_irq_regs(regs); | 668 | old_regs = set_irq_regs(regs); |
726 | irq_enter(); | 669 | irq_enter(); |
@@ -739,18 +682,14 @@ void __irq_entry handler_irq(int irq, struct pt_regs *regs) | |||
739 | orig_sp = set_hardirq_stack(); | 682 | orig_sp = set_hardirq_stack(); |
740 | 683 | ||
741 | while (bucket_pa) { | 684 | while (bucket_pa) { |
742 | struct irq_desc *desc; | ||
743 | unsigned long next_pa; | 685 | unsigned long next_pa; |
744 | unsigned int virt_irq; | 686 | unsigned int irq; |
745 | 687 | ||
746 | next_pa = bucket_get_chain_pa(bucket_pa); | 688 | next_pa = bucket_get_chain_pa(bucket_pa); |
747 | virt_irq = bucket_get_virt_irq(bucket_pa); | 689 | irq = bucket_get_irq(bucket_pa); |
748 | bucket_clear_chain_pa(bucket_pa); | 690 | bucket_clear_chain_pa(bucket_pa); |
749 | 691 | ||
750 | desc = irq_desc + virt_irq; | 692 | generic_handle_irq(irq); |
751 | |||
752 | if (!(desc->status & IRQ_DISABLED)) | ||
753 | desc->handle_irq(virt_irq, desc); | ||
754 | 693 | ||
755 | bucket_pa = next_pa; | 694 | bucket_pa = next_pa; |
756 | } | 695 | } |
@@ -793,16 +732,18 @@ void fixup_irqs(void) | |||
793 | unsigned int irq; | 732 | unsigned int irq; |
794 | 733 | ||
795 | for (irq = 0; irq < NR_IRQS; irq++) { | 734 | for (irq = 0; irq < NR_IRQS; irq++) { |
735 | struct irq_desc *desc = irq_to_desc(irq); | ||
736 | struct irq_data *data = irq_desc_get_irq_data(desc); | ||
796 | unsigned long flags; | 737 | unsigned long flags; |
797 | 738 | ||
798 | raw_spin_lock_irqsave(&irq_desc[irq].lock, flags); | 739 | raw_spin_lock_irqsave(&desc->lock, flags); |
799 | if (irq_desc[irq].action && | 740 | if (desc->action && !irqd_is_per_cpu(data)) { |
800 | !(irq_desc[irq].status & IRQ_PER_CPU)) { | 741 | if (data->chip->irq_set_affinity) |
801 | if (irq_desc[irq].chip->set_affinity) | 742 | data->chip->irq_set_affinity(data, |
802 | irq_desc[irq].chip->set_affinity(irq, | 743 | data->affinity, |
803 | irq_desc[irq].affinity); | 744 | false); |
804 | } | 745 | } |
805 | raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags); | 746 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
806 | } | 747 | } |
807 | 748 | ||
808 | tick_ops->disable_irq(); | 749 | tick_ops->disable_irq(); |
@@ -1040,5 +981,5 @@ void __init init_IRQ(void) | |||
1040 | : "i" (PSTATE_IE) | 981 | : "i" (PSTATE_IE) |
1041 | : "g1"); | 982 | : "g1"); |
1042 | 983 | ||
1043 | irq_desc[0].action = &timer_irq_action; | 984 | irq_to_desc(0)->action = &timer_irq_action; |
1044 | } | 985 | } |
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c new file mode 100644 index 000000000000..ea2dafc93d78 --- /dev/null +++ b/arch/sparc/kernel/jump_label.c | |||
@@ -0,0 +1,47 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/cpu.h> | ||
5 | |||
6 | #include <linux/jump_label.h> | ||
7 | #include <linux/memory.h> | ||
8 | |||
9 | #ifdef HAVE_JUMP_LABEL | ||
10 | |||
11 | void arch_jump_label_transform(struct jump_entry *entry, | ||
12 | enum jump_label_type type) | ||
13 | { | ||
14 | u32 val; | ||
15 | u32 *insn = (u32 *) (unsigned long) entry->code; | ||
16 | |||
17 | if (type == JUMP_LABEL_ENABLE) { | ||
18 | s32 off = (s32)entry->target - (s32)entry->code; | ||
19 | |||
20 | #ifdef CONFIG_SPARC64 | ||
21 | /* ba,pt %xcc, . + (off << 2) */ | ||
22 | val = 0x10680000 | ((u32) off >> 2); | ||
23 | #else | ||
24 | /* ba . + (off << 2) */ | ||
25 | val = 0x10800000 | ((u32) off >> 2); | ||
26 | #endif | ||
27 | } else { | ||
28 | val = 0x01000000; | ||
29 | } | ||
30 | |||
31 | get_online_cpus(); | ||
32 | mutex_lock(&text_mutex); | ||
33 | *insn = val; | ||
34 | flushi(insn); | ||
35 | mutex_unlock(&text_mutex); | ||
36 | put_online_cpus(); | ||
37 | } | ||
38 | |||
39 | void arch_jump_label_text_poke_early(jump_label_t addr) | ||
40 | { | ||
41 | u32 *insn_p = (u32 *) (unsigned long) addr; | ||
42 | |||
43 | *insn_p = 0x01000000; | ||
44 | flushi(insn_p); | ||
45 | } | ||
46 | |||
47 | #endif | ||
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 15d8a3f645c9..6f6544cfa0ef 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h | |||
@@ -3,12 +3,12 @@ | |||
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; | ||
8 | extern const char *sparc_pmu_type; | 9 | extern const char *sparc_pmu_type; |
9 | extern const char *sparc_fpu_type; | ||
10 | |||
11 | extern unsigned int fsr_storage; | 10 | extern unsigned int fsr_storage; |
11 | extern int ncpus_probed; | ||
12 | 12 | ||
13 | #ifdef CONFIG_SPARC32 | 13 | #ifdef CONFIG_SPARC32 |
14 | /* cpu.c */ | 14 | /* cpu.c */ |
@@ -26,6 +26,54 @@ extern int static_irq_count; | |||
26 | extern spinlock_t irq_action_lock; | 26 | extern spinlock_t irq_action_lock; |
27 | 27 | ||
28 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); | 28 | extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs); |
29 | extern void init_IRQ(void); | ||
30 | |||
31 | /* sun4c_irq.c */ | ||
32 | extern void sun4c_init_IRQ(void); | ||
33 | |||
34 | /* sun4m_irq.c */ | ||
35 | extern unsigned int lvl14_resolution; | ||
36 | |||
37 | extern void sun4m_init_IRQ(void); | ||
38 | extern void sun4m_unmask_profile_irq(void); | ||
39 | extern void sun4m_clear_profile_irq(int cpu); | ||
40 | |||
41 | /* sun4d_irq.c */ | ||
42 | extern spinlock_t sun4d_imsk_lock; | ||
43 | |||
44 | extern void sun4d_init_IRQ(void); | ||
45 | extern int sun4d_request_irq(unsigned int irq, | ||
46 | irq_handler_t handler, | ||
47 | unsigned long irqflags, | ||
48 | const char *devname, void *dev_id); | ||
49 | extern int show_sun4d_interrupts(struct seq_file *, void *); | ||
50 | extern void sun4d_distribute_irqs(void); | ||
51 | extern void sun4d_free_irq(unsigned int irq, void *dev_id); | ||
52 | |||
53 | /* head_32.S */ | ||
54 | extern unsigned int t_nmi[]; | ||
55 | extern unsigned int linux_trap_ipi15_sun4d[]; | ||
56 | extern unsigned int linux_trap_ipi15_sun4m[]; | ||
57 | |||
58 | extern struct tt_entry trapbase_cpu1; | ||
59 | extern struct tt_entry trapbase_cpu2; | ||
60 | extern struct tt_entry trapbase_cpu3; | ||
61 | |||
62 | extern char cputypval[]; | ||
63 | |||
64 | /* entry.S */ | ||
65 | extern unsigned long lvl14_save[4]; | ||
66 | extern unsigned int real_irq_entry[]; | ||
67 | extern unsigned int smp4d_ticker[]; | ||
68 | extern unsigned int patchme_maybe_smp_msg[]; | ||
69 | |||
70 | extern void floppy_hardint(void); | ||
71 | |||
72 | /* trampoline_32.S */ | ||
73 | extern int __smp4m_processor_id(void); | ||
74 | extern int __smp4d_processor_id(void); | ||
75 | extern unsigned long sun4m_cpu_startup; | ||
76 | extern unsigned long sun4d_cpu_startup; | ||
29 | 77 | ||
30 | #else /* CONFIG_SPARC32 */ | 78 | #else /* CONFIG_SPARC32 */ |
31 | #endif /* CONFIG_SPARC32 */ | 79 | #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 6a7b4dbc8e09..d17255a2bbac 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -19,51 +19,70 @@ | |||
19 | #include <asm/leon_amba.h> | 19 | #include <asm/leon_amba.h> |
20 | #include <asm/traps.h> | 20 | #include <asm/traps.h> |
21 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
22 | #include <asm/smp.h> | ||
23 | #include <asm/setup.h> | ||
22 | 24 | ||
23 | #include "prom.h" | 25 | #include "prom.h" |
24 | #include "irq.h" | 26 | #include "irq.h" |
25 | 27 | ||
26 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ | 28 | struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ |
27 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ | 29 | struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ |
28 | struct amba_apb_device leon_percpu_timer_dev[16]; | ||
29 | 30 | ||
30 | int leondebug_irq_disable; | 31 | int leondebug_irq_disable; |
31 | int leon_debug_irqout; | 32 | int leon_debug_irqout; |
32 | static int dummy_master_l10_counter; | 33 | static int dummy_master_l10_counter; |
34 | unsigned long amba_system_id; | ||
35 | static DEFINE_SPINLOCK(leon_irq_lock); | ||
33 | 36 | ||
34 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ | 37 | unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ |
38 | unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ | ||
39 | int leon3_ticker_irq; /* Timer ticker IRQ */ | ||
35 | unsigned int sparc_leon_eirq; | 40 | unsigned int sparc_leon_eirq; |
36 | #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) | 41 | #define LEON_IMASK(cpu) (&leon3_irqctrl_regs->mask[cpu]) |
42 | #define LEON_IACK (&leon3_irqctrl_regs->iclear) | ||
43 | #define LEON_DO_ACK_HW 1 | ||
37 | 44 | ||
38 | /* Return the IRQ of the pending IRQ on the extended IRQ controller */ | 45 | /* Return the last ACKed IRQ by the Extended IRQ controller. It has already |
39 | int sparc_leon_eirq_get(int eirq, int cpu) | 46 | * been (automatically) ACKed when the CPU takes the trap. |
47 | */ | ||
48 | static inline unsigned int leon_eirq_get(int cpu) | ||
40 | { | 49 | { |
41 | return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f; | 50 | return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f; |
42 | } | 51 | } |
43 | 52 | ||
44 | irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id) | 53 | /* Handle one or multiple IRQs from the extended interrupt controller */ |
54 | static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc) | ||
45 | { | 55 | { |
46 | printk(KERN_ERR "sparc_leon_eirq_isr: ERROR EXTENDED IRQ\n"); | 56 | unsigned int eirq; |
47 | return IRQ_HANDLED; | 57 | int cpu = sparc_leon3_cpuid(); |
58 | |||
59 | eirq = leon_eirq_get(cpu); | ||
60 | if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ | ||
61 | generic_handle_irq(irq_map[eirq]->irq); | ||
48 | } | 62 | } |
49 | 63 | ||
50 | /* The extended IRQ controller has been found, this function registers it */ | 64 | /* The extended IRQ controller has been found, this function registers it */ |
51 | void sparc_leon_eirq_register(int eirq) | 65 | void leon_eirq_setup(unsigned int eirq) |
52 | { | 66 | { |
53 | int irq; | 67 | unsigned long mask, oldmask; |
54 | 68 | unsigned int veirq; | |
55 | /* Register a "BAD" handler for this interrupt, it should never happen */ | ||
56 | irq = request_irq(eirq, sparc_leon_eirq_isr, | ||
57 | (IRQF_DISABLED | SA_STATIC_ALLOC), "extirq", NULL); | ||
58 | 69 | ||
59 | if (irq) { | 70 | if (eirq < 1 || eirq > 0xf) { |
60 | printk(KERN_ERR | 71 | printk(KERN_ERR "LEON EXT IRQ NUMBER BAD: %d\n", eirq); |
61 | "sparc_leon_eirq_register: unable to attach IRQ%d\n", | 72 | return; |
62 | eirq); | ||
63 | } else { | ||
64 | sparc_leon_eirq = eirq; | ||
65 | } | 73 | } |
66 | 74 | ||
75 | veirq = leon_build_device_irq(eirq, leon_handle_ext_irq, "extirq", 0); | ||
76 | |||
77 | /* | ||
78 | * Unmask the Extended IRQ, the IRQs routed through the Ext-IRQ | ||
79 | * controller have a mask-bit of their own, so this is safe. | ||
80 | */ | ||
81 | irq_link(veirq); | ||
82 | mask = 1 << eirq; | ||
83 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(boot_cpu_id)); | ||
84 | LEON3_BYPASS_STORE_PA(LEON_IMASK(boot_cpu_id), (oldmask | mask)); | ||
85 | sparc_leon_eirq = eirq; | ||
67 | } | 86 | } |
68 | 87 | ||
69 | static inline unsigned long get_irqmask(unsigned int irq) | 88 | static inline unsigned long get_irqmask(unsigned int irq) |
@@ -81,108 +100,327 @@ static inline unsigned long get_irqmask(unsigned int irq) | |||
81 | return mask; | 100 | return mask; |
82 | } | 101 | } |
83 | 102 | ||
84 | static void leon_enable_irq(unsigned int irq_nr) | 103 | #ifdef CONFIG_SMP |
104 | static int irq_choose_cpu(const struct cpumask *affinity) | ||
85 | { | 105 | { |
86 | unsigned long mask, flags; | 106 | cpumask_t mask; |
87 | mask = get_irqmask(irq_nr); | 107 | |
88 | local_irq_save(flags); | 108 | cpus_and(mask, cpu_online_map, *affinity); |
89 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 109 | if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask)) |
90 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); | 110 | return boot_cpu_id; |
91 | local_irq_restore(flags); | 111 | else |
112 | return first_cpu(mask); | ||
113 | } | ||
114 | #else | ||
115 | #define irq_choose_cpu(affinity) boot_cpu_id | ||
116 | #endif | ||
117 | |||
118 | static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest, | ||
119 | bool force) | ||
120 | { | ||
121 | unsigned long mask, oldmask, flags; | ||
122 | int oldcpu, newcpu; | ||
123 | |||
124 | mask = (unsigned long)data->chip_data; | ||
125 | oldcpu = irq_choose_cpu(data->affinity); | ||
126 | newcpu = irq_choose_cpu(dest); | ||
127 | |||
128 | if (oldcpu == newcpu) | ||
129 | goto out; | ||
130 | |||
131 | /* unmask on old CPU first before enabling on the selected CPU */ | ||
132 | spin_lock_irqsave(&leon_irq_lock, flags); | ||
133 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu)); | ||
134 | LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask)); | ||
135 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu)); | ||
136 | LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask)); | ||
137 | spin_unlock_irqrestore(&leon_irq_lock, flags); | ||
138 | out: | ||
139 | return IRQ_SET_MASK_OK; | ||
92 | } | 140 | } |
93 | 141 | ||
94 | static void leon_disable_irq(unsigned int irq_nr) | 142 | static void leon_unmask_irq(struct irq_data *data) |
95 | { | 143 | { |
96 | unsigned long mask, flags; | 144 | unsigned long mask, oldmask, flags; |
97 | mask = get_irqmask(irq_nr); | 145 | int cpu; |
98 | local_irq_save(flags); | 146 | |
99 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 147 | mask = (unsigned long)data->chip_data; |
100 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); | 148 | cpu = irq_choose_cpu(data->affinity); |
101 | local_irq_restore(flags); | 149 | spin_lock_irqsave(&leon_irq_lock, flags); |
150 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu)); | ||
151 | LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask)); | ||
152 | spin_unlock_irqrestore(&leon_irq_lock, flags); | ||
153 | } | ||
154 | |||
155 | static void leon_mask_irq(struct irq_data *data) | ||
156 | { | ||
157 | unsigned long mask, oldmask, flags; | ||
158 | int cpu; | ||
159 | |||
160 | mask = (unsigned long)data->chip_data; | ||
161 | cpu = irq_choose_cpu(data->affinity); | ||
162 | spin_lock_irqsave(&leon_irq_lock, flags); | ||
163 | oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu)); | ||
164 | LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask)); | ||
165 | spin_unlock_irqrestore(&leon_irq_lock, flags); | ||
166 | } | ||
167 | |||
168 | static unsigned int leon_startup_irq(struct irq_data *data) | ||
169 | { | ||
170 | irq_link(data->irq); | ||
171 | leon_unmask_irq(data); | ||
172 | return 0; | ||
173 | } | ||
102 | 174 | ||
175 | static void leon_shutdown_irq(struct irq_data *data) | ||
176 | { | ||
177 | leon_mask_irq(data); | ||
178 | irq_unlink(data->irq); | ||
179 | } | ||
180 | |||
181 | /* Used by external level sensitive IRQ handlers on the LEON: ACK IRQ ctrl */ | ||
182 | static void leon_eoi_irq(struct irq_data *data) | ||
183 | { | ||
184 | unsigned long mask = (unsigned long)data->chip_data; | ||
185 | |||
186 | if (mask & LEON_DO_ACK_HW) | ||
187 | LEON3_BYPASS_STORE_PA(LEON_IACK, mask & ~LEON_DO_ACK_HW); | ||
188 | } | ||
189 | |||
190 | static struct irq_chip leon_irq = { | ||
191 | .name = "leon", | ||
192 | .irq_startup = leon_startup_irq, | ||
193 | .irq_shutdown = leon_shutdown_irq, | ||
194 | .irq_mask = leon_mask_irq, | ||
195 | .irq_unmask = leon_unmask_irq, | ||
196 | .irq_eoi = leon_eoi_irq, | ||
197 | .irq_set_affinity = leon_set_affinity, | ||
198 | }; | ||
199 | |||
200 | /* | ||
201 | * Build a LEON IRQ for the edge triggered LEON IRQ controller: | ||
202 | * Edge (normal) IRQ - handle_simple_irq, ack=DONT-CARE, never ack | ||
203 | * Level IRQ (PCI|Level-GPIO) - handle_fasteoi_irq, ack=1, ack after ISR | ||
204 | * Per-CPU Edge - handle_percpu_irq, ack=0 | ||
205 | */ | ||
206 | unsigned int leon_build_device_irq(unsigned int real_irq, | ||
207 | irq_flow_handler_t flow_handler, | ||
208 | const char *name, int do_ack) | ||
209 | { | ||
210 | unsigned int irq; | ||
211 | unsigned long mask; | ||
212 | |||
213 | irq = 0; | ||
214 | mask = get_irqmask(real_irq); | ||
215 | if (mask == 0) | ||
216 | goto out; | ||
217 | |||
218 | irq = irq_alloc(real_irq, real_irq); | ||
219 | if (irq == 0) | ||
220 | goto out; | ||
221 | |||
222 | if (do_ack) | ||
223 | mask |= LEON_DO_ACK_HW; | ||
224 | |||
225 | irq_set_chip_and_handler_name(irq, &leon_irq, | ||
226 | flow_handler, name); | ||
227 | irq_set_chip_data(irq, (void *)mask); | ||
228 | |||
229 | out: | ||
230 | return irq; | ||
231 | } | ||
232 | |||
233 | static unsigned int _leon_build_device_irq(struct platform_device *op, | ||
234 | unsigned int real_irq) | ||
235 | { | ||
236 | return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0); | ||
237 | } | ||
238 | |||
239 | void leon_update_virq_handling(unsigned int virq, | ||
240 | irq_flow_handler_t flow_handler, | ||
241 | const char *name, int do_ack) | ||
242 | { | ||
243 | unsigned long mask = (unsigned long)irq_get_chip_data(virq); | ||
244 | |||
245 | mask &= ~LEON_DO_ACK_HW; | ||
246 | if (do_ack) | ||
247 | mask |= LEON_DO_ACK_HW; | ||
248 | |||
249 | irq_set_chip_and_handler_name(virq, &leon_irq, | ||
250 | flow_handler, name); | ||
251 | irq_set_chip_data(virq, (void *)mask); | ||
103 | } | 252 | } |
104 | 253 | ||
105 | void __init leon_init_timers(irq_handler_t counter_fn) | 254 | void __init leon_init_timers(irq_handler_t counter_fn) |
106 | { | 255 | { |
107 | int irq; | 256 | int irq, eirq; |
257 | struct device_node *rootnp, *np, *nnp; | ||
258 | struct property *pp; | ||
259 | int len; | ||
260 | int icsel; | ||
261 | int ampopts; | ||
262 | int err; | ||
108 | 263 | ||
109 | leondebug_irq_disable = 0; | 264 | leondebug_irq_disable = 0; |
110 | leon_debug_irqout = 0; | 265 | leon_debug_irqout = 0; |
111 | master_l10_counter = (unsigned int *)&dummy_master_l10_counter; | 266 | master_l10_counter = (unsigned int *)&dummy_master_l10_counter; |
112 | dummy_master_l10_counter = 0; | 267 | dummy_master_l10_counter = 0; |
113 | 268 | ||
114 | if (leon3_gptimer_regs && leon3_irqctrl_regs) { | 269 | rootnp = of_find_node_by_path("/ambapp0"); |
115 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); | 270 | if (!rootnp) |
116 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, | 271 | goto bad; |
117 | (((1000000 / 100) - 1))); | 272 | |
118 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); | 273 | /* Find System ID: GRLIB build ID and optional CHIP ID */ |
119 | 274 | pp = of_find_property(rootnp, "systemid", &len); | |
120 | #ifdef CONFIG_SMP | 275 | if (pp) |
121 | leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; | 276 | amba_system_id = *(unsigned long *)pp->value; |
122 | leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; | 277 | |
278 | /* Find IRQMP IRQ Controller Registers base adr otherwise bail out */ | ||
279 | np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); | ||
280 | if (!np) { | ||
281 | np = of_find_node_by_name(rootnp, "01_00d"); | ||
282 | if (!np) | ||
283 | goto bad; | ||
284 | } | ||
285 | pp = of_find_property(np, "reg", &len); | ||
286 | if (!pp) | ||
287 | goto bad; | ||
288 | leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; | ||
289 | |||
290 | /* Find GPTIMER Timer Registers base address otherwise bail out. */ | ||
291 | nnp = rootnp; | ||
292 | do { | ||
293 | np = of_find_node_by_name(nnp, "GAISLER_GPTIMER"); | ||
294 | if (!np) { | ||
295 | np = of_find_node_by_name(nnp, "01_011"); | ||
296 | if (!np) | ||
297 | goto bad; | ||
298 | } | ||
123 | 299 | ||
124 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | 300 | ampopts = 0; |
125 | (1<<LEON3_GPTIMER_SEPIRQ))) { | 301 | pp = of_find_property(np, "ampopts", &len); |
126 | prom_printf("irq timer not configured with separate irqs\n"); | 302 | if (pp) { |
127 | BUG(); | 303 | ampopts = *(int *)pp->value; |
304 | if (ampopts == 0) { | ||
305 | /* Skip this instance, resource already | ||
306 | * allocated by other OS */ | ||
307 | nnp = np; | ||
308 | continue; | ||
309 | } | ||
128 | } | 310 | } |
129 | 311 | ||
130 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); | 312 | /* Select Timer-Instance on Timer Core. Default is zero */ |
131 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/100) - 1))); | 313 | leon3_gptimer_idx = ampopts & 0x7; |
132 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); | ||
133 | # endif | ||
134 | 314 | ||
135 | } else { | 315 | pp = of_find_property(np, "reg", &len); |
136 | printk(KERN_ERR "No Timer/irqctrl found\n"); | 316 | if (pp) |
317 | leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **) | ||
318 | pp->value; | ||
319 | pp = of_find_property(np, "interrupts", &len); | ||
320 | if (pp) | ||
321 | leon3_gptimer_irq = *(unsigned int *)pp->value; | ||
322 | } while (0); | ||
323 | |||
324 | if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq)) | ||
325 | goto bad; | ||
326 | |||
327 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); | ||
328 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, | ||
329 | (((1000000 / HZ) - 1))); | ||
330 | LEON3_BYPASS_STORE_PA( | ||
331 | &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); | ||
332 | |||
333 | #ifdef CONFIG_SMP | ||
334 | leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx; | ||
335 | |||
336 | if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & | ||
337 | (1<<LEON3_GPTIMER_SEPIRQ))) { | ||
338 | printk(KERN_ERR "timer not configured with separate irqs\n"); | ||
137 | BUG(); | 339 | BUG(); |
138 | } | 340 | } |
139 | 341 | ||
140 | irq = request_irq(leon3_gptimer_irq, | 342 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, |
141 | counter_fn, | 343 | 0); |
142 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | 344 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, |
345 | (((1000000/HZ) - 1))); | ||
346 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | ||
347 | 0); | ||
348 | #endif | ||
143 | 349 | ||
144 | if (irq) { | 350 | /* |
145 | printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", | 351 | * The IRQ controller may (if implemented) consist of multiple |
146 | LEON_INTERRUPT_TIMER1); | 352 | * IRQ controllers, each mapped on a 4Kb boundary. |
353 | * Each CPU may be routed to different IRQCTRLs, however | ||
354 | * we assume that all CPUs (in SMP system) is routed to the | ||
355 | * same IRQ Controller, and for non-SMP only one IRQCTRL is | ||
356 | * accessed anyway. | ||
357 | * In AMP systems, Linux must run on CPU0 for the time being. | ||
358 | */ | ||
359 | icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[boot_cpu_id/8]); | ||
360 | icsel = (icsel >> ((7 - (boot_cpu_id&0x7)) * 4)) & 0xf; | ||
361 | leon3_irqctrl_regs += icsel; | ||
362 | |||
363 | /* Mask all IRQs on boot-cpu IRQ controller */ | ||
364 | LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[boot_cpu_id], 0); | ||
365 | |||
366 | /* Probe extended IRQ controller */ | ||
367 | eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) | ||
368 | >> 16) & 0xf; | ||
369 | if (eirq != 0) | ||
370 | leon_eirq_setup(eirq); | ||
371 | |||
372 | irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx); | ||
373 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); | ||
374 | if (err) { | ||
375 | printk(KERN_ERR "unable to attach timer IRQ%d\n", irq); | ||
147 | prom_halt(); | 376 | prom_halt(); |
148 | } | 377 | } |
149 | 378 | ||
150 | # ifdef CONFIG_SMP | 379 | #ifdef CONFIG_SMP |
151 | { | 380 | { |
152 | unsigned long flags; | 381 | unsigned long flags; |
153 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; | ||
154 | 382 | ||
155 | /* For SMP we use the level 14 ticker, however the bootup code | 383 | /* |
156 | * has copied the firmwares level 14 vector into boot cpu's | 384 | * In SMP, sun4m adds a IPI handler to IRQ trap handler that |
157 | * trap table, we must fix this now or we get squashed. | 385 | * LEON never must take, sun4d and LEON overwrites the branch |
386 | * with a NOP. | ||
158 | */ | 387 | */ |
159 | local_irq_save(flags); | 388 | local_irq_save(flags); |
160 | |||
161 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ | 389 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ |
162 | |||
163 | /* Adjust so that we jump directly to smpleon_ticker */ | ||
164 | trap_table->inst_three += smpleon_ticker - real_irq_entry; | ||
165 | |||
166 | local_flush_cache_all(); | 390 | local_flush_cache_all(); |
167 | local_irq_restore(flags); | 391 | local_irq_restore(flags); |
168 | } | 392 | } |
169 | # endif | 393 | #endif |
170 | 394 | ||
171 | if (leon3_gptimer_regs) { | 395 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, |
172 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, | 396 | LEON3_GPTIMER_EN | |
173 | LEON3_GPTIMER_EN | | 397 | LEON3_GPTIMER_RL | |
174 | LEON3_GPTIMER_RL | | 398 | LEON3_GPTIMER_LD | |
175 | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); | 399 | LEON3_GPTIMER_IRQEN); |
176 | 400 | ||
177 | #ifdef CONFIG_SMP | 401 | #ifdef CONFIG_SMP |
178 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, | 402 | /* Install per-cpu IRQ handler for broadcasted ticker */ |
179 | LEON3_GPTIMER_EN | | 403 | irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq, |
180 | LEON3_GPTIMER_RL | | 404 | "per-cpu", 0); |
181 | LEON3_GPTIMER_LD | | 405 | err = request_irq(irq, leon_percpu_timer_interrupt, |
182 | LEON3_GPTIMER_IRQEN); | 406 | IRQF_PERCPU | IRQF_TIMER, "ticker", |
183 | #endif | 407 | NULL); |
184 | 408 | if (err) { | |
409 | printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq); | ||
410 | prom_halt(); | ||
185 | } | 411 | } |
412 | |||
413 | LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, | ||
414 | LEON3_GPTIMER_EN | | ||
415 | LEON3_GPTIMER_RL | | ||
416 | LEON3_GPTIMER_LD | | ||
417 | LEON3_GPTIMER_IRQEN); | ||
418 | #endif | ||
419 | return; | ||
420 | bad: | ||
421 | printk(KERN_ERR "No Timer/irqctrl found\n"); | ||
422 | BUG(); | ||
423 | return; | ||
186 | } | 424 | } |
187 | 425 | ||
188 | void leon_clear_clock_irq(void) | 426 | void leon_clear_clock_irq(void) |
@@ -194,9 +432,6 @@ void leon_load_profile_irq(int cpu, unsigned int limit) | |||
194 | BUG(); | 432 | BUG(); |
195 | } | 433 | } |
196 | 434 | ||
197 | |||
198 | |||
199 | |||
200 | void __init leon_trans_init(struct device_node *dp) | 435 | void __init leon_trans_init(struct device_node *dp) |
201 | { | 436 | { |
202 | if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) { | 437 | if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) { |
@@ -250,22 +485,18 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) | |||
250 | { | 485 | { |
251 | unsigned long mask, flags, *addr; | 486 | unsigned long mask, flags, *addr; |
252 | mask = get_irqmask(irq_nr); | 487 | mask = get_irqmask(irq_nr); |
253 | local_irq_save(flags); | 488 | spin_lock_irqsave(&leon_irq_lock, flags); |
254 | addr = (unsigned long *)&(leon3_irqctrl_regs->mask[cpu]); | 489 | addr = (unsigned long *)LEON_IMASK(cpu); |
255 | LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | (mask))); | 490 | LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask)); |
256 | local_irq_restore(flags); | 491 | spin_unlock_irqrestore(&leon_irq_lock, flags); |
257 | } | 492 | } |
258 | 493 | ||
259 | #endif | 494 | #endif |
260 | 495 | ||
261 | void __init leon_init_IRQ(void) | 496 | void __init leon_init_IRQ(void) |
262 | { | 497 | { |
263 | sparc_init_timers = leon_init_timers; | 498 | sparc_irq_config.init_timers = leon_init_timers; |
264 | 499 | sparc_irq_config.build_device_irq = _leon_build_device_irq; | |
265 | BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM); | ||
266 | BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM); | ||
267 | BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM); | ||
268 | BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM); | ||
269 | 500 | ||
270 | BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, | 501 | BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, |
271 | BTFIXUPCALL_NORM); | 502 | BTFIXUPCALL_NORM); |
@@ -282,5 +513,5 @@ void __init leon_init_IRQ(void) | |||
282 | 513 | ||
283 | void __init leon_init(void) | 514 | void __init leon_init(void) |
284 | { | 515 | { |
285 | prom_build_more = &leon_node_init; | 516 | of_pdt_build_more = &leon_node_init; |
286 | } | 517 | } |
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c new file mode 100644 index 000000000000..a8a9a275037d --- /dev/null +++ b/arch/sparc/kernel/leon_pci.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * leon_pci.c: LEON Host PCI support | ||
3 | * | ||
4 | * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom | ||
5 | * | ||
6 | * Code is partially derived from pcic.c | ||
7 | */ | ||
8 | |||
9 | #include <linux/of_device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <asm/leon.h> | ||
13 | #include <asm/leon_pci.h> | ||
14 | |||
15 | /* The LEON architecture does not rely on a BIOS or bootloader to setup | ||
16 | * PCI for us. The Linux generic routines are used to setup resources, | ||
17 | * reset values of confuration-space registers settings ae preseved. | ||
18 | */ | ||
19 | void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) | ||
20 | { | ||
21 | struct pci_bus *root_bus; | ||
22 | |||
23 | root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info); | ||
24 | if (root_bus) { | ||
25 | root_bus->resource[0] = &info->io_space; | ||
26 | root_bus->resource[1] = &info->mem_space; | ||
27 | root_bus->resource[2] = NULL; | ||
28 | |||
29 | /* Init all PCI devices into PCI tree */ | ||
30 | pci_bus_add_devices(root_bus); | ||
31 | |||
32 | /* Setup IRQs of all devices using custom routines */ | ||
33 | pci_fixup_irqs(pci_common_swizzle, info->map_irq); | ||
34 | |||
35 | /* Assign devices with resources */ | ||
36 | pci_assign_unassigned_resources(); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | /* PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is | ||
41 | * accessed through a Window which is translated to low 64KB in PCI space, the | ||
42 | * first 4KB is not used so 60KB is available. | ||
43 | * | ||
44 | * This function is used by generic code to translate resource addresses into | ||
45 | * PCI addresses. | ||
46 | */ | ||
47 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
48 | struct resource *res) | ||
49 | { | ||
50 | struct leon_pci_info *info = dev->bus->sysdata; | ||
51 | |||
52 | region->start = res->start; | ||
53 | region->end = res->end; | ||
54 | |||
55 | if (res->flags & IORESOURCE_IO) { | ||
56 | region->start -= (info->io_space.start - 0x1000); | ||
57 | region->end -= (info->io_space.start - 0x1000); | ||
58 | } | ||
59 | } | ||
60 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
61 | |||
62 | /* see pcibios_resource_to_bus() comment */ | ||
63 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
64 | struct pci_bus_region *region) | ||
65 | { | ||
66 | struct leon_pci_info *info = dev->bus->sysdata; | ||
67 | |||
68 | res->start = region->start; | ||
69 | res->end = region->end; | ||
70 | |||
71 | if (res->flags & IORESOURCE_IO) { | ||
72 | res->start += (info->io_space.start - 0x1000); | ||
73 | res->end += (info->io_space.start - 0x1000); | ||
74 | } | ||
75 | } | ||
76 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
77 | |||
78 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) | ||
79 | { | ||
80 | struct leon_pci_info *info = pbus->sysdata; | ||
81 | struct pci_dev *dev; | ||
82 | int i, has_io, has_mem; | ||
83 | u16 cmd; | ||
84 | |||
85 | /* Generic PCI bus probing sets these to point at | ||
86 | * &io{port,mem}_resouce which is wrong for us. | ||
87 | */ | ||
88 | if (pbus->self == NULL) { | ||
89 | pbus->resource[0] = &info->io_space; | ||
90 | pbus->resource[1] = &info->mem_space; | ||
91 | pbus->resource[2] = NULL; | ||
92 | } | ||
93 | |||
94 | list_for_each_entry(dev, &pbus->devices, bus_list) { | ||
95 | /* | ||
96 | * We can not rely on that the bootloader has enabled I/O | ||
97 | * or memory access to PCI devices. Instead we enable it here | ||
98 | * if the device has BARs of respective type. | ||
99 | */ | ||
100 | has_io = has_mem = 0; | ||
101 | for (i = 0; i < PCI_ROM_RESOURCE; i++) { | ||
102 | unsigned long f = dev->resource[i].flags; | ||
103 | if (f & IORESOURCE_IO) | ||
104 | has_io = 1; | ||
105 | else if (f & IORESOURCE_MEM) | ||
106 | has_mem = 1; | ||
107 | } | ||
108 | /* ROM BARs are mapped into 32-bit memory space */ | ||
109 | if (dev->resource[PCI_ROM_RESOURCE].end != 0) { | ||
110 | dev->resource[PCI_ROM_RESOURCE].flags |= | ||
111 | IORESOURCE_ROM_ENABLE; | ||
112 | has_mem = 1; | ||
113 | } | ||
114 | pci_bus_read_config_word(pbus, dev->devfn, PCI_COMMAND, &cmd); | ||
115 | if (has_io && !(cmd & PCI_COMMAND_IO)) { | ||
116 | #ifdef CONFIG_PCI_DEBUG | ||
117 | printk(KERN_INFO "LEONPCI: Enabling I/O for dev %s\n", | ||
118 | pci_name(dev)); | ||
119 | #endif | ||
120 | cmd |= PCI_COMMAND_IO; | ||
121 | pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND, | ||
122 | cmd); | ||
123 | } | ||
124 | if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { | ||
125 | #ifdef CONFIG_PCI_DEBUG | ||
126 | printk(KERN_INFO "LEONPCI: Enabling MEMORY for dev" | ||
127 | "%s\n", pci_name(dev)); | ||
128 | #endif | ||
129 | cmd |= PCI_COMMAND_MEMORY; | ||
130 | pci_bus_write_config_word(pbus, dev->devfn, PCI_COMMAND, | ||
131 | cmd); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Other archs parse arguments here. | ||
138 | */ | ||
139 | char * __devinit pcibios_setup(char *str) | ||
140 | { | ||
141 | return str; | ||
142 | } | ||
143 | |||
144 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, | ||
145 | resource_size_t size, resource_size_t align) | ||
146 | { | ||
147 | return res->start; | ||
148 | } | ||
149 | |||
150 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
151 | { | ||
152 | return pci_enable_resources(dev, mask); | ||
153 | } | ||
154 | |||
155 | struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) | ||
156 | { | ||
157 | /* | ||
158 | * Currently the OpenBoot nodes are not connected with the PCI device, | ||
159 | * this is because the LEON PROM does not create PCI nodes. Eventually | ||
160 | * this will change and the same approach as pcic.c can be used to | ||
161 | * match PROM nodes with pci devices. | ||
162 | */ | ||
163 | return NULL; | ||
164 | } | ||
165 | EXPORT_SYMBOL(pci_device_to_OF_node); | ||
166 | |||
167 | void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) | ||
168 | { | ||
169 | #ifdef CONFIG_PCI_DEBUG | ||
170 | printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq, | ||
171 | pci_name(dev)); | ||
172 | #endif | ||
173 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
174 | } | ||
175 | |||
176 | /* in/out routines taken from pcic.c | ||
177 | * | ||
178 | * This probably belongs here rather than ioport.c because | ||
179 | * we do not want this crud linked into SBus kernels. | ||
180 | * Also, think for a moment about likes of floppy.c that | ||
181 | * include architecture specific parts. They may want to redefine ins/outs. | ||
182 | * | ||
183 | * We do not use horrible macros here because we want to | ||
184 | * advance pointer by sizeof(size). | ||
185 | */ | ||
186 | void outsb(unsigned long addr, const void *src, unsigned long count) | ||
187 | { | ||
188 | while (count) { | ||
189 | count -= 1; | ||
190 | outb(*(const char *)src, addr); | ||
191 | src += 1; | ||
192 | /* addr += 1; */ | ||
193 | } | ||
194 | } | ||
195 | EXPORT_SYMBOL(outsb); | ||
196 | |||
197 | void outsw(unsigned long addr, const void *src, unsigned long count) | ||
198 | { | ||
199 | while (count) { | ||
200 | count -= 2; | ||
201 | outw(*(const short *)src, addr); | ||
202 | src += 2; | ||
203 | /* addr += 2; */ | ||
204 | } | ||
205 | } | ||
206 | EXPORT_SYMBOL(outsw); | ||
207 | |||
208 | void outsl(unsigned long addr, const void *src, unsigned long count) | ||
209 | { | ||
210 | while (count) { | ||
211 | count -= 4; | ||
212 | outl(*(const long *)src, addr); | ||
213 | src += 4; | ||
214 | /* addr += 4; */ | ||
215 | } | ||
216 | } | ||
217 | EXPORT_SYMBOL(outsl); | ||
218 | |||
219 | void insb(unsigned long addr, void *dst, unsigned long count) | ||
220 | { | ||
221 | while (count) { | ||
222 | count -= 1; | ||
223 | *(unsigned char *)dst = inb(addr); | ||
224 | dst += 1; | ||
225 | /* addr += 1; */ | ||
226 | } | ||
227 | } | ||
228 | EXPORT_SYMBOL(insb); | ||
229 | |||
230 | void insw(unsigned long addr, void *dst, unsigned long count) | ||
231 | { | ||
232 | while (count) { | ||
233 | count -= 2; | ||
234 | *(unsigned short *)dst = inw(addr); | ||
235 | dst += 2; | ||
236 | /* addr += 2; */ | ||
237 | } | ||
238 | } | ||
239 | EXPORT_SYMBOL(insw); | ||
240 | |||
241 | void insl(unsigned long addr, void *dst, unsigned long count) | ||
242 | { | ||
243 | while (count) { | ||
244 | count -= 4; | ||
245 | /* | ||
246 | * XXX I am sure we are in for an unaligned trap here. | ||
247 | */ | ||
248 | *(unsigned long *)dst = inl(addr); | ||
249 | dst += 4; | ||
250 | /* addr += 4; */ | ||
251 | } | ||
252 | } | ||
253 | EXPORT_SYMBOL(insl); | ||
diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c new file mode 100644 index 000000000000..44dc093ee33a --- /dev/null +++ b/arch/sparc/kernel/leon_pci_grpci2.c | |||
@@ -0,0 +1,897 @@ | |||
1 | /* | ||
2 | * leon_pci_grpci2.c: GRPCI2 Host PCI driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/of_device.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <asm/io.h> | ||
14 | #include <asm/leon.h> | ||
15 | #include <asm/vaddrs.h> | ||
16 | #include <asm/sections.h> | ||
17 | #include <asm/leon_pci.h> | ||
18 | |||
19 | #include "irq.h" | ||
20 | |||
21 | struct grpci2_barcfg { | ||
22 | unsigned long pciadr; /* PCI Space Address */ | ||
23 | unsigned long ahbadr; /* PCI Base address mapped to this AHB addr */ | ||
24 | }; | ||
25 | |||
26 | /* Device Node Configuration options: | ||
27 | * - barcfgs : Custom Configuration of Host's 6 target BARs | ||
28 | * - irq_mask : Limit which PCI interrupts are enabled | ||
29 | * - do_reset : Force PCI Reset on startup | ||
30 | * | ||
31 | * barcfgs | ||
32 | * ======= | ||
33 | * | ||
34 | * Optional custom Target BAR configuration (see struct grpci2_barcfg). All | ||
35 | * addresses are physical. Array always contains 6 elements (len=2*4*6 bytes) | ||
36 | * | ||
37 | * -1 means not configured (let host driver do default setup). | ||
38 | * | ||
39 | * [i*2+0] = PCI Address of BAR[i] on target interface | ||
40 | * [i*2+1] = Accessing PCI address of BAR[i] result in this AMBA address | ||
41 | * | ||
42 | * | ||
43 | * irq_mask | ||
44 | * ======== | ||
45 | * | ||
46 | * Limit which PCI interrupts are enabled. 0=Disable, 1=Enable. By default | ||
47 | * all are enabled. Use this when PCI interrupt pins are floating on PCB. | ||
48 | * int, len=4. | ||
49 | * bit0 = PCI INTA# | ||
50 | * bit1 = PCI INTB# | ||
51 | * bit2 = PCI INTC# | ||
52 | * bit3 = PCI INTD# | ||
53 | * | ||
54 | * | ||
55 | * reset | ||
56 | * ===== | ||
57 | * | ||
58 | * Force PCI reset on startup. int, len=4 | ||
59 | */ | ||
60 | |||
61 | /* Enable Debugging Configuration Space Access */ | ||
62 | #undef GRPCI2_DEBUG_CFGACCESS | ||
63 | |||
64 | /* | ||
65 | * GRPCI2 APB Register MAP | ||
66 | */ | ||
67 | struct grpci2_regs { | ||
68 | unsigned int ctrl; /* 0x00 Control */ | ||
69 | unsigned int sts_cap; /* 0x04 Status / Capabilities */ | ||
70 | int res1; /* 0x08 */ | ||
71 | unsigned int io_map; /* 0x0C I/O Map address */ | ||
72 | unsigned int dma_ctrl; /* 0x10 DMA */ | ||
73 | unsigned int dma_bdbase; /* 0x14 DMA */ | ||
74 | int res2[2]; /* 0x18 */ | ||
75 | unsigned int bars[6]; /* 0x20 read-only PCI BARs */ | ||
76 | int res3[2]; /* 0x38 */ | ||
77 | unsigned int ahbmst_map[16]; /* 0x40 AHB->PCI Map per AHB Master */ | ||
78 | |||
79 | /* PCI Trace Buffer Registers (OPTIONAL) */ | ||
80 | unsigned int t_ctrl; /* 0x80 */ | ||
81 | unsigned int t_cnt; /* 0x84 */ | ||
82 | unsigned int t_adpat; /* 0x88 */ | ||
83 | unsigned int t_admask; /* 0x8C */ | ||
84 | unsigned int t_sigpat; /* 0x90 */ | ||
85 | unsigned int t_sigmask; /* 0x94 */ | ||
86 | unsigned int t_adstate; /* 0x98 */ | ||
87 | unsigned int t_sigstate; /* 0x9C */ | ||
88 | }; | ||
89 | |||
90 | #define REGLOAD(a) (be32_to_cpu(__raw_readl(&(a)))) | ||
91 | #define REGSTORE(a, v) (__raw_writel(cpu_to_be32(v), &(a))) | ||
92 | |||
93 | #define CTRL_BUS_BIT 16 | ||
94 | |||
95 | #define CTRL_RESET (1<<31) | ||
96 | #define CTRL_SI (1<<27) | ||
97 | #define CTRL_PE (1<<26) | ||
98 | #define CTRL_EI (1<<25) | ||
99 | #define CTRL_ER (1<<24) | ||
100 | #define CTRL_BUS (0xff<<CTRL_BUS_BIT) | ||
101 | #define CTRL_HOSTINT 0xf | ||
102 | |||
103 | #define STS_HOST_BIT 31 | ||
104 | #define STS_MST_BIT 30 | ||
105 | #define STS_TAR_BIT 29 | ||
106 | #define STS_DMA_BIT 28 | ||
107 | #define STS_DI_BIT 27 | ||
108 | #define STS_HI_BIT 26 | ||
109 | #define STS_IRQMODE_BIT 24 | ||
110 | #define STS_TRACE_BIT 23 | ||
111 | #define STS_CFGERRVALID_BIT 20 | ||
112 | #define STS_CFGERR_BIT 19 | ||
113 | #define STS_INTTYPE_BIT 12 | ||
114 | #define STS_INTSTS_BIT 8 | ||
115 | #define STS_FDEPTH_BIT 2 | ||
116 | #define STS_FNUM_BIT 0 | ||
117 | |||
118 | #define STS_HOST (1<<STS_HOST_BIT) | ||
119 | #define STS_MST (1<<STS_MST_BIT) | ||
120 | #define STS_TAR (1<<STS_TAR_BIT) | ||
121 | #define STS_DMA (1<<STS_DMA_BIT) | ||
122 | #define STS_DI (1<<STS_DI_BIT) | ||
123 | #define STS_HI (1<<STS_HI_BIT) | ||
124 | #define STS_IRQMODE (0x3<<STS_IRQMODE_BIT) | ||
125 | #define STS_TRACE (1<<STS_TRACE_BIT) | ||
126 | #define STS_CFGERRVALID (1<<STS_CFGERRVALID_BIT) | ||
127 | #define STS_CFGERR (1<<STS_CFGERR_BIT) | ||
128 | #define STS_INTTYPE (0x3f<<STS_INTTYPE_BIT) | ||
129 | #define STS_INTSTS (0xf<<STS_INTSTS_BIT) | ||
130 | #define STS_FDEPTH (0x7<<STS_FDEPTH_BIT) | ||
131 | #define STS_FNUM (0x3<<STS_FNUM_BIT) | ||
132 | |||
133 | #define STS_ISYSERR (1<<17) | ||
134 | #define STS_IDMA (1<<16) | ||
135 | #define STS_IDMAERR (1<<15) | ||
136 | #define STS_IMSTABRT (1<<14) | ||
137 | #define STS_ITGTABRT (1<<13) | ||
138 | #define STS_IPARERR (1<<12) | ||
139 | |||
140 | #define STS_ERR_IRQ (STS_ISYSERR | STS_IMSTABRT | STS_ITGTABRT | STS_IPARERR) | ||
141 | |||
142 | struct grpci2_bd_chan { | ||
143 | unsigned int ctrl; /* 0x00 DMA Control */ | ||
144 | unsigned int nchan; /* 0x04 Next DMA Channel Address */ | ||
145 | unsigned int nbd; /* 0x08 Next Data Descriptor in chan */ | ||
146 | unsigned int res; /* 0x0C Reserved */ | ||
147 | }; | ||
148 | |||
149 | #define BD_CHAN_EN 0x80000000 | ||
150 | #define BD_CHAN_TYPE 0x00300000 | ||
151 | #define BD_CHAN_BDCNT 0x0000ffff | ||
152 | #define BD_CHAN_EN_BIT 31 | ||
153 | #define BD_CHAN_TYPE_BIT 20 | ||
154 | #define BD_CHAN_BDCNT_BIT 0 | ||
155 | |||
156 | struct grpci2_bd_data { | ||
157 | unsigned int ctrl; /* 0x00 DMA Data Control */ | ||
158 | unsigned int pci_adr; /* 0x04 PCI Start Address */ | ||
159 | unsigned int ahb_adr; /* 0x08 AHB Start address */ | ||
160 | unsigned int next; /* 0x0C Next Data Descriptor in chan */ | ||
161 | }; | ||
162 | |||
163 | #define BD_DATA_EN 0x80000000 | ||
164 | #define BD_DATA_IE 0x40000000 | ||
165 | #define BD_DATA_DR 0x20000000 | ||
166 | #define BD_DATA_TYPE 0x00300000 | ||
167 | #define BD_DATA_ER 0x00080000 | ||
168 | #define BD_DATA_LEN 0x0000ffff | ||
169 | #define BD_DATA_EN_BIT 31 | ||
170 | #define BD_DATA_IE_BIT 30 | ||
171 | #define BD_DATA_DR_BIT 29 | ||
172 | #define BD_DATA_TYPE_BIT 20 | ||
173 | #define BD_DATA_ER_BIT 19 | ||
174 | #define BD_DATA_LEN_BIT 0 | ||
175 | |||
176 | /* GRPCI2 Capability */ | ||
177 | struct grpci2_cap_first { | ||
178 | unsigned int ctrl; | ||
179 | unsigned int pci2ahb_map[6]; | ||
180 | unsigned int ext2ahb_map; | ||
181 | unsigned int io_map; | ||
182 | unsigned int pcibar_size[6]; | ||
183 | }; | ||
184 | #define CAP9_CTRL_OFS 0 | ||
185 | #define CAP9_BAR_OFS 0x4 | ||
186 | #define CAP9_IOMAP_OFS 0x20 | ||
187 | #define CAP9_BARSIZE_OFS 0x24 | ||
188 | |||
189 | struct grpci2_priv { | ||
190 | struct leon_pci_info info; /* must be on top of this structure */ | ||
191 | struct grpci2_regs *regs; | ||
192 | char irq; | ||
193 | char irq_mode; /* IRQ Mode from CAPSTS REG */ | ||
194 | char bt_enabled; | ||
195 | char do_reset; | ||
196 | char irq_mask; | ||
197 | u32 pciid; /* PCI ID of Host */ | ||
198 | unsigned char irq_map[4]; | ||
199 | |||
200 | /* Virtual IRQ numbers */ | ||
201 | unsigned int virq_err; | ||
202 | unsigned int virq_dma; | ||
203 | |||
204 | /* AHB PCI Windows */ | ||
205 | unsigned long pci_area; /* MEMORY */ | ||
206 | unsigned long pci_area_end; | ||
207 | unsigned long pci_io; /* I/O */ | ||
208 | unsigned long pci_conf; /* CONFIGURATION */ | ||
209 | unsigned long pci_conf_end; | ||
210 | unsigned long pci_io_va; | ||
211 | |||
212 | struct grpci2_barcfg tgtbars[6]; | ||
213 | }; | ||
214 | |||
215 | DEFINE_SPINLOCK(grpci2_dev_lock); | ||
216 | struct grpci2_priv *grpci2priv; | ||
217 | |||
218 | int grpci2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
219 | { | ||
220 | struct grpci2_priv *priv = dev->bus->sysdata; | ||
221 | int irq_group; | ||
222 | |||
223 | /* Use default IRQ decoding on PCI BUS0 according slot numbering */ | ||
224 | irq_group = slot & 0x3; | ||
225 | pin = ((pin - 1) + irq_group) & 0x3; | ||
226 | |||
227 | return priv->irq_map[pin]; | ||
228 | } | ||
229 | |||
230 | static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus, | ||
231 | unsigned int devfn, int where, u32 *val) | ||
232 | { | ||
233 | unsigned int *pci_conf; | ||
234 | unsigned long flags; | ||
235 | u32 tmp; | ||
236 | |||
237 | if (where & 0x3) | ||
238 | return -EINVAL; | ||
239 | |||
240 | if (bus == 0 && PCI_SLOT(devfn) != 0) | ||
241 | devfn += (0x8 * 6); | ||
242 | |||
243 | /* Select bus */ | ||
244 | spin_lock_irqsave(&grpci2_dev_lock, flags); | ||
245 | REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | | ||
246 | (bus << 16)); | ||
247 | spin_unlock_irqrestore(&grpci2_dev_lock, flags); | ||
248 | |||
249 | /* clear old status */ | ||
250 | REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); | ||
251 | |||
252 | pci_conf = (unsigned int *) (priv->pci_conf | | ||
253 | (devfn << 8) | (where & 0xfc)); | ||
254 | tmp = LEON3_BYPASS_LOAD_PA(pci_conf); | ||
255 | |||
256 | /* Wait until GRPCI2 signals that CFG access is done, it should be | ||
257 | * done instantaneously unless a DMA operation is ongoing... | ||
258 | */ | ||
259 | while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) | ||
260 | ; | ||
261 | |||
262 | if (REGLOAD(priv->regs->sts_cap) & STS_CFGERR) { | ||
263 | *val = 0xffffffff; | ||
264 | } else { | ||
265 | /* Bus always little endian (unaffected by byte-swapping) */ | ||
266 | *val = flip_dword(tmp); | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int grpci2_cfg_r16(struct grpci2_priv *priv, unsigned int bus, | ||
273 | unsigned int devfn, int where, u32 *val) | ||
274 | { | ||
275 | u32 v; | ||
276 | int ret; | ||
277 | |||
278 | if (where & 0x1) | ||
279 | return -EINVAL; | ||
280 | ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); | ||
281 | *val = 0xffff & (v >> (8 * (where & 0x3))); | ||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int grpci2_cfg_r8(struct grpci2_priv *priv, unsigned int bus, | ||
286 | unsigned int devfn, int where, u32 *val) | ||
287 | { | ||
288 | u32 v; | ||
289 | int ret; | ||
290 | |||
291 | ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); | ||
292 | *val = 0xff & (v >> (8 * (where & 3))); | ||
293 | |||
294 | return ret; | ||
295 | } | ||
296 | |||
297 | static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus, | ||
298 | unsigned int devfn, int where, u32 val) | ||
299 | { | ||
300 | unsigned int *pci_conf; | ||
301 | unsigned long flags; | ||
302 | |||
303 | if (where & 0x3) | ||
304 | return -EINVAL; | ||
305 | |||
306 | if (bus == 0 && PCI_SLOT(devfn) != 0) | ||
307 | devfn += (0x8 * 6); | ||
308 | |||
309 | /* Select bus */ | ||
310 | spin_lock_irqsave(&grpci2_dev_lock, flags); | ||
311 | REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | | ||
312 | (bus << 16)); | ||
313 | spin_unlock_irqrestore(&grpci2_dev_lock, flags); | ||
314 | |||
315 | /* clear old status */ | ||
316 | REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); | ||
317 | |||
318 | pci_conf = (unsigned int *) (priv->pci_conf | | ||
319 | (devfn << 8) | (where & 0xfc)); | ||
320 | LEON3_BYPASS_STORE_PA(pci_conf, flip_dword(val)); | ||
321 | |||
322 | /* Wait until GRPCI2 signals that CFG access is done, it should be | ||
323 | * done instantaneously unless a DMA operation is ongoing... | ||
324 | */ | ||
325 | while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) | ||
326 | ; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int grpci2_cfg_w16(struct grpci2_priv *priv, unsigned int bus, | ||
332 | unsigned int devfn, int where, u32 val) | ||
333 | { | ||
334 | int ret; | ||
335 | u32 v; | ||
336 | |||
337 | if (where & 0x1) | ||
338 | return -EINVAL; | ||
339 | ret = grpci2_cfg_r32(priv, bus, devfn, where&~3, &v); | ||
340 | if (ret) | ||
341 | return ret; | ||
342 | v = (v & ~(0xffff << (8 * (where & 0x3)))) | | ||
343 | ((0xffff & val) << (8 * (where & 0x3))); | ||
344 | return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); | ||
345 | } | ||
346 | |||
347 | static int grpci2_cfg_w8(struct grpci2_priv *priv, unsigned int bus, | ||
348 | unsigned int devfn, int where, u32 val) | ||
349 | { | ||
350 | int ret; | ||
351 | u32 v; | ||
352 | |||
353 | ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); | ||
354 | if (ret != 0) | ||
355 | return ret; | ||
356 | v = (v & ~(0xff << (8 * (where & 0x3)))) | | ||
357 | ((0xff & val) << (8 * (where & 0x3))); | ||
358 | return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); | ||
359 | } | ||
360 | |||
361 | /* Read from Configuration Space. When entering here the PCI layer has taken | ||
362 | * the pci_lock spinlock and IRQ is off. | ||
363 | */ | ||
364 | static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn, | ||
365 | int where, int size, u32 *val) | ||
366 | { | ||
367 | struct grpci2_priv *priv = grpci2priv; | ||
368 | unsigned int busno = bus->number; | ||
369 | int ret; | ||
370 | |||
371 | if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) { | ||
372 | *val = ~0; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | switch (size) { | ||
377 | case 1: | ||
378 | ret = grpci2_cfg_r8(priv, busno, devfn, where, val); | ||
379 | break; | ||
380 | case 2: | ||
381 | ret = grpci2_cfg_r16(priv, busno, devfn, where, val); | ||
382 | break; | ||
383 | case 4: | ||
384 | ret = grpci2_cfg_r32(priv, busno, devfn, where, val); | ||
385 | break; | ||
386 | default: | ||
387 | ret = -EINVAL; | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | #ifdef GRPCI2_DEBUG_CFGACCESS | ||
392 | printk(KERN_INFO "grpci2_read_config: [%02x:%02x:%x] ofs=%d val=%x " | ||
393 | "size=%d\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, | ||
394 | *val, size); | ||
395 | #endif | ||
396 | |||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | /* Write to Configuration Space. When entering here the PCI layer has taken | ||
401 | * the pci_lock spinlock and IRQ is off. | ||
402 | */ | ||
403 | static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn, | ||
404 | int where, int size, u32 val) | ||
405 | { | ||
406 | struct grpci2_priv *priv = grpci2priv; | ||
407 | unsigned int busno = bus->number; | ||
408 | |||
409 | if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) | ||
410 | return 0; | ||
411 | |||
412 | #ifdef GRPCI2_DEBUG_CFGACCESS | ||
413 | printk(KERN_INFO "grpci2_write_config: [%02x:%02x:%x] ofs=%d size=%d " | ||
414 | "val=%x\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), | ||
415 | where, size, val); | ||
416 | #endif | ||
417 | |||
418 | switch (size) { | ||
419 | default: | ||
420 | return -EINVAL; | ||
421 | case 1: | ||
422 | return grpci2_cfg_w8(priv, busno, devfn, where, val); | ||
423 | case 2: | ||
424 | return grpci2_cfg_w16(priv, busno, devfn, where, val); | ||
425 | case 4: | ||
426 | return grpci2_cfg_w32(priv, busno, devfn, where, val); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | static struct pci_ops grpci2_ops = { | ||
431 | .read = grpci2_read_config, | ||
432 | .write = grpci2_write_config, | ||
433 | }; | ||
434 | |||
435 | /* GENIRQ IRQ chip implementation for GRPCI2 irqmode=0..2. In configuration | ||
436 | * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller | ||
437 | * this is not needed and the standard IRQ controller can be used. | ||
438 | */ | ||
439 | |||
440 | static void grpci2_mask_irq(struct irq_data *data) | ||
441 | { | ||
442 | unsigned long flags; | ||
443 | unsigned int irqidx; | ||
444 | struct grpci2_priv *priv = grpci2priv; | ||
445 | |||
446 | irqidx = (unsigned int)data->chip_data - 1; | ||
447 | if (irqidx > 3) /* only mask PCI interrupts here */ | ||
448 | return; | ||
449 | |||
450 | spin_lock_irqsave(&grpci2_dev_lock, flags); | ||
451 | REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) & ~(1 << irqidx)); | ||
452 | spin_unlock_irqrestore(&grpci2_dev_lock, flags); | ||
453 | } | ||
454 | |||
455 | static void grpci2_unmask_irq(struct irq_data *data) | ||
456 | { | ||
457 | unsigned long flags; | ||
458 | unsigned int irqidx; | ||
459 | struct grpci2_priv *priv = grpci2priv; | ||
460 | |||
461 | irqidx = (unsigned int)data->chip_data - 1; | ||
462 | if (irqidx > 3) /* only unmask PCI interrupts here */ | ||
463 | return; | ||
464 | |||
465 | spin_lock_irqsave(&grpci2_dev_lock, flags); | ||
466 | REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) | (1 << irqidx)); | ||
467 | spin_unlock_irqrestore(&grpci2_dev_lock, flags); | ||
468 | } | ||
469 | |||
470 | static unsigned int grpci2_startup_irq(struct irq_data *data) | ||
471 | { | ||
472 | grpci2_unmask_irq(data); | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static void grpci2_shutdown_irq(struct irq_data *data) | ||
477 | { | ||
478 | grpci2_mask_irq(data); | ||
479 | } | ||
480 | |||
481 | static struct irq_chip grpci2_irq = { | ||
482 | .name = "grpci2", | ||
483 | .irq_startup = grpci2_startup_irq, | ||
484 | .irq_shutdown = grpci2_shutdown_irq, | ||
485 | .irq_mask = grpci2_mask_irq, | ||
486 | .irq_unmask = grpci2_unmask_irq, | ||
487 | }; | ||
488 | |||
489 | /* Handle one or multiple IRQs from the PCI core */ | ||
490 | static void grpci2_pci_flow_irq(unsigned int irq, struct irq_desc *desc) | ||
491 | { | ||
492 | struct grpci2_priv *priv = grpci2priv; | ||
493 | int i, ack = 0; | ||
494 | unsigned int ctrl, sts_cap, pci_ints; | ||
495 | |||
496 | ctrl = REGLOAD(priv->regs->ctrl); | ||
497 | sts_cap = REGLOAD(priv->regs->sts_cap); | ||
498 | |||
499 | /* Error Interrupt? */ | ||
500 | if (sts_cap & STS_ERR_IRQ) { | ||
501 | generic_handle_irq(priv->virq_err); | ||
502 | ack = 1; | ||
503 | } | ||
504 | |||
505 | /* PCI Interrupt? */ | ||
506 | pci_ints = ((~sts_cap) >> STS_INTSTS_BIT) & ctrl & CTRL_HOSTINT; | ||
507 | if (pci_ints) { | ||
508 | /* Call respective PCI Interrupt handler */ | ||
509 | for (i = 0; i < 4; i++) { | ||
510 | if (pci_ints & (1 << i)) | ||
511 | generic_handle_irq(priv->irq_map[i]); | ||
512 | } | ||
513 | ack = 1; | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Decode DMA Interrupt only when shared with Err and PCI INTX#, when | ||
518 | * the DMA is a unique IRQ the DMA interrupts doesn't end up here, they | ||
519 | * goes directly to DMA ISR. | ||
520 | */ | ||
521 | if ((priv->irq_mode == 0) && (sts_cap & (STS_IDMA | STS_IDMAERR))) { | ||
522 | generic_handle_irq(priv->virq_dma); | ||
523 | ack = 1; | ||
524 | } | ||
525 | |||
526 | /* | ||
527 | * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ | ||
528 | * Controller, this must be done after IRQ sources have been handled to | ||
529 | * avoid double IRQ generation | ||
530 | */ | ||
531 | if (ack) | ||
532 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | ||
533 | } | ||
534 | |||
535 | /* Create a virtual IRQ */ | ||
536 | static unsigned int grpci2_build_device_irq(unsigned int irq) | ||
537 | { | ||
538 | unsigned int virq = 0, pil; | ||
539 | |||
540 | pil = 1 << 8; | ||
541 | virq = irq_alloc(irq, pil); | ||
542 | if (virq == 0) | ||
543 | goto out; | ||
544 | |||
545 | irq_set_chip_and_handler_name(virq, &grpci2_irq, handle_simple_irq, | ||
546 | "pcilvl"); | ||
547 | irq_set_chip_data(virq, (void *)irq); | ||
548 | |||
549 | out: | ||
550 | return virq; | ||
551 | } | ||
552 | |||
553 | void grpci2_hw_init(struct grpci2_priv *priv) | ||
554 | { | ||
555 | u32 ahbadr, pciadr, bar_sz, capptr, io_map, data; | ||
556 | struct grpci2_regs *regs = priv->regs; | ||
557 | int i; | ||
558 | struct grpci2_barcfg *barcfg = priv->tgtbars; | ||
559 | |||
560 | /* Reset any earlier setup */ | ||
561 | if (priv->do_reset) { | ||
562 | printk(KERN_INFO "GRPCI2: Resetting PCI bus\n"); | ||
563 | REGSTORE(regs->ctrl, CTRL_RESET); | ||
564 | ssleep(1); /* Wait for boards to settle */ | ||
565 | } | ||
566 | REGSTORE(regs->ctrl, 0); | ||
567 | REGSTORE(regs->sts_cap, ~0); /* Clear Status */ | ||
568 | REGSTORE(regs->dma_ctrl, 0); | ||
569 | REGSTORE(regs->dma_bdbase, 0); | ||
570 | |||
571 | /* Translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */ | ||
572 | REGSTORE(regs->io_map, REGLOAD(regs->io_map) & 0x0000ffff); | ||
573 | |||
574 | /* set 1:1 mapping between AHB -> PCI memory space, for all Masters | ||
575 | * Each AHB master has it's own mapping registers. Max 16 AHB masters. | ||
576 | */ | ||
577 | for (i = 0; i < 16; i++) | ||
578 | REGSTORE(regs->ahbmst_map[i], priv->pci_area); | ||
579 | |||
580 | /* Get the GRPCI2 Host PCI ID */ | ||
581 | grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid); | ||
582 | |||
583 | /* Get address to first (always defined) capability structure */ | ||
584 | grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr); | ||
585 | |||
586 | /* Enable/Disable Byte twisting */ | ||
587 | grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map); | ||
588 | io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0); | ||
589 | grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map); | ||
590 | |||
591 | /* Setup the Host's PCI Target BARs for other peripherals to access, | ||
592 | * and do DMA to the host's memory. The target BARs can be sized and | ||
593 | * enabled individually. | ||
594 | * | ||
595 | * User may set custom target BARs, but default is: | ||
596 | * The first BARs is used to map kernel low (DMA is part of normal | ||
597 | * region on sparc which is SRMMU_MAXMEM big) main memory 1:1 to the | ||
598 | * PCI bus, the other BARs are disabled. We assume that the first BAR | ||
599 | * is always available. | ||
600 | */ | ||
601 | for (i = 0; i < 6; i++) { | ||
602 | if (barcfg[i].pciadr != ~0 && barcfg[i].ahbadr != ~0) { | ||
603 | /* Target BARs must have the proper alignment */ | ||
604 | ahbadr = barcfg[i].ahbadr; | ||
605 | pciadr = barcfg[i].pciadr; | ||
606 | bar_sz = ((pciadr - 1) & ~pciadr) + 1; | ||
607 | } else { | ||
608 | if (i == 0) { | ||
609 | /* Map main memory */ | ||
610 | bar_sz = 0xf0000008; /* 256MB prefetchable */ | ||
611 | ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN( | ||
612 | (unsigned long) &_end)); | ||
613 | pciadr = ahbadr; | ||
614 | } else { | ||
615 | bar_sz = 0; | ||
616 | ahbadr = 0; | ||
617 | pciadr = 0; | ||
618 | } | ||
619 | } | ||
620 | grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz); | ||
621 | grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr); | ||
622 | grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr); | ||
623 | printk(KERN_INFO " TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n", | ||
624 | i, pciadr, ahbadr); | ||
625 | } | ||
626 | |||
627 | /* set as bus master and enable pci memory responses */ | ||
628 | grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data); | ||
629 | data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | ||
630 | grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data); | ||
631 | |||
632 | /* Enable Error respone (CPU-TRAP) on illegal memory access. */ | ||
633 | REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE); | ||
634 | } | ||
635 | |||
636 | static irqreturn_t grpci2_jump_interrupt(int irq, void *arg) | ||
637 | { | ||
638 | printk(KERN_ERR "GRPCI2: Jump IRQ happened\n"); | ||
639 | return IRQ_NONE; | ||
640 | } | ||
641 | |||
642 | /* Handle GRPCI2 Error Interrupt */ | ||
643 | static irqreturn_t grpci2_err_interrupt(int irq, void *arg) | ||
644 | { | ||
645 | struct grpci2_priv *priv = arg; | ||
646 | struct grpci2_regs *regs = priv->regs; | ||
647 | unsigned int status; | ||
648 | |||
649 | status = REGLOAD(regs->sts_cap); | ||
650 | if ((status & STS_ERR_IRQ) == 0) | ||
651 | return IRQ_NONE; | ||
652 | |||
653 | if (status & STS_IPARERR) | ||
654 | printk(KERN_ERR "GRPCI2: Parity Error\n"); | ||
655 | |||
656 | if (status & STS_ITGTABRT) | ||
657 | printk(KERN_ERR "GRPCI2: Target Abort\n"); | ||
658 | |||
659 | if (status & STS_IMSTABRT) | ||
660 | printk(KERN_ERR "GRPCI2: Master Abort\n"); | ||
661 | |||
662 | if (status & STS_ISYSERR) | ||
663 | printk(KERN_ERR "GRPCI2: System Error\n"); | ||
664 | |||
665 | /* Clear handled INT TYPE IRQs */ | ||
666 | REGSTORE(regs->sts_cap, status & STS_ERR_IRQ); | ||
667 | |||
668 | return IRQ_HANDLED; | ||
669 | } | ||
670 | |||
671 | static int __devinit grpci2_of_probe(struct platform_device *ofdev) | ||
672 | { | ||
673 | struct grpci2_regs *regs; | ||
674 | struct grpci2_priv *priv; | ||
675 | int err, i, len; | ||
676 | const int *tmp; | ||
677 | unsigned int capability; | ||
678 | |||
679 | if (grpci2priv) { | ||
680 | printk(KERN_ERR "GRPCI2: only one GRPCI2 core supported\n"); | ||
681 | return -ENODEV; | ||
682 | } | ||
683 | |||
684 | if (ofdev->num_resources < 3) { | ||
685 | printk(KERN_ERR "GRPCI2: not enough APB/AHB resources\n"); | ||
686 | return -EIO; | ||
687 | } | ||
688 | |||
689 | /* Find Device Address */ | ||
690 | regs = of_ioremap(&ofdev->resource[0], 0, | ||
691 | resource_size(&ofdev->resource[0]), | ||
692 | "grlib-grpci2 regs"); | ||
693 | if (regs == NULL) { | ||
694 | printk(KERN_ERR "GRPCI2: ioremap failed\n"); | ||
695 | return -EIO; | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | * Check that we're in Host Slot and that we can act as a Host Bridge | ||
700 | * and not only as target. | ||
701 | */ | ||
702 | capability = REGLOAD(regs->sts_cap); | ||
703 | if ((capability & STS_HOST) || !(capability & STS_MST)) { | ||
704 | printk(KERN_INFO "GRPCI2: not in host system slot\n"); | ||
705 | err = -EIO; | ||
706 | goto err1; | ||
707 | } | ||
708 | |||
709 | priv = grpci2priv = kzalloc(sizeof(struct grpci2_priv), GFP_KERNEL); | ||
710 | if (grpci2priv == NULL) { | ||
711 | err = -ENOMEM; | ||
712 | goto err1; | ||
713 | } | ||
714 | memset(grpci2priv, 0, sizeof(*grpci2priv)); | ||
715 | priv->regs = regs; | ||
716 | priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ | ||
717 | priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; | ||
718 | |||
719 | printk(KERN_INFO "GRPCI2: host found at %p, irq%d\n", regs, priv->irq); | ||
720 | |||
721 | /* Byte twisting should be made configurable from kernel command line */ | ||
722 | priv->bt_enabled = 1; | ||
723 | |||
724 | /* Let user do custom Target BAR assignment */ | ||
725 | tmp = of_get_property(ofdev->dev.of_node, "barcfg", &len); | ||
726 | if (tmp && (len == 2*4*6)) | ||
727 | memcpy(priv->tgtbars, tmp, 2*4*6); | ||
728 | else | ||
729 | memset(priv->tgtbars, -1, 2*4*6); | ||
730 | |||
731 | /* Limit IRQ unmasking in irq_mode 2 and 3 */ | ||
732 | tmp = of_get_property(ofdev->dev.of_node, "irq_mask", &len); | ||
733 | if (tmp && (len == 4)) | ||
734 | priv->do_reset = *tmp; | ||
735 | else | ||
736 | priv->irq_mask = 0xf; | ||
737 | |||
738 | /* Optional PCI reset. Force PCI reset on startup */ | ||
739 | tmp = of_get_property(ofdev->dev.of_node, "reset", &len); | ||
740 | if (tmp && (len == 4)) | ||
741 | priv->do_reset = *tmp; | ||
742 | else | ||
743 | priv->do_reset = 0; | ||
744 | |||
745 | /* Find PCI Memory, I/O and Configuration Space Windows */ | ||
746 | priv->pci_area = ofdev->resource[1].start; | ||
747 | priv->pci_area_end = ofdev->resource[1].end+1; | ||
748 | priv->pci_io = ofdev->resource[2].start; | ||
749 | priv->pci_conf = ofdev->resource[2].start + 0x10000; | ||
750 | priv->pci_conf_end = priv->pci_conf + 0x10000; | ||
751 | priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000); | ||
752 | if (!priv->pci_io_va) { | ||
753 | err = -EIO; | ||
754 | goto err2; | ||
755 | } | ||
756 | |||
757 | printk(KERN_INFO | ||
758 | "GRPCI2: MEMORY SPACE [0x%08lx - 0x%08lx]\n" | ||
759 | " I/O SPACE [0x%08lx - 0x%08lx]\n" | ||
760 | " CONFIG SPACE [0x%08lx - 0x%08lx]\n", | ||
761 | priv->pci_area, priv->pci_area_end-1, | ||
762 | priv->pci_io, priv->pci_conf-1, | ||
763 | priv->pci_conf, priv->pci_conf_end-1); | ||
764 | |||
765 | /* | ||
766 | * I/O Space resources in I/O Window mapped into Virtual Adr Space | ||
767 | * We never use low 4KB because some devices seem have problems using | ||
768 | * address 0. | ||
769 | */ | ||
770 | memset(&priv->info.io_space, 0, sizeof(struct resource)); | ||
771 | priv->info.io_space.name = "GRPCI2 PCI I/O Space"; | ||
772 | priv->info.io_space.start = priv->pci_io_va + 0x1000; | ||
773 | priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1; | ||
774 | priv->info.io_space.flags = IORESOURCE_IO; | ||
775 | |||
776 | /* | ||
777 | * GRPCI2 has no prefetchable memory, map everything as | ||
778 | * non-prefetchable memory | ||
779 | */ | ||
780 | memset(&priv->info.mem_space, 0, sizeof(struct resource)); | ||
781 | priv->info.mem_space.name = "GRPCI2 PCI MEM Space"; | ||
782 | priv->info.mem_space.start = priv->pci_area; | ||
783 | priv->info.mem_space.end = priv->pci_area_end - 1; | ||
784 | priv->info.mem_space.flags = IORESOURCE_MEM; | ||
785 | |||
786 | if (request_resource(&iomem_resource, &priv->info.mem_space) < 0) | ||
787 | goto err3; | ||
788 | if (request_resource(&ioport_resource, &priv->info.io_space) < 0) | ||
789 | goto err4; | ||
790 | |||
791 | grpci2_hw_init(priv); | ||
792 | |||
793 | /* | ||
794 | * Get PCI Interrupt to System IRQ mapping and setup IRQ handling | ||
795 | * Error IRQ always on PCI INTA. | ||
796 | */ | ||
797 | if (priv->irq_mode < 2) { | ||
798 | /* All PCI interrupts are shared using the same system IRQ */ | ||
799 | leon_update_virq_handling(priv->irq, grpci2_pci_flow_irq, | ||
800 | "pcilvl", 0); | ||
801 | |||
802 | priv->irq_map[0] = grpci2_build_device_irq(1); | ||
803 | priv->irq_map[1] = grpci2_build_device_irq(2); | ||
804 | priv->irq_map[2] = grpci2_build_device_irq(3); | ||
805 | priv->irq_map[3] = grpci2_build_device_irq(4); | ||
806 | |||
807 | priv->virq_err = grpci2_build_device_irq(5); | ||
808 | if (priv->irq_mode & 1) | ||
809 | priv->virq_dma = ofdev->archdata.irqs[1]; | ||
810 | else | ||
811 | priv->virq_dma = grpci2_build_device_irq(6); | ||
812 | |||
813 | /* Enable IRQs on LEON IRQ controller */ | ||
814 | err = request_irq(priv->irq, grpci2_jump_interrupt, 0, | ||
815 | "GRPCI2_JUMP", priv); | ||
816 | if (err) | ||
817 | printk(KERN_ERR "GRPCI2: ERR IRQ request failed\n"); | ||
818 | } else { | ||
819 | /* All PCI interrupts have an unique IRQ interrupt */ | ||
820 | for (i = 0; i < 4; i++) { | ||
821 | /* Make LEON IRQ layer handle level IRQ by acking */ | ||
822 | leon_update_virq_handling(ofdev->archdata.irqs[i], | ||
823 | handle_fasteoi_irq, "pcilvl", | ||
824 | 1); | ||
825 | priv->irq_map[i] = ofdev->archdata.irqs[i]; | ||
826 | } | ||
827 | priv->virq_err = priv->irq_map[0]; | ||
828 | if (priv->irq_mode & 1) | ||
829 | priv->virq_dma = ofdev->archdata.irqs[4]; | ||
830 | else | ||
831 | priv->virq_dma = priv->irq_map[0]; | ||
832 | |||
833 | /* Unmask all PCI interrupts, request_irq will not do that */ | ||
834 | REGSTORE(regs->ctrl, REGLOAD(regs->ctrl)|(priv->irq_mask&0xf)); | ||
835 | } | ||
836 | |||
837 | /* Setup IRQ handler for non-configuration space access errors */ | ||
838 | err = request_irq(priv->virq_err, grpci2_err_interrupt, IRQF_SHARED, | ||
839 | "GRPCI2_ERR", priv); | ||
840 | if (err) { | ||
841 | printk(KERN_DEBUG "GRPCI2: ERR VIRQ request failed: %d\n", err); | ||
842 | goto err5; | ||
843 | } | ||
844 | |||
845 | /* | ||
846 | * Enable Error Interrupts. PCI interrupts are unmasked once request_irq | ||
847 | * is called by the PCI Device drivers | ||
848 | */ | ||
849 | REGSTORE(regs->ctrl, REGLOAD(regs->ctrl) | CTRL_EI | CTRL_SI); | ||
850 | |||
851 | /* Init common layer and scan buses */ | ||
852 | priv->info.ops = &grpci2_ops; | ||
853 | priv->info.map_irq = grpci2_map_irq; | ||
854 | leon_pci_init(ofdev, &priv->info); | ||
855 | |||
856 | return 0; | ||
857 | |||
858 | err5: | ||
859 | release_resource(&priv->info.io_space); | ||
860 | err4: | ||
861 | release_resource(&priv->info.mem_space); | ||
862 | err3: | ||
863 | err = -ENOMEM; | ||
864 | iounmap((void *)priv->pci_io_va); | ||
865 | err2: | ||
866 | kfree(priv); | ||
867 | err1: | ||
868 | of_iounmap(&ofdev->resource[0], regs, | ||
869 | resource_size(&ofdev->resource[0])); | ||
870 | return err; | ||
871 | } | ||
872 | |||
873 | static struct of_device_id grpci2_of_match[] = { | ||
874 | { | ||
875 | .name = "GAISLER_GRPCI2", | ||
876 | }, | ||
877 | { | ||
878 | .name = "01_07c", | ||
879 | }, | ||
880 | {}, | ||
881 | }; | ||
882 | |||
883 | static struct platform_driver grpci2_of_driver = { | ||
884 | .driver = { | ||
885 | .name = "grpci2", | ||
886 | .owner = THIS_MODULE, | ||
887 | .of_match_table = grpci2_of_match, | ||
888 | }, | ||
889 | .probe = grpci2_of_probe, | ||
890 | }; | ||
891 | |||
892 | static int __init grpci2_init(void) | ||
893 | { | ||
894 | return platform_driver_register(&grpci2_of_driver); | ||
895 | } | ||
896 | |||
897 | subsys_initcall(grpci2_init); | ||
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 e1656fc41ccb..fe8fb44c609c 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
@@ -12,9 +12,9 @@ | |||
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/threads.h> | 13 | #include <linux/threads.h> |
14 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
17 | #include <linux/kernel_stat.h> | 16 | #include <linux/kernel_stat.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/ptrace.h> | 30 | #include <asm/ptrace.h> |
31 | #include <asm/atomic.h> | 31 | #include <asm/atomic.h> |
32 | #include <asm/irq_regs.h> | 32 | #include <asm/irq_regs.h> |
33 | #include <asm/traps.h> | ||
33 | 34 | ||
34 | #include <asm/delay.h> | 35 | #include <asm/delay.h> |
35 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
@@ -42,6 +43,8 @@ | |||
42 | #include <asm/leon.h> | 43 | #include <asm/leon.h> |
43 | #include <asm/leon_amba.h> | 44 | #include <asm/leon_amba.h> |
44 | 45 | ||
46 | #include "kernel.h" | ||
47 | |||
45 | #ifdef CONFIG_SPARC_LEON | 48 | #ifdef CONFIG_SPARC_LEON |
46 | 49 | ||
47 | #include "irq.h" | 50 | #include "irq.h" |
@@ -49,15 +52,18 @@ | |||
49 | extern ctxd_t *srmmu_ctx_table_phys; | 52 | extern ctxd_t *srmmu_ctx_table_phys; |
50 | static int smp_processors_ready; | 53 | static int smp_processors_ready; |
51 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | 54 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; |
52 | extern unsigned char boot_cpu_id; | ||
53 | extern cpumask_t smp_commenced_mask; | 55 | extern cpumask_t smp_commenced_mask; |
54 | void __init leon_configure_cache_smp(void); | 56 | void __init leon_configure_cache_smp(void); |
57 | static void leon_ipi_init(void); | ||
58 | |||
59 | /* IRQ number of LEON IPIs */ | ||
60 | int leon_ipi_irq = LEON3_IRQ_IPI_DEFAULT; | ||
55 | 61 | ||
56 | static inline unsigned long do_swap(volatile unsigned long *ptr, | 62 | static inline unsigned long do_swap(volatile unsigned long *ptr, |
57 | unsigned long val) | 63 | unsigned long val) |
58 | { | 64 | { |
59 | __asm__ __volatile__("swapa [%1] %2, %0\n\t" : "=&r"(val) | 65 | __asm__ __volatile__("swapa [%2] %3, %0\n\t" : "=&r"(val) |
60 | : "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) | 66 | : "0"(val), "r"(ptr), "i"(ASI_LEON_DCACHE_MISS) |
61 | : "memory"); | 67 | : "memory"); |
62 | return val; | 68 | return val; |
63 | } | 69 | } |
@@ -93,8 +99,6 @@ void __cpuinit leon_callin(void) | |||
93 | local_flush_cache_all(); | 99 | local_flush_cache_all(); |
94 | local_flush_tlb_all(); | 100 | local_flush_tlb_all(); |
95 | 101 | ||
96 | cpu_probe(); | ||
97 | |||
98 | /* Fix idle thread fields. */ | 102 | /* Fix idle thread fields. */ |
99 | __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_set[cpuid]) | 103 | __asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_set[cpuid]) |
100 | : "memory" /* paranoid */); | 104 | : "memory" /* paranoid */); |
@@ -103,11 +107,11 @@ void __cpuinit leon_callin(void) | |||
103 | atomic_inc(&init_mm.mm_count); | 107 | atomic_inc(&init_mm.mm_count); |
104 | current->active_mm = &init_mm; | 108 | current->active_mm = &init_mm; |
105 | 109 | ||
106 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 110 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
107 | mb(); | 111 | mb(); |
108 | 112 | ||
109 | local_irq_enable(); | 113 | local_irq_enable(); |
110 | cpu_set(cpuid, cpu_online_map); | 114 | set_cpu_online(cpuid, true); |
111 | } | 115 | } |
112 | 116 | ||
113 | /* | 117 | /* |
@@ -178,13 +182,16 @@ void __init leon_boot_cpus(void) | |||
178 | int nrcpu = leon_smp_nrcpus(); | 182 | int nrcpu = leon_smp_nrcpus(); |
179 | int me = smp_processor_id(); | 183 | int me = smp_processor_id(); |
180 | 184 | ||
185 | /* Setup IPI */ | ||
186 | leon_ipi_init(); | ||
187 | |||
181 | printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsigned int)me, | 188 | printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsigned int)me, |
182 | (unsigned int)nrcpu, (unsigned int)NR_CPUS, | 189 | (unsigned int)nrcpu, (unsigned int)NR_CPUS, |
183 | (unsigned int)&(leon3_irqctrl_regs->mpstatus)); | 190 | (unsigned int)&(leon3_irqctrl_regs->mpstatus)); |
184 | 191 | ||
185 | leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me); | 192 | leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me); |
186 | leon_enable_irq_cpu(LEON3_IRQ_TICKER, me); | 193 | leon_enable_irq_cpu(LEON3_IRQ_TICKER, me); |
187 | leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, me); | 194 | leon_enable_irq_cpu(leon_ipi_irq, me); |
188 | 195 | ||
189 | leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); | 196 | leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER); |
190 | 197 | ||
@@ -219,6 +226,10 @@ int __cpuinit leon_boot_one_cpu(int i) | |||
219 | (unsigned int)&leon3_irqctrl_regs->mpstatus); | 226 | (unsigned int)&leon3_irqctrl_regs->mpstatus); |
220 | local_flush_cache_all(); | 227 | local_flush_cache_all(); |
221 | 228 | ||
229 | /* Make sure all IRQs are of from the start for this new CPU */ | ||
230 | LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); | ||
231 | |||
232 | /* Wake one CPU */ | ||
222 | LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpstatus), 1 << i); | 233 | LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpstatus), 1 << i); |
223 | 234 | ||
224 | /* wheee... it's going... */ | 235 | /* wheee... it's going... */ |
@@ -235,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i) | |||
235 | } else { | 246 | } else { |
236 | leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i); | 247 | leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i); |
237 | leon_enable_irq_cpu(LEON3_IRQ_TICKER, i); | 248 | leon_enable_irq_cpu(LEON3_IRQ_TICKER, i); |
238 | leon_enable_irq_cpu(LEON3_IRQ_RESCHEDULE, i); | 249 | leon_enable_irq_cpu(leon_ipi_irq, i); |
239 | } | 250 | } |
240 | 251 | ||
241 | local_flush_cache_all(); | 252 | local_flush_cache_all(); |
@@ -261,24 +272,24 @@ void __init leon_smp_done(void) | |||
261 | local_flush_cache_all(); | 272 | local_flush_cache_all(); |
262 | 273 | ||
263 | /* Free unneeded trap tables */ | 274 | /* Free unneeded trap tables */ |
264 | if (!cpu_isset(1, cpu_present_map)) { | 275 | if (!cpu_present(1)) { |
265 | ClearPageReserved(virt_to_page(trapbase_cpu1)); | 276 | ClearPageReserved(virt_to_page(&trapbase_cpu1)); |
266 | init_page_count(virt_to_page(trapbase_cpu1)); | 277 | init_page_count(virt_to_page(&trapbase_cpu1)); |
267 | free_page((unsigned long)trapbase_cpu1); | 278 | free_page((unsigned long)&trapbase_cpu1); |
268 | totalram_pages++; | 279 | totalram_pages++; |
269 | num_physpages++; | 280 | num_physpages++; |
270 | } | 281 | } |
271 | if (!cpu_isset(2, cpu_present_map)) { | 282 | if (!cpu_present(2)) { |
272 | ClearPageReserved(virt_to_page(trapbase_cpu2)); | 283 | ClearPageReserved(virt_to_page(&trapbase_cpu2)); |
273 | init_page_count(virt_to_page(trapbase_cpu2)); | 284 | init_page_count(virt_to_page(&trapbase_cpu2)); |
274 | free_page((unsigned long)trapbase_cpu2); | 285 | free_page((unsigned long)&trapbase_cpu2); |
275 | totalram_pages++; | 286 | totalram_pages++; |
276 | num_physpages++; | 287 | num_physpages++; |
277 | } | 288 | } |
278 | if (!cpu_isset(3, cpu_present_map)) { | 289 | if (!cpu_present(3)) { |
279 | ClearPageReserved(virt_to_page(trapbase_cpu3)); | 290 | ClearPageReserved(virt_to_page(&trapbase_cpu3)); |
280 | init_page_count(virt_to_page(trapbase_cpu3)); | 291 | init_page_count(virt_to_page(&trapbase_cpu3)); |
281 | free_page((unsigned long)trapbase_cpu3); | 292 | free_page((unsigned long)&trapbase_cpu3); |
282 | totalram_pages++; | 293 | totalram_pages++; |
283 | num_physpages++; | 294 | num_physpages++; |
284 | } | 295 | } |
@@ -291,6 +302,99 @@ void leon_irq_rotate(int cpu) | |||
291 | { | 302 | { |
292 | } | 303 | } |
293 | 304 | ||
305 | struct leon_ipi_work { | ||
306 | int single; | ||
307 | int msk; | ||
308 | int resched; | ||
309 | }; | ||
310 | |||
311 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct leon_ipi_work, leon_ipi_work); | ||
312 | |||
313 | /* Initialize IPIs on the LEON, in order to save IRQ resources only one IRQ | ||
314 | * is used for all three types of IPIs. | ||
315 | */ | ||
316 | static void __init leon_ipi_init(void) | ||
317 | { | ||
318 | int cpu, len; | ||
319 | struct leon_ipi_work *work; | ||
320 | struct property *pp; | ||
321 | struct device_node *rootnp; | ||
322 | struct tt_entry *trap_table; | ||
323 | unsigned long flags; | ||
324 | |||
325 | /* Find IPI IRQ or stick with default value */ | ||
326 | rootnp = of_find_node_by_path("/ambapp0"); | ||
327 | if (rootnp) { | ||
328 | pp = of_find_property(rootnp, "ipi_num", &len); | ||
329 | if (pp && (*(int *)pp->value)) | ||
330 | leon_ipi_irq = *(int *)pp->value; | ||
331 | } | ||
332 | printk(KERN_INFO "leon: SMP IPIs at IRQ %d\n", leon_ipi_irq); | ||
333 | |||
334 | /* Adjust so that we jump directly to smpleon_ipi */ | ||
335 | local_irq_save(flags); | ||
336 | trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)]; | ||
337 | trap_table->inst_three += smpleon_ipi - real_irq_entry; | ||
338 | local_flush_cache_all(); | ||
339 | local_irq_restore(flags); | ||
340 | |||
341 | for_each_possible_cpu(cpu) { | ||
342 | work = &per_cpu(leon_ipi_work, cpu); | ||
343 | work->single = work->msk = work->resched = 0; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | static void leon_ipi_single(int cpu) | ||
348 | { | ||
349 | struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); | ||
350 | |||
351 | /* Mark work */ | ||
352 | work->single = 1; | ||
353 | |||
354 | /* Generate IRQ on the CPU */ | ||
355 | set_cpu_int(cpu, leon_ipi_irq); | ||
356 | } | ||
357 | |||
358 | static void leon_ipi_mask_one(int cpu) | ||
359 | { | ||
360 | struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); | ||
361 | |||
362 | /* Mark work */ | ||
363 | work->msk = 1; | ||
364 | |||
365 | /* Generate IRQ on the CPU */ | ||
366 | set_cpu_int(cpu, leon_ipi_irq); | ||
367 | } | ||
368 | |||
369 | static void leon_ipi_resched(int cpu) | ||
370 | { | ||
371 | struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); | ||
372 | |||
373 | /* Mark work */ | ||
374 | work->resched = 1; | ||
375 | |||
376 | /* Generate IRQ on the CPU (any IRQ will cause resched) */ | ||
377 | set_cpu_int(cpu, leon_ipi_irq); | ||
378 | } | ||
379 | |||
380 | void leonsmp_ipi_interrupt(void) | ||
381 | { | ||
382 | struct leon_ipi_work *work = &__get_cpu_var(leon_ipi_work); | ||
383 | |||
384 | if (work->single) { | ||
385 | work->single = 0; | ||
386 | smp_call_function_single_interrupt(); | ||
387 | } | ||
388 | if (work->msk) { | ||
389 | work->msk = 0; | ||
390 | smp_call_function_interrupt(); | ||
391 | } | ||
392 | if (work->resched) { | ||
393 | work->resched = 0; | ||
394 | smp_resched_interrupt(); | ||
395 | } | ||
396 | } | ||
397 | |||
294 | static struct smp_funcall { | 398 | static struct smp_funcall { |
295 | smpfunc_t func; | 399 | smpfunc_t func; |
296 | unsigned long arg1; | 400 | unsigned long arg1; |
@@ -336,10 +440,10 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
336 | { | 440 | { |
337 | register int i; | 441 | register int i; |
338 | 442 | ||
339 | cpu_clear(smp_processor_id(), mask); | 443 | cpumask_clear_cpu(smp_processor_id(), &mask); |
340 | cpus_and(mask, cpu_online_map, mask); | 444 | cpumask_and(&mask, cpu_online_mask, &mask); |
341 | for (i = 0; i <= high; i++) { | 445 | for (i = 0; i <= high; i++) { |
342 | if (cpu_isset(i, mask)) { | 446 | if (cpumask_test_cpu(i, &mask)) { |
343 | ccall_info.processors_in[i] = 0; | 447 | ccall_info.processors_in[i] = 0; |
344 | ccall_info.processors_out[i] = 0; | 448 | ccall_info.processors_out[i] = 0; |
345 | set_cpu_int(i, LEON3_IRQ_CROSS_CALL); | 449 | set_cpu_int(i, LEON3_IRQ_CROSS_CALL); |
@@ -353,7 +457,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
353 | 457 | ||
354 | i = 0; | 458 | i = 0; |
355 | do { | 459 | do { |
356 | if (!cpu_isset(i, mask)) | 460 | if (!cpumask_test_cpu(i, &mask)) |
357 | continue; | 461 | continue; |
358 | 462 | ||
359 | while (!ccall_info.processors_in[i]) | 463 | while (!ccall_info.processors_in[i]) |
@@ -362,7 +466,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
362 | 466 | ||
363 | i = 0; | 467 | i = 0; |
364 | do { | 468 | do { |
365 | if (!cpu_isset(i, mask)) | 469 | if (!cpumask_test_cpu(i, &mask)) |
366 | continue; | 470 | continue; |
367 | 471 | ||
368 | while (!ccall_info.processors_out[i]) | 472 | while (!ccall_info.processors_out[i]) |
@@ -385,27 +489,23 @@ void leon_cross_call_irq(void) | |||
385 | ccall_info.processors_out[i] = 1; | 489 | ccall_info.processors_out[i] = 1; |
386 | } | 490 | } |
387 | 491 | ||
388 | void leon_percpu_timer_interrupt(struct pt_regs *regs) | 492 | irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) |
389 | { | 493 | { |
390 | struct pt_regs *old_regs; | ||
391 | int cpu = smp_processor_id(); | 494 | int cpu = smp_processor_id(); |
392 | 495 | ||
393 | old_regs = set_irq_regs(regs); | ||
394 | |||
395 | leon_clear_profile_irq(cpu); | 496 | leon_clear_profile_irq(cpu); |
396 | 497 | ||
397 | profile_tick(CPU_PROFILING); | 498 | profile_tick(CPU_PROFILING); |
398 | 499 | ||
399 | if (!--prof_counter(cpu)) { | 500 | if (!--prof_counter(cpu)) { |
400 | int user = user_mode(regs); | 501 | int user = user_mode(get_irq_regs()); |
401 | 502 | ||
402 | irq_enter(); | ||
403 | update_process_times(user); | 503 | update_process_times(user); |
404 | irq_exit(); | ||
405 | 504 | ||
406 | prof_counter(cpu) = prof_multiplier(cpu); | 505 | prof_counter(cpu) = prof_multiplier(cpu); |
407 | } | 506 | } |
408 | set_irq_regs(old_regs); | 507 | |
508 | return IRQ_HANDLED; | ||
409 | } | 509 | } |
410 | 510 | ||
411 | static void __init smp_setup_percpu_timer(void) | 511 | static void __init smp_setup_percpu_timer(void) |
@@ -438,15 +538,6 @@ void __init leon_blackbox_current(unsigned *addr) | |||
438 | 538 | ||
439 | } | 539 | } |
440 | 540 | ||
441 | /* | ||
442 | * CPU idle callback function | ||
443 | * See .../arch/sparc/kernel/process.c | ||
444 | */ | ||
445 | void pmc_leon_idle(void) | ||
446 | { | ||
447 | __asm__ volatile ("mov %g0, %asr19"); | ||
448 | } | ||
449 | |||
450 | void __init leon_init_smp(void) | 541 | void __init leon_init_smp(void) |
451 | { | 542 | { |
452 | /* Patch ipi15 trap table */ | 543 | /* Patch ipi15 trap table */ |
@@ -457,13 +548,9 @@ void __init leon_init_smp(void) | |||
457 | BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); | 548 | BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); |
458 | BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, | 549 | BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, |
459 | BTFIXUPCALL_NORM); | 550 | BTFIXUPCALL_NORM); |
460 | 551 | BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM); | |
461 | #ifndef PMC_NO_IDLE | 552 | BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM); |
462 | /* Assign power management IDLE handler */ | 553 | BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM); |
463 | pm_idle = pmc_leon_idle; | ||
464 | printk(KERN_INFO "leon: power management initialized\n"); | ||
465 | #endif | ||
466 | |||
467 | } | 554 | } |
468 | 555 | ||
469 | #endif /* CONFIG_SPARC_LEON */ | 556 | #endif /* CONFIG_SPARC_LEON */ |
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 83e85c2e802a..42f28c7420e1 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c | |||
@@ -107,7 +107,7 @@ static struct mdesc_handle * __init mdesc_memblock_alloc(unsigned int mdesc_size | |||
107 | return hp; | 107 | return hp; |
108 | } | 108 | } |
109 | 109 | ||
110 | static void mdesc_memblock_free(struct mdesc_handle *hp) | 110 | static void __init mdesc_memblock_free(struct mdesc_handle *hp) |
111 | { | 111 | { |
112 | unsigned int alloc_size; | 112 | unsigned int alloc_size; |
113 | unsigned long start; | 113 | unsigned long start; |
@@ -768,7 +768,7 @@ static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handl | |||
768 | cpuid, NR_CPUS); | 768 | cpuid, NR_CPUS); |
769 | continue; | 769 | continue; |
770 | } | 770 | } |
771 | if (!cpu_isset(cpuid, *mask)) | 771 | if (!cpumask_test_cpu(cpuid, mask)) |
772 | continue; | 772 | continue; |
773 | #endif | 773 | #endif |
774 | 774 | ||
@@ -890,6 +890,7 @@ static ssize_t mdesc_read(struct file *file, char __user *buf, | |||
890 | static const struct file_operations mdesc_fops = { | 890 | static const struct file_operations mdesc_fops = { |
891 | .read = mdesc_read, | 891 | .read = mdesc_read, |
892 | .owner = THIS_MODULE, | 892 | .owner = THIS_MODULE, |
893 | .llseek = noop_llseek, | ||
893 | }; | 894 | }; |
894 | 895 | ||
895 | static struct miscdevice mdesc_misc = { | 896 | static struct miscdevice mdesc_misc = { |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index f848aadf54dc..99ba5baa9497 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
@@ -18,19 +18,16 @@ | |||
18 | #include <asm/spitfire.h> | 18 | #include <asm/spitfire.h> |
19 | 19 | ||
20 | #ifdef CONFIG_SPARC64 | 20 | #ifdef CONFIG_SPARC64 |
21 | static void *module_map(unsigned long size) | ||
22 | { | ||
23 | struct vm_struct *area; | ||
24 | 21 | ||
25 | size = PAGE_ALIGN(size); | 22 | #include <linux/jump_label.h> |
26 | if (!size || size > MODULES_LEN) | ||
27 | return NULL; | ||
28 | 23 | ||
29 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); | 24 | static void *module_map(unsigned long size) |
30 | if (!area) | 25 | { |
26 | if (PAGE_ALIGN(size) > MODULES_LEN) | ||
31 | return NULL; | 27 | return NULL; |
32 | 28 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, | |
33 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); | 29 | GFP_KERNEL, PAGE_KERNEL, -1, |
30 | __builtin_return_address(0)); | ||
34 | } | 31 | } |
35 | 32 | ||
36 | static char *dot2underscore(char *name) | 33 | static char *dot2underscore(char *name) |
@@ -217,7 +214,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, | |||
217 | me->name, | 214 | me->name, |
218 | (int) (ELF_R_TYPE(rel[i].r_info) & 0xff)); | 215 | (int) (ELF_R_TYPE(rel[i].r_info) & 0xff)); |
219 | return -ENOEXEC; | 216 | return -ENOEXEC; |
220 | }; | 217 | } |
221 | } | 218 | } |
222 | return 0; | 219 | return 0; |
223 | } | 220 | } |
@@ -227,6 +224,9 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
227 | const Elf_Shdr *sechdrs, | 224 | const Elf_Shdr *sechdrs, |
228 | struct module *me) | 225 | struct module *me) |
229 | { | 226 | { |
227 | /* make jump label nops */ | ||
228 | jump_label_apply_nops(me); | ||
229 | |||
230 | /* Cheetah's I-cache is fully coherent. */ | 230 | /* Cheetah's I-cache is fully coherent. */ |
231 | if (tlb_type == spitfire) { | 231 | if (tlb_type == spitfire) { |
232 | unsigned long va; | 232 | unsigned long va; |
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index a4bd7ba74c89..300f810142f5 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c | |||
@@ -270,8 +270,6 @@ int __init nmi_init(void) | |||
270 | atomic_set(&nmi_active, -1); | 270 | atomic_set(&nmi_active, -1); |
271 | } | 271 | } |
272 | } | 272 | } |
273 | if (!err) | ||
274 | init_hw_perf_events(); | ||
275 | 273 | ||
276 | return err; | 274 | return err; |
277 | } | 275 | } |
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/of_device_64.c b/arch/sparc/kernel/of_device_64.c index 63cd4e5d47c2..3bb2eace58cf 100644 --- a/arch/sparc/kernel/of_device_64.c +++ b/arch/sparc/kernel/of_device_64.c | |||
@@ -459,7 +459,7 @@ apply_interrupt_map(struct device_node *dp, struct device_node *pp, | |||
459 | * | 459 | * |
460 | * Handle this by deciding that, if we didn't get a | 460 | * Handle this by deciding that, if we didn't get a |
461 | * match in the parent's 'interrupt-map', and the | 461 | * match in the parent's 'interrupt-map', and the |
462 | * parent is an IRQ translater, then use the parent as | 462 | * parent is an IRQ translator, then use the parent as |
463 | * our IRQ controller. | 463 | * our IRQ controller. |
464 | */ | 464 | */ |
465 | if (pp->irq_trans) | 465 | if (pp->irq_trans) |
@@ -622,8 +622,9 @@ static unsigned int __init build_one_device_irq(struct platform_device *op, | |||
622 | out: | 622 | out: |
623 | nid = of_node_to_nid(dp); | 623 | nid = of_node_to_nid(dp); |
624 | if (nid != -1) { | 624 | if (nid != -1) { |
625 | cpumask_t numa_mask = *cpumask_of_node(nid); | 625 | cpumask_t numa_mask; |
626 | 626 | ||
627 | cpumask_copy(&numa_mask, cpumask_of_node(nid)); | ||
627 | irq_set_affinity(irq, &numa_mask); | 628 | irq_set_affinity(irq, &numa_mask); |
628 | } | 629 | } |
629 | 630 | ||
diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c index 49ddff56cb04..cb15bbf8a201 100644 --- a/arch/sparc/kernel/of_device_common.c +++ b/arch/sparc/kernel/of_device_common.c | |||
@@ -22,6 +22,33 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) | |||
22 | } | 22 | } |
23 | EXPORT_SYMBOL(irq_of_parse_and_map); | 23 | EXPORT_SYMBOL(irq_of_parse_and_map); |
24 | 24 | ||
25 | int of_address_to_resource(struct device_node *node, int index, | ||
26 | struct resource *r) | ||
27 | { | ||
28 | struct platform_device *op = of_find_device_by_node(node); | ||
29 | |||
30 | if (!op || index >= op->num_resources) | ||
31 | return -EINVAL; | ||
32 | |||
33 | memcpy(r, &op->archdata.resource[index], sizeof(*r)); | ||
34 | return 0; | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(of_address_to_resource); | ||
37 | |||
38 | void __iomem *of_iomap(struct device_node *node, int index) | ||
39 | { | ||
40 | struct platform_device *op = of_find_device_by_node(node); | ||
41 | struct resource *r; | ||
42 | |||
43 | if (!op || index >= op->num_resources) | ||
44 | return NULL; | ||
45 | |||
46 | r = &op->archdata.resource[index]; | ||
47 | |||
48 | return of_ioremap(r, 0, resource_size(r), (char *) r->name); | ||
49 | } | ||
50 | EXPORT_SYMBOL(of_iomap); | ||
51 | |||
25 | /* Take the archdata values for IOMMU, STC, and HOSTDATA found in | 52 | /* Take the archdata values for IOMMU, STC, and HOSTDATA found in |
26 | * BUS and propagate to all child platform_device objects. | 53 | * BUS and propagate to all child platform_device objects. |
27 | */ | 54 | */ |
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 4137579d9adc..713dc91020a6 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 = irq_get_msi_desc(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..a6895987fb70 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c | |||
@@ -281,7 +281,7 @@ static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
281 | case 4: | 281 | case 4: |
282 | *value = ret & 0xffffffff; | 282 | *value = ret & 0xffffffff; |
283 | break; | 283 | break; |
284 | }; | 284 | } |
285 | 285 | ||
286 | 286 | ||
287 | return PCIBIOS_SUCCESSFUL; | 287 | return PCIBIOS_SUCCESSFUL; |
@@ -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 | } |
@@ -453,7 +456,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
453 | 456 | ||
454 | default: | 457 | default: |
455 | break; | 458 | break; |
456 | }; | 459 | } |
457 | } | 460 | } |
458 | 461 | ||
459 | if (!saw_io || !saw_mem) { | 462 | if (!saw_io || !saw_mem) { |
diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c index efb896d68754..d29a32fcc5e4 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 = { |
@@ -455,8 +453,7 @@ static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm, | |||
455 | return 0; | 453 | return 0; |
456 | } | 454 | } |
457 | 455 | ||
458 | static int __devinit fire_probe(struct platform_device *op, | 456 | static int __devinit fire_probe(struct platform_device *op) |
459 | const struct of_device_id *match) | ||
460 | { | 457 | { |
461 | struct device_node *dp = op->dev.of_node; | 458 | struct device_node *dp = op->dev.of_node; |
462 | struct pci_pbm_info *pbm; | 459 | struct pci_pbm_info *pbm; |
@@ -499,7 +496,7 @@ out_err: | |||
499 | return err; | 496 | return err; |
500 | } | 497 | } |
501 | 498 | ||
502 | static struct of_device_id __initdata fire_match[] = { | 499 | static const struct of_device_id fire_match[] = { |
503 | { | 500 | { |
504 | .name = "pci", | 501 | .name = "pci", |
505 | .compatible = "pciex108e,80f0", | 502 | .compatible = "pciex108e,80f0", |
@@ -507,7 +504,7 @@ static struct of_device_id __initdata fire_match[] = { | |||
507 | {}, | 504 | {}, |
508 | }; | 505 | }; |
509 | 506 | ||
510 | static struct of_platform_driver fire_driver = { | 507 | static struct platform_driver fire_driver = { |
511 | .driver = { | 508 | .driver = { |
512 | .name = DRIVER_NAME, | 509 | .name = DRIVER_NAME, |
513 | .owner = THIS_MODULE, | 510 | .owner = THIS_MODULE, |
@@ -518,7 +515,7 @@ static struct of_platform_driver fire_driver = { | |||
518 | 515 | ||
519 | static int __init fire_init(void) | 516 | static int __init fire_init(void) |
520 | { | 517 | { |
521 | return of_register_platform_driver(&fire_driver); | 518 | return platform_driver_register(&fire_driver); |
522 | } | 519 | } |
523 | 520 | ||
524 | subsys_initcall(fire_init); | 521 | subsys_initcall(fire_init); |
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 548b8ca9c210..580651af73f2 100644 --- a/arch/sparc/kernel/pci_msi.c +++ b/arch/sparc/kernel/pci_msi.c | |||
@@ -30,13 +30,10 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie) | |||
30 | 30 | ||
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 | unsigned int irq; |
34 | unsigned int virt_irq; | ||
35 | 34 | ||
36 | virt_irq = pbm->msi_irq_table[msi - pbm->msi_first]; | 35 | irq = pbm->msi_irq_table[msi - pbm->msi_first]; |
37 | desc = irq_desc + virt_irq; | 36 | generic_handle_irq(irq); |
38 | |||
39 | desc->handle_irq(virt_irq, desc); | ||
40 | } | 37 | } |
41 | 38 | ||
42 | if (unlikely(err < 0)) | 39 | if (unlikely(err < 0)) |
@@ -114,14 +111,14 @@ static void free_msi(struct pci_pbm_info *pbm, int msi_num) | |||
114 | 111 | ||
115 | static struct irq_chip msi_irq = { | 112 | static struct irq_chip msi_irq = { |
116 | .name = "PCI-MSI", | 113 | .name = "PCI-MSI", |
117 | .mask = mask_msi_irq, | 114 | .irq_mask = mask_msi_irq, |
118 | .unmask = unmask_msi_irq, | 115 | .irq_unmask = unmask_msi_irq, |
119 | .enable = unmask_msi_irq, | 116 | .irq_enable = unmask_msi_irq, |
120 | .disable = mask_msi_irq, | 117 | .irq_disable = mask_msi_irq, |
121 | /* XXX affinity XXX */ | 118 | /* XXX affinity XXX */ |
122 | }; | 119 | }; |
123 | 120 | ||
124 | static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | 121 | static int sparc64_setup_msi_irq(unsigned int *irq_p, |
125 | struct pci_dev *pdev, | 122 | struct pci_dev *pdev, |
126 | struct msi_desc *entry) | 123 | struct msi_desc *entry) |
127 | { | 124 | { |
@@ -131,17 +128,17 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
131 | int msi, err; | 128 | int msi, err; |
132 | u32 msiqid; | 129 | u32 msiqid; |
133 | 130 | ||
134 | *virt_irq_p = virt_irq_alloc(0, 0); | 131 | *irq_p = irq_alloc(0, 0); |
135 | err = -ENOMEM; | 132 | err = -ENOMEM; |
136 | if (!*virt_irq_p) | 133 | if (!*irq_p) |
137 | goto out_err; | 134 | goto out_err; |
138 | 135 | ||
139 | set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq, | 136 | irq_set_chip_and_handler_name(*irq_p, &msi_irq, handle_simple_irq, |
140 | handle_simple_irq, "MSI"); | 137 | "MSI"); |
141 | 138 | ||
142 | err = alloc_msi(pbm); | 139 | err = alloc_msi(pbm); |
143 | if (unlikely(err < 0)) | 140 | if (unlikely(err < 0)) |
144 | goto out_virt_irq_free; | 141 | goto out_irq_free; |
145 | 142 | ||
146 | msi = err; | 143 | msi = err; |
147 | 144 | ||
@@ -152,7 +149,7 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
152 | if (err) | 149 | if (err) |
153 | goto out_msi_free; | 150 | goto out_msi_free; |
154 | 151 | ||
155 | pbm->msi_irq_table[msi - pbm->msi_first] = *virt_irq_p; | 152 | pbm->msi_irq_table[msi - pbm->msi_first] = *irq_p; |
156 | 153 | ||
157 | if (entry->msi_attrib.is_64) { | 154 | if (entry->msi_attrib.is_64) { |
158 | msg.address_hi = pbm->msi64_start >> 32; | 155 | msg.address_hi = pbm->msi64_start >> 32; |
@@ -163,24 +160,24 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p, | |||
163 | } | 160 | } |
164 | msg.data = msi; | 161 | msg.data = msi; |
165 | 162 | ||
166 | set_irq_msi(*virt_irq_p, entry); | 163 | irq_set_msi_desc(*irq_p, entry); |
167 | write_msi_msg(*virt_irq_p, &msg); | 164 | write_msi_msg(*irq_p, &msg); |
168 | 165 | ||
169 | return 0; | 166 | return 0; |
170 | 167 | ||
171 | out_msi_free: | 168 | out_msi_free: |
172 | free_msi(pbm, msi); | 169 | free_msi(pbm, msi); |
173 | 170 | ||
174 | out_virt_irq_free: | 171 | out_irq_free: |
175 | set_irq_chip(*virt_irq_p, NULL); | 172 | irq_set_chip(*irq_p, NULL); |
176 | virt_irq_free(*virt_irq_p); | 173 | irq_free(*irq_p); |
177 | *virt_irq_p = 0; | 174 | *irq_p = 0; |
178 | 175 | ||
179 | out_err: | 176 | out_err: |
180 | return err; | 177 | return err; |
181 | } | 178 | } |
182 | 179 | ||
183 | static void sparc64_teardown_msi_irq(unsigned int virt_irq, | 180 | static void sparc64_teardown_msi_irq(unsigned int irq, |
184 | struct pci_dev *pdev) | 181 | struct pci_dev *pdev) |
185 | { | 182 | { |
186 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 183 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
@@ -189,12 +186,12 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq, | |||
189 | int i, err; | 186 | int i, err; |
190 | 187 | ||
191 | for (i = 0; i < pbm->msi_num; i++) { | 188 | for (i = 0; i < pbm->msi_num; i++) { |
192 | if (pbm->msi_irq_table[i] == virt_irq) | 189 | if (pbm->msi_irq_table[i] == irq) |
193 | break; | 190 | break; |
194 | } | 191 | } |
195 | if (i >= pbm->msi_num) { | 192 | if (i >= pbm->msi_num) { |
196 | printk(KERN_ERR "%s: teardown: No MSI for irq %u\n", | 193 | printk(KERN_ERR "%s: teardown: No MSI for irq %u\n", |
197 | pbm->name, virt_irq); | 194 | pbm->name, irq); |
198 | return; | 195 | return; |
199 | } | 196 | } |
200 | 197 | ||
@@ -205,14 +202,14 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq, | |||
205 | if (err) { | 202 | if (err) { |
206 | printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, " | 203 | printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, " |
207 | "irq %u, gives error %d\n", | 204 | "irq %u, gives error %d\n", |
208 | pbm->name, msi_num, virt_irq, err); | 205 | pbm->name, msi_num, irq, err); |
209 | return; | 206 | return; |
210 | } | 207 | } |
211 | 208 | ||
212 | free_msi(pbm, msi_num); | 209 | free_msi(pbm, msi_num); |
213 | 210 | ||
214 | set_irq_chip(virt_irq, NULL); | 211 | irq_set_chip(irq, NULL); |
215 | virt_irq_free(virt_irq); | 212 | irq_free(irq); |
216 | } | 213 | } |
217 | 214 | ||
218 | static int msi_bitmap_alloc(struct pci_pbm_info *pbm) | 215 | static int msi_bitmap_alloc(struct pci_pbm_info *pbm) |
@@ -287,8 +284,9 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm, | |||
287 | 284 | ||
288 | nid = pbm->numa_node; | 285 | nid = pbm->numa_node; |
289 | if (nid != -1) { | 286 | if (nid != -1) { |
290 | cpumask_t numa_mask = *cpumask_of_node(nid); | 287 | cpumask_t numa_mask; |
291 | 288 | ||
289 | cpumask_copy(&numa_mask, cpumask_of_node(nid)); | ||
292 | irq_set_affinity(irq, &numa_mask); | 290 | irq_set_affinity(irq, &numa_mask); |
293 | } | 291 | } |
294 | err = request_irq(irq, sparc64_msiq_interrupt, 0, | 292 | err = request_irq(irq, sparc64_msiq_interrupt, 0, |
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index 22eab7cf3b11..86ae08d9b6ee 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c | |||
@@ -503,8 +503,7 @@ static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) | |||
503 | 503 | ||
504 | #define PSYCHO_CONFIGSPACE 0x001000000UL | 504 | #define PSYCHO_CONFIGSPACE 0x001000000UL |
505 | 505 | ||
506 | static int __devinit psycho_probe(struct platform_device *op, | 506 | static int __devinit psycho_probe(struct platform_device *op) |
507 | const struct of_device_id *match) | ||
508 | { | 507 | { |
509 | const struct linux_prom64_registers *pr_regs; | 508 | const struct linux_prom64_registers *pr_regs; |
510 | struct device_node *dp = op->dev.of_node; | 509 | struct device_node *dp = op->dev.of_node; |
@@ -593,7 +592,7 @@ out_err: | |||
593 | return err; | 592 | return err; |
594 | } | 593 | } |
595 | 594 | ||
596 | static struct of_device_id __initdata psycho_match[] = { | 595 | static const struct of_device_id psycho_match[] = { |
597 | { | 596 | { |
598 | .name = "pci", | 597 | .name = "pci", |
599 | .compatible = "pci108e,8000", | 598 | .compatible = "pci108e,8000", |
@@ -601,7 +600,7 @@ static struct of_device_id __initdata psycho_match[] = { | |||
601 | {}, | 600 | {}, |
602 | }; | 601 | }; |
603 | 602 | ||
604 | static struct of_platform_driver psycho_driver = { | 603 | static struct platform_driver psycho_driver = { |
605 | .driver = { | 604 | .driver = { |
606 | .name = DRIVER_NAME, | 605 | .name = DRIVER_NAME, |
607 | .owner = THIS_MODULE, | 606 | .owner = THIS_MODULE, |
@@ -612,7 +611,7 @@ static struct of_platform_driver psycho_driver = { | |||
612 | 611 | ||
613 | static int __init psycho_init(void) | 612 | static int __init psycho_init(void) |
614 | { | 613 | { |
615 | return of_register_platform_driver(&psycho_driver); | 614 | return platform_driver_register(&psycho_driver); |
616 | } | 615 | } |
617 | 616 | ||
618 | subsys_initcall(psycho_init); | 617 | subsys_initcall(psycho_init); |
diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 5c3f5ec4cabc..d1840dbdaa2f 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c | |||
@@ -452,9 +452,10 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm, | |||
452 | sabre_scan_bus(pbm, &op->dev); | 452 | sabre_scan_bus(pbm, &op->dev); |
453 | } | 453 | } |
454 | 454 | ||
455 | static int __devinit sabre_probe(struct platform_device *op, | 455 | static const struct of_device_id sabre_match[]; |
456 | const struct of_device_id *match) | 456 | static int __devinit sabre_probe(struct platform_device *op) |
457 | { | 457 | { |
458 | const struct of_device_id *match; | ||
458 | const struct linux_prom64_registers *pr_regs; | 459 | const struct linux_prom64_registers *pr_regs; |
459 | struct device_node *dp = op->dev.of_node; | 460 | struct device_node *dp = op->dev.of_node; |
460 | struct pci_pbm_info *pbm; | 461 | struct pci_pbm_info *pbm; |
@@ -464,7 +465,8 @@ static int __devinit sabre_probe(struct platform_device *op, | |||
464 | const u32 *vdma; | 465 | const u32 *vdma; |
465 | u64 clear_irq; | 466 | u64 clear_irq; |
466 | 467 | ||
467 | hummingbird_p = (match->data != NULL); | 468 | match = of_match_device(sabre_match, &op->dev); |
469 | hummingbird_p = match && (match->data != NULL); | ||
468 | if (!hummingbird_p) { | 470 | if (!hummingbird_p) { |
469 | struct device_node *cpu_dp; | 471 | struct device_node *cpu_dp; |
470 | 472 | ||
@@ -582,7 +584,7 @@ out_err: | |||
582 | return err; | 584 | return err; |
583 | } | 585 | } |
584 | 586 | ||
585 | static struct of_device_id __initdata sabre_match[] = { | 587 | static const struct of_device_id sabre_match[] = { |
586 | { | 588 | { |
587 | .name = "pci", | 589 | .name = "pci", |
588 | .compatible = "pci108e,a001", | 590 | .compatible = "pci108e,a001", |
@@ -595,7 +597,7 @@ static struct of_device_id __initdata sabre_match[] = { | |||
595 | {}, | 597 | {}, |
596 | }; | 598 | }; |
597 | 599 | ||
598 | static struct of_platform_driver sabre_driver = { | 600 | static struct platform_driver sabre_driver = { |
599 | .driver = { | 601 | .driver = { |
600 | .name = DRIVER_NAME, | 602 | .name = DRIVER_NAME, |
601 | .owner = THIS_MODULE, | 603 | .owner = THIS_MODULE, |
@@ -606,7 +608,7 @@ static struct of_platform_driver sabre_driver = { | |||
606 | 608 | ||
607 | static int __init sabre_init(void) | 609 | static int __init sabre_init(void) |
608 | { | 610 | { |
609 | return of_register_platform_driver(&sabre_driver); | 611 | return platform_driver_register(&sabre_driver); |
610 | } | 612 | } |
611 | 613 | ||
612 | subsys_initcall(sabre_init); | 614 | subsys_initcall(sabre_init); |
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 445a47a2fb3d..f030b02edddd 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c | |||
@@ -264,7 +264,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
264 | default: | 264 | default: |
265 | type_string = "ECC Error"; | 265 | type_string = "ECC Error"; |
266 | break; | 266 | break; |
267 | }; | 267 | } |
268 | printk("%s: IOMMU Error, type[%s]\n", | 268 | printk("%s: IOMMU Error, type[%s]\n", |
269 | pbm->name, type_string); | 269 | pbm->name, type_string); |
270 | 270 | ||
@@ -319,7 +319,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
319 | default: | 319 | default: |
320 | type_string = "ECC Error"; | 320 | type_string = "ECC Error"; |
321 | break; | 321 | break; |
322 | }; | 322 | } |
323 | printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) " | 323 | printk("%s: IOMMU TAG(%d)[error(%s) ctx(%x) wr(%d) str(%d) " |
324 | "sz(%dK) vpg(%08lx)]\n", | 324 | "sz(%dK) vpg(%08lx)]\n", |
325 | pbm->name, i, type_string, | 325 | pbm->name, i, type_string, |
@@ -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: |
@@ -1328,7 +1328,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, | |||
1328 | default: | 1328 | default: |
1329 | chipset_name = "SCHIZO"; | 1329 | chipset_name = "SCHIZO"; |
1330 | break; | 1330 | break; |
1331 | }; | 1331 | } |
1332 | 1332 | ||
1333 | /* For SCHIZO, three OBP regs: | 1333 | /* For SCHIZO, three OBP regs: |
1334 | * 1) PBM controller regs | 1334 | * 1) PBM controller regs |
@@ -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 | ||
@@ -1460,10 +1458,15 @@ out_err: | |||
1460 | return err; | 1458 | return err; |
1461 | } | 1459 | } |
1462 | 1460 | ||
1463 | static int __devinit schizo_probe(struct platform_device *op, | 1461 | static const struct of_device_id schizo_match[]; |
1464 | const struct of_device_id *match) | 1462 | static int __devinit schizo_probe(struct platform_device *op) |
1465 | { | 1463 | { |
1466 | return __schizo_init(op, (unsigned long) match->data); | 1464 | const struct of_device_id *match; |
1465 | |||
1466 | match = of_match_device(schizo_match, &op->dev); | ||
1467 | if (!match) | ||
1468 | return -EINVAL; | ||
1469 | return __schizo_init(op, (unsigned long)match->data); | ||
1467 | } | 1470 | } |
1468 | 1471 | ||
1469 | /* The ordering of this table is very important. Some Tomatillo | 1472 | /* The ordering of this table is very important. Some Tomatillo |
@@ -1471,7 +1474,7 @@ static int __devinit schizo_probe(struct platform_device *op, | |||
1471 | * and pci108e,8001. So list the chips in reverse chronological | 1474 | * and pci108e,8001. So list the chips in reverse chronological |
1472 | * order. | 1475 | * order. |
1473 | */ | 1476 | */ |
1474 | static struct of_device_id __initdata schizo_match[] = { | 1477 | static const struct of_device_id schizo_match[] = { |
1475 | { | 1478 | { |
1476 | .name = "pci", | 1479 | .name = "pci", |
1477 | .compatible = "pci108e,a801", | 1480 | .compatible = "pci108e,a801", |
@@ -1490,7 +1493,7 @@ static struct of_device_id __initdata schizo_match[] = { | |||
1490 | {}, | 1493 | {}, |
1491 | }; | 1494 | }; |
1492 | 1495 | ||
1493 | static struct of_platform_driver schizo_driver = { | 1496 | static struct platform_driver schizo_driver = { |
1494 | .driver = { | 1497 | .driver = { |
1495 | .name = DRIVER_NAME, | 1498 | .name = DRIVER_NAME, |
1496 | .owner = THIS_MODULE, | 1499 | .owner = THIS_MODULE, |
@@ -1501,7 +1504,7 @@ static struct of_platform_driver schizo_driver = { | |||
1501 | 1504 | ||
1502 | static int __init schizo_init(void) | 1505 | static int __init schizo_init(void) |
1503 | { | 1506 | { |
1504 | return of_register_platform_driver(&schizo_driver); | 1507 | return platform_driver_register(&schizo_driver); |
1505 | } | 1508 | } |
1506 | 1509 | ||
1507 | subsys_initcall(schizo_init); | 1510 | subsys_initcall(schizo_init); |
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c index 743344aa6d8a..b01a06e9ae4e 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 = { |
@@ -918,8 +917,7 @@ static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm, | |||
918 | return 0; | 917 | return 0; |
919 | } | 918 | } |
920 | 919 | ||
921 | static int __devinit pci_sun4v_probe(struct platform_device *op, | 920 | static int __devinit pci_sun4v_probe(struct platform_device *op) |
922 | const struct of_device_id *match) | ||
923 | { | 921 | { |
924 | const struct linux_prom64_registers *regs; | 922 | const struct linux_prom64_registers *regs; |
925 | static int hvapi_negotiated = 0; | 923 | static int hvapi_negotiated = 0; |
@@ -1000,7 +998,7 @@ out_err: | |||
1000 | return err; | 998 | return err; |
1001 | } | 999 | } |
1002 | 1000 | ||
1003 | static struct of_device_id __initdata pci_sun4v_match[] = { | 1001 | static const struct of_device_id pci_sun4v_match[] = { |
1004 | { | 1002 | { |
1005 | .name = "pci", | 1003 | .name = "pci", |
1006 | .compatible = "SUNW,sun4v-pci", | 1004 | .compatible = "SUNW,sun4v-pci", |
@@ -1008,7 +1006,7 @@ static struct of_device_id __initdata pci_sun4v_match[] = { | |||
1008 | {}, | 1006 | {}, |
1009 | }; | 1007 | }; |
1010 | 1008 | ||
1011 | static struct of_platform_driver pci_sun4v_driver = { | 1009 | static struct platform_driver pci_sun4v_driver = { |
1012 | .driver = { | 1010 | .driver = { |
1013 | .name = DRIVER_NAME, | 1011 | .name = DRIVER_NAME, |
1014 | .owner = THIS_MODULE, | 1012 | .owner = THIS_MODULE, |
@@ -1019,7 +1017,7 @@ static struct of_platform_driver pci_sun4v_driver = { | |||
1019 | 1017 | ||
1020 | static int __init pci_sun4v_init(void) | 1018 | static int __init pci_sun4v_init(void) |
1021 | { | 1019 | { |
1022 | return of_register_platform_driver(&pci_sun4v_driver); | 1020 | return platform_driver_register(&pci_sun4v_driver); |
1023 | } | 1021 | } |
1024 | 1022 | ||
1025 | subsys_initcall(pci_sun4v_init); | 1023 | subsys_initcall(pci_sun4v_init); |
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index d36a8d391ca0..948601a066ff 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c | |||
@@ -164,6 +164,9 @@ void __iomem *pcic_regs; | |||
164 | volatile int pcic_speculative; | 164 | volatile int pcic_speculative; |
165 | volatile int pcic_trapped; | 165 | volatile int pcic_trapped; |
166 | 166 | ||
167 | /* forward */ | ||
168 | unsigned int pcic_build_device_irq(struct platform_device *op, | ||
169 | unsigned int real_irq); | ||
167 | 170 | ||
168 | #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) | 171 | #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) |
169 | 172 | ||
@@ -284,7 +287,7 @@ int __init pcic_probe(void) | |||
284 | struct linux_prom_registers regs[PROMREG_MAX]; | 287 | struct linux_prom_registers regs[PROMREG_MAX]; |
285 | struct linux_pbm_info* pbm; | 288 | struct linux_pbm_info* pbm; |
286 | char namebuf[64]; | 289 | char namebuf[64]; |
287 | int node; | 290 | phandle node; |
288 | int err; | 291 | int err; |
289 | 292 | ||
290 | if (pcic0_up) { | 293 | if (pcic0_up) { |
@@ -440,7 +443,7 @@ static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm, | |||
440 | { | 443 | { |
441 | struct linux_prom_pci_registers regs[PROMREG_MAX]; | 444 | struct linux_prom_pci_registers regs[PROMREG_MAX]; |
442 | int err; | 445 | int err; |
443 | int node = prom_getchild(pbm->prom_node); | 446 | phandle node = prom_getchild(pbm->prom_node); |
444 | 447 | ||
445 | while(node) { | 448 | while(node) { |
446 | err = prom_getproperty(node, "reg", | 449 | err = prom_getproperty(node, "reg", |
@@ -523,6 +526,7 @@ static void | |||
523 | pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) | 526 | pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) |
524 | { | 527 | { |
525 | struct pcic_ca2irq *p; | 528 | struct pcic_ca2irq *p; |
529 | unsigned int real_irq; | ||
526 | int i, ivec; | 530 | int i, ivec; |
527 | char namebuf[64]; | 531 | char namebuf[64]; |
528 | 532 | ||
@@ -551,26 +555,25 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) | |||
551 | i = p->pin; | 555 | i = p->pin; |
552 | if (i >= 0 && i < 4) { | 556 | if (i >= 0 && i < 4) { |
553 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); | 557 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); |
554 | dev->irq = ivec >> (i << 2) & 0xF; | 558 | real_irq = ivec >> (i << 2) & 0xF; |
555 | } else if (i >= 4 && i < 8) { | 559 | } else if (i >= 4 && i < 8) { |
556 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); | 560 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); |
557 | dev->irq = ivec >> ((i-4) << 2) & 0xF; | 561 | real_irq = ivec >> ((i-4) << 2) & 0xF; |
558 | } else { /* Corrupted map */ | 562 | } else { /* Corrupted map */ |
559 | printk("PCIC: BAD PIN %d\n", i); for (;;) {} | 563 | printk("PCIC: BAD PIN %d\n", i); for (;;) {} |
560 | } | 564 | } |
561 | /* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ | 565 | /* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ |
562 | 566 | ||
563 | /* | 567 | /* real_irq means PROM did not bother to program the upper |
564 | * dev->irq=0 means PROM did not bother to program the upper | ||
565 | * half of PCIC. This happens on JS-E with PROM 3.11, for instance. | 568 | * half of PCIC. This happens on JS-E with PROM 3.11, for instance. |
566 | */ | 569 | */ |
567 | if (dev->irq == 0 || p->force) { | 570 | if (real_irq == 0 || p->force) { |
568 | if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ | 571 | if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ |
569 | printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} | 572 | printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} |
570 | } | 573 | } |
571 | printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", | 574 | printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", |
572 | p->irq, p->pin, dev->bus->number, dev->devfn); | 575 | p->irq, p->pin, dev->bus->number, dev->devfn); |
573 | dev->irq = p->irq; | 576 | real_irq = p->irq; |
574 | 577 | ||
575 | i = p->pin; | 578 | i = p->pin; |
576 | if (i >= 4) { | 579 | if (i >= 4) { |
@@ -584,7 +587,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) | |||
584 | ivec |= p->irq << (i << 2); | 587 | ivec |= p->irq << (i << 2); |
585 | writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); | 588 | writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); |
586 | } | 589 | } |
587 | } | 590 | } |
591 | dev->irq = pcic_build_device_irq(NULL, real_irq); | ||
588 | } | 592 | } |
589 | 593 | ||
590 | /* | 594 | /* |
@@ -700,10 +704,8 @@ static void pcic_clear_clock_irq(void) | |||
700 | 704 | ||
701 | static irqreturn_t pcic_timer_handler (int irq, void *h) | 705 | static irqreturn_t pcic_timer_handler (int irq, void *h) |
702 | { | 706 | { |
703 | write_seqlock(&xtime_lock); /* Dummy, to show that we remember */ | ||
704 | pcic_clear_clock_irq(); | 707 | pcic_clear_clock_irq(); |
705 | do_timer(1); | 708 | xtime_update(1); |
706 | write_sequnlock(&xtime_lock); | ||
707 | #ifndef CONFIG_SMP | 709 | #ifndef CONFIG_SMP |
708 | update_process_times(user_mode(get_irq_regs())); | 710 | update_process_times(user_mode(get_irq_regs())); |
709 | #endif | 711 | #endif |
@@ -731,6 +733,7 @@ void __init pci_time_init(void) | |||
731 | struct linux_pcic *pcic = &pcic0; | 733 | struct linux_pcic *pcic = &pcic0; |
732 | unsigned long v; | 734 | unsigned long v; |
733 | int timer_irq, irq; | 735 | int timer_irq, irq; |
736 | int err; | ||
734 | 737 | ||
735 | do_arch_gettimeoffset = pci_gettimeoffset; | 738 | do_arch_gettimeoffset = pci_gettimeoffset; |
736 | 739 | ||
@@ -742,9 +745,10 @@ void __init pci_time_init(void) | |||
742 | timer_irq = PCI_COUNTER_IRQ_SYS(v); | 745 | timer_irq = PCI_COUNTER_IRQ_SYS(v); |
743 | writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), | 746 | writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), |
744 | pcic->pcic_regs+PCI_COUNTER_IRQ); | 747 | pcic->pcic_regs+PCI_COUNTER_IRQ); |
745 | irq = request_irq(timer_irq, pcic_timer_handler, | 748 | irq = pcic_build_device_irq(NULL, timer_irq); |
746 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | 749 | err = request_irq(irq, pcic_timer_handler, |
747 | if (irq) { | 750 | IRQF_TIMER, "timer", NULL); |
751 | if (err) { | ||
748 | prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); | 752 | prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); |
749 | prom_halt(); | 753 | prom_halt(); |
750 | } | 754 | } |
@@ -805,50 +809,73 @@ static inline unsigned long get_irqmask(int irq_nr) | |||
805 | return 1 << irq_nr; | 809 | return 1 << irq_nr; |
806 | } | 810 | } |
807 | 811 | ||
808 | static void pcic_disable_irq(unsigned int irq_nr) | 812 | static void pcic_mask_irq(struct irq_data *data) |
809 | { | 813 | { |
810 | unsigned long mask, flags; | 814 | unsigned long mask, flags; |
811 | 815 | ||
812 | mask = get_irqmask(irq_nr); | 816 | mask = (unsigned long)data->chip_data; |
813 | local_irq_save(flags); | 817 | local_irq_save(flags); |
814 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); | 818 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); |
815 | local_irq_restore(flags); | 819 | local_irq_restore(flags); |
816 | } | 820 | } |
817 | 821 | ||
818 | static void pcic_enable_irq(unsigned int irq_nr) | 822 | static void pcic_unmask_irq(struct irq_data *data) |
819 | { | 823 | { |
820 | unsigned long mask, flags; | 824 | unsigned long mask, flags; |
821 | 825 | ||
822 | mask = get_irqmask(irq_nr); | 826 | mask = (unsigned long)data->chip_data; |
823 | local_irq_save(flags); | 827 | local_irq_save(flags); |
824 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); | 828 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); |
825 | local_irq_restore(flags); | 829 | local_irq_restore(flags); |
826 | } | 830 | } |
827 | 831 | ||
828 | static void pcic_load_profile_irq(int cpu, unsigned int limit) | 832 | static unsigned int pcic_startup_irq(struct irq_data *data) |
829 | { | 833 | { |
830 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); | 834 | irq_link(data->irq); |
835 | pcic_unmask_irq(data); | ||
836 | return 0; | ||
831 | } | 837 | } |
832 | 838 | ||
833 | /* We assume the caller has disabled local interrupts when these are called, | 839 | static struct irq_chip pcic_irq = { |
834 | * or else very bizarre behavior will result. | 840 | .name = "pcic", |
835 | */ | 841 | .irq_startup = pcic_startup_irq, |
836 | static void pcic_disable_pil_irq(unsigned int pil) | 842 | .irq_mask = pcic_mask_irq, |
843 | .irq_unmask = pcic_unmask_irq, | ||
844 | }; | ||
845 | |||
846 | unsigned int pcic_build_device_irq(struct platform_device *op, | ||
847 | unsigned int real_irq) | ||
837 | { | 848 | { |
838 | writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); | 849 | unsigned int irq; |
850 | unsigned long mask; | ||
851 | |||
852 | irq = 0; | ||
853 | mask = get_irqmask(real_irq); | ||
854 | if (mask == 0) | ||
855 | goto out; | ||
856 | |||
857 | irq = irq_alloc(real_irq, real_irq); | ||
858 | if (irq == 0) | ||
859 | goto out; | ||
860 | |||
861 | irq_set_chip_and_handler_name(irq, &pcic_irq, | ||
862 | handle_level_irq, "PCIC"); | ||
863 | irq_set_chip_data(irq, (void *)mask); | ||
864 | |||
865 | out: | ||
866 | return irq; | ||
839 | } | 867 | } |
840 | 868 | ||
841 | static void pcic_enable_pil_irq(unsigned int pil) | 869 | |
870 | static void pcic_load_profile_irq(int cpu, unsigned int limit) | ||
842 | { | 871 | { |
843 | writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); | 872 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); |
844 | } | 873 | } |
845 | 874 | ||
846 | void __init sun4m_pci_init_IRQ(void) | 875 | void __init sun4m_pci_init_IRQ(void) |
847 | { | 876 | { |
848 | BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); | 877 | sparc_irq_config.build_device_irq = pcic_build_device_irq; |
849 | BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM); | 878 | |
850 | BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); | ||
851 | BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); | ||
852 | BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); | 879 | BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); |
853 | BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); | 880 | BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); |
854 | } | 881 | } |
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index c4a6a50b4849..8ac23e660080 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/irq.h> | 8 | #include <linux/irq.h> |
9 | 9 | ||
10 | #include <linux/perf_event.h> | 10 | #include <linux/irq_work.h> |
11 | #include <linux/ftrace.h> | 11 | #include <linux/ftrace.h> |
12 | 12 | ||
13 | #include <asm/pil.h> | 13 | #include <asm/pil.h> |
@@ -43,14 +43,14 @@ void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs) | |||
43 | 43 | ||
44 | old_regs = set_irq_regs(regs); | 44 | old_regs = set_irq_regs(regs); |
45 | irq_enter(); | 45 | irq_enter(); |
46 | #ifdef CONFIG_PERF_EVENTS | 46 | #ifdef CONFIG_IRQ_WORK |
47 | perf_event_do_pending(); | 47 | irq_work_run(); |
48 | #endif | 48 | #endif |
49 | irq_exit(); | 49 | irq_exit(); |
50 | set_irq_regs(old_regs); | 50 | set_irq_regs(old_regs); |
51 | } | 51 | } |
52 | 52 | ||
53 | void set_perf_event_pending(void) | 53 | void arch_irq_work_raise(void) |
54 | { | 54 | { |
55 | set_softint(1 << PIL_DEFERRED_PCR_WORK); | 55 | set_softint(1 << PIL_DEFERRED_PCR_WORK); |
56 | } | 56 | } |
@@ -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 | ||
@@ -167,5 +167,3 @@ out_unregister: | |||
167 | unregister_perf_hsvc(); | 167 | unregister_perf_hsvc(); |
168 | return err; | 168 | return err; |
169 | } | 169 | } |
170 | |||
171 | arch_initcall(pcr_arch_init); | ||
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 6318e622cfb0..2cb0e1c001e2 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/nmi.h> | 26 | #include <asm/nmi.h> |
27 | #include <asm/pcr.h> | 27 | #include <asm/pcr.h> |
28 | 28 | ||
29 | #include "kernel.h" | ||
29 | #include "kstack.h" | 30 | #include "kstack.h" |
30 | 31 | ||
31 | /* Sparc64 chips have two performance counters, 32-bits each, with | 32 | /* Sparc64 chips have two performance counters, 32-bits each, with |
@@ -658,13 +659,16 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr) | |||
658 | 659 | ||
659 | enc = perf_event_get_enc(cpuc->events[i]); | 660 | enc = perf_event_get_enc(cpuc->events[i]); |
660 | pcr &= ~mask_for_index(idx); | 661 | pcr &= ~mask_for_index(idx); |
661 | pcr |= event_encoding(enc, idx); | 662 | if (hwc->state & PERF_HES_STOPPED) |
663 | pcr |= nop_for_index(idx); | ||
664 | else | ||
665 | pcr |= event_encoding(enc, idx); | ||
662 | } | 666 | } |
663 | out: | 667 | out: |
664 | return pcr; | 668 | return pcr; |
665 | } | 669 | } |
666 | 670 | ||
667 | void hw_perf_enable(void) | 671 | static void sparc_pmu_enable(struct pmu *pmu) |
668 | { | 672 | { |
669 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 673 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
670 | u64 pcr; | 674 | u64 pcr; |
@@ -691,7 +695,7 @@ void hw_perf_enable(void) | |||
691 | pcr_ops->write(cpuc->pcr); | 695 | pcr_ops->write(cpuc->pcr); |
692 | } | 696 | } |
693 | 697 | ||
694 | void hw_perf_disable(void) | 698 | static void sparc_pmu_disable(struct pmu *pmu) |
695 | { | 699 | { |
696 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 700 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
697 | u64 val; | 701 | u64 val; |
@@ -710,19 +714,65 @@ void hw_perf_disable(void) | |||
710 | pcr_ops->write(cpuc->pcr); | 714 | pcr_ops->write(cpuc->pcr); |
711 | } | 715 | } |
712 | 716 | ||
713 | static void sparc_pmu_disable(struct perf_event *event) | 717 | static int active_event_index(struct cpu_hw_events *cpuc, |
718 | struct perf_event *event) | ||
719 | { | ||
720 | int i; | ||
721 | |||
722 | for (i = 0; i < cpuc->n_events; i++) { | ||
723 | if (cpuc->event[i] == event) | ||
724 | break; | ||
725 | } | ||
726 | BUG_ON(i == cpuc->n_events); | ||
727 | return cpuc->current_idx[i]; | ||
728 | } | ||
729 | |||
730 | static void sparc_pmu_start(struct perf_event *event, int flags) | ||
731 | { | ||
732 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
733 | int idx = active_event_index(cpuc, event); | ||
734 | |||
735 | if (flags & PERF_EF_RELOAD) { | ||
736 | WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); | ||
737 | sparc_perf_event_set_period(event, &event->hw, idx); | ||
738 | } | ||
739 | |||
740 | event->hw.state = 0; | ||
741 | |||
742 | sparc_pmu_enable_event(cpuc, &event->hw, idx); | ||
743 | } | ||
744 | |||
745 | static void sparc_pmu_stop(struct perf_event *event, int flags) | ||
746 | { | ||
747 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
748 | int idx = active_event_index(cpuc, event); | ||
749 | |||
750 | if (!(event->hw.state & PERF_HES_STOPPED)) { | ||
751 | sparc_pmu_disable_event(cpuc, &event->hw, idx); | ||
752 | event->hw.state |= PERF_HES_STOPPED; | ||
753 | } | ||
754 | |||
755 | if (!(event->hw.state & PERF_HES_UPTODATE) && (flags & PERF_EF_UPDATE)) { | ||
756 | sparc_perf_event_update(event, &event->hw, idx); | ||
757 | event->hw.state |= PERF_HES_UPTODATE; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | static void sparc_pmu_del(struct perf_event *event, int _flags) | ||
714 | { | 762 | { |
715 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 763 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
716 | struct hw_perf_event *hwc = &event->hw; | ||
717 | unsigned long flags; | 764 | unsigned long flags; |
718 | int i; | 765 | int i; |
719 | 766 | ||
720 | local_irq_save(flags); | 767 | local_irq_save(flags); |
721 | perf_disable(); | 768 | perf_pmu_disable(event->pmu); |
722 | 769 | ||
723 | for (i = 0; i < cpuc->n_events; i++) { | 770 | for (i = 0; i < cpuc->n_events; i++) { |
724 | if (event == cpuc->event[i]) { | 771 | if (event == cpuc->event[i]) { |
725 | int idx = cpuc->current_idx[i]; | 772 | /* Absorb the final count and turn off the |
773 | * event. | ||
774 | */ | ||
775 | sparc_pmu_stop(event, PERF_EF_UPDATE); | ||
726 | 776 | ||
727 | /* Shift remaining entries down into | 777 | /* Shift remaining entries down into |
728 | * the existing slot. | 778 | * the existing slot. |
@@ -734,13 +784,6 @@ static void sparc_pmu_disable(struct perf_event *event) | |||
734 | cpuc->current_idx[i]; | 784 | cpuc->current_idx[i]; |
735 | } | 785 | } |
736 | 786 | ||
737 | /* Absorb the final count and turn off the | ||
738 | * event. | ||
739 | */ | ||
740 | sparc_pmu_disable_event(cpuc, hwc, idx); | ||
741 | barrier(); | ||
742 | sparc_perf_event_update(event, hwc, idx); | ||
743 | |||
744 | perf_event_update_userpage(event); | 787 | perf_event_update_userpage(event); |
745 | 788 | ||
746 | cpuc->n_events--; | 789 | cpuc->n_events--; |
@@ -748,23 +791,10 @@ static void sparc_pmu_disable(struct perf_event *event) | |||
748 | } | 791 | } |
749 | } | 792 | } |
750 | 793 | ||
751 | perf_enable(); | 794 | perf_pmu_enable(event->pmu); |
752 | local_irq_restore(flags); | 795 | local_irq_restore(flags); |
753 | } | 796 | } |
754 | 797 | ||
755 | static int active_event_index(struct cpu_hw_events *cpuc, | ||
756 | struct perf_event *event) | ||
757 | { | ||
758 | int i; | ||
759 | |||
760 | for (i = 0; i < cpuc->n_events; i++) { | ||
761 | if (cpuc->event[i] == event) | ||
762 | break; | ||
763 | } | ||
764 | BUG_ON(i == cpuc->n_events); | ||
765 | return cpuc->current_idx[i]; | ||
766 | } | ||
767 | |||
768 | static void sparc_pmu_read(struct perf_event *event) | 798 | static void sparc_pmu_read(struct perf_event *event) |
769 | { | 799 | { |
770 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 800 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
@@ -774,15 +804,6 @@ static void sparc_pmu_read(struct perf_event *event) | |||
774 | sparc_perf_event_update(event, hwc, idx); | 804 | sparc_perf_event_update(event, hwc, idx); |
775 | } | 805 | } |
776 | 806 | ||
777 | static void sparc_pmu_unthrottle(struct perf_event *event) | ||
778 | { | ||
779 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
780 | int idx = active_event_index(cpuc, event); | ||
781 | struct hw_perf_event *hwc = &event->hw; | ||
782 | |||
783 | sparc_pmu_enable_event(cpuc, hwc, idx); | ||
784 | } | ||
785 | |||
786 | static atomic_t active_events = ATOMIC_INIT(0); | 807 | static atomic_t active_events = ATOMIC_INIT(0); |
787 | static DEFINE_MUTEX(pmc_grab_mutex); | 808 | static DEFINE_MUTEX(pmc_grab_mutex); |
788 | 809 | ||
@@ -877,7 +898,7 @@ static int sparc_check_constraints(struct perf_event **evts, | |||
877 | if (!n_ev) | 898 | if (!n_ev) |
878 | return 0; | 899 | return 0; |
879 | 900 | ||
880 | if (n_ev > perf_max_events) | 901 | if (n_ev > MAX_HWEVENTS) |
881 | return -1; | 902 | return -1; |
882 | 903 | ||
883 | msk0 = perf_event_get_msk(events[0]); | 904 | msk0 = perf_event_get_msk(events[0]); |
@@ -984,26 +1005,30 @@ static int collect_events(struct perf_event *group, int max_count, | |||
984 | return n; | 1005 | return n; |
985 | } | 1006 | } |
986 | 1007 | ||
987 | static int sparc_pmu_enable(struct perf_event *event) | 1008 | static int sparc_pmu_add(struct perf_event *event, int ef_flags) |
988 | { | 1009 | { |
989 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1010 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
990 | int n0, ret = -EAGAIN; | 1011 | int n0, ret = -EAGAIN; |
991 | unsigned long flags; | 1012 | unsigned long flags; |
992 | 1013 | ||
993 | local_irq_save(flags); | 1014 | local_irq_save(flags); |
994 | perf_disable(); | 1015 | perf_pmu_disable(event->pmu); |
995 | 1016 | ||
996 | n0 = cpuc->n_events; | 1017 | n0 = cpuc->n_events; |
997 | if (n0 >= perf_max_events) | 1018 | if (n0 >= MAX_HWEVENTS) |
998 | goto out; | 1019 | goto out; |
999 | 1020 | ||
1000 | cpuc->event[n0] = event; | 1021 | cpuc->event[n0] = event; |
1001 | cpuc->events[n0] = event->hw.event_base; | 1022 | cpuc->events[n0] = event->hw.event_base; |
1002 | cpuc->current_idx[n0] = PIC_NO_INDEX; | 1023 | cpuc->current_idx[n0] = PIC_NO_INDEX; |
1003 | 1024 | ||
1025 | event->hw.state = PERF_HES_UPTODATE; | ||
1026 | if (!(ef_flags & PERF_EF_START)) | ||
1027 | event->hw.state |= PERF_HES_STOPPED; | ||
1028 | |||
1004 | /* | 1029 | /* |
1005 | * If group events scheduling transaction was started, | 1030 | * If group events scheduling transaction was started, |
1006 | * skip the schedulability test here, it will be peformed | 1031 | * skip the schedulability test here, it will be performed |
1007 | * at commit time(->commit_txn) as a whole | 1032 | * at commit time(->commit_txn) as a whole |
1008 | */ | 1033 | */ |
1009 | if (cpuc->group_flag & PERF_EVENT_TXN) | 1034 | if (cpuc->group_flag & PERF_EVENT_TXN) |
@@ -1020,12 +1045,12 @@ nocheck: | |||
1020 | 1045 | ||
1021 | ret = 0; | 1046 | ret = 0; |
1022 | out: | 1047 | out: |
1023 | perf_enable(); | 1048 | perf_pmu_enable(event->pmu); |
1024 | local_irq_restore(flags); | 1049 | local_irq_restore(flags); |
1025 | return ret; | 1050 | return ret; |
1026 | } | 1051 | } |
1027 | 1052 | ||
1028 | static int __hw_perf_event_init(struct perf_event *event) | 1053 | static int sparc_pmu_event_init(struct perf_event *event) |
1029 | { | 1054 | { |
1030 | struct perf_event_attr *attr = &event->attr; | 1055 | struct perf_event_attr *attr = &event->attr; |
1031 | struct perf_event *evts[MAX_HWEVENTS]; | 1056 | struct perf_event *evts[MAX_HWEVENTS]; |
@@ -1038,22 +1063,33 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
1038 | if (atomic_read(&nmi_active) < 0) | 1063 | if (atomic_read(&nmi_active) < 0) |
1039 | return -ENODEV; | 1064 | return -ENODEV; |
1040 | 1065 | ||
1041 | pmap = NULL; | 1066 | switch (attr->type) { |
1042 | if (attr->type == PERF_TYPE_HARDWARE) { | 1067 | case PERF_TYPE_HARDWARE: |
1043 | if (attr->config >= sparc_pmu->max_events) | 1068 | if (attr->config >= sparc_pmu->max_events) |
1044 | return -EINVAL; | 1069 | return -EINVAL; |
1045 | pmap = sparc_pmu->event_map(attr->config); | 1070 | pmap = sparc_pmu->event_map(attr->config); |
1046 | } else if (attr->type == PERF_TYPE_HW_CACHE) { | 1071 | break; |
1072 | |||
1073 | case PERF_TYPE_HW_CACHE: | ||
1047 | pmap = sparc_map_cache_event(attr->config); | 1074 | pmap = sparc_map_cache_event(attr->config); |
1048 | if (IS_ERR(pmap)) | 1075 | if (IS_ERR(pmap)) |
1049 | return PTR_ERR(pmap); | 1076 | return PTR_ERR(pmap); |
1050 | } else if (attr->type != PERF_TYPE_RAW) | 1077 | break; |
1051 | return -EOPNOTSUPP; | 1078 | |
1079 | case PERF_TYPE_RAW: | ||
1080 | pmap = NULL; | ||
1081 | break; | ||
1082 | |||
1083 | default: | ||
1084 | return -ENOENT; | ||
1085 | |||
1086 | } | ||
1052 | 1087 | ||
1053 | if (pmap) { | 1088 | if (pmap) { |
1054 | hwc->event_base = perf_event_encode(pmap); | 1089 | hwc->event_base = perf_event_encode(pmap); |
1055 | } else { | 1090 | } else { |
1056 | /* User gives us "(encoding << 16) | pic_mask" for | 1091 | /* |
1092 | * User gives us "(encoding << 16) | pic_mask" for | ||
1057 | * PERF_TYPE_RAW events. | 1093 | * PERF_TYPE_RAW events. |
1058 | */ | 1094 | */ |
1059 | hwc->event_base = attr->config; | 1095 | hwc->event_base = attr->config; |
@@ -1071,7 +1107,7 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
1071 | n = 0; | 1107 | n = 0; |
1072 | if (event->group_leader != event) { | 1108 | if (event->group_leader != event) { |
1073 | n = collect_events(event->group_leader, | 1109 | n = collect_events(event->group_leader, |
1074 | perf_max_events - 1, | 1110 | MAX_HWEVENTS - 1, |
1075 | evts, events, current_idx_dmy); | 1111 | evts, events, current_idx_dmy); |
1076 | if (n < 0) | 1112 | if (n < 0) |
1077 | return -EINVAL; | 1113 | return -EINVAL; |
@@ -1107,10 +1143,11 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
1107 | * Set the flag to make pmu::enable() not perform the | 1143 | * Set the flag to make pmu::enable() not perform the |
1108 | * schedulability test, it will be performed at commit time | 1144 | * schedulability test, it will be performed at commit time |
1109 | */ | 1145 | */ |
1110 | static void sparc_pmu_start_txn(const struct pmu *pmu) | 1146 | static void sparc_pmu_start_txn(struct pmu *pmu) |
1111 | { | 1147 | { |
1112 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 1148 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); |
1113 | 1149 | ||
1150 | perf_pmu_disable(pmu); | ||
1114 | cpuhw->group_flag |= PERF_EVENT_TXN; | 1151 | cpuhw->group_flag |= PERF_EVENT_TXN; |
1115 | } | 1152 | } |
1116 | 1153 | ||
@@ -1119,11 +1156,12 @@ static void sparc_pmu_start_txn(const struct pmu *pmu) | |||
1119 | * Clear the flag and pmu::enable() will perform the | 1156 | * Clear the flag and pmu::enable() will perform the |
1120 | * schedulability test. | 1157 | * schedulability test. |
1121 | */ | 1158 | */ |
1122 | static void sparc_pmu_cancel_txn(const struct pmu *pmu) | 1159 | static void sparc_pmu_cancel_txn(struct pmu *pmu) |
1123 | { | 1160 | { |
1124 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 1161 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); |
1125 | 1162 | ||
1126 | cpuhw->group_flag &= ~PERF_EVENT_TXN; | 1163 | cpuhw->group_flag &= ~PERF_EVENT_TXN; |
1164 | perf_pmu_enable(pmu); | ||
1127 | } | 1165 | } |
1128 | 1166 | ||
1129 | /* | 1167 | /* |
@@ -1131,7 +1169,7 @@ static void sparc_pmu_cancel_txn(const struct pmu *pmu) | |||
1131 | * Perform the group schedulability test as a whole | 1169 | * Perform the group schedulability test as a whole |
1132 | * Return 0 if success | 1170 | * Return 0 if success |
1133 | */ | 1171 | */ |
1134 | static int sparc_pmu_commit_txn(const struct pmu *pmu) | 1172 | static int sparc_pmu_commit_txn(struct pmu *pmu) |
1135 | { | 1173 | { |
1136 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1174 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
1137 | int n; | 1175 | int n; |
@@ -1147,28 +1185,24 @@ static int sparc_pmu_commit_txn(const struct pmu *pmu) | |||
1147 | return -EAGAIN; | 1185 | return -EAGAIN; |
1148 | 1186 | ||
1149 | cpuc->group_flag &= ~PERF_EVENT_TXN; | 1187 | cpuc->group_flag &= ~PERF_EVENT_TXN; |
1188 | perf_pmu_enable(pmu); | ||
1150 | return 0; | 1189 | return 0; |
1151 | } | 1190 | } |
1152 | 1191 | ||
1153 | static const struct pmu pmu = { | 1192 | static struct pmu pmu = { |
1154 | .enable = sparc_pmu_enable, | 1193 | .pmu_enable = sparc_pmu_enable, |
1155 | .disable = sparc_pmu_disable, | 1194 | .pmu_disable = sparc_pmu_disable, |
1195 | .event_init = sparc_pmu_event_init, | ||
1196 | .add = sparc_pmu_add, | ||
1197 | .del = sparc_pmu_del, | ||
1198 | .start = sparc_pmu_start, | ||
1199 | .stop = sparc_pmu_stop, | ||
1156 | .read = sparc_pmu_read, | 1200 | .read = sparc_pmu_read, |
1157 | .unthrottle = sparc_pmu_unthrottle, | ||
1158 | .start_txn = sparc_pmu_start_txn, | 1201 | .start_txn = sparc_pmu_start_txn, |
1159 | .cancel_txn = sparc_pmu_cancel_txn, | 1202 | .cancel_txn = sparc_pmu_cancel_txn, |
1160 | .commit_txn = sparc_pmu_commit_txn, | 1203 | .commit_txn = sparc_pmu_commit_txn, |
1161 | }; | 1204 | }; |
1162 | 1205 | ||
1163 | const struct pmu *hw_perf_event_init(struct perf_event *event) | ||
1164 | { | ||
1165 | int err = __hw_perf_event_init(event); | ||
1166 | |||
1167 | if (err) | ||
1168 | return ERR_PTR(err); | ||
1169 | return &pmu; | ||
1170 | } | ||
1171 | |||
1172 | void perf_event_print_debug(void) | 1206 | void perf_event_print_debug(void) |
1173 | { | 1207 | { |
1174 | unsigned long flags; | 1208 | unsigned long flags; |
@@ -1244,7 +1278,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self, | |||
1244 | continue; | 1278 | continue; |
1245 | 1279 | ||
1246 | if (perf_event_overflow(event, 1, &data, regs)) | 1280 | if (perf_event_overflow(event, 1, &data, regs)) |
1247 | sparc_pmu_disable_event(cpuc, hwc, idx); | 1281 | sparc_pmu_stop(event, 0); |
1248 | } | 1282 | } |
1249 | 1283 | ||
1250 | return NOTIFY_STOP; | 1284 | return NOTIFY_STOP; |
@@ -1274,39 +1308,35 @@ static bool __init supported_pmu(void) | |||
1274 | return false; | 1308 | return false; |
1275 | } | 1309 | } |
1276 | 1310 | ||
1277 | void __init init_hw_perf_events(void) | 1311 | int __init init_hw_perf_events(void) |
1278 | { | 1312 | { |
1279 | pr_info("Performance events: "); | 1313 | pr_info("Performance events: "); |
1280 | 1314 | ||
1281 | if (!supported_pmu()) { | 1315 | if (!supported_pmu()) { |
1282 | pr_cont("No support for PMU type '%s'\n", sparc_pmu_type); | 1316 | pr_cont("No support for PMU type '%s'\n", sparc_pmu_type); |
1283 | return; | 1317 | return 0; |
1284 | } | 1318 | } |
1285 | 1319 | ||
1286 | pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); | 1320 | pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); |
1287 | 1321 | ||
1288 | /* All sparc64 PMUs currently have 2 events. */ | 1322 | perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); |
1289 | perf_max_events = 2; | ||
1290 | |||
1291 | register_die_notifier(&perf_event_nmi_notifier); | 1323 | register_die_notifier(&perf_event_nmi_notifier); |
1292 | } | ||
1293 | 1324 | ||
1294 | static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) | 1325 | return 0; |
1295 | { | ||
1296 | if (entry->nr < PERF_MAX_STACK_DEPTH) | ||
1297 | entry->ip[entry->nr++] = ip; | ||
1298 | } | 1326 | } |
1327 | early_initcall(init_hw_perf_events); | ||
1299 | 1328 | ||
1300 | static void perf_callchain_kernel(struct pt_regs *regs, | 1329 | void perf_callchain_kernel(struct perf_callchain_entry *entry, |
1301 | struct perf_callchain_entry *entry) | 1330 | struct pt_regs *regs) |
1302 | { | 1331 | { |
1303 | unsigned long ksp, fp; | 1332 | unsigned long ksp, fp; |
1304 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1333 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1305 | int graph = 0; | 1334 | int graph = 0; |
1306 | #endif | 1335 | #endif |
1307 | 1336 | ||
1308 | callchain_store(entry, PERF_CONTEXT_KERNEL); | 1337 | stack_trace_flush(); |
1309 | callchain_store(entry, regs->tpc); | 1338 | |
1339 | perf_callchain_store(entry, regs->tpc); | ||
1310 | 1340 | ||
1311 | ksp = regs->u_regs[UREG_I6]; | 1341 | ksp = regs->u_regs[UREG_I6]; |
1312 | fp = ksp + STACK_BIAS; | 1342 | fp = ksp + STACK_BIAS; |
@@ -1330,13 +1360,13 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
1330 | pc = sf->callers_pc; | 1360 | pc = sf->callers_pc; |
1331 | fp = (unsigned long)sf->fp + STACK_BIAS; | 1361 | fp = (unsigned long)sf->fp + STACK_BIAS; |
1332 | } | 1362 | } |
1333 | callchain_store(entry, pc); | 1363 | perf_callchain_store(entry, pc); |
1334 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1364 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1335 | if ((pc + 8UL) == (unsigned long) &return_to_handler) { | 1365 | if ((pc + 8UL) == (unsigned long) &return_to_handler) { |
1336 | int index = current->curr_ret_stack; | 1366 | int index = current->curr_ret_stack; |
1337 | if (current->ret_stack && index >= graph) { | 1367 | if (current->ret_stack && index >= graph) { |
1338 | pc = current->ret_stack[index - graph].ret; | 1368 | pc = current->ret_stack[index - graph].ret; |
1339 | callchain_store(entry, pc); | 1369 | perf_callchain_store(entry, pc); |
1340 | graph++; | 1370 | graph++; |
1341 | } | 1371 | } |
1342 | } | 1372 | } |
@@ -1344,13 +1374,12 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
1344 | } while (entry->nr < PERF_MAX_STACK_DEPTH); | 1374 | } while (entry->nr < PERF_MAX_STACK_DEPTH); |
1345 | } | 1375 | } |
1346 | 1376 | ||
1347 | static void perf_callchain_user_64(struct pt_regs *regs, | 1377 | static void perf_callchain_user_64(struct perf_callchain_entry *entry, |
1348 | struct perf_callchain_entry *entry) | 1378 | struct pt_regs *regs) |
1349 | { | 1379 | { |
1350 | unsigned long ufp; | 1380 | unsigned long ufp; |
1351 | 1381 | ||
1352 | callchain_store(entry, PERF_CONTEXT_USER); | 1382 | perf_callchain_store(entry, regs->tpc); |
1353 | callchain_store(entry, regs->tpc); | ||
1354 | 1383 | ||
1355 | ufp = regs->u_regs[UREG_I6] + STACK_BIAS; | 1384 | ufp = regs->u_regs[UREG_I6] + STACK_BIAS; |
1356 | do { | 1385 | do { |
@@ -1363,17 +1392,16 @@ static void perf_callchain_user_64(struct pt_regs *regs, | |||
1363 | 1392 | ||
1364 | pc = sf.callers_pc; | 1393 | pc = sf.callers_pc; |
1365 | ufp = (unsigned long)sf.fp + STACK_BIAS; | 1394 | ufp = (unsigned long)sf.fp + STACK_BIAS; |
1366 | callchain_store(entry, pc); | 1395 | perf_callchain_store(entry, pc); |
1367 | } while (entry->nr < PERF_MAX_STACK_DEPTH); | 1396 | } while (entry->nr < PERF_MAX_STACK_DEPTH); |
1368 | } | 1397 | } |
1369 | 1398 | ||
1370 | static void perf_callchain_user_32(struct pt_regs *regs, | 1399 | static void perf_callchain_user_32(struct perf_callchain_entry *entry, |
1371 | struct perf_callchain_entry *entry) | 1400 | struct pt_regs *regs) |
1372 | { | 1401 | { |
1373 | unsigned long ufp; | 1402 | unsigned long ufp; |
1374 | 1403 | ||
1375 | callchain_store(entry, PERF_CONTEXT_USER); | 1404 | perf_callchain_store(entry, regs->tpc); |
1376 | callchain_store(entry, regs->tpc); | ||
1377 | 1405 | ||
1378 | ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; | 1406 | ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; |
1379 | do { | 1407 | do { |
@@ -1386,34 +1414,16 @@ static void perf_callchain_user_32(struct pt_regs *regs, | |||
1386 | 1414 | ||
1387 | pc = sf.callers_pc; | 1415 | pc = sf.callers_pc; |
1388 | ufp = (unsigned long)sf.fp; | 1416 | ufp = (unsigned long)sf.fp; |
1389 | callchain_store(entry, pc); | 1417 | perf_callchain_store(entry, pc); |
1390 | } while (entry->nr < PERF_MAX_STACK_DEPTH); | 1418 | } while (entry->nr < PERF_MAX_STACK_DEPTH); |
1391 | } | 1419 | } |
1392 | 1420 | ||
1393 | /* Like powerpc we can't get PMU interrupts within the PMU handler, | 1421 | void |
1394 | * so no need for separate NMI and IRQ chains as on x86. | 1422 | perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) |
1395 | */ | ||
1396 | static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); | ||
1397 | |||
1398 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | ||
1399 | { | 1423 | { |
1400 | struct perf_callchain_entry *entry = &__get_cpu_var(callchain); | 1424 | flushw_user(); |
1401 | 1425 | if (test_thread_flag(TIF_32BIT)) | |
1402 | entry->nr = 0; | 1426 | perf_callchain_user_32(entry, regs); |
1403 | if (!user_mode(regs)) { | 1427 | else |
1404 | stack_trace_flush(); | 1428 | perf_callchain_user_64(entry, regs); |
1405 | perf_callchain_kernel(regs, entry); | ||
1406 | if (current->mm) | ||
1407 | regs = task_pt_regs(current); | ||
1408 | else | ||
1409 | regs = NULL; | ||
1410 | } | ||
1411 | if (regs) { | ||
1412 | flushw_user(); | ||
1413 | if (test_thread_flag(TIF_32BIT)) | ||
1414 | perf_callchain_user_32(regs, entry); | ||
1415 | else | ||
1416 | perf_callchain_user_64(regs, entry); | ||
1417 | } | ||
1418 | return entry; | ||
1419 | } | 1429 | } |
diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 94536a85f161..6a585d393580 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c | |||
@@ -51,8 +51,7 @@ static void pmc_swift_idle(void) | |||
51 | #endif | 51 | #endif |
52 | } | 52 | } |
53 | 53 | ||
54 | static int __devinit pmc_probe(struct platform_device *op, | 54 | static int __devinit pmc_probe(struct platform_device *op) |
55 | const struct of_device_id *match) | ||
56 | { | 55 | { |
57 | regs = of_ioremap(&op->resource[0], 0, | 56 | regs = of_ioremap(&op->resource[0], 0, |
58 | resource_size(&op->resource[0]), PMC_OBPNAME); | 57 | resource_size(&op->resource[0]), PMC_OBPNAME); |
@@ -70,7 +69,7 @@ static int __devinit pmc_probe(struct platform_device *op, | |||
70 | return 0; | 69 | return 0; |
71 | } | 70 | } |
72 | 71 | ||
73 | static struct of_device_id __initdata pmc_match[] = { | 72 | static struct of_device_id pmc_match[] = { |
74 | { | 73 | { |
75 | .name = PMC_OBPNAME, | 74 | .name = PMC_OBPNAME, |
76 | }, | 75 | }, |
@@ -78,7 +77,7 @@ static struct of_device_id __initdata pmc_match[] = { | |||
78 | }; | 77 | }; |
79 | MODULE_DEVICE_TABLE(of, pmc_match); | 78 | MODULE_DEVICE_TABLE(of, pmc_match); |
80 | 79 | ||
81 | static struct of_platform_driver pmc_driver = { | 80 | static struct platform_driver pmc_driver = { |
82 | .driver = { | 81 | .driver = { |
83 | .name = "pmc", | 82 | .name = "pmc", |
84 | .owner = THIS_MODULE, | 83 | .owner = THIS_MODULE, |
@@ -89,7 +88,7 @@ static struct of_platform_driver pmc_driver = { | |||
89 | 88 | ||
90 | static int __init pmc_init(void) | 89 | static int __init pmc_init(void) |
91 | { | 90 | { |
92 | return of_register_platform_driver(&pmc_driver); | 91 | return platform_driver_register(&pmc_driver); |
93 | } | 92 | } |
94 | 93 | ||
95 | /* This driver is not critical to the boot process | 94 | /* This driver is not critical to the boot process |
diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c index 2c59f4d387dd..cb4c0f57c024 100644 --- a/arch/sparc/kernel/power.c +++ b/arch/sparc/kernel/power.c | |||
@@ -33,7 +33,7 @@ static int __devinit has_button_interrupt(unsigned int irq, struct device_node * | |||
33 | return 1; | 33 | return 1; |
34 | } | 34 | } |
35 | 35 | ||
36 | static int __devinit power_probe(struct platform_device *op, const struct of_device_id *match) | 36 | static int __devinit power_probe(struct platform_device *op) |
37 | { | 37 | { |
38 | struct resource *res = &op->resource[0]; | 38 | struct resource *res = &op->resource[0]; |
39 | unsigned int irq = op->archdata.irqs[0]; | 39 | unsigned int irq = op->archdata.irqs[0]; |
@@ -52,14 +52,14 @@ static int __devinit power_probe(struct platform_device *op, const struct of_dev | |||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct of_device_id __initdata power_match[] = { | 55 | static const struct of_device_id power_match[] = { |
56 | { | 56 | { |
57 | .name = "power", | 57 | .name = "power", |
58 | }, | 58 | }, |
59 | {}, | 59 | {}, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static struct of_platform_driver power_driver = { | 62 | static struct platform_driver power_driver = { |
63 | .probe = power_probe, | 63 | .probe = power_probe, |
64 | .driver = { | 64 | .driver = { |
65 | .name = "power", | 65 | .name = "power", |
@@ -70,7 +70,7 @@ static struct of_platform_driver power_driver = { | |||
70 | 70 | ||
71 | static int __init power_init(void) | 71 | static int __init power_init(void) |
72 | { | 72 | { |
73 | return of_register_platform_driver(&power_driver); | 73 | return platform_driver_register(&power_driver); |
74 | } | 74 | } |
75 | 75 | ||
76 | device_initcall(power_init); | 76 | device_initcall(power_init); |
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 17529298c50a..c8cc461ff75f 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c | |||
@@ -128,8 +128,16 @@ void cpu_idle(void) | |||
128 | set_thread_flag(TIF_POLLING_NRFLAG); | 128 | set_thread_flag(TIF_POLLING_NRFLAG); |
129 | /* endless idle loop with no priority at all */ | 129 | /* endless idle loop with no priority at all */ |
130 | while(1) { | 130 | while(1) { |
131 | while (!need_resched()) | 131 | #ifdef CONFIG_SPARC_LEON |
132 | cpu_relax(); | 132 | if (pm_idle) { |
133 | while (!need_resched()) | ||
134 | (*pm_idle)(); | ||
135 | } else | ||
136 | #endif | ||
137 | { | ||
138 | while (!need_resched()) | ||
139 | cpu_relax(); | ||
140 | } | ||
133 | preempt_enable_no_resched(); | 141 | preempt_enable_no_resched(); |
134 | schedule(); | 142 | schedule(); |
135 | preempt_disable(); | 143 | preempt_disable(); |
diff --git a/arch/sparc/kernel/prom.h b/arch/sparc/kernel/prom.h index eeb04a782ec8..cf5fe1c0b024 100644 --- a/arch/sparc/kernel/prom.h +++ b/arch/sparc/kernel/prom.h | |||
@@ -4,12 +4,6 @@ | |||
4 | #include <linux/spinlock.h> | 4 | #include <linux/spinlock.h> |
5 | #include <asm/prom.h> | 5 | #include <asm/prom.h> |
6 | 6 | ||
7 | extern void * prom_early_alloc(unsigned long size); | ||
8 | extern void irq_trans_init(struct device_node *dp); | ||
9 | |||
10 | extern unsigned int prom_unique_id; | ||
11 | |||
12 | extern char *build_path_component(struct device_node *dp); | ||
13 | extern void of_console_init(void); | 7 | extern void of_console_init(void); |
14 | 8 | ||
15 | extern unsigned int prom_early_allocated; | 9 | extern unsigned int prom_early_allocated; |
diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 0a37e8cfd160..5ce3d15a99b0 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c | |||
@@ -136,18 +136,29 @@ static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) | |||
136 | /* "name:vendor:device@irq,addrlo" */ | 136 | /* "name:vendor:device@irq,addrlo" */ |
137 | static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) | 137 | static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) |
138 | { | 138 | { |
139 | struct amba_prom_registers *regs; unsigned int *intr; | 139 | struct amba_prom_registers *regs; |
140 | unsigned int *device, *vendor; | 140 | unsigned int *intr, *device, *vendor, reg0; |
141 | struct property *prop; | 141 | struct property *prop; |
142 | int interrupt = 0; | ||
142 | 143 | ||
144 | /* In order to get a unique ID in the device tree (multiple AMBA devices | ||
145 | * may have the same name) the node number is printed | ||
146 | */ | ||
143 | prop = of_find_property(dp, "reg", NULL); | 147 | prop = of_find_property(dp, "reg", NULL); |
144 | if (!prop) | 148 | if (!prop) { |
145 | return; | 149 | reg0 = (unsigned int)dp->phandle; |
146 | regs = prop->value; | 150 | } else { |
151 | regs = prop->value; | ||
152 | reg0 = regs->phys_addr; | ||
153 | } | ||
154 | |||
155 | /* Not all cores have Interrupt */ | ||
147 | prop = of_find_property(dp, "interrupts", NULL); | 156 | prop = of_find_property(dp, "interrupts", NULL); |
148 | if (!prop) | 157 | if (!prop) |
149 | return; | 158 | intr = &interrupt; /* IRQ0 does not exist */ |
150 | intr = prop->value; | 159 | else |
160 | intr = prop->value; | ||
161 | |||
151 | prop = of_find_property(dp, "vendor", NULL); | 162 | prop = of_find_property(dp, "vendor", NULL); |
152 | if (!prop) | 163 | if (!prop) |
153 | return; | 164 | return; |
@@ -159,7 +170,7 @@ static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) | |||
159 | 170 | ||
160 | sprintf(tmp_buf, "%s:%d:%d@%x,%x", | 171 | sprintf(tmp_buf, "%s:%d:%d@%x,%x", |
161 | dp->name, *vendor, *device, | 172 | dp->name, *vendor, *device, |
162 | *intr, regs->phys_addr); | 173 | *intr, reg0); |
163 | } | 174 | } |
164 | 175 | ||
165 | static void __init __build_path_component(struct device_node *dp, char *tmp_buf) | 176 | static void __init __build_path_component(struct device_node *dp, char *tmp_buf) |
@@ -315,7 +326,6 @@ void __init of_console_init(void) | |||
315 | of_console_options = NULL; | 326 | of_console_options = NULL; |
316 | } | 327 | } |
317 | 328 | ||
318 | prom_printf(msg, of_console_path); | ||
319 | printk(msg, of_console_path); | 329 | printk(msg, of_console_path); |
320 | } | 330 | } |
321 | 331 | ||
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 1f830da2ddf2..ed25834328f4 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c | |||
@@ -20,14 +20,13 @@ | |||
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <linux/of_pdt.h> | ||
23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
24 | #include <asm/oplib.h> | 25 | #include <asm/oplib.h> |
25 | #include <asm/leon.h> | 26 | #include <asm/leon.h> |
26 | 27 | ||
27 | #include "prom.h" | 28 | #include "prom.h" |
28 | 29 | ||
29 | void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp); | ||
30 | |||
31 | struct device_node *of_console_device; | 30 | struct device_node *of_console_device; |
32 | EXPORT_SYMBOL(of_console_device); | 31 | EXPORT_SYMBOL(of_console_device); |
33 | 32 | ||
@@ -119,192 +118,47 @@ int of_find_in_proplist(const char *list, const char *match, int len) | |||
119 | } | 118 | } |
120 | EXPORT_SYMBOL(of_find_in_proplist); | 119 | EXPORT_SYMBOL(of_find_in_proplist); |
121 | 120 | ||
122 | unsigned int prom_unique_id; | 121 | /* |
123 | 122 | * SPARC32 and SPARC64's prom_nextprop() do things differently | |
124 | static struct property * __init build_one_prop(phandle node, char *prev, | 123 | * here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', |
125 | char *special_name, | 124 | * returning NULL on an error. SPARC64 fills in 'buf', but sets it to an |
126 | void *special_val, | 125 | * empty string upon error. |
127 | int special_len) | 126 | */ |
127 | static int __init handle_nextprop_quirks(char *buf, const char *name) | ||
128 | { | 128 | { |
129 | static struct property *tmp = NULL; | 129 | if (!name || strlen(name) == 0) |
130 | struct property *p; | 130 | return -1; |
131 | const char *name; | ||
132 | |||
133 | if (tmp) { | ||
134 | p = tmp; | ||
135 | memset(p, 0, sizeof(*p) + 32); | ||
136 | tmp = NULL; | ||
137 | } else { | ||
138 | p = prom_early_alloc(sizeof(struct property) + 32); | ||
139 | p->unique_id = prom_unique_id++; | ||
140 | } | ||
141 | |||
142 | p->name = (char *) (p + 1); | ||
143 | if (special_name) { | ||
144 | strcpy(p->name, special_name); | ||
145 | p->length = special_len; | ||
146 | p->value = prom_early_alloc(special_len); | ||
147 | memcpy(p->value, special_val, special_len); | ||
148 | } else { | ||
149 | if (prev == NULL) { | ||
150 | name = prom_firstprop(node, p->name); | ||
151 | } else { | ||
152 | name = prom_nextprop(node, prev, p->name); | ||
153 | } | ||
154 | 131 | ||
155 | if (!name || strlen(name) == 0) { | ||
156 | tmp = p; | ||
157 | return NULL; | ||
158 | } | ||
159 | #ifdef CONFIG_SPARC32 | 132 | #ifdef CONFIG_SPARC32 |
160 | strcpy(p->name, name); | 133 | strcpy(buf, name); |
161 | #endif | 134 | #endif |
162 | p->length = prom_getproplen(node, p->name); | 135 | return 0; |
163 | if (p->length <= 0) { | ||
164 | p->length = 0; | ||
165 | } else { | ||
166 | int len; | ||
167 | |||
168 | p->value = prom_early_alloc(p->length + 1); | ||
169 | len = prom_getproperty(node, p->name, p->value, | ||
170 | p->length); | ||
171 | if (len <= 0) | ||
172 | p->length = 0; | ||
173 | ((unsigned char *)p->value)[p->length] = '\0'; | ||
174 | } | ||
175 | } | ||
176 | return p; | ||
177 | } | ||
178 | |||
179 | static struct property * __init build_prop_list(phandle node) | ||
180 | { | ||
181 | struct property *head, *tail; | ||
182 | |||
183 | head = tail = build_one_prop(node, NULL, | ||
184 | ".node", &node, sizeof(node)); | ||
185 | |||
186 | tail->next = build_one_prop(node, NULL, NULL, NULL, 0); | ||
187 | tail = tail->next; | ||
188 | while(tail) { | ||
189 | tail->next = build_one_prop(node, tail->name, | ||
190 | NULL, NULL, 0); | ||
191 | tail = tail->next; | ||
192 | } | ||
193 | |||
194 | return head; | ||
195 | } | ||
196 | |||
197 | static char * __init get_one_property(phandle node, const char *name) | ||
198 | { | ||
199 | char *buf = "<NULL>"; | ||
200 | int len; | ||
201 | |||
202 | len = prom_getproplen(node, name); | ||
203 | if (len > 0) { | ||
204 | buf = prom_early_alloc(len); | ||
205 | len = prom_getproperty(node, name, buf, len); | ||
206 | } | ||
207 | |||
208 | return buf; | ||
209 | } | ||
210 | |||
211 | static struct device_node * __init prom_create_node(phandle node, | ||
212 | struct device_node *parent) | ||
213 | { | ||
214 | struct device_node *dp; | ||
215 | |||
216 | if (!node) | ||
217 | return NULL; | ||
218 | |||
219 | dp = prom_early_alloc(sizeof(*dp)); | ||
220 | dp->unique_id = prom_unique_id++; | ||
221 | dp->parent = parent; | ||
222 | |||
223 | kref_init(&dp->kref); | ||
224 | |||
225 | dp->name = get_one_property(node, "name"); | ||
226 | dp->type = get_one_property(node, "device_type"); | ||
227 | dp->phandle = node; | ||
228 | |||
229 | dp->properties = build_prop_list(node); | ||
230 | |||
231 | irq_trans_init(dp); | ||
232 | |||
233 | return dp; | ||
234 | } | ||
235 | |||
236 | char * __init build_full_name(struct device_node *dp) | ||
237 | { | ||
238 | int len, ourlen, plen; | ||
239 | char *n; | ||
240 | |||
241 | plen = strlen(dp->parent->full_name); | ||
242 | ourlen = strlen(dp->path_component_name); | ||
243 | len = ourlen + plen + 2; | ||
244 | |||
245 | n = prom_early_alloc(len); | ||
246 | strcpy(n, dp->parent->full_name); | ||
247 | if (!of_node_is_root(dp->parent)) { | ||
248 | strcpy(n + plen, "/"); | ||
249 | plen++; | ||
250 | } | ||
251 | strcpy(n + plen, dp->path_component_name); | ||
252 | |||
253 | return n; | ||
254 | } | 136 | } |
255 | 137 | ||
256 | static struct device_node * __init prom_build_tree(struct device_node *parent, | 138 | static int __init prom_common_nextprop(phandle node, char *prev, char *buf) |
257 | phandle node, | ||
258 | struct device_node ***nextp) | ||
259 | { | 139 | { |
260 | struct device_node *ret = NULL, *prev_sibling = NULL; | 140 | const char *name; |
261 | struct device_node *dp; | ||
262 | |||
263 | while (1) { | ||
264 | dp = prom_create_node(node, parent); | ||
265 | if (!dp) | ||
266 | break; | ||
267 | |||
268 | if (prev_sibling) | ||
269 | prev_sibling->sibling = dp; | ||
270 | |||
271 | if (!ret) | ||
272 | ret = dp; | ||
273 | prev_sibling = dp; | ||
274 | |||
275 | *(*nextp) = dp; | ||
276 | *nextp = &dp->allnext; | ||
277 | |||
278 | dp->path_component_name = build_path_component(dp); | ||
279 | dp->full_name = build_full_name(dp); | ||
280 | |||
281 | dp->child = prom_build_tree(dp, prom_getchild(node), nextp); | ||
282 | |||
283 | if (prom_build_more) | ||
284 | prom_build_more(dp, nextp); | ||
285 | |||
286 | node = prom_getsibling(node); | ||
287 | } | ||
288 | 141 | ||
289 | return ret; | 142 | buf[0] = '\0'; |
143 | name = prom_nextprop(node, prev, buf); | ||
144 | return handle_nextprop_quirks(buf, name); | ||
290 | } | 145 | } |
291 | 146 | ||
292 | unsigned int prom_early_allocated __initdata; | 147 | unsigned int prom_early_allocated __initdata; |
293 | 148 | ||
149 | static struct of_pdt_ops prom_sparc_ops __initdata = { | ||
150 | .nextprop = prom_common_nextprop, | ||
151 | .getproplen = prom_getproplen, | ||
152 | .getproperty = prom_getproperty, | ||
153 | .getchild = prom_getchild, | ||
154 | .getsibling = prom_getsibling, | ||
155 | }; | ||
156 | |||
294 | void __init prom_build_devicetree(void) | 157 | void __init prom_build_devicetree(void) |
295 | { | 158 | { |
296 | struct device_node **nextp; | 159 | of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops); |
297 | |||
298 | allnodes = prom_create_node(prom_root_node, NULL); | ||
299 | allnodes->path_component_name = ""; | ||
300 | allnodes->full_name = "/"; | ||
301 | |||
302 | nextp = &allnodes->allnext; | ||
303 | allnodes->child = prom_build_tree(allnodes, | ||
304 | prom_getchild(allnodes->phandle), | ||
305 | &nextp); | ||
306 | of_console_init(); | 160 | of_console_init(); |
307 | 161 | ||
308 | printk("PROM: Built device tree with %u bytes of memory.\n", | 162 | pr_info("PROM: Built device tree with %u bytes of memory.\n", |
309 | prom_early_allocated); | 163 | prom_early_allocated); |
310 | } | 164 | } |
diff --git a/arch/sparc/kernel/prom_irqtrans.c b/arch/sparc/kernel/prom_irqtrans.c index ce651147fabc..40e4936bd479 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, |
@@ -694,7 +694,7 @@ static unsigned int sbus_of_build_irq(struct device_node *dp, | |||
694 | case 3: | 694 | case 3: |
695 | iclr = reg_base + SYSIO_ICLR_SLOT3; | 695 | iclr = reg_base + SYSIO_ICLR_SLOT3; |
696 | break; | 696 | break; |
697 | }; | 697 | } |
698 | 698 | ||
699 | iclr += ((unsigned long)sbus_level - 1UL) * 8UL; | 699 | iclr += ((unsigned long)sbus_level - 1UL) * 8UL; |
700 | } | 700 | } |
diff --git a/arch/sparc/kernel/psycho_common.c b/arch/sparc/kernel/psycho_common.c index fe2af66bb198..8db48e808ed4 100644 --- a/arch/sparc/kernel/psycho_common.c +++ b/arch/sparc/kernel/psycho_common.c | |||
@@ -228,7 +228,7 @@ void psycho_check_iommu_error(struct pci_pbm_info *pbm, | |||
228 | default: | 228 | default: |
229 | type_str = "ECC Error"; | 229 | type_str = "ECC Error"; |
230 | break; | 230 | break; |
231 | }; | 231 | } |
232 | printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", | 232 | printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", |
233 | pbm->name, type_str); | 233 | pbm->name, type_str); |
234 | 234 | ||
diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c index e608f397e11f..27b9e93d0121 100644 --- a/arch/sparc/kernel/ptrace_32.c +++ b/arch/sparc/kernel/ptrace_32.c | |||
@@ -323,18 +323,35 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
323 | return &user_sparc32_view; | 323 | return &user_sparc32_view; |
324 | } | 324 | } |
325 | 325 | ||
326 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 326 | struct fps { |
327 | unsigned long regs[32]; | ||
328 | unsigned long fsr; | ||
329 | unsigned long flags; | ||
330 | unsigned long extra; | ||
331 | unsigned long fpqd; | ||
332 | struct fq { | ||
333 | unsigned long *insnaddr; | ||
334 | unsigned long insn; | ||
335 | } fpq[16]; | ||
336 | }; | ||
337 | |||
338 | long arch_ptrace(struct task_struct *child, long request, | ||
339 | unsigned long addr, unsigned long data) | ||
327 | { | 340 | { |
328 | unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; | 341 | unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; |
342 | void __user *addr2p; | ||
329 | const struct user_regset_view *view; | 343 | const struct user_regset_view *view; |
344 | struct pt_regs __user *pregs; | ||
345 | struct fps __user *fps; | ||
330 | int ret; | 346 | int ret; |
331 | 347 | ||
332 | view = task_user_regset_view(current); | 348 | view = task_user_regset_view(current); |
349 | addr2p = (void __user *) addr2; | ||
350 | pregs = (struct pt_regs __user *) addr; | ||
351 | fps = (struct fps __user *) addr; | ||
333 | 352 | ||
334 | switch(request) { | 353 | switch(request) { |
335 | case PTRACE_GETREGS: { | 354 | case PTRACE_GETREGS: { |
336 | struct pt_regs __user *pregs = (struct pt_regs __user *) addr; | ||
337 | |||
338 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | 355 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, |
339 | 32 * sizeof(u32), | 356 | 32 * sizeof(u32), |
340 | 4 * sizeof(u32), | 357 | 4 * sizeof(u32), |
@@ -348,8 +365,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
348 | } | 365 | } |
349 | 366 | ||
350 | case PTRACE_SETREGS: { | 367 | case PTRACE_SETREGS: { |
351 | struct pt_regs __user *pregs = (struct pt_regs __user *) addr; | ||
352 | |||
353 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | 368 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, |
354 | 32 * sizeof(u32), | 369 | 32 * sizeof(u32), |
355 | 4 * sizeof(u32), | 370 | 4 * sizeof(u32), |
@@ -363,19 +378,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
363 | } | 378 | } |
364 | 379 | ||
365 | case PTRACE_GETFPREGS: { | 380 | case PTRACE_GETFPREGS: { |
366 | struct fps { | ||
367 | unsigned long regs[32]; | ||
368 | unsigned long fsr; | ||
369 | unsigned long flags; | ||
370 | unsigned long extra; | ||
371 | unsigned long fpqd; | ||
372 | struct fq { | ||
373 | unsigned long *insnaddr; | ||
374 | unsigned long insn; | ||
375 | } fpq[16]; | ||
376 | }; | ||
377 | struct fps __user *fps = (struct fps __user *) addr; | ||
378 | |||
379 | ret = copy_regset_to_user(child, view, REGSET_FP, | 381 | ret = copy_regset_to_user(child, view, REGSET_FP, |
380 | 0 * sizeof(u32), | 382 | 0 * sizeof(u32), |
381 | 32 * sizeof(u32), | 383 | 32 * sizeof(u32), |
@@ -397,19 +399,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
397 | } | 399 | } |
398 | 400 | ||
399 | case PTRACE_SETFPREGS: { | 401 | case PTRACE_SETFPREGS: { |
400 | struct fps { | ||
401 | unsigned long regs[32]; | ||
402 | unsigned long fsr; | ||
403 | unsigned long flags; | ||
404 | unsigned long extra; | ||
405 | unsigned long fpqd; | ||
406 | struct fq { | ||
407 | unsigned long *insnaddr; | ||
408 | unsigned long insn; | ||
409 | } fpq[16]; | ||
410 | }; | ||
411 | struct fps __user *fps = (struct fps __user *) addr; | ||
412 | |||
413 | ret = copy_regset_from_user(child, view, REGSET_FP, | 402 | ret = copy_regset_from_user(child, view, REGSET_FP, |
414 | 0 * sizeof(u32), | 403 | 0 * sizeof(u32), |
415 | 32 * sizeof(u32), | 404 | 32 * sizeof(u32), |
@@ -424,8 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
424 | 413 | ||
425 | case PTRACE_READTEXT: | 414 | case PTRACE_READTEXT: |
426 | case PTRACE_READDATA: | 415 | case PTRACE_READDATA: |
427 | ret = ptrace_readdata(child, addr, | 416 | ret = ptrace_readdata(child, addr, addr2p, data); |
428 | (void __user *) addr2, data); | ||
429 | 417 | ||
430 | if (ret == data) | 418 | if (ret == data) |
431 | ret = 0; | 419 | ret = 0; |
@@ -435,8 +423,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
435 | 423 | ||
436 | case PTRACE_WRITETEXT: | 424 | case PTRACE_WRITETEXT: |
437 | case PTRACE_WRITEDATA: | 425 | case PTRACE_WRITEDATA: |
438 | ret = ptrace_writedata(child, (void __user *) addr2, | 426 | ret = ptrace_writedata(child, addr2p, addr, data); |
439 | addr, data); | ||
440 | 427 | ||
441 | if (ret == data) | 428 | if (ret == data) |
442 | ret = 0; | 429 | ret = 0; |
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index aa90da08bf61..96ee50a80661 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c | |||
@@ -969,16 +969,19 @@ struct fps { | |||
969 | unsigned long fsr; | 969 | unsigned long fsr; |
970 | }; | 970 | }; |
971 | 971 | ||
972 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 972 | long arch_ptrace(struct task_struct *child, long request, |
973 | unsigned long addr, unsigned long data) | ||
973 | { | 974 | { |
974 | const struct user_regset_view *view = task_user_regset_view(current); | 975 | const struct user_regset_view *view = task_user_regset_view(current); |
975 | unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; | 976 | unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; |
976 | struct pt_regs __user *pregs; | 977 | struct pt_regs __user *pregs; |
977 | struct fps __user *fps; | 978 | struct fps __user *fps; |
979 | void __user *addr2p; | ||
978 | int ret; | 980 | int ret; |
979 | 981 | ||
980 | pregs = (struct pt_regs __user *) (unsigned long) addr; | 982 | pregs = (struct pt_regs __user *) addr; |
981 | fps = (struct fps __user *) (unsigned long) addr; | 983 | fps = (struct fps __user *) addr; |
984 | addr2p = (void __user *) addr2; | ||
982 | 985 | ||
983 | switch (request) { | 986 | switch (request) { |
984 | case PTRACE_PEEKUSR: | 987 | case PTRACE_PEEKUSR: |
@@ -1029,8 +1032,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
1029 | 1032 | ||
1030 | case PTRACE_READTEXT: | 1033 | case PTRACE_READTEXT: |
1031 | case PTRACE_READDATA: | 1034 | case PTRACE_READDATA: |
1032 | ret = ptrace_readdata(child, addr, | 1035 | ret = ptrace_readdata(child, addr, addr2p, data); |
1033 | (char __user *)addr2, data); | ||
1034 | if (ret == data) | 1036 | if (ret == data) |
1035 | ret = 0; | 1037 | ret = 0; |
1036 | else if (ret >= 0) | 1038 | else if (ret >= 0) |
@@ -1039,8 +1041,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
1039 | 1041 | ||
1040 | case PTRACE_WRITETEXT: | 1042 | case PTRACE_WRITETEXT: |
1041 | case PTRACE_WRITEDATA: | 1043 | case PTRACE_WRITEDATA: |
1042 | ret = ptrace_writedata(child, (char __user *) addr2, | 1044 | ret = ptrace_writedata(child, addr2p, addr, data); |
1043 | addr, data); | ||
1044 | if (ret == data) | 1045 | if (ret == data) |
1045 | ret = 0; | 1046 | ret = 0; |
1046 | else if (ret >= 0) | 1047 | else if (ret >= 0) |
@@ -1085,6 +1086,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
1085 | 1086 | ||
1086 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 1087 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) |
1087 | { | 1088 | { |
1089 | #ifdef CONFIG_AUDITSYSCALL | ||
1088 | if (unlikely(current->audit_context)) { | 1090 | if (unlikely(current->audit_context)) { |
1089 | unsigned long tstate = regs->tstate; | 1091 | unsigned long tstate = regs->tstate; |
1090 | int result = AUDITSC_SUCCESS; | 1092 | int result = AUDITSC_SUCCESS; |
@@ -1094,7 +1096,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) | |||
1094 | 1096 | ||
1095 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | 1097 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); |
1096 | } | 1098 | } |
1097 | 1099 | #endif | |
1098 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 1100 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
1099 | trace_sys_exit(regs, regs->u_regs[UREG_G1]); | 1101 | trace_sys_exit(regs, regs->u_regs[UREG_G1]); |
1100 | 1102 | ||
diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S index 4da2e1f66290..5f5f74c2c2ca 100644 --- a/arch/sparc/kernel/rtrap_32.S +++ b/arch/sparc/kernel/rtrap_32.S | |||
@@ -78,9 +78,9 @@ signal_p: | |||
78 | call do_notify_resume | 78 | call do_notify_resume |
79 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr | 79 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr |
80 | 80 | ||
81 | /* Fall through. */ | 81 | b signal_p |
82 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr | 82 | ld [%curptr + TI_FLAGS], %g2 |
83 | clr %l6 | 83 | |
84 | ret_trap_continue: | 84 | ret_trap_continue: |
85 | sethi %hi(PSR_SYSCALL), %g1 | 85 | sethi %hi(PSR_SYSCALL), %g1 |
86 | andn %t_psr, %g1, %t_psr | 86 | andn %t_psr, %g1, %t_psr |
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 090b9e9ad5e3..77f1b95e0806 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S | |||
@@ -34,37 +34,9 @@ __handle_preemption: | |||
34 | __handle_user_windows: | 34 | __handle_user_windows: |
35 | call fault_in_user_windows | 35 | call fault_in_user_windows |
36 | wrpr %g0, RTRAP_PSTATE, %pstate | 36 | wrpr %g0, RTRAP_PSTATE, %pstate |
37 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | 37 | ba,pt %xcc, __handle_preemption_continue |
38 | /* Redo sched+sig checks */ | 38 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate |
39 | ldx [%g6 + TI_FLAGS], %l0 | ||
40 | andcc %l0, _TIF_NEED_RESCHED, %g0 | ||
41 | |||
42 | be,pt %xcc, 1f | ||
43 | nop | ||
44 | call schedule | ||
45 | wrpr %g0, RTRAP_PSTATE, %pstate | ||
46 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | ||
47 | ldx [%g6 + TI_FLAGS], %l0 | ||
48 | |||
49 | 1: andcc %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0 | ||
50 | be,pt %xcc, __handle_user_windows_continue | ||
51 | nop | ||
52 | mov %l5, %o1 | ||
53 | add %sp, PTREGS_OFF, %o0 | ||
54 | mov %l0, %o2 | ||
55 | |||
56 | call do_notify_resume | ||
57 | wrpr %g0, RTRAP_PSTATE, %pstate | ||
58 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | ||
59 | /* Signal delivery can modify pt_regs tstate, so we must | ||
60 | * reload it. | ||
61 | */ | ||
62 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 | ||
63 | sethi %hi(0xf << 20), %l4 | ||
64 | and %l1, %l4, %l4 | ||
65 | ba,pt %xcc, __handle_user_windows_continue | ||
66 | 39 | ||
67 | andn %l1, %l4, %l1 | ||
68 | __handle_userfpu: | 40 | __handle_userfpu: |
69 | rd %fprs, %l5 | 41 | rd %fprs, %l5 |
70 | andcc %l5, FPRS_FEF, %g0 | 42 | andcc %l5, FPRS_FEF, %g0 |
@@ -87,7 +59,7 @@ __handle_signal: | |||
87 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 | 59 | ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 |
88 | sethi %hi(0xf << 20), %l4 | 60 | sethi %hi(0xf << 20), %l4 |
89 | and %l1, %l4, %l4 | 61 | and %l1, %l4, %l4 |
90 | ba,pt %xcc, __handle_signal_continue | 62 | ba,pt %xcc, __handle_preemption_continue |
91 | andn %l1, %l4, %l1 | 63 | andn %l1, %l4, %l1 |
92 | 64 | ||
93 | /* When returning from a NMI (%pil==15) interrupt we want to | 65 | /* When returning from a NMI (%pil==15) interrupt we want to |
@@ -177,11 +149,9 @@ __handle_preemption_continue: | |||
177 | bne,pn %xcc, __handle_preemption | 149 | bne,pn %xcc, __handle_preemption |
178 | andcc %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0 | 150 | andcc %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0 |
179 | bne,pn %xcc, __handle_signal | 151 | bne,pn %xcc, __handle_signal |
180 | __handle_signal_continue: | ||
181 | ldub [%g6 + TI_WSAVED], %o2 | 152 | ldub [%g6 + TI_WSAVED], %o2 |
182 | brnz,pn %o2, __handle_user_windows | 153 | brnz,pn %o2, __handle_user_windows |
183 | nop | 154 | nop |
184 | __handle_user_windows_continue: | ||
185 | sethi %hi(TSTATE_PEF), %o0 | 155 | sethi %hi(TSTATE_PEF), %o0 |
186 | andcc %l1, %o0, %g0 | 156 | andcc %l1, %o0, %g0 |
187 | 157 | ||
diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c index 2ca32d13abcf..a161b9c77f05 100644 --- a/arch/sparc/kernel/sbus.c +++ b/arch/sparc/kernel/sbus.c | |||
@@ -97,7 +97,7 @@ void sbus_set_sbus64(struct device *dev, int bursts) | |||
97 | 97 | ||
98 | default: | 98 | default: |
99 | return; | 99 | return; |
100 | }; | 100 | } |
101 | 101 | ||
102 | val = upa_readq(cfg_reg); | 102 | val = upa_readq(cfg_reg); |
103 | if (val & (1UL << 14UL)) { | 103 | if (val & (1UL << 14UL)) { |
@@ -244,7 +244,7 @@ static unsigned int sbus_build_irq(struct platform_device *op, unsigned int ino) | |||
244 | case 3: | 244 | case 3: |
245 | iclr = reg_base + SYSIO_ICLR_SLOT3; | 245 | iclr = reg_base + SYSIO_ICLR_SLOT3; |
246 | break; | 246 | break; |
247 | }; | 247 | } |
248 | 248 | ||
249 | iclr += ((unsigned long)sbus_level - 1UL) * 8UL; | 249 | iclr += ((unsigned long)sbus_level - 1UL) * 8UL; |
250 | } | 250 | } |
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index b22ce6100403..d26e1f6c717a 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c | |||
@@ -82,7 +82,7 @@ static void prom_sync_me(void) | |||
82 | "nop\n\t" : : "r" (&trapbase)); | 82 | "nop\n\t" : : "r" (&trapbase)); |
83 | 83 | ||
84 | prom_printf("PROM SYNC COMMAND...\n"); | 84 | prom_printf("PROM SYNC COMMAND...\n"); |
85 | show_free_areas(); | 85 | show_free_areas(0); |
86 | if(current->pid != 0) { | 86 | if(current->pid != 0) { |
87 | local_irq_enable(); | 87 | local_irq_enable(); |
88 | sys_sync(); | 88 | sys_sync(); |
@@ -103,16 +103,20 @@ static unsigned int boot_flags __initdata = 0; | |||
103 | /* Exported for mm/init.c:paging_init. */ | 103 | /* Exported for mm/init.c:paging_init. */ |
104 | unsigned long cmdline_memory_size __initdata = 0; | 104 | unsigned long cmdline_memory_size __initdata = 0; |
105 | 105 | ||
106 | /* which CPU booted us (0xff = not set) */ | ||
107 | unsigned char boot_cpu_id = 0xff; /* 0xff will make it into DATA section... */ | ||
108 | unsigned char boot_cpu_id4; /* boot_cpu_id << 2 */ | ||
109 | |||
106 | static void | 110 | static void |
107 | prom_console_write(struct console *con, const char *s, unsigned n) | 111 | prom_console_write(struct console *con, const char *s, unsigned n) |
108 | { | 112 | { |
109 | prom_write(s, n); | 113 | prom_write(s, n); |
110 | } | 114 | } |
111 | 115 | ||
112 | static struct console prom_debug_console = { | 116 | static struct console prom_early_console = { |
113 | .name = "debug", | 117 | .name = "earlyprom", |
114 | .write = prom_console_write, | 118 | .write = prom_console_write, |
115 | .flags = CON_PRINTBUFFER, | 119 | .flags = CON_PRINTBUFFER | CON_BOOT, |
116 | .index = -1, | 120 | .index = -1, |
117 | }; | 121 | }; |
118 | 122 | ||
@@ -133,8 +137,7 @@ static void __init process_switch(char c) | |||
133 | prom_halt(); | 137 | prom_halt(); |
134 | break; | 138 | break; |
135 | case 'p': | 139 | case 'p': |
136 | /* Use PROM debug console. */ | 140 | /* Just ignore, this behavior is now the default. */ |
137 | register_console(&prom_debug_console); | ||
138 | break; | 141 | break; |
139 | default: | 142 | default: |
140 | printk("Unknown boot switch (-%c)\n", c); | 143 | printk("Unknown boot switch (-%c)\n", c); |
@@ -184,8 +187,6 @@ static void __init boot_flags_init(char *commands) | |||
184 | */ | 187 | */ |
185 | 188 | ||
186 | extern void sun4c_probe_vac(void); | 189 | extern void sun4c_probe_vac(void); |
187 | extern char cputypval; | ||
188 | extern unsigned long start, end; | ||
189 | 190 | ||
190 | extern unsigned short root_flags; | 191 | extern unsigned short root_flags; |
191 | extern unsigned short root_dev; | 192 | extern unsigned short root_dev; |
@@ -210,30 +211,34 @@ void __init setup_arch(char **cmdline_p) | |||
210 | int i; | 211 | int i; |
211 | unsigned long highest_paddr; | 212 | unsigned long highest_paddr; |
212 | 213 | ||
213 | sparc_ttable = (struct tt_entry *) &start; | 214 | sparc_ttable = (struct tt_entry *) &trapbase; |
214 | 215 | ||
215 | /* Initialize PROM console and command line. */ | 216 | /* Initialize PROM console and command line. */ |
216 | *cmdline_p = prom_getbootargs(); | 217 | *cmdline_p = prom_getbootargs(); |
217 | strcpy(boot_command_line, *cmdline_p); | 218 | strcpy(boot_command_line, *cmdline_p); |
218 | parse_early_param(); | 219 | parse_early_param(); |
219 | 220 | ||
221 | boot_flags_init(*cmdline_p); | ||
222 | |||
223 | register_console(&prom_early_console); | ||
224 | |||
220 | /* Set sparc_cpu_model */ | 225 | /* Set sparc_cpu_model */ |
221 | sparc_cpu_model = sun_unknown; | 226 | sparc_cpu_model = sun_unknown; |
222 | if (!strcmp(&cputypval,"sun4 ")) | 227 | if (!strcmp(&cputypval[0], "sun4 ")) |
223 | sparc_cpu_model = sun4; | 228 | sparc_cpu_model = sun4; |
224 | if (!strcmp(&cputypval,"sun4c")) | 229 | if (!strcmp(&cputypval[0], "sun4c")) |
225 | sparc_cpu_model = sun4c; | 230 | sparc_cpu_model = sun4c; |
226 | if (!strcmp(&cputypval,"sun4m")) | 231 | if (!strcmp(&cputypval[0], "sun4m")) |
227 | sparc_cpu_model = sun4m; | 232 | sparc_cpu_model = sun4m; |
228 | if (!strcmp(&cputypval,"sun4s")) | 233 | if (!strcmp(&cputypval[0], "sun4s")) |
229 | sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ | 234 | sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ |
230 | if (!strcmp(&cputypval,"sun4d")) | 235 | if (!strcmp(&cputypval[0], "sun4d")) |
231 | sparc_cpu_model = sun4d; | 236 | sparc_cpu_model = sun4d; |
232 | if (!strcmp(&cputypval,"sun4e")) | 237 | if (!strcmp(&cputypval[0], "sun4e")) |
233 | sparc_cpu_model = sun4e; | 238 | sparc_cpu_model = sun4e; |
234 | if (!strcmp(&cputypval,"sun4u")) | 239 | if (!strcmp(&cputypval[0], "sun4u")) |
235 | sparc_cpu_model = sun4u; | 240 | sparc_cpu_model = sun4u; |
236 | if (!strncmp(&cputypval, "leon" , 4)) | 241 | if (!strncmp(&cputypval[0], "leon" , 4)) |
237 | sparc_cpu_model = sparc_leon; | 242 | sparc_cpu_model = sparc_leon; |
238 | 243 | ||
239 | printk("ARCH: "); | 244 | printk("ARCH: "); |
@@ -262,12 +267,11 @@ void __init setup_arch(char **cmdline_p) | |||
262 | default: | 267 | default: |
263 | printk("UNKNOWN!\n"); | 268 | printk("UNKNOWN!\n"); |
264 | break; | 269 | break; |
265 | }; | 270 | } |
266 | 271 | ||
267 | #ifdef CONFIG_DUMMY_CONSOLE | 272 | #ifdef CONFIG_DUMMY_CONSOLE |
268 | conswitchp = &dummy_con; | 273 | conswitchp = &dummy_con; |
269 | #endif | 274 | #endif |
270 | boot_flags_init(*cmdline_p); | ||
271 | 275 | ||
272 | idprom_init(); | 276 | idprom_init(); |
273 | if (ARCH_SUN4C) | 277 | if (ARCH_SUN4C) |
@@ -313,75 +317,6 @@ void __init setup_arch(char **cmdline_p) | |||
313 | smp_setup_cpu_possible_map(); | 317 | smp_setup_cpu_possible_map(); |
314 | } | 318 | } |
315 | 319 | ||
316 | static int ncpus_probed; | ||
317 | |||
318 | static int show_cpuinfo(struct seq_file *m, void *__unused) | ||
319 | { | ||
320 | seq_printf(m, | ||
321 | "cpu\t\t: %s\n" | ||
322 | "fpu\t\t: %s\n" | ||
323 | "promlib\t\t: Version %d Revision %d\n" | ||
324 | "prom\t\t: %d.%d\n" | ||
325 | "type\t\t: %s\n" | ||
326 | "ncpus probed\t: %d\n" | ||
327 | "ncpus active\t: %d\n" | ||
328 | #ifndef CONFIG_SMP | ||
329 | "CPU0Bogo\t: %lu.%02lu\n" | ||
330 | "CPU0ClkTck\t: %ld\n" | ||
331 | #endif | ||
332 | , | ||
333 | sparc_cpu_type, | ||
334 | sparc_fpu_type , | ||
335 | romvec->pv_romvers, | ||
336 | prom_rev, | ||
337 | romvec->pv_printrev >> 16, | ||
338 | romvec->pv_printrev & 0xffff, | ||
339 | &cputypval, | ||
340 | ncpus_probed, | ||
341 | num_online_cpus() | ||
342 | #ifndef CONFIG_SMP | ||
343 | , cpu_data(0).udelay_val/(500000/HZ), | ||
344 | (cpu_data(0).udelay_val/(5000/HZ)) % 100, | ||
345 | cpu_data(0).clock_tick | ||
346 | #endif | ||
347 | ); | ||
348 | |||
349 | #ifdef CONFIG_SMP | ||
350 | smp_bogo(m); | ||
351 | #endif | ||
352 | mmu_info(m); | ||
353 | #ifdef CONFIG_SMP | ||
354 | smp_info(m); | ||
355 | #endif | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
360 | { | ||
361 | /* The pointer we are returning is arbitrary, | ||
362 | * it just has to be non-NULL and not IS_ERR | ||
363 | * in the success case. | ||
364 | */ | ||
365 | return *pos == 0 ? &c_start : NULL; | ||
366 | } | ||
367 | |||
368 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
369 | { | ||
370 | ++*pos; | ||
371 | return c_start(m, pos); | ||
372 | } | ||
373 | |||
374 | static void c_stop(struct seq_file *m, void *v) | ||
375 | { | ||
376 | } | ||
377 | |||
378 | const struct seq_operations cpuinfo_op = { | ||
379 | .start =c_start, | ||
380 | .next = c_next, | ||
381 | .stop = c_stop, | ||
382 | .show = show_cpuinfo, | ||
383 | }; | ||
384 | |||
385 | extern int stop_a_enabled; | 320 | extern int stop_a_enabled; |
386 | 321 | ||
387 | void sun_do_break(void) | 322 | void sun_do_break(void) |
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 5f72de67588b..c4dd0999da86 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c | |||
@@ -209,7 +209,7 @@ void __init per_cpu_patch(void) | |||
209 | default: | 209 | default: |
210 | prom_printf("Unknown cpu type, halting.\n"); | 210 | prom_printf("Unknown cpu type, halting.\n"); |
211 | prom_halt(); | 211 | prom_halt(); |
212 | }; | 212 | } |
213 | 213 | ||
214 | *(unsigned int *) (addr + 0) = insns[0]; | 214 | *(unsigned int *) (addr + 0) = insns[0]; |
215 | wmb(); | 215 | wmb(); |
@@ -315,7 +315,7 @@ void __init setup_arch(char **cmdline_p) | |||
315 | 315 | ||
316 | #ifdef CONFIG_IP_PNP | 316 | #ifdef CONFIG_IP_PNP |
317 | if (!ic_set_manually) { | 317 | if (!ic_set_manually) { |
318 | int chosen = prom_finddevice ("/chosen"); | 318 | phandle chosen = prom_finddevice("/chosen"); |
319 | u32 cl, sv, gw; | 319 | u32 cl, sv, gw; |
320 | 320 | ||
321 | cl = prom_getintdefault (chosen, "client-ip", 0); | 321 | cl = prom_getintdefault (chosen, "client-ip", 0); |
@@ -339,84 +339,6 @@ void __init setup_arch(char **cmdline_p) | |||
339 | paging_init(); | 339 | paging_init(); |
340 | } | 340 | } |
341 | 341 | ||
342 | /* BUFFER is PAGE_SIZE bytes long. */ | ||
343 | |||
344 | extern void smp_info(struct seq_file *); | ||
345 | extern void smp_bogo(struct seq_file *); | ||
346 | extern void mmu_info(struct seq_file *); | ||
347 | |||
348 | unsigned int dcache_parity_tl1_occurred; | ||
349 | unsigned int icache_parity_tl1_occurred; | ||
350 | |||
351 | int ncpus_probed; | ||
352 | |||
353 | static int show_cpuinfo(struct seq_file *m, void *__unused) | ||
354 | { | ||
355 | seq_printf(m, | ||
356 | "cpu\t\t: %s\n" | ||
357 | "fpu\t\t: %s\n" | ||
358 | "pmu\t\t: %s\n" | ||
359 | "prom\t\t: %s\n" | ||
360 | "type\t\t: %s\n" | ||
361 | "ncpus probed\t: %d\n" | ||
362 | "ncpus active\t: %d\n" | ||
363 | "D$ parity tl1\t: %u\n" | ||
364 | "I$ parity tl1\t: %u\n" | ||
365 | #ifndef CONFIG_SMP | ||
366 | "Cpu0ClkTck\t: %016lx\n" | ||
367 | #endif | ||
368 | , | ||
369 | sparc_cpu_type, | ||
370 | sparc_fpu_type, | ||
371 | sparc_pmu_type, | ||
372 | prom_version, | ||
373 | ((tlb_type == hypervisor) ? | ||
374 | "sun4v" : | ||
375 | "sun4u"), | ||
376 | ncpus_probed, | ||
377 | num_online_cpus(), | ||
378 | dcache_parity_tl1_occurred, | ||
379 | icache_parity_tl1_occurred | ||
380 | #ifndef CONFIG_SMP | ||
381 | , cpu_data(0).clock_tick | ||
382 | #endif | ||
383 | ); | ||
384 | #ifdef CONFIG_SMP | ||
385 | smp_bogo(m); | ||
386 | #endif | ||
387 | mmu_info(m); | ||
388 | #ifdef CONFIG_SMP | ||
389 | smp_info(m); | ||
390 | #endif | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
395 | { | ||
396 | /* The pointer we are returning is arbitrary, | ||
397 | * it just has to be non-NULL and not IS_ERR | ||
398 | * in the success case. | ||
399 | */ | ||
400 | return *pos == 0 ? &c_start : NULL; | ||
401 | } | ||
402 | |||
403 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
404 | { | ||
405 | ++*pos; | ||
406 | return c_start(m, pos); | ||
407 | } | ||
408 | |||
409 | static void c_stop(struct seq_file *m, void *v) | ||
410 | { | ||
411 | } | ||
412 | |||
413 | const struct seq_operations cpuinfo_op = { | ||
414 | .start =c_start, | ||
415 | .next = c_next, | ||
416 | .stop = c_stop, | ||
417 | .show = show_cpuinfo, | ||
418 | }; | ||
419 | |||
420 | extern int stop_a_enabled; | 342 | extern int stop_a_enabled; |
421 | 343 | ||
422 | void sun_do_break(void) | 344 | void sun_do_break(void) |
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 91c10fb70858..21b125341bf7 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c | |||
@@ -37,8 +37,6 @@ | |||
37 | #include "irq.h" | 37 | #include "irq.h" |
38 | 38 | ||
39 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; | 39 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; |
40 | unsigned char boot_cpu_id = 0; | ||
41 | unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */ | ||
42 | 40 | ||
43 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; | 41 | cpumask_t smp_commenced_mask = CPU_MASK_NONE; |
44 | 42 | ||
@@ -53,6 +51,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE; | |||
53 | void __cpuinit smp_store_cpu_info(int id) | 51 | void __cpuinit smp_store_cpu_info(int id) |
54 | { | 52 | { |
55 | int cpu_node; | 53 | int cpu_node; |
54 | int mid; | ||
56 | 55 | ||
57 | cpu_data(id).udelay_val = loops_per_jiffy; | 56 | cpu_data(id).udelay_val = loops_per_jiffy; |
58 | 57 | ||
@@ -60,10 +59,13 @@ void __cpuinit smp_store_cpu_info(int id) | |||
60 | cpu_data(id).clock_tick = prom_getintdefault(cpu_node, | 59 | cpu_data(id).clock_tick = prom_getintdefault(cpu_node, |
61 | "clock-frequency", 0); | 60 | "clock-frequency", 0); |
62 | cpu_data(id).prom_node = cpu_node; | 61 | cpu_data(id).prom_node = cpu_node; |
63 | cpu_data(id).mid = cpu_get_hwmid(cpu_node); | 62 | mid = cpu_get_hwmid(cpu_node); |
64 | 63 | ||
65 | if (cpu_data(id).mid < 0) | 64 | if (mid < 0) { |
66 | panic("No MID found for CPU%d at node 0x%08d", id, cpu_node); | 65 | printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node); |
66 | mid = 0; | ||
67 | } | ||
68 | cpu_data(id).mid = mid; | ||
67 | } | 69 | } |
68 | 70 | ||
69 | void __init smp_cpus_done(unsigned int max_cpus) | 71 | void __init smp_cpus_done(unsigned int max_cpus) |
@@ -112,7 +114,7 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
112 | printk("UNKNOWN!\n"); | 114 | printk("UNKNOWN!\n"); |
113 | BUG(); | 115 | BUG(); |
114 | break; | 116 | break; |
115 | }; | 117 | } |
116 | } | 118 | } |
117 | 119 | ||
118 | void cpu_panic(void) | 120 | void cpu_panic(void) |
@@ -125,13 +127,58 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; | |||
125 | 127 | ||
126 | void smp_send_reschedule(int cpu) | 128 | void smp_send_reschedule(int cpu) |
127 | { | 129 | { |
128 | /* See sparc64 */ | 130 | /* |
131 | * CPU model dependent way of implementing IPI generation targeting | ||
132 | * a single CPU. The trap handler needs only to do trap entry/return | ||
133 | * to call schedule. | ||
134 | */ | ||
135 | BTFIXUP_CALL(smp_ipi_resched)(cpu); | ||
129 | } | 136 | } |
130 | 137 | ||
131 | void smp_send_stop(void) | 138 | void smp_send_stop(void) |
132 | { | 139 | { |
133 | } | 140 | } |
134 | 141 | ||
142 | void arch_send_call_function_single_ipi(int cpu) | ||
143 | { | ||
144 | /* trigger one IPI single call on one CPU */ | ||
145 | BTFIXUP_CALL(smp_ipi_single)(cpu); | ||
146 | } | ||
147 | |||
148 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
149 | { | ||
150 | int cpu; | ||
151 | |||
152 | /* trigger IPI mask call on each CPU */ | ||
153 | for_each_cpu(cpu, mask) | ||
154 | BTFIXUP_CALL(smp_ipi_mask_one)(cpu); | ||
155 | } | ||
156 | |||
157 | void smp_resched_interrupt(void) | ||
158 | { | ||
159 | irq_enter(); | ||
160 | scheduler_ipi(); | ||
161 | local_cpu_data().irq_resched_count++; | ||
162 | irq_exit(); | ||
163 | /* re-schedule routine called by interrupt return code. */ | ||
164 | } | ||
165 | |||
166 | void smp_call_function_single_interrupt(void) | ||
167 | { | ||
168 | irq_enter(); | ||
169 | generic_smp_call_function_single_interrupt(); | ||
170 | local_cpu_data().irq_call_count++; | ||
171 | irq_exit(); | ||
172 | } | ||
173 | |||
174 | void smp_call_function_interrupt(void) | ||
175 | { | ||
176 | irq_enter(); | ||
177 | generic_smp_call_function_interrupt(); | ||
178 | local_cpu_data().irq_call_count++; | ||
179 | irq_exit(); | ||
180 | } | ||
181 | |||
135 | void smp_flush_cache_all(void) | 182 | void smp_flush_cache_all(void) |
136 | { | 183 | { |
137 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); | 184 | xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); |
@@ -147,9 +194,10 @@ void smp_flush_tlb_all(void) | |||
147 | void smp_flush_cache_mm(struct mm_struct *mm) | 194 | void smp_flush_cache_mm(struct mm_struct *mm) |
148 | { | 195 | { |
149 | if(mm->context != NO_CONTEXT) { | 196 | if(mm->context != NO_CONTEXT) { |
150 | cpumask_t cpu_mask = *mm_cpumask(mm); | 197 | cpumask_t cpu_mask; |
151 | cpu_clear(smp_processor_id(), cpu_mask); | 198 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
152 | if (!cpus_empty(cpu_mask)) | 199 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
200 | if (!cpumask_empty(&cpu_mask)) | ||
153 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm); | 201 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm); |
154 | local_flush_cache_mm(mm); | 202 | local_flush_cache_mm(mm); |
155 | } | 203 | } |
@@ -158,9 +206,10 @@ void smp_flush_cache_mm(struct mm_struct *mm) | |||
158 | void smp_flush_tlb_mm(struct mm_struct *mm) | 206 | void smp_flush_tlb_mm(struct mm_struct *mm) |
159 | { | 207 | { |
160 | if(mm->context != NO_CONTEXT) { | 208 | if(mm->context != NO_CONTEXT) { |
161 | cpumask_t cpu_mask = *mm_cpumask(mm); | 209 | cpumask_t cpu_mask; |
162 | cpu_clear(smp_processor_id(), cpu_mask); | 210 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
163 | if (!cpus_empty(cpu_mask)) { | 211 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
212 | if (!cpumask_empty(&cpu_mask)) { | ||
164 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); | 213 | xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); |
165 | if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) | 214 | if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) |
166 | cpumask_copy(mm_cpumask(mm), | 215 | cpumask_copy(mm_cpumask(mm), |
@@ -176,9 +225,10 @@ void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start, | |||
176 | struct mm_struct *mm = vma->vm_mm; | 225 | struct mm_struct *mm = vma->vm_mm; |
177 | 226 | ||
178 | if (mm->context != NO_CONTEXT) { | 227 | if (mm->context != NO_CONTEXT) { |
179 | cpumask_t cpu_mask = *mm_cpumask(mm); | 228 | cpumask_t cpu_mask; |
180 | cpu_clear(smp_processor_id(), cpu_mask); | 229 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
181 | if (!cpus_empty(cpu_mask)) | 230 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
231 | if (!cpumask_empty(&cpu_mask)) | ||
182 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end); | 232 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end); |
183 | local_flush_cache_range(vma, start, end); | 233 | local_flush_cache_range(vma, start, end); |
184 | } | 234 | } |
@@ -190,9 +240,10 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
190 | struct mm_struct *mm = vma->vm_mm; | 240 | struct mm_struct *mm = vma->vm_mm; |
191 | 241 | ||
192 | if (mm->context != NO_CONTEXT) { | 242 | if (mm->context != NO_CONTEXT) { |
193 | cpumask_t cpu_mask = *mm_cpumask(mm); | 243 | cpumask_t cpu_mask; |
194 | cpu_clear(smp_processor_id(), cpu_mask); | 244 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
195 | if (!cpus_empty(cpu_mask)) | 245 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
246 | if (!cpumask_empty(&cpu_mask)) | ||
196 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end); | 247 | xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end); |
197 | local_flush_tlb_range(vma, start, end); | 248 | local_flush_tlb_range(vma, start, end); |
198 | } | 249 | } |
@@ -203,9 +254,10 @@ void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page) | |||
203 | struct mm_struct *mm = vma->vm_mm; | 254 | struct mm_struct *mm = vma->vm_mm; |
204 | 255 | ||
205 | if(mm->context != NO_CONTEXT) { | 256 | if(mm->context != NO_CONTEXT) { |
206 | cpumask_t cpu_mask = *mm_cpumask(mm); | 257 | cpumask_t cpu_mask; |
207 | cpu_clear(smp_processor_id(), cpu_mask); | 258 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
208 | if (!cpus_empty(cpu_mask)) | 259 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
260 | if (!cpumask_empty(&cpu_mask)) | ||
209 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page); | 261 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page); |
210 | local_flush_cache_page(vma, page); | 262 | local_flush_cache_page(vma, page); |
211 | } | 263 | } |
@@ -216,19 +268,15 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) | |||
216 | struct mm_struct *mm = vma->vm_mm; | 268 | struct mm_struct *mm = vma->vm_mm; |
217 | 269 | ||
218 | if(mm->context != NO_CONTEXT) { | 270 | if(mm->context != NO_CONTEXT) { |
219 | cpumask_t cpu_mask = *mm_cpumask(mm); | 271 | cpumask_t cpu_mask; |
220 | cpu_clear(smp_processor_id(), cpu_mask); | 272 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
221 | if (!cpus_empty(cpu_mask)) | 273 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
274 | if (!cpumask_empty(&cpu_mask)) | ||
222 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page); | 275 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page); |
223 | local_flush_tlb_page(vma, page); | 276 | local_flush_tlb_page(vma, page); |
224 | } | 277 | } |
225 | } | 278 | } |
226 | 279 | ||
227 | void smp_reschedule_irq(void) | ||
228 | { | ||
229 | set_need_resched(); | ||
230 | } | ||
231 | |||
232 | void smp_flush_page_to_ram(unsigned long page) | 280 | void smp_flush_page_to_ram(unsigned long page) |
233 | { | 281 | { |
234 | /* Current theory is that those who call this are the one's | 282 | /* Current theory is that those who call this are the one's |
@@ -245,9 +293,10 @@ void smp_flush_page_to_ram(unsigned long page) | |||
245 | 293 | ||
246 | void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) | 294 | void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) |
247 | { | 295 | { |
248 | cpumask_t cpu_mask = *mm_cpumask(mm); | 296 | cpumask_t cpu_mask; |
249 | cpu_clear(smp_processor_id(), cpu_mask); | 297 | cpumask_copy(&cpu_mask, mm_cpumask(mm)); |
250 | if (!cpus_empty(cpu_mask)) | 298 | cpumask_clear_cpu(smp_processor_id(), &cpu_mask); |
299 | if (!cpumask_empty(&cpu_mask)) | ||
251 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr); | 300 | xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr); |
252 | local_flush_sig_insns(mm, insn_addr); | 301 | local_flush_sig_insns(mm, insn_addr); |
253 | } | 302 | } |
@@ -325,7 +374,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
325 | printk("UNKNOWN!\n"); | 374 | printk("UNKNOWN!\n"); |
326 | BUG(); | 375 | BUG(); |
327 | break; | 376 | break; |
328 | }; | 377 | } |
329 | } | 378 | } |
330 | 379 | ||
331 | /* Set this up early so that things like the scheduler can init | 380 | /* Set this up early so that things like the scheduler can init |
@@ -398,10 +447,10 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
398 | printk("UNKNOWN!\n"); | 447 | printk("UNKNOWN!\n"); |
399 | BUG(); | 448 | BUG(); |
400 | break; | 449 | break; |
401 | }; | 450 | } |
402 | 451 | ||
403 | if (!ret) { | 452 | if (!ret) { |
404 | cpu_set(cpu, smp_commenced_mask); | 453 | cpumask_set_cpu(cpu, &smp_commenced_mask); |
405 | while (!cpu_online(cpu)) | 454 | while (!cpu_online(cpu)) |
406 | mb(); | 455 | mb(); |
407 | } | 456 | } |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index b6a2b8f47040..99cb17251bb5 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <asm/mdesc.h> | 49 | #include <asm/mdesc.h> |
50 | #include <asm/ldc.h> | 50 | #include <asm/ldc.h> |
51 | #include <asm/hypervisor.h> | 51 | #include <asm/hypervisor.h> |
52 | #include <asm/pcr.h> | ||
52 | 53 | ||
53 | #include "cpumap.h" | 54 | #include "cpumap.h" |
54 | 55 | ||
@@ -120,11 +121,11 @@ void __cpuinit smp_callin(void) | |||
120 | /* inform the notifiers about the new cpu */ | 121 | /* inform the notifiers about the new cpu */ |
121 | notify_cpu_starting(cpuid); | 122 | notify_cpu_starting(cpuid); |
122 | 123 | ||
123 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 124 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
124 | rmb(); | 125 | rmb(); |
125 | 126 | ||
126 | ipi_call_lock_irq(); | 127 | ipi_call_lock_irq(); |
127 | cpu_set(cpuid, cpu_online_map); | 128 | set_cpu_online(cpuid, true); |
128 | ipi_call_unlock_irq(); | 129 | ipi_call_unlock_irq(); |
129 | 130 | ||
130 | /* idle thread is expected to have preempt disabled */ | 131 | /* idle thread is expected to have preempt disabled */ |
@@ -188,7 +189,7 @@ static inline long get_delta (long *rt, long *master) | |||
188 | void smp_synchronize_tick_client(void) | 189 | void smp_synchronize_tick_client(void) |
189 | { | 190 | { |
190 | long i, delta, adj, adjust_latency = 0, done = 0; | 191 | long i, delta, adj, adjust_latency = 0, done = 0; |
191 | unsigned long flags, rt, master_time_stamp, bound; | 192 | unsigned long flags, rt, master_time_stamp; |
192 | #if DEBUG_TICK_SYNC | 193 | #if DEBUG_TICK_SYNC |
193 | struct { | 194 | struct { |
194 | long rt; /* roundtrip time */ | 195 | long rt; /* roundtrip time */ |
@@ -207,10 +208,8 @@ void smp_synchronize_tick_client(void) | |||
207 | { | 208 | { |
208 | for (i = 0; i < NUM_ROUNDS; i++) { | 209 | for (i = 0; i < NUM_ROUNDS; i++) { |
209 | delta = get_delta(&rt, &master_time_stamp); | 210 | delta = get_delta(&rt, &master_time_stamp); |
210 | if (delta == 0) { | 211 | if (delta == 0) |
211 | done = 1; /* let's lock on to this... */ | 212 | done = 1; /* let's lock on to this... */ |
212 | bound = rt; | ||
213 | } | ||
214 | 213 | ||
215 | if (!done) { | 214 | if (!done) { |
216 | if (i > 0) { | 215 | if (i > 0) { |
@@ -786,7 +785,7 @@ static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask | |||
786 | 785 | ||
787 | /* Send cross call to all processors mentioned in MASK_P | 786 | /* Send cross call to all processors mentioned in MASK_P |
788 | * except self. Really, there are only two cases currently, | 787 | * except self. Really, there are only two cases currently, |
789 | * "&cpu_online_map" and "&mm->cpu_vm_mask". | 788 | * "cpu_online_mask" and "mm_cpumask(mm)". |
790 | */ | 789 | */ |
791 | static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, const cpumask_t *mask) | 790 | static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, const cpumask_t *mask) |
792 | { | 791 | { |
@@ -798,7 +797,7 @@ static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 d | |||
798 | /* Send cross call to all processors except self. */ | 797 | /* Send cross call to all processors except self. */ |
799 | static void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) | 798 | static void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2) |
800 | { | 799 | { |
801 | smp_cross_call_masked(func, ctx, data1, data2, &cpu_online_map); | 800 | smp_cross_call_masked(func, ctx, data1, data2, cpu_online_mask); |
802 | } | 801 | } |
803 | 802 | ||
804 | extern unsigned long xcall_sync_tick; | 803 | extern unsigned long xcall_sync_tick; |
@@ -806,7 +805,7 @@ extern unsigned long xcall_sync_tick; | |||
806 | static void smp_start_sync_tick_client(int cpu) | 805 | static void smp_start_sync_tick_client(int cpu) |
807 | { | 806 | { |
808 | xcall_deliver((u64) &xcall_sync_tick, 0, 0, | 807 | xcall_deliver((u64) &xcall_sync_tick, 0, 0, |
809 | &cpumask_of_cpu(cpu)); | 808 | cpumask_of(cpu)); |
810 | } | 809 | } |
811 | 810 | ||
812 | extern unsigned long xcall_call_function; | 811 | extern unsigned long xcall_call_function; |
@@ -821,7 +820,7 @@ extern unsigned long xcall_call_function_single; | |||
821 | void arch_send_call_function_single_ipi(int cpu) | 820 | void arch_send_call_function_single_ipi(int cpu) |
822 | { | 821 | { |
823 | xcall_deliver((u64) &xcall_call_function_single, 0, 0, | 822 | xcall_deliver((u64) &xcall_call_function_single, 0, 0, |
824 | &cpumask_of_cpu(cpu)); | 823 | cpumask_of(cpu)); |
825 | } | 824 | } |
826 | 825 | ||
827 | void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) | 826 | void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) |
@@ -919,7 +918,7 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) | |||
919 | } | 918 | } |
920 | if (data0) { | 919 | if (data0) { |
921 | xcall_deliver(data0, __pa(pg_addr), | 920 | xcall_deliver(data0, __pa(pg_addr), |
922 | (u64) pg_addr, &cpumask_of_cpu(cpu)); | 921 | (u64) pg_addr, cpumask_of(cpu)); |
923 | #ifdef CONFIG_DEBUG_DCFLUSH | 922 | #ifdef CONFIG_DEBUG_DCFLUSH |
924 | atomic_inc(&dcpage_flushes_xcall); | 923 | atomic_inc(&dcpage_flushes_xcall); |
925 | #endif | 924 | #endif |
@@ -932,13 +931,12 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) | |||
932 | 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) |
933 | { | 932 | { |
934 | void *pg_addr; | 933 | void *pg_addr; |
935 | int this_cpu; | ||
936 | u64 data0; | 934 | u64 data0; |
937 | 935 | ||
938 | if (tlb_type == hypervisor) | 936 | if (tlb_type == hypervisor) |
939 | return; | 937 | return; |
940 | 938 | ||
941 | this_cpu = get_cpu(); | 939 | preempt_disable(); |
942 | 940 | ||
943 | #ifdef CONFIG_DEBUG_DCFLUSH | 941 | #ifdef CONFIG_DEBUG_DCFLUSH |
944 | atomic_inc(&dcpage_flushes); | 942 | atomic_inc(&dcpage_flushes); |
@@ -956,14 +954,14 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) | |||
956 | } | 954 | } |
957 | if (data0) { | 955 | if (data0) { |
958 | xcall_deliver(data0, __pa(pg_addr), | 956 | xcall_deliver(data0, __pa(pg_addr), |
959 | (u64) pg_addr, &cpu_online_map); | 957 | (u64) pg_addr, cpu_online_mask); |
960 | #ifdef CONFIG_DEBUG_DCFLUSH | 958 | #ifdef CONFIG_DEBUG_DCFLUSH |
961 | atomic_inc(&dcpage_flushes_xcall); | 959 | atomic_inc(&dcpage_flushes_xcall); |
962 | #endif | 960 | #endif |
963 | } | 961 | } |
964 | __local_flush_dcache_page(page); | 962 | __local_flush_dcache_page(page); |
965 | 963 | ||
966 | put_cpu(); | 964 | preempt_enable(); |
967 | } | 965 | } |
968 | 966 | ||
969 | 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) |
@@ -1199,32 +1197,32 @@ void __devinit smp_fill_in_sib_core_maps(void) | |||
1199 | for_each_present_cpu(i) { | 1197 | for_each_present_cpu(i) { |
1200 | unsigned int j; | 1198 | unsigned int j; |
1201 | 1199 | ||
1202 | cpus_clear(cpu_core_map[i]); | 1200 | cpumask_clear(&cpu_core_map[i]); |
1203 | if (cpu_data(i).core_id == 0) { | 1201 | if (cpu_data(i).core_id == 0) { |
1204 | cpu_set(i, cpu_core_map[i]); | 1202 | cpumask_set_cpu(i, &cpu_core_map[i]); |
1205 | continue; | 1203 | continue; |
1206 | } | 1204 | } |
1207 | 1205 | ||
1208 | for_each_present_cpu(j) { | 1206 | for_each_present_cpu(j) { |
1209 | if (cpu_data(i).core_id == | 1207 | if (cpu_data(i).core_id == |
1210 | cpu_data(j).core_id) | 1208 | cpu_data(j).core_id) |
1211 | cpu_set(j, cpu_core_map[i]); | 1209 | cpumask_set_cpu(j, &cpu_core_map[i]); |
1212 | } | 1210 | } |
1213 | } | 1211 | } |
1214 | 1212 | ||
1215 | for_each_present_cpu(i) { | 1213 | for_each_present_cpu(i) { |
1216 | unsigned int j; | 1214 | unsigned int j; |
1217 | 1215 | ||
1218 | cpus_clear(per_cpu(cpu_sibling_map, i)); | 1216 | cpumask_clear(&per_cpu(cpu_sibling_map, i)); |
1219 | if (cpu_data(i).proc_id == -1) { | 1217 | if (cpu_data(i).proc_id == -1) { |
1220 | cpu_set(i, per_cpu(cpu_sibling_map, i)); | 1218 | cpumask_set_cpu(i, &per_cpu(cpu_sibling_map, i)); |
1221 | continue; | 1219 | continue; |
1222 | } | 1220 | } |
1223 | 1221 | ||
1224 | for_each_present_cpu(j) { | 1222 | for_each_present_cpu(j) { |
1225 | if (cpu_data(i).proc_id == | 1223 | if (cpu_data(i).proc_id == |
1226 | cpu_data(j).proc_id) | 1224 | cpu_data(j).proc_id) |
1227 | cpu_set(j, per_cpu(cpu_sibling_map, i)); | 1225 | cpumask_set_cpu(j, &per_cpu(cpu_sibling_map, i)); |
1228 | } | 1226 | } |
1229 | } | 1227 | } |
1230 | } | 1228 | } |
@@ -1234,10 +1232,10 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
1234 | int ret = smp_boot_one_cpu(cpu); | 1232 | int ret = smp_boot_one_cpu(cpu); |
1235 | 1233 | ||
1236 | if (!ret) { | 1234 | if (!ret) { |
1237 | cpu_set(cpu, smp_commenced_mask); | 1235 | cpumask_set_cpu(cpu, &smp_commenced_mask); |
1238 | while (!cpu_isset(cpu, cpu_online_map)) | 1236 | while (!cpu_online(cpu)) |
1239 | mb(); | 1237 | mb(); |
1240 | if (!cpu_isset(cpu, cpu_online_map)) { | 1238 | if (!cpu_online(cpu)) { |
1241 | ret = -ENODEV; | 1239 | ret = -ENODEV; |
1242 | } else { | 1240 | } else { |
1243 | /* On SUN4V, writes to %tick and %stick are | 1241 | /* On SUN4V, writes to %tick and %stick are |
@@ -1271,7 +1269,7 @@ void cpu_play_dead(void) | |||
1271 | tb->nonresum_mondo_pa, 0); | 1269 | tb->nonresum_mondo_pa, 0); |
1272 | } | 1270 | } |
1273 | 1271 | ||
1274 | cpu_clear(cpu, smp_commenced_mask); | 1272 | cpumask_clear_cpu(cpu, &smp_commenced_mask); |
1275 | membar_safe("#Sync"); | 1273 | membar_safe("#Sync"); |
1276 | 1274 | ||
1277 | local_irq_disable(); | 1275 | local_irq_disable(); |
@@ -1292,13 +1290,13 @@ int __cpu_disable(void) | |||
1292 | cpuinfo_sparc *c; | 1290 | cpuinfo_sparc *c; |
1293 | int i; | 1291 | int i; |
1294 | 1292 | ||
1295 | for_each_cpu_mask(i, cpu_core_map[cpu]) | 1293 | for_each_cpu(i, &cpu_core_map[cpu]) |
1296 | cpu_clear(cpu, cpu_core_map[i]); | 1294 | cpumask_clear_cpu(cpu, &cpu_core_map[i]); |
1297 | cpus_clear(cpu_core_map[cpu]); | 1295 | cpumask_clear(&cpu_core_map[cpu]); |
1298 | 1296 | ||
1299 | for_each_cpu_mask(i, per_cpu(cpu_sibling_map, cpu)) | 1297 | for_each_cpu(i, &per_cpu(cpu_sibling_map, cpu)) |
1300 | cpu_clear(cpu, per_cpu(cpu_sibling_map, i)); | 1298 | cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, i)); |
1301 | cpus_clear(per_cpu(cpu_sibling_map, cpu)); | 1299 | cpumask_clear(&per_cpu(cpu_sibling_map, cpu)); |
1302 | 1300 | ||
1303 | c = &cpu_data(cpu); | 1301 | c = &cpu_data(cpu); |
1304 | 1302 | ||
@@ -1315,7 +1313,7 @@ int __cpu_disable(void) | |||
1315 | local_irq_disable(); | 1313 | local_irq_disable(); |
1316 | 1314 | ||
1317 | ipi_call_lock(); | 1315 | ipi_call_lock(); |
1318 | cpu_clear(cpu, cpu_online_map); | 1316 | set_cpu_online(cpu, false); |
1319 | ipi_call_unlock(); | 1317 | ipi_call_unlock(); |
1320 | 1318 | ||
1321 | cpu_map_rebuild(); | 1319 | cpu_map_rebuild(); |
@@ -1329,11 +1327,11 @@ void __cpu_die(unsigned int cpu) | |||
1329 | 1327 | ||
1330 | for (i = 0; i < 100; i++) { | 1328 | for (i = 0; i < 100; i++) { |
1331 | smp_rmb(); | 1329 | smp_rmb(); |
1332 | if (!cpu_isset(cpu, smp_commenced_mask)) | 1330 | if (!cpumask_test_cpu(cpu, &smp_commenced_mask)) |
1333 | break; | 1331 | break; |
1334 | msleep(100); | 1332 | msleep(100); |
1335 | } | 1333 | } |
1336 | if (cpu_isset(cpu, smp_commenced_mask)) { | 1334 | if (cpumask_test_cpu(cpu, &smp_commenced_mask)) { |
1337 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 1335 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
1338 | } else { | 1336 | } else { |
1339 | #if defined(CONFIG_SUN_LDOMS) | 1337 | #if defined(CONFIG_SUN_LDOMS) |
@@ -1343,7 +1341,7 @@ void __cpu_die(unsigned int cpu) | |||
1343 | do { | 1341 | do { |
1344 | hv_err = sun4v_cpu_stop(cpu); | 1342 | hv_err = sun4v_cpu_stop(cpu); |
1345 | if (hv_err == HV_EOK) { | 1343 | if (hv_err == HV_EOK) { |
1346 | cpu_clear(cpu, cpu_present_map); | 1344 | set_cpu_present(cpu, false); |
1347 | break; | 1345 | break; |
1348 | } | 1346 | } |
1349 | } while (--limit > 0); | 1347 | } while (--limit > 0); |
@@ -1358,17 +1356,19 @@ void __cpu_die(unsigned int cpu) | |||
1358 | 1356 | ||
1359 | void __init smp_cpus_done(unsigned int max_cpus) | 1357 | void __init smp_cpus_done(unsigned int max_cpus) |
1360 | { | 1358 | { |
1359 | pcr_arch_init(); | ||
1361 | } | 1360 | } |
1362 | 1361 | ||
1363 | void smp_send_reschedule(int cpu) | 1362 | void smp_send_reschedule(int cpu) |
1364 | { | 1363 | { |
1365 | xcall_deliver((u64) &xcall_receive_signal, 0, 0, | 1364 | xcall_deliver((u64) &xcall_receive_signal, 0, 0, |
1366 | &cpumask_of_cpu(cpu)); | 1365 | cpumask_of(cpu)); |
1367 | } | 1366 | } |
1368 | 1367 | ||
1369 | void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) | 1368 | void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) |
1370 | { | 1369 | { |
1371 | clear_softint(1 << irq); | 1370 | clear_softint(1 << irq); |
1371 | scheduler_ipi(); | ||
1372 | } | 1372 | } |
1373 | 1373 | ||
1374 | /* This is a nop because we capture all other cpus | 1374 | /* This is a nop because we capture all other cpus |
diff --git a/arch/sparc/kernel/starfire.c b/arch/sparc/kernel/starfire.c index 060d0f3a6151..82281a566bb8 100644 --- a/arch/sparc/kernel/starfire.c +++ b/arch/sparc/kernel/starfire.c | |||
@@ -23,8 +23,8 @@ int this_is_starfire = 0; | |||
23 | 23 | ||
24 | void check_if_starfire(void) | 24 | void check_if_starfire(void) |
25 | { | 25 | { |
26 | int ssnode = prom_finddevice("/ssp-serial"); | 26 | phandle ssnode = prom_finddevice("/ssp-serial"); |
27 | if (ssnode != 0 && ssnode != -1) | 27 | if (ssnode != 0 && (s32)ssnode != -1) |
28 | this_is_starfire = 1; | 28 | this_is_starfire = 1; |
29 | } | 29 | } |
30 | 30 | ||
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 892fb884910a..f6bf25a2ff80 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,73 +59,100 @@ | |||
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_mask_irq(struct irq_data *data) |
64 | { | 69 | { |
65 | unsigned long flags; | 70 | unsigned long mask = (unsigned long)data->chip_data; |
66 | unsigned char current_mask, new_mask; | 71 | |
67 | 72 | if (mask) { | |
68 | local_irq_save(flags); | 73 | unsigned long flags; |
69 | irq_nr &= (NR_IRQS - 1); | 74 | |
70 | current_mask = sbus_readb(interrupt_enable); | 75 | local_irq_save(flags); |
71 | switch(irq_nr) { | 76 | mask = sbus_readb(interrupt_enable) & ~mask; |
72 | case 1: | 77 | sbus_writeb(mask, interrupt_enable); |
73 | new_mask = ((current_mask) & (~(SUN4C_INT_E1))); | ||
74 | break; | ||
75 | case 8: | ||
76 | new_mask = ((current_mask) & (~(SUN4C_INT_E8))); | ||
77 | break; | ||
78 | case 10: | ||
79 | new_mask = ((current_mask) & (~(SUN4C_INT_E10))); | ||
80 | break; | ||
81 | case 14: | ||
82 | new_mask = ((current_mask) & (~(SUN4C_INT_E14))); | ||
83 | break; | ||
84 | default: | ||
85 | local_irq_restore(flags); | 78 | local_irq_restore(flags); |
86 | return; | ||
87 | } | 79 | } |
88 | sbus_writeb(new_mask, interrupt_enable); | ||
89 | local_irq_restore(flags); | ||
90 | } | 80 | } |
91 | 81 | ||
92 | static void sun4c_enable_irq(unsigned int irq_nr) | 82 | static void sun4c_unmask_irq(struct irq_data *data) |
93 | { | 83 | { |
94 | unsigned long flags; | 84 | unsigned long mask = (unsigned long)data->chip_data; |
95 | unsigned char current_mask, new_mask; | 85 | |
96 | 86 | if (mask) { | |
97 | local_irq_save(flags); | 87 | unsigned long flags; |
98 | irq_nr &= (NR_IRQS - 1); | 88 | |
99 | current_mask = sbus_readb(interrupt_enable); | 89 | local_irq_save(flags); |
100 | switch(irq_nr) { | 90 | mask = sbus_readb(interrupt_enable) | mask; |
101 | case 1: | 91 | sbus_writeb(mask, interrupt_enable); |
102 | new_mask = ((current_mask) | SUN4C_INT_E1); | ||
103 | break; | ||
104 | case 8: | ||
105 | new_mask = ((current_mask) | SUN4C_INT_E8); | ||
106 | break; | ||
107 | case 10: | ||
108 | new_mask = ((current_mask) | SUN4C_INT_E10); | ||
109 | break; | ||
110 | case 14: | ||
111 | new_mask = ((current_mask) | SUN4C_INT_E14); | ||
112 | break; | ||
113 | default: | ||
114 | local_irq_restore(flags); | 92 | local_irq_restore(flags); |
115 | return; | ||
116 | } | 93 | } |
117 | sbus_writeb(new_mask, interrupt_enable); | 94 | } |
118 | local_irq_restore(flags); | 95 | |
96 | static unsigned int sun4c_startup_irq(struct irq_data *data) | ||
97 | { | ||
98 | irq_link(data->irq); | ||
99 | sun4c_unmask_irq(data); | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static void sun4c_shutdown_irq(struct irq_data *data) | ||
105 | { | ||
106 | sun4c_mask_irq(data); | ||
107 | irq_unlink(data->irq); | ||
108 | } | ||
109 | |||
110 | static struct irq_chip sun4c_irq = { | ||
111 | .name = "sun4c", | ||
112 | .irq_startup = sun4c_startup_irq, | ||
113 | .irq_shutdown = sun4c_shutdown_irq, | ||
114 | .irq_mask = sun4c_mask_irq, | ||
115 | .irq_unmask = sun4c_unmask_irq, | ||
116 | }; | ||
117 | |||
118 | static unsigned int sun4c_build_device_irq(struct platform_device *op, | ||
119 | unsigned int real_irq) | ||
120 | { | ||
121 | unsigned int irq; | ||
122 | |||
123 | if (real_irq >= 16) { | ||
124 | prom_printf("Bogus sun4c IRQ %u\n", real_irq); | ||
125 | prom_halt(); | ||
126 | } | ||
127 | |||
128 | irq = irq_alloc(real_irq, real_irq); | ||
129 | if (irq) { | ||
130 | unsigned long mask = 0UL; | ||
131 | |||
132 | switch (real_irq) { | ||
133 | case 1: | ||
134 | mask = SUN4C_INT_E1; | ||
135 | break; | ||
136 | case 8: | ||
137 | mask = SUN4C_INT_E8; | ||
138 | break; | ||
139 | case 10: | ||
140 | mask = SUN4C_INT_E10; | ||
141 | break; | ||
142 | case 14: | ||
143 | mask = SUN4C_INT_E14; | ||
144 | break; | ||
145 | default: | ||
146 | /* All the rest are either always enabled, | ||
147 | * or are for signalling software interrupts. | ||
148 | */ | ||
149 | break; | ||
150 | } | ||
151 | irq_set_chip_and_handler_name(irq, &sun4c_irq, | ||
152 | handle_level_irq, "level"); | ||
153 | irq_set_chip_data(irq, (void *)mask); | ||
154 | } | ||
155 | return irq; | ||
119 | } | 156 | } |
120 | 157 | ||
121 | struct sun4c_timer_info { | 158 | struct sun4c_timer_info { |
@@ -139,8 +176,9 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) | |||
139 | 176 | ||
140 | static void __init sun4c_init_timers(irq_handler_t counter_fn) | 177 | static void __init sun4c_init_timers(irq_handler_t counter_fn) |
141 | { | 178 | { |
142 | const struct linux_prom_irqs *irq; | 179 | const struct linux_prom_irqs *prom_irqs; |
143 | struct device_node *dp; | 180 | struct device_node *dp; |
181 | unsigned int irq; | ||
144 | const u32 *addr; | 182 | const u32 *addr; |
145 | int err; | 183 | int err; |
146 | 184 | ||
@@ -158,9 +196,9 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) | |||
158 | 196 | ||
159 | sun4c_timers = (void __iomem *) (unsigned long) addr[0]; | 197 | sun4c_timers = (void __iomem *) (unsigned long) addr[0]; |
160 | 198 | ||
161 | irq = of_get_property(dp, "intr", NULL); | 199 | prom_irqs = of_get_property(dp, "intr", NULL); |
162 | of_node_put(dp); | 200 | of_node_put(dp); |
163 | if (!irq) { | 201 | if (!prom_irqs) { |
164 | prom_printf("sun4c_init_timers: No intr property\n"); | 202 | prom_printf("sun4c_init_timers: No intr property\n"); |
165 | prom_halt(); | 203 | prom_halt(); |
166 | } | 204 | } |
@@ -173,19 +211,21 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) | |||
173 | 211 | ||
174 | master_l10_counter = &sun4c_timers->l10_count; | 212 | master_l10_counter = &sun4c_timers->l10_count; |
175 | 213 | ||
176 | err = request_irq(irq[0].pri, counter_fn, | 214 | irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri); |
177 | (IRQF_DISABLED | SA_STATIC_ALLOC), | 215 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); |
178 | "timer", NULL); | ||
179 | if (err) { | 216 | if (err) { |
180 | prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); | 217 | prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); |
181 | prom_halt(); | 218 | prom_halt(); |
182 | } | 219 | } |
183 | 220 | ||
184 | sun4c_disable_irq(irq[1].pri); | 221 | /* disable timer interrupt */ |
222 | sun4c_mask_irq(irq_get_irq_data(irq)); | ||
185 | } | 223 | } |
186 | 224 | ||
187 | #ifdef CONFIG_SMP | 225 | #ifdef CONFIG_SMP |
188 | static void sun4c_nop(void) {} | 226 | static void sun4c_nop(void) |
227 | { | ||
228 | } | ||
189 | #endif | 229 | #endif |
190 | 230 | ||
191 | void __init sun4c_init_IRQ(void) | 231 | void __init sun4c_init_IRQ(void) |
@@ -208,13 +248,12 @@ void __init sun4c_init_IRQ(void) | |||
208 | 248 | ||
209 | interrupt_enable = (void __iomem *) (unsigned long) addr[0]; | 249 | interrupt_enable = (void __iomem *) (unsigned long) addr[0]; |
210 | 250 | ||
211 | BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); | ||
212 | BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); | ||
213 | BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); | ||
214 | BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); | ||
215 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); | 251 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); |
216 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); | 252 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); |
217 | sparc_init_timers = sun4c_init_timers; | 253 | |
254 | sparc_irq_config.init_timers = sun4c_init_timers; | ||
255 | sparc_irq_config.build_device_irq = sun4c_build_device_irq; | ||
256 | |||
218 | #ifdef CONFIG_SMP | 257 | #ifdef CONFIG_SMP |
219 | BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); | 258 | BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); |
220 | BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); | 259 | 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..1d13c5bda0b1 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c | |||
@@ -1,50 +1,41 @@ | |||
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> | 17 | #include <asm/setup.h> |
42 | 18 | ||
43 | #include "kernel.h" | 19 | #include "kernel.h" |
44 | #include "irq.h" | 20 | #include "irq.h" |
45 | 21 | ||
46 | /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ | 22 | /* Sun4d interrupts fall roughly into two categories. SBUS and |
47 | /* #define DISTRIBUTE_IRQS */ | 23 | * cpu local. CPU local interrupts cover the timer interrupts |
24 | * and whatnot, and we encode those as normal PILs between | ||
25 | * 0 and 15. | ||
26 | * SBUS interrupts are encodes as a combination of board, level and slot. | ||
27 | */ | ||
28 | |||
29 | struct sun4d_handler_data { | ||
30 | unsigned int cpuid; /* target cpu */ | ||
31 | unsigned int real_irq; /* interrupt level */ | ||
32 | }; | ||
33 | |||
34 | |||
35 | static unsigned int sun4d_encode_irq(int board, int lvl, int slot) | ||
36 | { | ||
37 | return (board + 1) << 5 | (lvl << 2) | slot; | ||
38 | } | ||
48 | 39 | ||
49 | struct sun4d_timer_regs { | 40 | struct sun4d_timer_regs { |
50 | u32 l10_timer_limit; | 41 | u32 l10_timer_limit; |
@@ -56,320 +47,201 @@ struct sun4d_timer_regs { | |||
56 | 47 | ||
57 | static struct sun4d_timer_regs __iomem *sun4d_timers; | 48 | static struct sun4d_timer_regs __iomem *sun4d_timers; |
58 | 49 | ||
59 | #define TIMER_IRQ 10 | 50 | #define SUN4D_TIMER_IRQ 10 |
60 | |||
61 | #define MAX_STATIC_ALLOC 4 | ||
62 | extern int static_irq_count; | ||
63 | static unsigned char sbus_tid[32]; | ||
64 | |||
65 | static struct irqaction *irq_action[NR_IRQS]; | ||
66 | extern spinlock_t irq_action_lock; | ||
67 | 51 | ||
68 | static struct sbus_action { | 52 | /* Specify which cpu handle interrupts from which board. |
69 | struct irqaction *action; | 53 | * Index is board - value is cpu. |
70 | /* For SMP this needs to be extended */ | 54 | */ |
71 | } *sbus_actions; | 55 | static unsigned char board_to_cpu[32]; |
72 | 56 | ||
73 | static int pil_to_sbus[] = { | 57 | static int pil_to_sbus[] = { |
74 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | 58 | 0, |
75 | }; | 59 | 0, |
76 | 60 | 1, | |
77 | static int sbus_to_pil[] = { | 61 | 2, |
78 | 0, 2, 3, 5, 7, 9, 11, 13, | 62 | 0, |
63 | 3, | ||
64 | 0, | ||
65 | 4, | ||
66 | 0, | ||
67 | 5, | ||
68 | 0, | ||
69 | 6, | ||
70 | 0, | ||
71 | 7, | ||
72 | 0, | ||
73 | 0, | ||
79 | }; | 74 | }; |
80 | 75 | ||
81 | static int nsbi; | ||
82 | |||
83 | /* Exported for sun4d_smp.c */ | 76 | /* Exported for sun4d_smp.c */ |
84 | DEFINE_SPINLOCK(sun4d_imsk_lock); | 77 | DEFINE_SPINLOCK(sun4d_imsk_lock); |
85 | 78 | ||
86 | int show_sun4d_interrupts(struct seq_file *p, void *v) | 79 | /* SBUS interrupts are encoded integers including the board number |
87 | { | 80 | * (plus one), the SBUS level, and the SBUS slot number. Sun4D |
88 | int i = *(loff_t *) v, j = 0, k = 0, sbusl; | 81 | * IRQ dispatch is done by: |
89 | struct irqaction * action; | 82 | * |
90 | unsigned long flags; | 83 | * 1) Reading the BW local interrupt table in order to get the bus |
91 | #ifdef CONFIG_SMP | 84 | * interrupt mask. |
92 | int x; | 85 | * |
93 | #endif | 86 | * This table is indexed by SBUS interrupt level which can be |
94 | 87 | * derived from the PIL we got interrupted on. | |
95 | spin_lock_irqsave(&irq_action_lock, flags); | 88 | * |
96 | if (i < NR_IRQS) { | 89 | * 2) For each bus showing interrupt pending from #1, read the |
97 | sbusl = pil_to_sbus[i]; | 90 | * SBI interrupt state register. This will indicate which slots |
98 | if (!sbusl) { | 91 | * have interrupts pending for that SBUS interrupt level. |
99 | action = *(i + irq_action); | 92 | * |
100 | if (!action) | 93 | * 3) Call the genreric IRQ support. |
101 | goto out_unlock; | 94 | */ |
102 | } else { | 95 | static void sun4d_sbus_handler_irq(int sbusl) |
103 | for (j = 0; j < nsbi; j++) { | ||
104 | for (k = 0; k < 4; k++) | ||
105 | if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action)) | ||
106 | goto found_it; | ||
107 | } | ||
108 | goto out_unlock; | ||
109 | } | ||
110 | found_it: seq_printf(p, "%3d: ", i); | ||
111 | #ifndef CONFIG_SMP | ||
112 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
113 | #else | ||
114 | for_each_online_cpu(x) | ||
115 | seq_printf(p, "%10u ", | ||
116 | kstat_cpu(cpu_logical_map(x)).irqs[i]); | ||
117 | #endif | ||
118 | seq_printf(p, "%c %s", | ||
119 | (action->flags & IRQF_DISABLED) ? '+' : ' ', | ||
120 | action->name); | ||
121 | action = action->next; | ||
122 | for (;;) { | ||
123 | for (; action; action = action->next) { | ||
124 | seq_printf(p, ",%s %s", | ||
125 | (action->flags & IRQF_DISABLED) ? " +" : "", | ||
126 | action->name); | ||
127 | } | ||
128 | if (!sbusl) break; | ||
129 | k++; | ||
130 | if (k < 4) | ||
131 | action = sbus_actions [(j << 5) + (sbusl << 2) + k].action; | ||
132 | else { | ||
133 | j++; | ||
134 | if (j == nsbi) break; | ||
135 | k = 0; | ||
136 | action = sbus_actions [(j << 5) + (sbusl << 2)].action; | ||
137 | } | ||
138 | } | ||
139 | seq_putc(p, '\n'); | ||
140 | } | ||
141 | out_unlock: | ||
142 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | void sun4d_free_irq(unsigned int irq, void *dev_id) | ||
147 | { | 96 | { |
148 | struct irqaction *action, **actionp; | 97 | unsigned int bus_mask; |
149 | struct irqaction *tmp = NULL; | 98 | unsigned int sbino, slot; |
150 | unsigned long flags; | 99 | unsigned int sbil; |
151 | 100 | ||
152 | spin_lock_irqsave(&irq_action_lock, flags); | 101 | bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff; |
153 | if (irq < 15) | 102 | bw_clear_intr_mask(sbusl, bus_mask); |
154 | actionp = irq + irq_action; | 103 | |
155 | else | 104 | sbil = (sbusl << 2); |
156 | actionp = &(sbus_actions[irq - (1 << 5)].action); | 105 | /* Loop for each pending SBI */ |
157 | action = *actionp; | 106 | for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) { |
158 | if (!action) { | 107 | unsigned int idx, mask; |
159 | printk("Trying to free free IRQ%d\n",irq); | 108 | |
160 | goto out_unlock; | 109 | if (!(bus_mask & 1)) |
161 | } | 110 | continue; |
162 | if (dev_id) { | 111 | /* XXX This seems to ACK the irq twice. acquire_sbi() |
163 | for (; action; action = action->next) { | 112 | * XXX uses swap, therefore this writes 0xf << sbil, |
164 | if (action->dev_id == dev_id) | 113 | * XXX then later release_sbi() will write the individual |
165 | break; | 114 | * XXX bits which were set again. |
166 | tmp = action; | ||
167 | } | ||
168 | if (!action) { | ||
169 | printk("Trying to free free shared IRQ%d\n",irq); | ||
170 | goto out_unlock; | ||
171 | } | ||
172 | } else if (action->flags & IRQF_SHARED) { | ||
173 | printk("Trying to free shared IRQ%d with NULL device ID\n", irq); | ||
174 | goto out_unlock; | ||
175 | } | ||
176 | if (action->flags & SA_STATIC_ALLOC) | ||
177 | { | ||
178 | /* This interrupt is marked as specially allocated | ||
179 | * so it is a bad idea to free it. | ||
180 | */ | 115 | */ |
181 | printk("Attempt to free statically allocated IRQ%d (%s)\n", | 116 | mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil); |
182 | irq, action->name); | 117 | mask &= (0xf << sbil); |
183 | goto out_unlock; | ||
184 | } | ||
185 | |||
186 | if (tmp) | ||
187 | tmp->next = action->next; | ||
188 | else | ||
189 | *actionp = action->next; | ||
190 | |||
191 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
192 | 118 | ||
193 | synchronize_irq(irq); | 119 | /* Loop for each pending SBI slot */ |
120 | slot = (1 << sbil); | ||
121 | for (idx = 0; mask != 0; idx++, slot <<= 1) { | ||
122 | unsigned int pil; | ||
123 | struct irq_bucket *p; | ||
194 | 124 | ||
195 | spin_lock_irqsave(&irq_action_lock, flags); | 125 | if (!(mask & slot)) |
126 | continue; | ||
196 | 127 | ||
197 | kfree(action); | 128 | mask &= ~slot; |
129 | pil = sun4d_encode_irq(sbino, sbusl, idx); | ||
198 | 130 | ||
199 | if (!(*actionp)) | 131 | p = irq_map[pil]; |
200 | __disable_irq(irq); | 132 | while (p) { |
133 | struct irq_bucket *next; | ||
201 | 134 | ||
202 | out_unlock: | 135 | next = p->next; |
203 | spin_unlock_irqrestore(&irq_action_lock, flags); | 136 | generic_handle_irq(p->irq); |
137 | p = next; | ||
138 | } | ||
139 | release_sbi(SBI2DEVID(sbino), slot); | ||
140 | } | ||
141 | } | ||
204 | } | 142 | } |
205 | 143 | ||
206 | extern void unexpected_irq(int, void *, struct pt_regs *); | 144 | void sun4d_handler_irq(int pil, struct pt_regs *regs) |
207 | |||
208 | void sun4d_handler_irq(int irq, struct pt_regs * regs) | ||
209 | { | 145 | { |
210 | struct pt_regs *old_regs; | 146 | struct pt_regs *old_regs; |
211 | struct irqaction * action; | ||
212 | int cpu = smp_processor_id(); | ||
213 | /* SBUS IRQ level (1 - 7) */ | 147 | /* SBUS IRQ level (1 - 7) */ |
214 | int sbusl = pil_to_sbus[irq]; | 148 | int sbusl = pil_to_sbus[pil]; |
215 | 149 | ||
216 | /* FIXME: Is this necessary?? */ | 150 | /* FIXME: Is this necessary?? */ |
217 | cc_get_ipen(); | 151 | cc_get_ipen(); |
218 | 152 | ||
219 | cc_set_iclr(1 << irq); | 153 | cc_set_iclr(1 << pil); |
220 | 154 | ||
155 | #ifdef CONFIG_SMP | ||
156 | /* | ||
157 | * Check IPI data structures after IRQ has been cleared. Hard and Soft | ||
158 | * IRQ can happen at the same time, so both cases are always handled. | ||
159 | */ | ||
160 | if (pil == SUN4D_IPI_IRQ) | ||
161 | sun4d_ipi_interrupt(); | ||
162 | #endif | ||
163 | |||
221 | old_regs = set_irq_regs(regs); | 164 | old_regs = set_irq_regs(regs); |
222 | irq_enter(); | 165 | irq_enter(); |
223 | kstat_cpu(cpu).irqs[irq]++; | 166 | if (sbusl == 0) { |
224 | if (!sbusl) { | 167 | /* cpu interrupt */ |
225 | action = *(irq + irq_action); | 168 | struct irq_bucket *p; |
226 | if (!action) | 169 | |
227 | unexpected_irq(irq, NULL, regs); | 170 | p = irq_map[pil]; |
228 | do { | 171 | while (p) { |
229 | action->handler(irq, action->dev_id); | 172 | struct irq_bucket *next; |
230 | action = action->next; | 173 | |
231 | } while (action); | 174 | next = p->next; |
175 | generic_handle_irq(p->irq); | ||
176 | p = next; | ||
177 | } | ||
232 | } else { | 178 | } else { |
233 | int bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff; | 179 | /* SBUS interrupt */ |
234 | int sbino; | 180 | sun4d_sbus_handler_irq(sbusl); |
235 | struct sbus_action *actionp; | ||
236 | unsigned mask, slot; | ||
237 | int sbil = (sbusl << 2); | ||
238 | |||
239 | bw_clear_intr_mask(sbusl, bus_mask); | ||
240 | |||
241 | /* Loop for each pending SBI */ | ||
242 | for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) | ||
243 | if (bus_mask & 1) { | ||
244 | mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil); | ||
245 | mask &= (0xf << sbil); | ||
246 | actionp = sbus_actions + (sbino << 5) + (sbil); | ||
247 | /* Loop for each pending SBI slot */ | ||
248 | for (slot = (1 << sbil); mask; slot <<= 1, actionp++) | ||
249 | if (mask & slot) { | ||
250 | mask &= ~slot; | ||
251 | action = actionp->action; | ||
252 | |||
253 | if (!action) | ||
254 | unexpected_irq(irq, NULL, regs); | ||
255 | do { | ||
256 | action->handler(irq, action->dev_id); | ||
257 | action = action->next; | ||
258 | } while (action); | ||
259 | release_sbi(SBI2DEVID(sbino), slot); | ||
260 | } | ||
261 | } | ||
262 | } | 181 | } |
263 | irq_exit(); | 182 | irq_exit(); |
264 | set_irq_regs(old_regs); | 183 | set_irq_regs(old_regs); |
265 | } | 184 | } |
266 | 185 | ||
267 | int sun4d_request_irq(unsigned int irq, | 186 | |
268 | irq_handler_t handler, | 187 | static void sun4d_mask_irq(struct irq_data *data) |
269 | unsigned long irqflags, const char * devname, void *dev_id) | ||
270 | { | 188 | { |
271 | struct irqaction *action, *tmp = NULL, **actionp; | 189 | struct sun4d_handler_data *handler_data = data->handler_data; |
190 | unsigned int real_irq; | ||
191 | #ifdef CONFIG_SMP | ||
192 | int cpuid = handler_data->cpuid; | ||
272 | unsigned long flags; | 193 | unsigned long flags; |
273 | int ret; | 194 | #endif |
274 | 195 | real_irq = handler_data->real_irq; | |
275 | if(irq > 14 && irq < (1 << 5)) { | 196 | #ifdef CONFIG_SMP |
276 | ret = -EINVAL; | 197 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
277 | goto out; | 198 | cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq)); |
278 | } | 199 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
279 | 200 | #else | |
280 | if (!handler) { | 201 | cc_set_imsk(cc_get_imsk() | (1 << real_irq)); |
281 | ret = -EINVAL; | 202 | #endif |
282 | goto out; | ||
283 | } | ||
284 | |||
285 | spin_lock_irqsave(&irq_action_lock, flags); | ||
286 | |||
287 | if (irq >= (1 << 5)) | ||
288 | actionp = &(sbus_actions[irq - (1 << 5)].action); | ||
289 | else | ||
290 | actionp = irq + irq_action; | ||
291 | action = *actionp; | ||
292 | |||
293 | if (action) { | ||
294 | if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) { | ||
295 | for (tmp = action; tmp->next; tmp = tmp->next); | ||
296 | } else { | ||
297 | ret = -EBUSY; | ||
298 | goto out_unlock; | ||
299 | } | ||
300 | if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) { | ||
301 | printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); | ||
302 | ret = -EBUSY; | ||
303 | goto out_unlock; | ||
304 | } | ||
305 | action = NULL; /* Or else! */ | ||
306 | } | ||
307 | |||
308 | /* If this is flagged as statically allocated then we use our | ||
309 | * private struct which is never freed. | ||
310 | */ | ||
311 | if (irqflags & SA_STATIC_ALLOC) { | ||
312 | if (static_irq_count < MAX_STATIC_ALLOC) | ||
313 | action = &static_irqaction[static_irq_count++]; | ||
314 | else | ||
315 | printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); | ||
316 | } | ||
317 | |||
318 | if (action == NULL) | ||
319 | action = kmalloc(sizeof(struct irqaction), | ||
320 | GFP_ATOMIC); | ||
321 | |||
322 | if (!action) { | ||
323 | ret = -ENOMEM; | ||
324 | goto out_unlock; | ||
325 | } | ||
326 | |||
327 | action->handler = handler; | ||
328 | action->flags = irqflags; | ||
329 | action->name = devname; | ||
330 | action->next = NULL; | ||
331 | action->dev_id = dev_id; | ||
332 | |||
333 | if (tmp) | ||
334 | tmp->next = action; | ||
335 | else | ||
336 | *actionp = action; | ||
337 | |||
338 | __enable_irq(irq); | ||
339 | |||
340 | ret = 0; | ||
341 | out_unlock: | ||
342 | spin_unlock_irqrestore(&irq_action_lock, flags); | ||
343 | out: | ||
344 | return ret; | ||
345 | } | 203 | } |
346 | 204 | ||
347 | static void sun4d_disable_irq(unsigned int irq) | 205 | static void sun4d_unmask_irq(struct irq_data *data) |
348 | { | 206 | { |
349 | int tid = sbus_tid[(irq >> 5) - 1]; | 207 | struct sun4d_handler_data *handler_data = data->handler_data; |
208 | unsigned int real_irq; | ||
209 | #ifdef CONFIG_SMP | ||
210 | int cpuid = handler_data->cpuid; | ||
350 | unsigned long flags; | 211 | unsigned long flags; |
351 | 212 | #endif | |
352 | if (irq < NR_IRQS) | 213 | real_irq = handler_data->real_irq; |
353 | return; | ||
354 | 214 | ||
215 | #ifdef CONFIG_SMP | ||
355 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 216 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
356 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); | 217 | cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq)); |
357 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 218 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
219 | #else | ||
220 | cc_set_imsk(cc_get_imsk() & ~(1 << real_irq)); | ||
221 | #endif | ||
358 | } | 222 | } |
359 | 223 | ||
360 | static void sun4d_enable_irq(unsigned int irq) | 224 | static unsigned int sun4d_startup_irq(struct irq_data *data) |
361 | { | 225 | { |
362 | int tid = sbus_tid[(irq >> 5) - 1]; | 226 | irq_link(data->irq); |
363 | unsigned long flags; | 227 | sun4d_unmask_irq(data); |
364 | 228 | return 0; | |
365 | if (irq < NR_IRQS) | 229 | } |
366 | return; | ||
367 | 230 | ||
368 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 231 | static void sun4d_shutdown_irq(struct irq_data *data) |
369 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); | 232 | { |
370 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 233 | sun4d_mask_irq(data); |
234 | irq_unlink(data->irq); | ||
371 | } | 235 | } |
372 | 236 | ||
237 | struct irq_chip sun4d_irq = { | ||
238 | .name = "sun4d", | ||
239 | .irq_startup = sun4d_startup_irq, | ||
240 | .irq_shutdown = sun4d_shutdown_irq, | ||
241 | .irq_unmask = sun4d_unmask_irq, | ||
242 | .irq_mask = sun4d_mask_irq, | ||
243 | }; | ||
244 | |||
373 | #ifdef CONFIG_SMP | 245 | #ifdef CONFIG_SMP |
374 | static void sun4d_set_cpu_int(int cpu, int level) | 246 | static void sun4d_set_cpu_int(int cpu, int level) |
375 | { | 247 | { |
@@ -389,44 +261,6 @@ void __init sun4d_distribute_irqs(void) | |||
389 | { | 261 | { |
390 | struct device_node *dp; | 262 | struct device_node *dp; |
391 | 263 | ||
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); | 264 | int cpuid = cpu_logical_map(1); |
431 | 265 | ||
432 | if (cpuid == -1) | 266 | if (cpuid == -1) |
@@ -434,14 +268,13 @@ void __init sun4d_distribute_irqs(void) | |||
434 | for_each_node_by_name(dp, "sbi") { | 268 | for_each_node_by_name(dp, "sbi") { |
435 | int devid = of_getintprop_default(dp, "device-id", 0); | 269 | int devid = of_getintprop_default(dp, "device-id", 0); |
436 | int board = of_getintprop_default(dp, "board#", 0); | 270 | int board = of_getintprop_default(dp, "board#", 0); |
437 | sbus_tid[board] = cpuid; | 271 | board_to_cpu[board] = cpuid; |
438 | set_sbi_tid(devid, cpuid << 3); | 272 | set_sbi_tid(devid, cpuid << 3); |
439 | } | 273 | } |
440 | printk("All sbus IRQs directed to CPU%d\n", cpuid); | 274 | printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid); |
441 | #endif | ||
442 | } | 275 | } |
443 | #endif | 276 | #endif |
444 | 277 | ||
445 | static void sun4d_clear_clock_irq(void) | 278 | static void sun4d_clear_clock_irq(void) |
446 | { | 279 | { |
447 | sbus_readl(&sun4d_timers->l10_timer_limit); | 280 | sbus_readl(&sun4d_timers->l10_timer_limit); |
@@ -462,14 +295,115 @@ static void __init sun4d_load_profile_irqs(void) | |||
462 | } | 295 | } |
463 | } | 296 | } |
464 | 297 | ||
298 | unsigned int _sun4d_build_device_irq(unsigned int real_irq, | ||
299 | unsigned int pil, | ||
300 | unsigned int board) | ||
301 | { | ||
302 | struct sun4d_handler_data *handler_data; | ||
303 | unsigned int irq; | ||
304 | |||
305 | irq = irq_alloc(real_irq, pil); | ||
306 | if (irq == 0) { | ||
307 | prom_printf("IRQ: allocate for %d %d %d failed\n", | ||
308 | real_irq, pil, board); | ||
309 | goto err_out; | ||
310 | } | ||
311 | |||
312 | handler_data = irq_get_handler_data(irq); | ||
313 | if (unlikely(handler_data)) | ||
314 | goto err_out; | ||
315 | |||
316 | handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC); | ||
317 | if (unlikely(!handler_data)) { | ||
318 | prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n"); | ||
319 | prom_halt(); | ||
320 | } | ||
321 | handler_data->cpuid = board_to_cpu[board]; | ||
322 | handler_data->real_irq = real_irq; | ||
323 | irq_set_chip_and_handler_name(irq, &sun4d_irq, | ||
324 | handle_level_irq, "level"); | ||
325 | irq_set_handler_data(irq, handler_data); | ||
326 | |||
327 | err_out: | ||
328 | return irq; | ||
329 | } | ||
330 | |||
331 | |||
332 | |||
333 | unsigned int sun4d_build_device_irq(struct platform_device *op, | ||
334 | unsigned int real_irq) | ||
335 | { | ||
336 | struct device_node *dp = op->dev.of_node; | ||
337 | struct device_node *board_parent, *bus = dp->parent; | ||
338 | char *bus_connection; | ||
339 | const struct linux_prom_registers *regs; | ||
340 | unsigned int pil; | ||
341 | unsigned int irq; | ||
342 | int board, slot; | ||
343 | int sbusl; | ||
344 | |||
345 | irq = real_irq; | ||
346 | while (bus) { | ||
347 | if (!strcmp(bus->name, "sbi")) { | ||
348 | bus_connection = "io-unit"; | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | if (!strcmp(bus->name, "bootbus")) { | ||
353 | bus_connection = "cpu-unit"; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | bus = bus->parent; | ||
358 | } | ||
359 | if (!bus) | ||
360 | goto err_out; | ||
361 | |||
362 | regs = of_get_property(dp, "reg", NULL); | ||
363 | if (!regs) | ||
364 | goto err_out; | ||
365 | |||
366 | slot = regs->which_io; | ||
367 | |||
368 | /* | ||
369 | * If Bus nodes parent is not io-unit/cpu-unit or the io-unit/cpu-unit | ||
370 | * lacks a "board#" property, something is very wrong. | ||
371 | */ | ||
372 | if (!bus->parent || strcmp(bus->parent->name, bus_connection)) { | ||
373 | printk(KERN_ERR "%s: Error, parent is not %s.\n", | ||
374 | bus->full_name, bus_connection); | ||
375 | goto err_out; | ||
376 | } | ||
377 | board_parent = bus->parent; | ||
378 | board = of_getintprop_default(board_parent, "board#", -1); | ||
379 | if (board == -1) { | ||
380 | printk(KERN_ERR "%s: Error, lacks board# property.\n", | ||
381 | board_parent->full_name); | ||
382 | goto err_out; | ||
383 | } | ||
384 | |||
385 | sbusl = pil_to_sbus[real_irq]; | ||
386 | if (sbusl) | ||
387 | pil = sun4d_encode_irq(board, sbusl, slot); | ||
388 | else | ||
389 | pil = real_irq; | ||
390 | |||
391 | irq = _sun4d_build_device_irq(real_irq, pil, board); | ||
392 | err_out: | ||
393 | return irq; | ||
394 | } | ||
395 | |||
396 | unsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq) | ||
397 | { | ||
398 | return _sun4d_build_device_irq(real_irq, real_irq, board); | ||
399 | } | ||
400 | |||
401 | |||
465 | static void __init sun4d_fixup_trap_table(void) | 402 | static void __init sun4d_fixup_trap_table(void) |
466 | { | 403 | { |
467 | #ifdef CONFIG_SMP | 404 | #ifdef CONFIG_SMP |
468 | unsigned long flags; | 405 | unsigned long flags; |
469 | extern unsigned long lvl14_save[4]; | ||
470 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; | 406 | 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 | 407 | ||
474 | /* Adjust so that we jump directly to smp4d_ticker */ | 408 | /* Adjust so that we jump directly to smp4d_ticker */ |
475 | lvl14_save[2] += smp4d_ticker - real_irq_entry; | 409 | lvl14_save[2] += smp4d_ticker - real_irq_entry; |
@@ -493,8 +427,10 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) | |||
493 | { | 427 | { |
494 | struct device_node *dp; | 428 | struct device_node *dp; |
495 | struct resource res; | 429 | struct resource res; |
430 | unsigned int irq; | ||
496 | const u32 *reg; | 431 | const u32 *reg; |
497 | int err; | 432 | int err; |
433 | int board; | ||
498 | 434 | ||
499 | dp = of_find_node_by_name(NULL, "cpu-unit"); | 435 | dp = of_find_node_by_name(NULL, "cpu-unit"); |
500 | if (!dp) { | 436 | if (!dp) { |
@@ -507,12 +443,19 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) | |||
507 | * bootbus. | 443 | * bootbus. |
508 | */ | 444 | */ |
509 | reg = of_get_property(dp, "reg", NULL); | 445 | reg = of_get_property(dp, "reg", NULL); |
510 | of_node_put(dp); | ||
511 | if (!reg) { | 446 | if (!reg) { |
512 | prom_printf("sun4d_init_timers: No reg property\n"); | 447 | prom_printf("sun4d_init_timers: No reg property\n"); |
513 | prom_halt(); | 448 | prom_halt(); |
514 | } | 449 | } |
515 | 450 | ||
451 | board = of_getintprop_default(dp, "board#", -1); | ||
452 | if (board == -1) { | ||
453 | prom_printf("sun4d_init_timers: No board# property on cpu-unit\n"); | ||
454 | prom_halt(); | ||
455 | } | ||
456 | |||
457 | of_node_put(dp); | ||
458 | |||
516 | res.start = reg[1]; | 459 | res.start = reg[1]; |
517 | res.end = reg[2] - 1; | 460 | res.end = reg[2] - 1; |
518 | res.flags = reg[0] & 0xff; | 461 | res.flags = reg[0] & 0xff; |
@@ -527,11 +470,11 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) | |||
527 | 470 | ||
528 | master_l10_counter = &sun4d_timers->l10_cur_count; | 471 | master_l10_counter = &sun4d_timers->l10_cur_count; |
529 | 472 | ||
530 | err = request_irq(TIMER_IRQ, counter_fn, | 473 | irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); |
531 | (IRQF_DISABLED | SA_STATIC_ALLOC), | 474 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); |
532 | "timer", NULL); | ||
533 | if (err) { | 475 | if (err) { |
534 | prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); | 476 | prom_printf("sun4d_init_timers: request_irq() failed with %d\n", |
477 | err); | ||
535 | prom_halt(); | 478 | prom_halt(); |
536 | } | 479 | } |
537 | sun4d_load_profile_irqs(); | 480 | sun4d_load_profile_irqs(); |
@@ -541,32 +484,22 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) | |||
541 | void __init sun4d_init_sbi_irq(void) | 484 | void __init sun4d_init_sbi_irq(void) |
542 | { | 485 | { |
543 | struct device_node *dp; | 486 | struct device_node *dp; |
544 | int target_cpu = 0; | 487 | int target_cpu; |
545 | 488 | ||
546 | #ifdef CONFIG_SMP | ||
547 | target_cpu = boot_cpu_id; | 489 | target_cpu = boot_cpu_id; |
548 | #endif | ||
549 | |||
550 | nsbi = 0; | ||
551 | for_each_node_by_name(dp, "sbi") | ||
552 | nsbi++; | ||
553 | sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); | ||
554 | if (!sbus_actions) { | ||
555 | prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); | ||
556 | prom_halt(); | ||
557 | } | ||
558 | for_each_node_by_name(dp, "sbi") { | 490 | for_each_node_by_name(dp, "sbi") { |
559 | int devid = of_getintprop_default(dp, "device-id", 0); | 491 | int devid = of_getintprop_default(dp, "device-id", 0); |
560 | int board = of_getintprop_default(dp, "board#", 0); | 492 | int board = of_getintprop_default(dp, "board#", 0); |
561 | unsigned int mask; | 493 | unsigned int mask; |
562 | 494 | ||
563 | set_sbi_tid(devid, target_cpu << 3); | 495 | set_sbi_tid(devid, target_cpu << 3); |
564 | sbus_tid[board] = target_cpu; | 496 | board_to_cpu[board] = target_cpu; |
565 | 497 | ||
566 | /* Get rid of pending irqs from PROM */ | 498 | /* Get rid of pending irqs from PROM */ |
567 | mask = acquire_sbi(devid, 0xffffffff); | 499 | mask = acquire_sbi(devid, 0xffffffff); |
568 | if (mask) { | 500 | if (mask) { |
569 | printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board); | 501 | printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n", |
502 | mask, board); | ||
570 | release_sbi(devid, mask); | 503 | release_sbi(devid, mask); |
571 | } | 504 | } |
572 | } | 505 | } |
@@ -576,11 +509,12 @@ void __init sun4d_init_IRQ(void) | |||
576 | { | 509 | { |
577 | local_irq_disable(); | 510 | local_irq_disable(); |
578 | 511 | ||
579 | BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); | ||
580 | BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); | ||
581 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); | 512 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); |
582 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); | 513 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); |
583 | sparc_init_timers = sun4d_init_timers; | 514 | |
515 | sparc_irq_config.init_timers = sun4d_init_timers; | ||
516 | sparc_irq_config.build_device_irq = sun4d_build_device_irq; | ||
517 | |||
584 | #ifdef CONFIG_SMP | 518 | #ifdef CONFIG_SMP |
585 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); | 519 | BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); |
586 | BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); | 520 | 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..133387980b56 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 | { |
@@ -68,9 +32,8 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon | |||
68 | return val; | 32 | return val; |
69 | } | 33 | } |
70 | 34 | ||
35 | static void smp4d_ipi_init(void); | ||
71 | static void smp_setup_percpu_timer(void); | 36 | static void smp_setup_percpu_timer(void); |
72 | extern void cpu_probe(void); | ||
73 | extern void sun4d_distribute_irqs(void); | ||
74 | 37 | ||
75 | static unsigned char cpu_leds[32]; | 38 | static unsigned char cpu_leds[32]; |
76 | 39 | ||
@@ -86,9 +49,8 @@ static inline void show_leds(int cpuid) | |||
86 | void __cpuinit smp4d_callin(void) | 49 | void __cpuinit smp4d_callin(void) |
87 | { | 50 | { |
88 | int cpuid = hard_smp4d_processor_id(); | 51 | int cpuid = hard_smp4d_processor_id(); |
89 | extern spinlock_t sun4d_imsk_lock; | ||
90 | unsigned long flags; | 52 | unsigned long flags; |
91 | 53 | ||
92 | /* Show we are alive */ | 54 | /* Show we are alive */ |
93 | cpu_leds[cpuid] = 0x6; | 55 | cpu_leds[cpuid] = 0x6; |
94 | show_leds(cpuid); | 56 | show_leds(cpuid); |
@@ -118,15 +80,13 @@ void __cpuinit smp4d_callin(void) | |||
118 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); | 80 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); |
119 | local_flush_cache_all(); | 81 | local_flush_cache_all(); |
120 | local_flush_tlb_all(); | 82 | local_flush_tlb_all(); |
121 | |||
122 | cpu_probe(); | ||
123 | 83 | ||
124 | while((unsigned long)current_set[cpuid] < PAGE_OFFSET) | 84 | while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) |
125 | barrier(); | 85 | barrier(); |
126 | 86 | ||
127 | while(current_set[cpuid]->cpu != cpuid) | 87 | while (current_set[cpuid]->cpu != cpuid) |
128 | barrier(); | 88 | barrier(); |
129 | 89 | ||
130 | /* Fix idle thread fields. */ | 90 | /* Fix idle thread fields. */ |
131 | __asm__ __volatile__("ld [%0], %%g6\n\t" | 91 | __asm__ __volatile__("ld [%0], %%g6\n\t" |
132 | : : "r" (¤t_set[cpuid]) | 92 | : : "r" (¤t_set[cpuid]) |
@@ -134,17 +94,17 @@ void __cpuinit smp4d_callin(void) | |||
134 | 94 | ||
135 | cpu_leds[cpuid] = 0x9; | 95 | cpu_leds[cpuid] = 0x9; |
136 | show_leds(cpuid); | 96 | show_leds(cpuid); |
137 | 97 | ||
138 | /* Attach to the address space of init_task. */ | 98 | /* Attach to the address space of init_task. */ |
139 | atomic_inc(&init_mm.mm_count); | 99 | atomic_inc(&init_mm.mm_count); |
140 | current->active_mm = &init_mm; | 100 | current->active_mm = &init_mm; |
141 | 101 | ||
142 | local_flush_cache_all(); | 102 | local_flush_cache_all(); |
143 | local_flush_tlb_all(); | 103 | local_flush_tlb_all(); |
144 | 104 | ||
145 | local_irq_enable(); /* We don't allow PIL 14 yet */ | 105 | local_irq_enable(); /* We don't allow PIL 14 yet */ |
146 | 106 | ||
147 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 107 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
148 | barrier(); | 108 | barrier(); |
149 | 109 | ||
150 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 110 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
@@ -154,17 +114,12 @@ void __cpuinit smp4d_callin(void) | |||
154 | 114 | ||
155 | } | 115 | } |
156 | 116 | ||
157 | extern void init_IRQ(void); | ||
158 | extern void cpu_panic(void); | ||
159 | |||
160 | /* | 117 | /* |
161 | * Cycle through the processors asking the PROM to start each one. | 118 | * Cycle through the processors asking the PROM to start each one. |
162 | */ | 119 | */ |
163 | |||
164 | extern struct linux_prom_registers smp_penguin_ctable; | ||
165 | |||
166 | void __init smp4d_boot_cpus(void) | 120 | void __init smp4d_boot_cpus(void) |
167 | { | 121 | { |
122 | smp4d_ipi_init(); | ||
168 | if (boot_cpu_id) | 123 | if (boot_cpu_id) |
169 | current_set[0] = NULL; | 124 | current_set[0] = NULL; |
170 | smp_setup_percpu_timer(); | 125 | smp_setup_percpu_timer(); |
@@ -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 | } |
@@ -237,6 +191,80 @@ void __init smp4d_smp_done(void) | |||
237 | sun4d_distribute_irqs(); | 191 | sun4d_distribute_irqs(); |
238 | } | 192 | } |
239 | 193 | ||
194 | /* Memory structure giving interrupt handler information about IPI generated */ | ||
195 | struct sun4d_ipi_work { | ||
196 | int single; | ||
197 | int msk; | ||
198 | int resched; | ||
199 | }; | ||
200 | |||
201 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work); | ||
202 | |||
203 | /* Initialize IPIs on the SUN4D SMP machine */ | ||
204 | static void __init smp4d_ipi_init(void) | ||
205 | { | ||
206 | int cpu; | ||
207 | struct sun4d_ipi_work *work; | ||
208 | |||
209 | printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ); | ||
210 | |||
211 | for_each_possible_cpu(cpu) { | ||
212 | work = &per_cpu(sun4d_ipi_work, cpu); | ||
213 | work->single = work->msk = work->resched = 0; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void sun4d_ipi_interrupt(void) | ||
218 | { | ||
219 | struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work); | ||
220 | |||
221 | if (work->single) { | ||
222 | work->single = 0; | ||
223 | smp_call_function_single_interrupt(); | ||
224 | } | ||
225 | if (work->msk) { | ||
226 | work->msk = 0; | ||
227 | smp_call_function_interrupt(); | ||
228 | } | ||
229 | if (work->resched) { | ||
230 | work->resched = 0; | ||
231 | smp_resched_interrupt(); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | static void smp4d_ipi_single(int cpu) | ||
236 | { | ||
237 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
238 | |||
239 | /* Mark work */ | ||
240 | work->single = 1; | ||
241 | |||
242 | /* Generate IRQ on the CPU */ | ||
243 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
244 | } | ||
245 | |||
246 | static void smp4d_ipi_mask_one(int cpu) | ||
247 | { | ||
248 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
249 | |||
250 | /* Mark work */ | ||
251 | work->msk = 1; | ||
252 | |||
253 | /* Generate IRQ on the CPU */ | ||
254 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
255 | } | ||
256 | |||
257 | static void smp4d_ipi_resched(int cpu) | ||
258 | { | ||
259 | struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); | ||
260 | |||
261 | /* Mark work */ | ||
262 | work->resched = 1; | ||
263 | |||
264 | /* Generate IRQ on the CPU (any IRQ will cause resched) */ | ||
265 | sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); | ||
266 | } | ||
267 | |||
240 | static struct smp_funcall { | 268 | static struct smp_funcall { |
241 | smpfunc_t func; | 269 | smpfunc_t func; |
242 | unsigned long arg1; | 270 | unsigned long arg1; |
@@ -255,14 +283,17 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
255 | unsigned long arg2, unsigned long arg3, | 283 | unsigned long arg2, unsigned long arg3, |
256 | unsigned long arg4) | 284 | unsigned long arg4) |
257 | { | 285 | { |
258 | if(smp_processors_ready) { | 286 | if (smp_processors_ready) { |
259 | register int high = smp_highest_cpu; | 287 | register int high = smp_highest_cpu; |
260 | unsigned long flags; | 288 | unsigned long flags; |
261 | 289 | ||
262 | spin_lock_irqsave(&cross_call_lock, flags); | 290 | spin_lock_irqsave(&cross_call_lock, flags); |
263 | 291 | ||
264 | { | 292 | { |
265 | /* If you make changes here, make sure gcc generates proper code... */ | 293 | /* |
294 | * If you make changes here, make sure | ||
295 | * gcc generates proper code... | ||
296 | */ | ||
266 | register smpfunc_t f asm("i0") = func; | 297 | register smpfunc_t f asm("i0") = func; |
267 | register unsigned long a1 asm("i1") = arg1; | 298 | register unsigned long a1 asm("i1") = arg1; |
268 | register unsigned long a2 asm("i2") = arg2; | 299 | register unsigned long a2 asm("i2") = arg2; |
@@ -282,10 +313,10 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
282 | { | 313 | { |
283 | register int i; | 314 | register int i; |
284 | 315 | ||
285 | cpu_clear(smp_processor_id(), mask); | 316 | cpumask_clear_cpu(smp_processor_id(), &mask); |
286 | cpus_and(mask, cpu_online_map, mask); | 317 | cpumask_and(&mask, cpu_online_mask, &mask); |
287 | for(i = 0; i <= high; i++) { | 318 | for (i = 0; i <= high; i++) { |
288 | if (cpu_isset(i, mask)) { | 319 | if (cpumask_test_cpu(i, &mask)) { |
289 | ccall_info.processors_in[i] = 0; | 320 | ccall_info.processors_in[i] = 0; |
290 | ccall_info.processors_out[i] = 0; | 321 | ccall_info.processors_out[i] = 0; |
291 | sun4d_send_ipi(i, IRQ_CROSS_CALL); | 322 | sun4d_send_ipi(i, IRQ_CROSS_CALL); |
@@ -298,19 +329,19 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
298 | 329 | ||
299 | i = 0; | 330 | i = 0; |
300 | do { | 331 | do { |
301 | if (!cpu_isset(i, mask)) | 332 | if (!cpumask_test_cpu(i, &mask)) |
302 | continue; | 333 | continue; |
303 | while(!ccall_info.processors_in[i]) | 334 | while (!ccall_info.processors_in[i]) |
304 | barrier(); | 335 | barrier(); |
305 | } while(++i <= high); | 336 | } while (++i <= high); |
306 | 337 | ||
307 | i = 0; | 338 | i = 0; |
308 | do { | 339 | do { |
309 | if (!cpu_isset(i, mask)) | 340 | if (!cpumask_test_cpu(i, &mask)) |
310 | continue; | 341 | continue; |
311 | while(!ccall_info.processors_out[i]) | 342 | while (!ccall_info.processors_out[i]) |
312 | barrier(); | 343 | barrier(); |
313 | } while(++i <= high); | 344 | } while (++i <= high); |
314 | } | 345 | } |
315 | 346 | ||
316 | spin_unlock_irqrestore(&cross_call_lock, flags); | 347 | spin_unlock_irqrestore(&cross_call_lock, flags); |
@@ -336,7 +367,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
336 | static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; | 367 | static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; |
337 | 368 | ||
338 | old_regs = set_irq_regs(regs); | 369 | old_regs = set_irq_regs(regs); |
339 | bw_get_prof_limit(cpu); | 370 | bw_get_prof_limit(cpu); |
340 | bw_clear_intr_mask(0, 1); /* INTR_TABLE[0] & 1 is Profile IRQ */ | 371 | bw_clear_intr_mask(0, 1); /* INTR_TABLE[0] & 1 is Profile IRQ */ |
341 | 372 | ||
342 | cpu_tick[cpu]++; | 373 | cpu_tick[cpu]++; |
@@ -349,7 +380,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
349 | 380 | ||
350 | profile_tick(CPU_PROFILING); | 381 | profile_tick(CPU_PROFILING); |
351 | 382 | ||
352 | if(!--prof_counter(cpu)) { | 383 | if (!--prof_counter(cpu)) { |
353 | int user = user_mode(regs); | 384 | int user = user_mode(regs); |
354 | 385 | ||
355 | irq_enter(); | 386 | irq_enter(); |
@@ -361,8 +392,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | |||
361 | set_irq_regs(old_regs); | 392 | set_irq_regs(old_regs); |
362 | } | 393 | } |
363 | 394 | ||
364 | extern unsigned int lvl14_resolution; | ||
365 | |||
366 | static void __cpuinit smp_setup_percpu_timer(void) | 395 | static void __cpuinit smp_setup_percpu_timer(void) |
367 | { | 396 | { |
368 | int cpu = hard_smp4d_processor_id(); | 397 | int cpu = hard_smp4d_processor_id(); |
@@ -374,16 +403,16 @@ static void __cpuinit smp_setup_percpu_timer(void) | |||
374 | void __init smp4d_blackbox_id(unsigned *addr) | 403 | void __init smp4d_blackbox_id(unsigned *addr) |
375 | { | 404 | { |
376 | int rd = *addr & 0x3e000000; | 405 | int rd = *addr & 0x3e000000; |
377 | 406 | ||
378 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ | 407 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ |
379 | addr[1] = 0x01000000; /* nop */ | 408 | addr[1] = 0x01000000; /* nop */ |
380 | addr[2] = 0x01000000; /* nop */ | 409 | addr[2] = 0x01000000; /* nop */ |
381 | } | 410 | } |
382 | 411 | ||
383 | void __init smp4d_blackbox_current(unsigned *addr) | 412 | void __init smp4d_blackbox_current(unsigned *addr) |
384 | { | 413 | { |
385 | int rd = *addr & 0x3e000000; | 414 | int rd = *addr & 0x3e000000; |
386 | 415 | ||
387 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ | 416 | addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */ |
388 | addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ | 417 | addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */ |
389 | addr[4] = 0x01000000; /* nop */ | 418 | addr[4] = 0x01000000; /* nop */ |
@@ -392,17 +421,19 @@ void __init smp4d_blackbox_current(unsigned *addr) | |||
392 | void __init sun4d_init_smp(void) | 421 | void __init sun4d_init_smp(void) |
393 | { | 422 | { |
394 | int i; | 423 | int i; |
395 | extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[]; | ||
396 | 424 | ||
397 | /* Patch ipi15 trap table */ | 425 | /* Patch ipi15 trap table */ |
398 | t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); | 426 | t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); |
399 | 427 | ||
400 | /* And set btfixup... */ | 428 | /* And set btfixup... */ |
401 | BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); | 429 | BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id); |
402 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); | 430 | BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); |
403 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); | 431 | BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); |
404 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); | 432 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); |
405 | 433 | BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM); | |
434 | BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM); | ||
435 | BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM); | ||
436 | |||
406 | for (i = 0; i < NR_CPUS; i++) { | 437 | for (i = 0; i < NR_CPUS; i++) { |
407 | ccall_info.processors_in[i] = 1; | 438 | ccall_info.processors_in[i] = 1; |
408 | ccall_info.processors_out[i] = 1; | 439 | ccall_info.processors_out[i] = 1; |
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 7f3b97ff62c1..422c16dad1f6 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,62 @@ 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 | ||
155 | static unsigned long irq_mask[0x50] = { | 98 | |
156 | /* SMP */ | 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 | struct sun4m_handler_data { | ||
104 | bool percpu; | ||
105 | long mask; | ||
106 | }; | ||
107 | |||
108 | /* Dave Redman (djhr@tadpole.co.uk) | ||
109 | * The sun4m interrupt registers. | ||
110 | */ | ||
111 | #define SUN4M_INT_ENABLE 0x80000000 | ||
112 | #define SUN4M_INT_E14 0x00000080 | ||
113 | #define SUN4M_INT_E10 0x00080000 | ||
114 | |||
115 | #define SUN4M_HARD_INT(x) (0x000000001 << (x)) | ||
116 | #define SUN4M_SOFT_INT(x) (0x000010000 << (x)) | ||
117 | |||
118 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ | ||
119 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ | ||
120 | #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ | ||
121 | #define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ | ||
122 | #define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ | ||
123 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ | ||
124 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ | ||
125 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ | ||
126 | #define SUN4M_INT_REALTIME 0x00080000 /* system timer */ | ||
127 | #define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ | ||
128 | #define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ | ||
129 | #define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ | ||
130 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ | ||
131 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ | ||
132 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ | ||
133 | #define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ | ||
134 | |||
135 | #define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ | ||
136 | SUN4M_INT_M2S_WRITE_ERR | \ | ||
137 | SUN4M_INT_ECC_ERR | \ | ||
138 | SUN4M_INT_VME_ERR) | ||
139 | |||
140 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) | ||
141 | #define SUN4M_INT_VME(x) (1 << (x)) | ||
142 | |||
143 | /* Interrupt levels used by OBP */ | ||
144 | #define OBP_INT_LEVEL_SOFT 0x10 | ||
145 | #define OBP_INT_LEVEL_ONBOARD 0x20 | ||
146 | #define OBP_INT_LEVEL_SBUS 0x30 | ||
147 | #define OBP_INT_LEVEL_VME 0x40 | ||
148 | |||
149 | #define SUN4M_TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) | ||
150 | #define SUN4M_PROFILE_IRQ (OBP_INT_LEVEL_ONBOARD | 14) | ||
151 | |||
152 | static unsigned long sun4m_imask[0x50] = { | ||
153 | /* 0x00 - SMP */ | ||
157 | 0, SUN4M_SOFT_INT(1), | 154 | 0, SUN4M_SOFT_INT(1), |
158 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), | 155 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
159 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), | 156 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
@@ -162,7 +159,7 @@ static unsigned long irq_mask[0x50] = { | |||
162 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | 159 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
163 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), | 160 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
164 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), | 161 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
165 | /* soft */ | 162 | /* 0x10 - soft */ |
166 | 0, SUN4M_SOFT_INT(1), | 163 | 0, SUN4M_SOFT_INT(1), |
167 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), | 164 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
168 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), | 165 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
@@ -171,122 +168,129 @@ static unsigned long irq_mask[0x50] = { | |||
171 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | 168 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
172 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), | 169 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
173 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), | 170 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
174 | /* onboard */ | 171 | /* 0x20 - onboard */ |
175 | 0, 0, 0, 0, | 172 | 0, 0, 0, 0, |
176 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, | 173 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, |
177 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, | 174 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, |
178 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, | 175 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, |
179 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), | 176 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), |
180 | SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, | 177 | SUN4M_INT_AUDIO, SUN4M_INT_E14, SUN4M_INT_MODULE_ERR, |
181 | /* sbus */ | 178 | /* 0x30 - sbus */ |
182 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), | 179 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), |
183 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), | 180 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), |
184 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), | 181 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), |
185 | 0, SUN4M_INT_SBUS(6), 0, 0, | 182 | 0, SUN4M_INT_SBUS(6), 0, 0, |
186 | /* vme */ | 183 | /* 0x40 - vme */ |
187 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), | 184 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), |
188 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), | 185 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), |
189 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), | 186 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), |
190 | 0, SUN4M_INT_VME(6), 0, 0 | 187 | 0, SUN4M_INT_VME(6), 0, 0 |
191 | }; | 188 | }; |
192 | 189 | ||
193 | static unsigned long sun4m_get_irqmask(unsigned int irq) | 190 | static void sun4m_mask_irq(struct irq_data *data) |
194 | { | ||
195 | unsigned long mask; | ||
196 | |||
197 | if (irq < 0x50) | ||
198 | mask = irq_mask[irq]; | ||
199 | else | ||
200 | mask = 0; | ||
201 | |||
202 | if (!mask) | ||
203 | printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", | ||
204 | irq); | ||
205 | |||
206 | return mask; | ||
207 | } | ||
208 | |||
209 | static void sun4m_disable_irq(unsigned int irq_nr) | ||
210 | { | 191 | { |
211 | unsigned long mask, flags; | 192 | struct sun4m_handler_data *handler_data = data->handler_data; |
212 | int cpu = smp_processor_id(); | 193 | int cpu = smp_processor_id(); |
213 | 194 | ||
214 | mask = sun4m_get_irqmask(irq_nr); | 195 | if (handler_data->mask) { |
215 | local_irq_save(flags); | 196 | unsigned long flags; |
216 | if (irq_nr > 15) | 197 | |
217 | sbus_writel(mask, &sun4m_irq_global->mask_set); | 198 | local_irq_save(flags); |
218 | else | 199 | if (handler_data->percpu) { |
219 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); | 200 | sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->set); |
220 | local_irq_restore(flags); | 201 | } else { |
202 | sbus_writel(handler_data->mask, &sun4m_irq_global->mask_set); | ||
203 | } | ||
204 | local_irq_restore(flags); | ||
205 | } | ||
221 | } | 206 | } |
222 | 207 | ||
223 | static void sun4m_enable_irq(unsigned int irq_nr) | 208 | static void sun4m_unmask_irq(struct irq_data *data) |
224 | { | 209 | { |
225 | unsigned long mask, flags; | 210 | struct sun4m_handler_data *handler_data = data->handler_data; |
226 | int cpu = smp_processor_id(); | 211 | int cpu = smp_processor_id(); |
227 | 212 | ||
228 | /* Dreadful floppy hack. When we use 0x2b instead of | 213 | if (handler_data->mask) { |
229 | * 0x0b the system blows (it starts to whistle!). | 214 | unsigned long flags; |
230 | * So we continue to use 0x0b. Fixme ASAP. --P3 | 215 | |
231 | */ | ||
232 | if (irq_nr != 0x0b) { | ||
233 | mask = sun4m_get_irqmask(irq_nr); | ||
234 | local_irq_save(flags); | ||
235 | if (irq_nr > 15) | ||
236 | sbus_writel(mask, &sun4m_irq_global->mask_clear); | ||
237 | else | ||
238 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); | ||
239 | local_irq_restore(flags); | ||
240 | } else { | ||
241 | local_irq_save(flags); | 216 | local_irq_save(flags); |
242 | sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); | 217 | if (handler_data->percpu) { |
218 | sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear); | ||
219 | } else { | ||
220 | sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear); | ||
221 | } | ||
243 | local_irq_restore(flags); | 222 | local_irq_restore(flags); |
244 | } | 223 | } |
245 | } | 224 | } |
246 | 225 | ||
247 | static unsigned long cpu_pil_to_imask[16] = { | 226 | static unsigned int sun4m_startup_irq(struct irq_data *data) |
248 | /*0*/ 0x00000000, | 227 | { |
249 | /*1*/ 0x00000000, | 228 | irq_link(data->irq); |
250 | /*2*/ SUN4M_INT_SBUS(0) | SUN4M_INT_VME(0), | 229 | sun4m_unmask_irq(data); |
251 | /*3*/ SUN4M_INT_SBUS(1) | SUN4M_INT_VME(1), | 230 | return 0; |
252 | /*4*/ SUN4M_INT_SCSI, | 231 | } |
253 | /*5*/ SUN4M_INT_SBUS(2) | SUN4M_INT_VME(2), | ||
254 | /*6*/ SUN4M_INT_ETHERNET, | ||
255 | /*7*/ SUN4M_INT_SBUS(3) | SUN4M_INT_VME(3), | ||
256 | /*8*/ SUN4M_INT_VIDEO, | ||
257 | /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, | ||
258 | /*10*/ SUN4M_INT_REALTIME, | ||
259 | /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, | ||
260 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, | ||
261 | /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, | ||
262 | /*14*/ SUN4M_INT_E14, | ||
263 | /*15*/ SUN4M_INT_ERROR | ||
264 | }; | ||
265 | 232 | ||
266 | /* We assume the caller has disabled local interrupts when these are called, | 233 | static void sun4m_shutdown_irq(struct irq_data *data) |
267 | * or else very bizarre behavior will result. | ||
268 | */ | ||
269 | static void sun4m_disable_pil_irq(unsigned int pil) | ||
270 | { | 234 | { |
271 | sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); | 235 | sun4m_mask_irq(data); |
236 | irq_unlink(data->irq); | ||
272 | } | 237 | } |
273 | 238 | ||
274 | static void sun4m_enable_pil_irq(unsigned int pil) | 239 | static struct irq_chip sun4m_irq = { |
240 | .name = "sun4m", | ||
241 | .irq_startup = sun4m_startup_irq, | ||
242 | .irq_shutdown = sun4m_shutdown_irq, | ||
243 | .irq_mask = sun4m_mask_irq, | ||
244 | .irq_unmask = sun4m_unmask_irq, | ||
245 | }; | ||
246 | |||
247 | |||
248 | static unsigned int sun4m_build_device_irq(struct platform_device *op, | ||
249 | unsigned int real_irq) | ||
275 | { | 250 | { |
276 | sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); | 251 | struct sun4m_handler_data *handler_data; |
252 | unsigned int irq; | ||
253 | unsigned int pil; | ||
254 | |||
255 | if (real_irq >= OBP_INT_LEVEL_VME) { | ||
256 | prom_printf("Bogus sun4m IRQ %u\n", real_irq); | ||
257 | prom_halt(); | ||
258 | } | ||
259 | pil = (real_irq & 0xf); | ||
260 | irq = irq_alloc(real_irq, pil); | ||
261 | |||
262 | if (irq == 0) | ||
263 | goto out; | ||
264 | |||
265 | handler_data = irq_get_handler_data(irq); | ||
266 | if (unlikely(handler_data)) | ||
267 | goto out; | ||
268 | |||
269 | handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC); | ||
270 | if (unlikely(!handler_data)) { | ||
271 | prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n"); | ||
272 | prom_halt(); | ||
273 | } | ||
274 | |||
275 | handler_data->mask = sun4m_imask[real_irq]; | ||
276 | handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD; | ||
277 | irq_set_chip_and_handler_name(irq, &sun4m_irq, | ||
278 | handle_level_irq, "level"); | ||
279 | irq_set_handler_data(irq, handler_data); | ||
280 | |||
281 | out: | ||
282 | return irq; | ||
277 | } | 283 | } |
278 | 284 | ||
279 | #ifdef CONFIG_SMP | 285 | #ifdef CONFIG_SMP |
280 | static void sun4m_send_ipi(int cpu, int level) | 286 | static void sun4m_send_ipi(int cpu, int level) |
281 | { | 287 | { |
282 | unsigned long mask = sun4m_get_irqmask(level); | 288 | sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set); |
283 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); | ||
284 | } | 289 | } |
285 | 290 | ||
286 | static void sun4m_clear_ipi(int cpu, int level) | 291 | static void sun4m_clear_ipi(int cpu, int level) |
287 | { | 292 | { |
288 | unsigned long mask = sun4m_get_irqmask(level); | 293 | sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear); |
289 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); | ||
290 | } | 294 | } |
291 | 295 | ||
292 | static void sun4m_set_udt(int cpu) | 296 | static void sun4m_set_udt(int cpu) |
@@ -314,7 +318,6 @@ struct sun4m_timer_global { | |||
314 | 318 | ||
315 | static struct sun4m_timer_global __iomem *timers_global; | 319 | static struct sun4m_timer_global __iomem *timers_global; |
316 | 320 | ||
317 | #define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) | ||
318 | 321 | ||
319 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); | 322 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); |
320 | 323 | ||
@@ -350,7 +353,15 @@ void sun4m_nmi(struct pt_regs *regs) | |||
350 | prom_halt(); | 353 | prom_halt(); |
351 | } | 354 | } |
352 | 355 | ||
353 | /* Exported for sun4m_smp.c */ | 356 | void sun4m_unmask_profile_irq(void) |
357 | { | ||
358 | unsigned long flags; | ||
359 | |||
360 | local_irq_save(flags); | ||
361 | sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear); | ||
362 | local_irq_restore(flags); | ||
363 | } | ||
364 | |||
354 | void sun4m_clear_profile_irq(int cpu) | 365 | void sun4m_clear_profile_irq(int cpu) |
355 | { | 366 | { |
356 | sbus_readl(&timers_percpu[cpu]->l14_limit); | 367 | sbus_readl(&timers_percpu[cpu]->l14_limit); |
@@ -365,6 +376,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
365 | { | 376 | { |
366 | struct device_node *dp = of_find_node_by_name(NULL, "counter"); | 377 | struct device_node *dp = of_find_node_by_name(NULL, "counter"); |
367 | int i, err, len, num_cpu_timers; | 378 | int i, err, len, num_cpu_timers; |
379 | unsigned int irq; | ||
368 | const u32 *addr; | 380 | const u32 *addr; |
369 | 381 | ||
370 | if (!dp) { | 382 | if (!dp) { |
@@ -391,8 +403,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
391 | 403 | ||
392 | master_l10_counter = &timers_global->l10_count; | 404 | master_l10_counter = &timers_global->l10_count; |
393 | 405 | ||
394 | err = request_irq(TIMER_IRQ, counter_fn, | 406 | irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ); |
395 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | 407 | |
408 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); | ||
396 | if (err) { | 409 | if (err) { |
397 | printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", | 410 | printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", |
398 | err); | 411 | err); |
@@ -407,7 +420,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
407 | #ifdef CONFIG_SMP | 420 | #ifdef CONFIG_SMP |
408 | { | 421 | { |
409 | unsigned long flags; | 422 | unsigned long flags; |
410 | extern unsigned long lvl14_save[4]; | ||
411 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; | 423 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; |
412 | 424 | ||
413 | /* For SMP we use the level 14 ticker, however the bootup code | 425 | /* For SMP we use the level 14 ticker, however the bootup code |
@@ -460,13 +472,12 @@ void __init sun4m_init_IRQ(void) | |||
460 | if (num_cpu_iregs == 4) | 472 | if (num_cpu_iregs == 4) |
461 | sbus_writel(0, &sun4m_irq_global->interrupt_target); | 473 | sbus_writel(0, &sun4m_irq_global->interrupt_target); |
462 | 474 | ||
463 | BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); | ||
464 | BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); | ||
465 | BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); | ||
466 | BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); | ||
467 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); | 475 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); |
468 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); | 476 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); |
469 | sparc_init_timers = sun4m_init_timers; | 477 | |
478 | sparc_irq_config.init_timers = sun4m_init_timers; | ||
479 | sparc_irq_config.build_device_irq = sun4m_build_device_irq; | ||
480 | |||
470 | #ifdef CONFIG_SMP | 481 | #ifdef CONFIG_SMP |
471 | BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); | 482 | BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); |
472 | BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); | 483 | 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..594768686525 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
@@ -1,59 +1,25 @@ | |||
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 | ||
18 | #define IRQ_IPI_SINGLE 12 | ||
19 | #define IRQ_IPI_MASK 13 | ||
20 | #define IRQ_IPI_RESCHED 14 | ||
38 | #define IRQ_CROSS_CALL 15 | 21 | #define IRQ_CROSS_CALL 15 |
39 | 22 | ||
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 | 23 | static inline unsigned long |
58 | swap_ulong(volatile unsigned long *ptr, unsigned long val) | 24 | swap_ulong(volatile unsigned long *ptr, unsigned long val) |
59 | { | 25 | { |
@@ -63,8 +29,8 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) | |||
63 | return val; | 29 | return val; |
64 | } | 30 | } |
65 | 31 | ||
32 | static void smp4m_ipi_init(void); | ||
66 | static void smp_setup_percpu_timer(void); | 33 | static void smp_setup_percpu_timer(void); |
67 | extern void cpu_probe(void); | ||
68 | 34 | ||
69 | void __cpuinit smp4m_callin(void) | 35 | void __cpuinit smp4m_callin(void) |
70 | { | 36 | { |
@@ -96,8 +62,6 @@ void __cpuinit smp4m_callin(void) | |||
96 | /* XXX: What's up with all the flushes? */ | 62 | /* XXX: What's up with all the flushes? */ |
97 | local_flush_cache_all(); | 63 | local_flush_cache_all(); |
98 | local_flush_tlb_all(); | 64 | local_flush_tlb_all(); |
99 | |||
100 | cpu_probe(); | ||
101 | 65 | ||
102 | /* Fix idle thread fields. */ | 66 | /* Fix idle thread fields. */ |
103 | __asm__ __volatile__("ld [%0], %%g6\n\t" | 67 | __asm__ __volatile__("ld [%0], %%g6\n\t" |
@@ -108,7 +72,7 @@ void __cpuinit smp4m_callin(void) | |||
108 | atomic_inc(&init_mm.mm_count); | 72 | atomic_inc(&init_mm.mm_count); |
109 | current->active_mm = &init_mm; | 73 | current->active_mm = &init_mm; |
110 | 74 | ||
111 | while (!cpu_isset(cpuid, smp_commenced_mask)) | 75 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
112 | mb(); | 76 | mb(); |
113 | 77 | ||
114 | local_irq_enable(); | 78 | local_irq_enable(); |
@@ -119,18 +83,15 @@ void __cpuinit smp4m_callin(void) | |||
119 | /* | 83 | /* |
120 | * Cycle through the processors asking the PROM to start each one. | 84 | * Cycle through the processors asking the PROM to start each one. |
121 | */ | 85 | */ |
122 | |||
123 | extern struct linux_prom_registers smp_penguin_ctable; | ||
124 | |||
125 | void __init smp4m_boot_cpus(void) | 86 | void __init smp4m_boot_cpus(void) |
126 | { | 87 | { |
88 | smp4m_ipi_init(); | ||
127 | smp_setup_percpu_timer(); | 89 | smp_setup_percpu_timer(); |
128 | local_flush_cache_all(); | 90 | local_flush_cache_all(); |
129 | } | 91 | } |
130 | 92 | ||
131 | int __cpuinit smp4m_boot_one_cpu(int i) | 93 | int __cpuinit smp4m_boot_one_cpu(int i) |
132 | { | 94 | { |
133 | extern unsigned long sun4m_cpu_startup; | ||
134 | unsigned long *entry = &sun4m_cpu_startup; | 95 | unsigned long *entry = &sun4m_cpu_startup; |
135 | struct task_struct *p; | 96 | struct task_struct *p; |
136 | int timeout; | 97 | int timeout; |
@@ -142,7 +103,7 @@ int __cpuinit smp4m_boot_one_cpu(int i) | |||
142 | p = fork_idle(i); | 103 | p = fork_idle(i); |
143 | current_set[i] = task_thread_info(p); | 104 | current_set[i] = task_thread_info(p); |
144 | /* See trampoline.S for details... */ | 105 | /* See trampoline.S for details... */ |
145 | entry += ((i-1) * 3); | 106 | entry += ((i - 1) * 3); |
146 | 107 | ||
147 | /* | 108 | /* |
148 | * Initialize the contexts table | 109 | * Initialize the contexts table |
@@ -154,20 +115,19 @@ int __cpuinit smp4m_boot_one_cpu(int i) | |||
154 | smp_penguin_ctable.reg_size = 0; | 115 | smp_penguin_ctable.reg_size = 0; |
155 | 116 | ||
156 | /* whirrr, whirrr, whirrrrrrrrr... */ | 117 | /* whirrr, whirrr, whirrrrrrrrr... */ |
157 | printk("Starting CPU %d at %p\n", i, entry); | 118 | printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); |
158 | local_flush_cache_all(); | 119 | local_flush_cache_all(); |
159 | prom_startcpu(cpu_node, | 120 | prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); |
160 | &smp_penguin_ctable, 0, (char *)entry); | ||
161 | 121 | ||
162 | /* wheee... it's going... */ | 122 | /* wheee... it's going... */ |
163 | for(timeout = 0; timeout < 10000; timeout++) { | 123 | for (timeout = 0; timeout < 10000; timeout++) { |
164 | if(cpu_callin_map[i]) | 124 | if (cpu_callin_map[i]) |
165 | break; | 125 | break; |
166 | udelay(200); | 126 | udelay(200); |
167 | } | 127 | } |
168 | 128 | ||
169 | if (!(cpu_callin_map[i])) { | 129 | if (!(cpu_callin_map[i])) { |
170 | printk("Processor %d is stuck.\n", i); | 130 | printk(KERN_ERR "Processor %d is stuck.\n", i); |
171 | return -ENODEV; | 131 | return -ENODEV; |
172 | } | 132 | } |
173 | 133 | ||
@@ -193,17 +153,25 @@ void __init smp4m_smp_done(void) | |||
193 | /* Ok, they are spinning and ready to go. */ | 153 | /* Ok, they are spinning and ready to go. */ |
194 | } | 154 | } |
195 | 155 | ||
196 | /* At each hardware IRQ, we get this called to forward IRQ reception | 156 | |
197 | * to the next processor. The caller must disable the IRQ level being | 157 | /* Initialize IPIs on the SUN4M SMP machine */ |
198 | * serviced globally so that there are no double interrupts received. | 158 | static void __init smp4m_ipi_init(void) |
199 | * | ||
200 | * XXX See sparc64 irq.c. | ||
201 | */ | ||
202 | void smp4m_irq_rotate(int cpu) | ||
203 | { | 159 | { |
204 | int next = cpu_data(cpu).next; | 160 | } |
205 | if (next != cpu) | 161 | |
206 | set_irq_udt(next); | 162 | static void smp4m_ipi_resched(int cpu) |
163 | { | ||
164 | set_cpu_int(cpu, IRQ_IPI_RESCHED); | ||
165 | } | ||
166 | |||
167 | static void smp4m_ipi_single(int cpu) | ||
168 | { | ||
169 | set_cpu_int(cpu, IRQ_IPI_SINGLE); | ||
170 | } | ||
171 | |||
172 | static void smp4m_ipi_mask_one(int cpu) | ||
173 | { | ||
174 | set_cpu_int(cpu, IRQ_IPI_MASK); | ||
207 | } | 175 | } |
208 | 176 | ||
209 | static struct smp_funcall { | 177 | static struct smp_funcall { |
@@ -241,10 +209,10 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
241 | { | 209 | { |
242 | register int i; | 210 | register int i; |
243 | 211 | ||
244 | cpu_clear(smp_processor_id(), mask); | 212 | cpumask_clear_cpu(smp_processor_id(), &mask); |
245 | cpus_and(mask, cpu_online_map, mask); | 213 | cpumask_and(&mask, cpu_online_mask, &mask); |
246 | for(i = 0; i < ncpus; i++) { | 214 | for (i = 0; i < ncpus; i++) { |
247 | if (cpu_isset(i, mask)) { | 215 | if (cpumask_test_cpu(i, &mask)) { |
248 | ccall_info.processors_in[i] = 0; | 216 | ccall_info.processors_in[i] = 0; |
249 | ccall_info.processors_out[i] = 0; | 217 | ccall_info.processors_out[i] = 0; |
250 | set_cpu_int(i, IRQ_CROSS_CALL); | 218 | set_cpu_int(i, IRQ_CROSS_CALL); |
@@ -260,21 +228,20 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | |||
260 | 228 | ||
261 | i = 0; | 229 | i = 0; |
262 | do { | 230 | do { |
263 | if (!cpu_isset(i, mask)) | 231 | if (!cpumask_test_cpu(i, &mask)) |
264 | continue; | 232 | continue; |
265 | while(!ccall_info.processors_in[i]) | 233 | while (!ccall_info.processors_in[i]) |
266 | barrier(); | 234 | barrier(); |
267 | } while(++i < ncpus); | 235 | } while (++i < ncpus); |
268 | 236 | ||
269 | i = 0; | 237 | i = 0; |
270 | do { | 238 | do { |
271 | if (!cpu_isset(i, mask)) | 239 | if (!cpumask_test_cpu(i, &mask)) |
272 | continue; | 240 | continue; |
273 | while(!ccall_info.processors_out[i]) | 241 | while (!ccall_info.processors_out[i]) |
274 | barrier(); | 242 | barrier(); |
275 | } while(++i < ncpus); | 243 | } while (++i < ncpus); |
276 | } | 244 | } |
277 | |||
278 | spin_unlock_irqrestore(&cross_call_lock, flags); | 245 | spin_unlock_irqrestore(&cross_call_lock, flags); |
279 | } | 246 | } |
280 | 247 | ||
@@ -289,8 +256,6 @@ void smp4m_cross_call_irq(void) | |||
289 | ccall_info.processors_out[i] = 1; | 256 | ccall_info.processors_out[i] = 1; |
290 | } | 257 | } |
291 | 258 | ||
292 | extern void sun4m_clear_profile_irq(int cpu); | ||
293 | |||
294 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | 259 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) |
295 | { | 260 | { |
296 | struct pt_regs *old_regs; | 261 | struct pt_regs *old_regs; |
@@ -302,7 +267,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
302 | 267 | ||
303 | profile_tick(CPU_PROFILING); | 268 | profile_tick(CPU_PROFILING); |
304 | 269 | ||
305 | if(!--prof_counter(cpu)) { | 270 | if (!--prof_counter(cpu)) { |
306 | int user = user_mode(regs); | 271 | int user = user_mode(regs); |
307 | 272 | ||
308 | irq_enter(); | 273 | irq_enter(); |
@@ -314,8 +279,6 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
314 | set_irq_regs(old_regs); | 279 | set_irq_regs(old_regs); |
315 | } | 280 | } |
316 | 281 | ||
317 | extern unsigned int lvl14_resolution; | ||
318 | |||
319 | static void __cpuinit smp_setup_percpu_timer(void) | 282 | static void __cpuinit smp_setup_percpu_timer(void) |
320 | { | 283 | { |
321 | int cpu = smp_processor_id(); | 284 | int cpu = smp_processor_id(); |
@@ -323,17 +286,17 @@ static void __cpuinit smp_setup_percpu_timer(void) | |||
323 | prof_counter(cpu) = prof_multiplier(cpu) = 1; | 286 | prof_counter(cpu) = prof_multiplier(cpu) = 1; |
324 | load_profile_irq(cpu, lvl14_resolution); | 287 | load_profile_irq(cpu, lvl14_resolution); |
325 | 288 | ||
326 | if(cpu == boot_cpu_id) | 289 | if (cpu == boot_cpu_id) |
327 | enable_pil_irq(14); | 290 | sun4m_unmask_profile_irq(); |
328 | } | 291 | } |
329 | 292 | ||
330 | static void __init smp4m_blackbox_id(unsigned *addr) | 293 | static void __init smp4m_blackbox_id(unsigned *addr) |
331 | { | 294 | { |
332 | int rd = *addr & 0x3e000000; | 295 | int rd = *addr & 0x3e000000; |
333 | int rs1 = rd >> 11; | 296 | int rs1 = rd >> 11; |
334 | 297 | ||
335 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ | 298 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ |
336 | addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */ | 299 | addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */ |
337 | addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */ | 300 | addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */ |
338 | } | 301 | } |
339 | 302 | ||
@@ -341,9 +304,9 @@ static void __init smp4m_blackbox_current(unsigned *addr) | |||
341 | { | 304 | { |
342 | int rd = *addr & 0x3e000000; | 305 | int rd = *addr & 0x3e000000; |
343 | int rs1 = rd >> 11; | 306 | int rs1 = rd >> 11; |
344 | 307 | ||
345 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ | 308 | addr[0] = 0x81580000 | rd; /* rd %tbr, reg */ |
346 | addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */ | 309 | addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */ |
347 | addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */ | 310 | addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */ |
348 | } | 311 | } |
349 | 312 | ||
@@ -353,4 +316,7 @@ void __init sun4m_init_smp(void) | |||
353 | BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); | 316 | BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current); |
354 | BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); | 317 | BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM); |
355 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); | 318 | BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM); |
319 | BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM); | ||
320 | BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM); | ||
321 | BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM); | ||
356 | } | 322 | } |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index e6375a750d9a..170cd8e8eb2a 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/resource.h> | 17 | #include <linux/resource.h> |
18 | #include <linux/times.h> | 18 | #include <linux/times.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/sem.h> | 20 | #include <linux/sem.h> |
22 | #include <linux/msg.h> | 21 | #include <linux/msg.h> |
23 | #include <linux/shm.h> | 22 | #include <linux/shm.h> |
@@ -110,7 +109,7 @@ asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compa | |||
110 | 109 | ||
111 | default: | 110 | default: |
112 | return -ENOSYS; | 111 | return -ENOSYS; |
113 | }; | 112 | } |
114 | 113 | ||
115 | return -ENOSYS; | 114 | return -ENOSYS; |
116 | } | 115 | } |
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 675c9e11ada5..42b282fa6112 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/mman.h> | 19 | #include <linux/mman.h> |
20 | #include <linux/utsname.h> | 20 | #include <linux/utsname.h> |
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/ipc.h> | 22 | #include <linux/ipc.h> |
24 | 23 | ||
25 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index f836f4e93afe..908b47a5ee24 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 |
@@ -455,7 +460,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second | |||
455 | default: | 460 | default: |
456 | err = -ENOSYS; | 461 | err = -ENOSYS; |
457 | goto out; | 462 | goto out; |
458 | }; | 463 | } |
459 | } | 464 | } |
460 | if (call <= MSGCTL) { | 465 | if (call <= MSGCTL) { |
461 | switch (call) { | 466 | switch (call) { |
@@ -476,7 +481,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second | |||
476 | default: | 481 | default: |
477 | err = -ENOSYS; | 482 | err = -ENOSYS; |
478 | goto out; | 483 | goto out; |
479 | }; | 484 | } |
480 | } | 485 | } |
481 | if (call <= SHMCTL) { | 486 | if (call <= SHMCTL) { |
482 | switch (call) { | 487 | switch (call) { |
@@ -502,7 +507,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second | |||
502 | default: | 507 | default: |
503 | err = -ENOSYS; | 508 | err = -ENOSYS; |
504 | goto out; | 509 | goto out; |
505 | }; | 510 | } |
506 | } else { | 511 | } else { |
507 | err = -ENOSYS; | 512 | err = -ENOSYS; |
508 | } | 513 | } |
diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index 1eb8b00aed75..7408201d7efb 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c | |||
@@ -103,9 +103,10 @@ static unsigned long run_on_cpu(unsigned long cpu, | |||
103 | unsigned long (*func)(unsigned long), | 103 | unsigned long (*func)(unsigned long), |
104 | unsigned long arg) | 104 | unsigned long arg) |
105 | { | 105 | { |
106 | cpumask_t old_affinity = current->cpus_allowed; | 106 | cpumask_t old_affinity; |
107 | unsigned long ret; | 107 | unsigned long ret; |
108 | 108 | ||
109 | cpumask_copy(&old_affinity, tsk_cpus_allowed(current)); | ||
109 | /* should return -EINVAL to userspace */ | 110 | /* should return -EINVAL to userspace */ |
110 | if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) | 111 | if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) |
111 | return 0; | 112 | return 0; |
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index ec396e1916b9..6e492d59f6b1 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S | |||
@@ -83,5 +83,5 @@ sys_call_table: | |||
83 | /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 | 83 | /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 |
84 | /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv | 84 | /*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv |
85 | /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init | 85 | /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init |
86 | /*330*/ .long sys_fanotify_mark, sys_prlimit64 | 86 | /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime |
87 | 87 | /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns | |
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 8cfcaa549580..f566518483b5 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S | |||
@@ -84,7 +84,8 @@ sys_call_table32: | |||
84 | .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 | 84 | .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 |
85 | /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv | 85 | /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv |
86 | .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init | 86 | .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init |
87 | /*330*/ .word sys32_fanotify_mark, sys_prlimit64 | 87 | /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime |
88 | .word sys_syncfs, compat_sys_sendmmsg, sys_setns | ||
88 | 89 | ||
89 | #endif /* CONFIG_COMPAT */ | 90 | #endif /* CONFIG_COMPAT */ |
90 | 91 | ||
@@ -160,4 +161,5 @@ sys_call_table: | |||
160 | .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 | 161 | .word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1 |
161 | /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv | 162 | /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv |
162 | .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init | 163 | .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init |
163 | /*330*/ .word sys_fanotify_mark, sys_prlimit64 | 164 | /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime |
165 | .word sys_syncfs, sys_sendmmsg, sys_setns | ||
diff --git a/arch/sparc/kernel/tadpole.c b/arch/sparc/kernel/tadpole.c index f476a5f4af6a..9aba8bd5a78b 100644 --- a/arch/sparc/kernel/tadpole.c +++ b/arch/sparc/kernel/tadpole.c | |||
@@ -100,7 +100,7 @@ static void swift_clockstop(void) | |||
100 | 100 | ||
101 | void __init clock_stop_probe(void) | 101 | void __init clock_stop_probe(void) |
102 | { | 102 | { |
103 | unsigned int node, clk_nd; | 103 | phandle node, clk_nd; |
104 | char name[20]; | 104 | char name[20]; |
105 | 105 | ||
106 | prom_getstring(prom_root_node, "name", name, sizeof(name)); | 106 | prom_getstring(prom_root_node, "name", name, sizeof(name)); |
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 9c743b1886ff..1060e0672a4b 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c | |||
@@ -85,7 +85,7 @@ int update_persistent_clock(struct timespec now) | |||
85 | 85 | ||
86 | /* | 86 | /* |
87 | * timer_interrupt() needs to keep up the real-time clock, | 87 | * timer_interrupt() needs to keep up the real-time clock, |
88 | * as well as call the "do_timer()" routine every clocktick | 88 | * as well as call the "xtime_update()" routine every clocktick |
89 | */ | 89 | */ |
90 | 90 | ||
91 | #define TICK_SIZE (tick_nsec / 1000) | 91 | #define TICK_SIZE (tick_nsec / 1000) |
@@ -96,14 +96,9 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) | |||
96 | profile_tick(CPU_PROFILING); | 96 | profile_tick(CPU_PROFILING); |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | /* Protect counter clear so that do_gettimeoffset works */ | ||
100 | write_seqlock(&xtime_lock); | ||
101 | |||
102 | clear_clock_irq(); | 99 | clear_clock_irq(); |
103 | 100 | ||
104 | do_timer(1); | 101 | xtime_update(1); |
105 | |||
106 | write_sequnlock(&xtime_lock); | ||
107 | 102 | ||
108 | #ifndef CONFIG_SMP | 103 | #ifndef CONFIG_SMP |
109 | update_process_times(user_mode(get_irq_regs())); | 104 | update_process_times(user_mode(get_irq_regs())); |
@@ -142,7 +137,7 @@ static struct platform_device m48t59_rtc = { | |||
142 | }, | 137 | }, |
143 | }; | 138 | }; |
144 | 139 | ||
145 | static int __devinit clock_probe(struct platform_device *op, const struct of_device_id *match) | 140 | static int __devinit clock_probe(struct platform_device *op) |
146 | { | 141 | { |
147 | struct device_node *dp = op->dev.of_node; | 142 | struct device_node *dp = op->dev.of_node; |
148 | const char *model = of_get_property(dp, "model", NULL); | 143 | const char *model = of_get_property(dp, "model", NULL); |
@@ -150,6 +145,10 @@ static int __devinit clock_probe(struct platform_device *op, const struct of_dev | |||
150 | if (!model) | 145 | if (!model) |
151 | return -ENODEV; | 146 | return -ENODEV; |
152 | 147 | ||
148 | /* Only the primary RTC has an address property */ | ||
149 | if (!of_find_property(dp, "address", NULL)) | ||
150 | return -ENODEV; | ||
151 | |||
153 | m48t59_rtc.resource = &op->resource[0]; | 152 | m48t59_rtc.resource = &op->resource[0]; |
154 | if (!strcmp(model, "mk48t02")) { | 153 | if (!strcmp(model, "mk48t02")) { |
155 | /* Map the clock register io area read-only */ | 154 | /* Map the clock register io area read-only */ |
@@ -169,14 +168,14 @@ static int __devinit clock_probe(struct platform_device *op, const struct of_dev | |||
169 | return 0; | 168 | return 0; |
170 | } | 169 | } |
171 | 170 | ||
172 | static struct of_device_id __initdata clock_match[] = { | 171 | static struct of_device_id clock_match[] = { |
173 | { | 172 | { |
174 | .name = "eeprom", | 173 | .name = "eeprom", |
175 | }, | 174 | }, |
176 | {}, | 175 | {}, |
177 | }; | 176 | }; |
178 | 177 | ||
179 | static struct of_platform_driver clock_driver = { | 178 | static struct platform_driver clock_driver = { |
180 | .probe = clock_probe, | 179 | .probe = clock_probe, |
181 | .driver = { | 180 | .driver = { |
182 | .name = "rtc", | 181 | .name = "rtc", |
@@ -189,7 +188,7 @@ static struct of_platform_driver clock_driver = { | |||
189 | /* Probe for the mostek real time clock chip. */ | 188 | /* Probe for the mostek real time clock chip. */ |
190 | static int __init clock_init(void) | 189 | static int __init clock_init(void) |
191 | { | 190 | { |
192 | return of_register_platform_driver(&clock_driver); | 191 | return platform_driver_register(&clock_driver); |
193 | } | 192 | } |
194 | /* Must be after subsys_initcall() so that busses are probed. Must | 193 | /* Must be after subsys_initcall() so that busses are probed. Must |
195 | * be before device_initcall() because things like the RTC driver | 194 | * be before device_initcall() because things like the RTC driver |
@@ -224,19 +223,15 @@ static void __init sbus_time_init(void) | |||
224 | 223 | ||
225 | btfixup(); | 224 | btfixup(); |
226 | 225 | ||
227 | sparc_init_timers(timer_interrupt); | 226 | sparc_irq_config.init_timers(timer_interrupt); |
228 | } | 227 | } |
229 | 228 | ||
230 | void __init time_init(void) | 229 | void __init time_init(void) |
231 | { | 230 | { |
232 | #ifdef CONFIG_PCI | 231 | if (pcic_present()) |
233 | extern void pci_time_init(void); | ||
234 | if (pcic_present()) { | ||
235 | pci_time_init(); | 232 | pci_time_init(); |
236 | return; | 233 | else |
237 | } | 234 | sbus_time_init(); |
238 | #endif | ||
239 | sbus_time_init(); | ||
240 | } | 235 | } |
241 | 236 | ||
242 | 237 | ||
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 3bc9c9979b92..1db6b18964d2 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -419,7 +419,7 @@ static struct platform_device rtc_cmos_device = { | |||
419 | .num_resources = 1, | 419 | .num_resources = 1, |
420 | }; | 420 | }; |
421 | 421 | ||
422 | static int __devinit rtc_probe(struct platform_device *op, const struct of_device_id *match) | 422 | static int __devinit rtc_probe(struct platform_device *op) |
423 | { | 423 | { |
424 | struct resource *r; | 424 | struct resource *r; |
425 | 425 | ||
@@ -442,7 +442,7 @@ static int __devinit rtc_probe(struct platform_device *op, const struct of_devic | |||
442 | return platform_device_register(&rtc_cmos_device); | 442 | return platform_device_register(&rtc_cmos_device); |
443 | } | 443 | } |
444 | 444 | ||
445 | static struct of_device_id __initdata rtc_match[] = { | 445 | static const struct of_device_id rtc_match[] = { |
446 | { | 446 | { |
447 | .name = "rtc", | 447 | .name = "rtc", |
448 | .compatible = "m5819", | 448 | .compatible = "m5819", |
@@ -462,7 +462,7 @@ static struct of_device_id __initdata rtc_match[] = { | |||
462 | {}, | 462 | {}, |
463 | }; | 463 | }; |
464 | 464 | ||
465 | static struct of_platform_driver rtc_driver = { | 465 | static struct platform_driver rtc_driver = { |
466 | .probe = rtc_probe, | 466 | .probe = rtc_probe, |
467 | .driver = { | 467 | .driver = { |
468 | .name = "rtc", | 468 | .name = "rtc", |
@@ -477,7 +477,7 @@ static struct platform_device rtc_bq4802_device = { | |||
477 | .num_resources = 1, | 477 | .num_resources = 1, |
478 | }; | 478 | }; |
479 | 479 | ||
480 | static int __devinit bq4802_probe(struct platform_device *op, const struct of_device_id *match) | 480 | static int __devinit bq4802_probe(struct platform_device *op) |
481 | { | 481 | { |
482 | 482 | ||
483 | printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n", | 483 | printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n", |
@@ -487,7 +487,7 @@ static int __devinit bq4802_probe(struct platform_device *op, const struct of_de | |||
487 | return platform_device_register(&rtc_bq4802_device); | 487 | return platform_device_register(&rtc_bq4802_device); |
488 | } | 488 | } |
489 | 489 | ||
490 | static struct of_device_id __initdata bq4802_match[] = { | 490 | static const struct of_device_id bq4802_match[] = { |
491 | { | 491 | { |
492 | .name = "rtc", | 492 | .name = "rtc", |
493 | .compatible = "bq4802", | 493 | .compatible = "bq4802", |
@@ -495,7 +495,7 @@ static struct of_device_id __initdata bq4802_match[] = { | |||
495 | {}, | 495 | {}, |
496 | }; | 496 | }; |
497 | 497 | ||
498 | static struct of_platform_driver bq4802_driver = { | 498 | static struct platform_driver bq4802_driver = { |
499 | .probe = bq4802_probe, | 499 | .probe = bq4802_probe, |
500 | .driver = { | 500 | .driver = { |
501 | .name = "bq4802", | 501 | .name = "bq4802", |
@@ -534,7 +534,7 @@ static struct platform_device m48t59_rtc = { | |||
534 | }, | 534 | }, |
535 | }; | 535 | }; |
536 | 536 | ||
537 | static int __devinit mostek_probe(struct platform_device *op, const struct of_device_id *match) | 537 | static int __devinit mostek_probe(struct platform_device *op) |
538 | { | 538 | { |
539 | struct device_node *dp = op->dev.of_node; | 539 | struct device_node *dp = op->dev.of_node; |
540 | 540 | ||
@@ -552,14 +552,14 @@ static int __devinit mostek_probe(struct platform_device *op, const struct of_de | |||
552 | return platform_device_register(&m48t59_rtc); | 552 | return platform_device_register(&m48t59_rtc); |
553 | } | 553 | } |
554 | 554 | ||
555 | static struct of_device_id __initdata mostek_match[] = { | 555 | static const struct of_device_id mostek_match[] = { |
556 | { | 556 | { |
557 | .name = "eeprom", | 557 | .name = "eeprom", |
558 | }, | 558 | }, |
559 | {}, | 559 | {}, |
560 | }; | 560 | }; |
561 | 561 | ||
562 | static struct of_platform_driver mostek_driver = { | 562 | static struct platform_driver mostek_driver = { |
563 | .probe = mostek_probe, | 563 | .probe = mostek_probe, |
564 | .driver = { | 564 | .driver = { |
565 | .name = "mostek", | 565 | .name = "mostek", |
@@ -586,9 +586,9 @@ static int __init clock_init(void) | |||
586 | if (tlb_type == hypervisor) | 586 | if (tlb_type == hypervisor) |
587 | return platform_device_register(&rtc_sun4v_device); | 587 | return platform_device_register(&rtc_sun4v_device); |
588 | 588 | ||
589 | (void) of_register_platform_driver(&rtc_driver); | 589 | (void) platform_driver_register(&rtc_driver); |
590 | (void) of_register_platform_driver(&mostek_driver); | 590 | (void) platform_driver_register(&mostek_driver); |
591 | (void) of_register_platform_driver(&bq4802_driver); | 591 | (void) platform_driver_register(&bq4802_driver); |
592 | 592 | ||
593 | return 0; | 593 | return 0; |
594 | } | 594 | } |
@@ -708,7 +708,7 @@ static void sparc64_timer_setup(enum clock_event_mode mode, | |||
708 | case CLOCK_EVT_MODE_UNUSED: | 708 | case CLOCK_EVT_MODE_UNUSED: |
709 | WARN_ON(1); | 709 | WARN_ON(1); |
710 | break; | 710 | break; |
711 | }; | 711 | } |
712 | } | 712 | } |
713 | 713 | ||
714 | static struct clock_event_device sparc64_clockevent = { | 714 | static struct clock_event_device sparc64_clockevent = { |
@@ -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 42ad2ba85010..0cbdaa41cd1e 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -622,7 +622,7 @@ static const char CHAFSR_PERR_msg[] = | |||
622 | static const char CHAFSR_IERR_msg[] = | 622 | static const char CHAFSR_IERR_msg[] = |
623 | "Internal processor error"; | 623 | "Internal processor error"; |
624 | static const char CHAFSR_ISAP_msg[] = | 624 | static const char CHAFSR_ISAP_msg[] = |
625 | "System request parity error on incoming addresss"; | 625 | "System request parity error on incoming address"; |
626 | static const char CHAFSR_UCU_msg[] = | 626 | static const char CHAFSR_UCU_msg[] = |
627 | "Uncorrectable E-cache ECC error for ifetch/data"; | 627 | "Uncorrectable E-cache ECC error for ifetch/data"; |
628 | static const char CHAFSR_UCC_msg[] = | 628 | static const char CHAFSR_UCC_msg[] = |
@@ -1804,7 +1804,7 @@ static const char *sun4v_err_type_to_str(u32 type) | |||
1804 | return "warning resumable"; | 1804 | return "warning resumable"; |
1805 | default: | 1805 | default: |
1806 | return "unknown"; | 1806 | return "unknown"; |
1807 | }; | 1807 | } |
1808 | } | 1808 | } |
1809 | 1809 | ||
1810 | static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) | 1810 | static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) |
@@ -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_32.S b/arch/sparc/kernel/una_asm_32.S index 8cc03458eb7e..8f096e84a937 100644 --- a/arch/sparc/kernel/una_asm_32.S +++ b/arch/sparc/kernel/una_asm_32.S | |||
@@ -24,9 +24,9 @@ retl_efault: | |||
24 | .globl __do_int_store | 24 | .globl __do_int_store |
25 | __do_int_store: | 25 | __do_int_store: |
26 | ld [%o2], %g1 | 26 | ld [%o2], %g1 |
27 | cmp %1, 2 | 27 | cmp %o1, 2 |
28 | be 2f | 28 | be 2f |
29 | cmp %1, 4 | 29 | cmp %o1, 4 |
30 | be 1f | 30 | be 1f |
31 | srl %g1, 24, %g2 | 31 | srl %g1, 24, %g2 |
32 | srl %g1, 16, %g7 | 32 | srl %g1, 16, %g7 |
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/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c index 12b9f352595f..4491f4cb2695 100644 --- a/arch/sparc/kernel/unaligned_32.c +++ b/arch/sparc/kernel/unaligned_32.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/perf_event.h> | 19 | #include <linux/perf_event.h> |
21 | 20 | ||
22 | enum direction { | 21 | enum direction { |
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index c752c4c479bd..b2b019ea8caa 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c | |||
@@ -211,7 +211,7 @@ static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr, | |||
211 | default: | 211 | default: |
212 | BUG(); | 212 | BUG(); |
213 | break; | 213 | break; |
214 | }; | 214 | } |
215 | } | 215 | } |
216 | return __do_int_store(dst_addr, size, src_val, asi); | 216 | return __do_int_store(dst_addr, size, src_val, asi); |
217 | } | 217 | } |
@@ -328,7 +328,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
328 | case ASI_SNFL: | 328 | case ASI_SNFL: |
329 | asi &= ~0x08; | 329 | asi &= ~0x08; |
330 | break; | 330 | break; |
331 | }; | 331 | } |
332 | switch (dir) { | 332 | switch (dir) { |
333 | case load: | 333 | case load: |
334 | reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); | 334 | reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); |
@@ -351,7 +351,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) | |||
351 | default: | 351 | default: |
352 | BUG(); | 352 | BUG(); |
353 | break; | 353 | break; |
354 | }; | 354 | } |
355 | *reg_addr = val_in; | 355 | *reg_addr = val_in; |
356 | } | 356 | } |
357 | break; | 357 | break; |
diff --git a/arch/sparc/kernel/us2e_cpufreq.c b/arch/sparc/kernel/us2e_cpufreq.c index 8f982b76c712..489fc15f3194 100644 --- a/arch/sparc/kernel/us2e_cpufreq.c +++ b/arch/sparc/kernel/us2e_cpufreq.c | |||
@@ -176,7 +176,7 @@ static unsigned long index_to_estar_mode(unsigned int index) | |||
176 | 176 | ||
177 | default: | 177 | default: |
178 | BUG(); | 178 | BUG(); |
179 | }; | 179 | } |
180 | } | 180 | } |
181 | 181 | ||
182 | static unsigned long index_to_divisor(unsigned int index) | 182 | static unsigned long index_to_divisor(unsigned int index) |
@@ -199,7 +199,7 @@ static unsigned long index_to_divisor(unsigned int index) | |||
199 | 199 | ||
200 | default: | 200 | default: |
201 | BUG(); | 201 | BUG(); |
202 | }; | 202 | } |
203 | } | 203 | } |
204 | 204 | ||
205 | static unsigned long estar_to_divisor(unsigned long estar) | 205 | static unsigned long estar_to_divisor(unsigned long estar) |
@@ -224,7 +224,7 @@ static unsigned long estar_to_divisor(unsigned long estar) | |||
224 | break; | 224 | break; |
225 | default: | 225 | default: |
226 | BUG(); | 226 | BUG(); |
227 | }; | 227 | } |
228 | 228 | ||
229 | return ret; | 229 | return ret; |
230 | } | 230 | } |
@@ -237,7 +237,7 @@ static unsigned int us2e_freq_get(unsigned int cpu) | |||
237 | if (!cpu_online(cpu)) | 237 | if (!cpu_online(cpu)) |
238 | return 0; | 238 | return 0; |
239 | 239 | ||
240 | cpus_allowed = current->cpus_allowed; | 240 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); |
241 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | 241 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
242 | 242 | ||
243 | clock_tick = sparc64_get_clock_tick(cpu) / 1000; | 243 | clock_tick = sparc64_get_clock_tick(cpu) / 1000; |
@@ -258,7 +258,7 @@ static void us2e_set_cpu_divider_index(unsigned int cpu, unsigned int index) | |||
258 | if (!cpu_online(cpu)) | 258 | if (!cpu_online(cpu)) |
259 | return; | 259 | return; |
260 | 260 | ||
261 | cpus_allowed = current->cpus_allowed; | 261 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); |
262 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | 262 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
263 | 263 | ||
264 | new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000; | 264 | new_freq = clock_tick = sparc64_get_clock_tick(cpu) / 1000; |
diff --git a/arch/sparc/kernel/us3_cpufreq.c b/arch/sparc/kernel/us3_cpufreq.c index f35d1e794548..eb1624b931d9 100644 --- a/arch/sparc/kernel/us3_cpufreq.c +++ b/arch/sparc/kernel/us3_cpufreq.c | |||
@@ -71,7 +71,7 @@ static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg | |||
71 | break; | 71 | break; |
72 | default: | 72 | default: |
73 | BUG(); | 73 | BUG(); |
74 | }; | 74 | } |
75 | 75 | ||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
@@ -85,7 +85,7 @@ static unsigned int us3_freq_get(unsigned int cpu) | |||
85 | if (!cpu_online(cpu)) | 85 | if (!cpu_online(cpu)) |
86 | return 0; | 86 | return 0; |
87 | 87 | ||
88 | cpus_allowed = current->cpus_allowed; | 88 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); |
89 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | 89 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
90 | 90 | ||
91 | reg = read_safari_cfg(); | 91 | reg = read_safari_cfg(); |
@@ -105,7 +105,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) | |||
105 | if (!cpu_online(cpu)) | 105 | if (!cpu_online(cpu)) |
106 | return; | 106 | return; |
107 | 107 | ||
108 | cpus_allowed = current->cpus_allowed; | 108 | cpumask_copy(&cpus_allowed, tsk_cpus_allowed(current)); |
109 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); | 109 | set_cpus_allowed_ptr(current, cpumask_of(cpu)); |
110 | 110 | ||
111 | new_freq = sparc64_get_clock_tick(cpu) / 1000; | 111 | new_freq = sparc64_get_clock_tick(cpu) / 1000; |
@@ -125,7 +125,7 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) | |||
125 | 125 | ||
126 | default: | 126 | default: |
127 | BUG(); | 127 | BUG(); |
128 | }; | 128 | } |
129 | 129 | ||
130 | reg = read_safari_cfg(); | 130 | reg = read_safari_cfg(); |
131 | 131 | ||
diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c index aa6ac70d4fd5..29348ea139c3 100644 --- a/arch/sparc/kernel/viohs.c +++ b/arch/sparc/kernel/viohs.c | |||
@@ -363,7 +363,7 @@ static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt) | |||
363 | 363 | ||
364 | default: | 364 | default: |
365 | return handshake_failure(vio); | 365 | return handshake_failure(vio); |
366 | }; | 366 | } |
367 | } | 367 | } |
368 | 368 | ||
369 | static int process_attr(struct vio_driver_state *vio, void *pkt) | 369 | static int process_attr(struct vio_driver_state *vio, void *pkt) |
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index 9dfd2ebcb157..36357717d691 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c | |||
@@ -334,7 +334,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
334 | left = edge32_tab_l[(rs1 >> 2) & 0x1].left; | 334 | left = edge32_tab_l[(rs1 >> 2) & 0x1].left; |
335 | right = edge32_tab_l[(rs2 >> 2) & 0x1].right; | 335 | right = edge32_tab_l[(rs2 >> 2) & 0x1].right; |
336 | break; | 336 | break; |
337 | }; | 337 | } |
338 | 338 | ||
339 | if ((rs1 & ~0x7UL) == (rs2 & ~0x7UL)) | 339 | if ((rs1 & ~0x7UL) == (rs2 & ~0x7UL)) |
340 | rd_val = right & left; | 340 | rd_val = right & left; |
@@ -360,7 +360,7 @@ static void edge(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
360 | tstate = regs->tstate & ~(TSTATE_XCC | TSTATE_ICC); | 360 | tstate = regs->tstate & ~(TSTATE_XCC | TSTATE_ICC); |
361 | regs->tstate = tstate | (ccr << 32UL); | 361 | regs->tstate = tstate | (ccr << 32UL); |
362 | } | 362 | } |
363 | }; | 363 | } |
364 | } | 364 | } |
365 | 365 | ||
366 | static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf) | 366 | static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf) |
@@ -392,7 +392,7 @@ static void array(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
392 | 392 | ||
393 | case ARRAY32_OPF: | 393 | case ARRAY32_OPF: |
394 | rd_val <<= 2; | 394 | rd_val <<= 2; |
395 | }; | 395 | } |
396 | 396 | ||
397 | store_reg(regs, rd_val, RD(insn)); | 397 | store_reg(regs, rd_val, RD(insn)); |
398 | } | 398 | } |
@@ -577,7 +577,7 @@ static void pformat(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
577 | *fpd_regaddr(f, RD(insn)) = rd_val; | 577 | *fpd_regaddr(f, RD(insn)) = rd_val; |
578 | break; | 578 | break; |
579 | } | 579 | } |
580 | }; | 580 | } |
581 | } | 581 | } |
582 | 582 | ||
583 | static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf) | 583 | static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf) |
@@ -693,7 +693,7 @@ static void pmul(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
693 | *fpd_regaddr(f, RD(insn)) = rd_val; | 693 | *fpd_regaddr(f, RD(insn)) = rd_val; |
694 | break; | 694 | break; |
695 | } | 695 | } |
696 | }; | 696 | } |
697 | } | 697 | } |
698 | 698 | ||
699 | static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf) | 699 | static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf) |
@@ -786,7 +786,7 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf) | |||
786 | rd_val |= 1 << i; | 786 | rd_val |= 1 << i; |
787 | } | 787 | } |
788 | break; | 788 | break; |
789 | }; | 789 | } |
790 | 790 | ||
791 | maybe_flush_windows(0, 0, RD(insn), 0); | 791 | maybe_flush_windows(0, 0, RD(insn), 0); |
792 | store_reg(regs, rd_val, RD(insn)); | 792 | store_reg(regs, rd_val, RD(insn)); |
@@ -885,7 +885,7 @@ int vis_emul(struct pt_regs *regs, unsigned int insn) | |||
885 | case BSHUFFLE_OPF: | 885 | case BSHUFFLE_OPF: |
886 | bshuffle(regs, insn); | 886 | bshuffle(regs, insn); |
887 | break; | 887 | break; |
888 | }; | 888 | } |
889 | 889 | ||
890 | regs->tpc = regs->tnpc; | 890 | regs->tpc = regs->tnpc; |
891 | regs->tnpc += 4; | 891 | regs->tnpc += 4; |
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 0c1e6783657f..c0220759003e 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S | |||
@@ -108,7 +108,7 @@ SECTIONS | |||
108 | __sun4v_2insn_patch_end = .; | 108 | __sun4v_2insn_patch_end = .; |
109 | } | 109 | } |
110 | 110 | ||
111 | PERCPU(PAGE_SIZE) | 111 | PERCPU_SECTION(SMP_CACHE_BYTES) |
112 | 112 | ||
113 | . = ALIGN(PAGE_SIZE); | 113 | . = ALIGN(PAGE_SIZE); |
114 | __init_end = .; | 114 | __init_end = .; |
diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c index b351770cbdd6..3107381e576d 100644 --- a/arch/sparc/kernel/windows.c +++ b/arch/sparc/kernel/windows.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/smp.h> | 11 | #include <linux/smp.h> |
12 | #include <linux/smp_lock.h> | ||
13 | 12 | ||
14 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
15 | 14 | ||
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 846d1c4374ea..7f01b8fce8bc 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
@@ -15,7 +15,6 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o | |||
15 | lib-$(CONFIG_SPARC32) += copy_user.o locks.o | 15 | lib-$(CONFIG_SPARC32) += copy_user.o locks.o |
16 | lib-y += atomic_$(BITS).o | 16 | lib-y += atomic_$(BITS).o |
17 | lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o | 17 | lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o |
18 | lib-$(CONFIG_SPARC32) += rwsem_32.o | ||
19 | lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o | 18 | lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o |
20 | 19 | ||
21 | lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o | 20 | lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o |
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index cbddeb38ffda..d3c7a12ad879 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #define ATOMIC_HASH(a) (&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)]) | 16 | #define ATOMIC_HASH(a) (&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)]) |
17 | 17 | ||
18 | spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { | 18 | spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { |
19 | [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED | 19 | [0 ... (ATOMIC_HASH_SIZE-1)] = __SPIN_LOCK_UNLOCKED(__atomic_hash) |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #else /* SMP */ | 22 | #else /* SMP */ |
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c index 764b3eb7b604..48d00e72ce15 100644 --- a/arch/sparc/lib/bitext.c +++ b/arch/sparc/lib/bitext.c | |||
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/string.h> | 12 | #include <linux/string.h> |
13 | #include <linux/bitops.h> | 13 | #include <linux/bitmap.h> |
14 | 14 | ||
15 | #include <asm/bitext.h> | 15 | #include <asm/bitext.h> |
16 | 16 | ||
@@ -80,8 +80,7 @@ int bit_map_string_get(struct bit_map *t, int len, int align) | |||
80 | while (test_bit(offset + i, t->map) == 0) { | 80 | while (test_bit(offset + i, t->map) == 0) { |
81 | i++; | 81 | i++; |
82 | if (i == len) { | 82 | if (i == len) { |
83 | for (i = 0; i < len; i++) | 83 | bitmap_set(t->map, offset, len); |
84 | __set_bit(offset + i, t->map); | ||
85 | if (offset == t->first_free) | 84 | if (offset == t->first_free) |
86 | t->first_free = find_next_zero_bit | 85 | t->first_free = find_next_zero_bit |
87 | (t->map, t->size, | 86 | (t->map, t->size, |
diff --git a/arch/sparc/lib/checksum_32.S b/arch/sparc/lib/checksum_32.S index 3632cb34e914..0084c3361e15 100644 --- a/arch/sparc/lib/checksum_32.S +++ b/arch/sparc/lib/checksum_32.S | |||
@@ -289,10 +289,16 @@ cc_end_cruft: | |||
289 | 289 | ||
290 | /* Also, handle the alignment code out of band. */ | 290 | /* Also, handle the alignment code out of band. */ |
291 | cc_dword_align: | 291 | cc_dword_align: |
292 | cmp %g1, 6 | 292 | cmp %g1, 16 |
293 | bl,a ccte | 293 | bge 1f |
294 | srl %g1, 1, %o3 | ||
295 | 2: cmp %o3, 0 | ||
296 | be,a ccte | ||
294 | andcc %g1, 0xf, %o3 | 297 | andcc %g1, 0xf, %o3 |
295 | andcc %o0, 0x1, %g0 | 298 | andcc %o3, %o0, %g0 ! Check %o0 only (%o1 has the same last 2 bits) |
299 | be,a 2b | ||
300 | srl %o3, 1, %o3 | ||
301 | 1: andcc %o0, 0x1, %g0 | ||
296 | bne ccslow | 302 | bne ccslow |
297 | andcc %o0, 0x2, %g0 | 303 | andcc %o0, 0x2, %g0 |
298 | be 1f | 304 | be 1f |
diff --git a/arch/sparc/lib/rwsem_32.S b/arch/sparc/lib/rwsem_32.S deleted file mode 100644 index 9675268e7fde..000000000000 --- a/arch/sparc/lib/rwsem_32.S +++ /dev/null | |||
@@ -1,204 +0,0 @@ | |||
1 | /* | ||
2 | * Assembly part of rw semaphores. | ||
3 | * | ||
4 | * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) | ||
5 | */ | ||
6 | |||
7 | #include <asm/ptrace.h> | ||
8 | #include <asm/psr.h> | ||
9 | |||
10 | .section .sched.text, "ax" | ||
11 | .align 4 | ||
12 | |||
13 | .globl ___down_read | ||
14 | ___down_read: | ||
15 | rd %psr, %g3 | ||
16 | nop | ||
17 | nop | ||
18 | nop | ||
19 | or %g3, PSR_PIL, %g7 | ||
20 | wr %g7, 0, %psr | ||
21 | nop | ||
22 | nop | ||
23 | nop | ||
24 | #ifdef CONFIG_SMP | ||
25 | 1: ldstub [%g1 + 4], %g7 | ||
26 | tst %g7 | ||
27 | bne 1b | ||
28 | ld [%g1], %g7 | ||
29 | sub %g7, 1, %g7 | ||
30 | st %g7, [%g1] | ||
31 | stb %g0, [%g1 + 4] | ||
32 | #else | ||
33 | ld [%g1], %g7 | ||
34 | sub %g7, 1, %g7 | ||
35 | st %g7, [%g1] | ||
36 | #endif | ||
37 | wr %g3, 0, %psr | ||
38 | add %g7, 1, %g7 | ||
39 | nop | ||
40 | nop | ||
41 | subcc %g7, 1, %g7 | ||
42 | bneg 3f | ||
43 | nop | ||
44 | 2: jmpl %o7, %g0 | ||
45 | mov %g4, %o7 | ||
46 | 3: save %sp, -64, %sp | ||
47 | mov %g1, %l1 | ||
48 | mov %g4, %l4 | ||
49 | bcs 4f | ||
50 | mov %g5, %l5 | ||
51 | call down_read_failed | ||
52 | mov %l1, %o0 | ||
53 | mov %l1, %g1 | ||
54 | mov %l4, %g4 | ||
55 | ba ___down_read | ||
56 | restore %l5, %g0, %g5 | ||
57 | 4: call down_read_failed_biased | ||
58 | mov %l1, %o0 | ||
59 | mov %l1, %g1 | ||
60 | mov %l4, %g4 | ||
61 | ba 2b | ||
62 | restore %l5, %g0, %g5 | ||
63 | |||
64 | .globl ___down_write | ||
65 | ___down_write: | ||
66 | rd %psr, %g3 | ||
67 | nop | ||
68 | nop | ||
69 | nop | ||
70 | or %g3, PSR_PIL, %g7 | ||
71 | wr %g7, 0, %psr | ||
72 | sethi %hi(0x01000000), %g2 | ||
73 | nop | ||
74 | nop | ||
75 | #ifdef CONFIG_SMP | ||
76 | 1: ldstub [%g1 + 4], %g7 | ||
77 | tst %g7 | ||
78 | bne 1b | ||
79 | ld [%g1], %g7 | ||
80 | sub %g7, %g2, %g7 | ||
81 | st %g7, [%g1] | ||
82 | stb %g0, [%g1 + 4] | ||
83 | #else | ||
84 | ld [%g1], %g7 | ||
85 | sub %g7, %g2, %g7 | ||
86 | st %g7, [%g1] | ||
87 | #endif | ||
88 | wr %g3, 0, %psr | ||
89 | add %g7, %g2, %g7 | ||
90 | nop | ||
91 | nop | ||
92 | subcc %g7, %g2, %g7 | ||
93 | bne 3f | ||
94 | nop | ||
95 | 2: jmpl %o7, %g0 | ||
96 | mov %g4, %o7 | ||
97 | 3: save %sp, -64, %sp | ||
98 | mov %g1, %l1 | ||
99 | mov %g4, %l4 | ||
100 | bcs 4f | ||
101 | mov %g5, %l5 | ||
102 | call down_write_failed | ||
103 | mov %l1, %o0 | ||
104 | mov %l1, %g1 | ||
105 | mov %l4, %g4 | ||
106 | ba ___down_write | ||
107 | restore %l5, %g0, %g5 | ||
108 | 4: call down_write_failed_biased | ||
109 | mov %l1, %o0 | ||
110 | mov %l1, %g1 | ||
111 | mov %l4, %g4 | ||
112 | ba 2b | ||
113 | restore %l5, %g0, %g5 | ||
114 | |||
115 | .text | ||
116 | .globl ___up_read | ||
117 | ___up_read: | ||
118 | rd %psr, %g3 | ||
119 | nop | ||
120 | nop | ||
121 | nop | ||
122 | or %g3, PSR_PIL, %g7 | ||
123 | wr %g7, 0, %psr | ||
124 | nop | ||
125 | nop | ||
126 | nop | ||
127 | #ifdef CONFIG_SMP | ||
128 | 1: ldstub [%g1 + 4], %g7 | ||
129 | tst %g7 | ||
130 | bne 1b | ||
131 | ld [%g1], %g7 | ||
132 | add %g7, 1, %g7 | ||
133 | st %g7, [%g1] | ||
134 | stb %g0, [%g1 + 4] | ||
135 | #else | ||
136 | ld [%g1], %g7 | ||
137 | add %g7, 1, %g7 | ||
138 | st %g7, [%g1] | ||
139 | #endif | ||
140 | wr %g3, 0, %psr | ||
141 | nop | ||
142 | nop | ||
143 | nop | ||
144 | cmp %g7, 0 | ||
145 | be 3f | ||
146 | nop | ||
147 | 2: jmpl %o7, %g0 | ||
148 | mov %g4, %o7 | ||
149 | 3: save %sp, -64, %sp | ||
150 | mov %g1, %l1 | ||
151 | mov %g4, %l4 | ||
152 | mov %g5, %l5 | ||
153 | clr %o1 | ||
154 | call __rwsem_wake | ||
155 | mov %l1, %o0 | ||
156 | mov %l1, %g1 | ||
157 | mov %l4, %g4 | ||
158 | ba 2b | ||
159 | restore %l5, %g0, %g5 | ||
160 | |||
161 | .globl ___up_write | ||
162 | ___up_write: | ||
163 | rd %psr, %g3 | ||
164 | nop | ||
165 | nop | ||
166 | nop | ||
167 | or %g3, PSR_PIL, %g7 | ||
168 | wr %g7, 0, %psr | ||
169 | sethi %hi(0x01000000), %g2 | ||
170 | nop | ||
171 | nop | ||
172 | #ifdef CONFIG_SMP | ||
173 | 1: ldstub [%g1 + 4], %g7 | ||
174 | tst %g7 | ||
175 | bne 1b | ||
176 | ld [%g1], %g7 | ||
177 | add %g7, %g2, %g7 | ||
178 | st %g7, [%g1] | ||
179 | stb %g0, [%g1 + 4] | ||
180 | #else | ||
181 | ld [%g1], %g7 | ||
182 | add %g7, %g2, %g7 | ||
183 | st %g7, [%g1] | ||
184 | #endif | ||
185 | wr %g3, 0, %psr | ||
186 | sub %g7, %g2, %g7 | ||
187 | nop | ||
188 | nop | ||
189 | addcc %g7, %g2, %g7 | ||
190 | bcs 3f | ||
191 | nop | ||
192 | 2: jmpl %o7, %g0 | ||
193 | mov %g4, %o7 | ||
194 | 3: save %sp, -64, %sp | ||
195 | mov %g1, %l1 | ||
196 | mov %g4, %l4 | ||
197 | mov %g5, %l5 | ||
198 | mov %g7, %o1 | ||
199 | call __rwsem_wake | ||
200 | mov %l1, %o0 | ||
201 | mov %l1, %g1 | ||
202 | mov %l4, %g4 | ||
203 | ba 2b | ||
204 | restore %l5, %g0, %g5 | ||
diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile index b9085ecbb27b..825dbee94d84 100644 --- a/arch/sparc/math-emu/Makefile +++ b/arch/sparc/math-emu/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the FPU instruction emulation. | 2 | # Makefile for the FPU instruction emulation. |
3 | # | 3 | # |
4 | 4 | ||
5 | # supress all warnings - as math.c produces a lot! | 5 | # suppress all warnings - as math.c produces a lot! |
6 | ccflags-y := -w | 6 | ccflags-y := -w |
7 | 7 | ||
8 | obj-y := math_$(BITS).o | 8 | obj-y := math_$(BITS).o |
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index bd8601601afa..7543ddbdadb2 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -135,7 +135,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, | |||
135 | 135 | ||
136 | default: | 136 | default: |
137 | break; | 137 | break; |
138 | }; | 138 | } |
139 | 139 | ||
140 | memset(®s, 0, sizeof (regs)); | 140 | memset(®s, 0, sizeof (regs)); |
141 | regs.pc = pc; | 141 | regs.pc = pc; |
@@ -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.. |
@@ -539,6 +538,12 @@ do_sigbus: | |||
539 | __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); | 538 | __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address); |
540 | } | 539 | } |
541 | 540 | ||
541 | static void check_stack_aligned(unsigned long sp) | ||
542 | { | ||
543 | if (sp & 0x7UL) | ||
544 | force_sig(SIGILL, current); | ||
545 | } | ||
546 | |||
542 | void window_overflow_fault(void) | 547 | void window_overflow_fault(void) |
543 | { | 548 | { |
544 | unsigned long sp; | 549 | unsigned long sp; |
@@ -547,6 +552,8 @@ void window_overflow_fault(void) | |||
547 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 552 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
548 | force_user_fault(sp + 0x38, 1); | 553 | force_user_fault(sp + 0x38, 1); |
549 | force_user_fault(sp, 1); | 554 | force_user_fault(sp, 1); |
555 | |||
556 | check_stack_aligned(sp); | ||
550 | } | 557 | } |
551 | 558 | ||
552 | void window_underflow_fault(unsigned long sp) | 559 | void window_underflow_fault(unsigned long sp) |
@@ -554,6 +561,8 @@ void window_underflow_fault(unsigned long sp) | |||
554 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 561 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
555 | force_user_fault(sp + 0x38, 0); | 562 | force_user_fault(sp + 0x38, 0); |
556 | force_user_fault(sp, 0); | 563 | force_user_fault(sp, 0); |
564 | |||
565 | check_stack_aligned(sp); | ||
557 | } | 566 | } |
558 | 567 | ||
559 | void window_ret_fault(struct pt_regs *regs) | 568 | void window_ret_fault(struct pt_regs *regs) |
@@ -564,4 +573,6 @@ void window_ret_fault(struct pt_regs *regs) | |||
564 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) | 573 | if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) |
565 | force_user_fault(sp + 0x38, 0); | 574 | force_user_fault(sp + 0x38, 0); |
566 | force_user_fault(sp, 0); | 575 | force_user_fault(sp, 0); |
576 | |||
577 | check_stack_aligned(sp); | ||
567 | } | 578 | } |
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c index 5edcac184eaf..e6067b75f11c 100644 --- a/arch/sparc/mm/generic_32.c +++ b/arch/sparc/mm/generic_32.c | |||
@@ -50,7 +50,7 @@ static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned | |||
50 | end = PGDIR_SIZE; | 50 | end = PGDIR_SIZE; |
51 | offset -= address; | 51 | offset -= address; |
52 | do { | 52 | do { |
53 | pte_t * pte = pte_alloc_map(mm, pmd, address); | 53 | pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); |
54 | if (!pte) | 54 | if (!pte) |
55 | return -ENOMEM; | 55 | return -ENOMEM; |
56 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); | 56 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); |
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c index 04f2bf4cd571..3cb00dfd4bd6 100644 --- a/arch/sparc/mm/generic_64.c +++ b/arch/sparc/mm/generic_64.c | |||
@@ -92,7 +92,7 @@ static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned | |||
92 | end = PGDIR_SIZE; | 92 | end = PGDIR_SIZE; |
93 | offset -= address; | 93 | offset -= address; |
94 | do { | 94 | do { |
95 | pte_t * pte = pte_alloc_map(mm, pmd, address); | 95 | pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); |
96 | if (!pte) | 96 | if (!pte) |
97 | return -ENOMEM; | 97 | return -ENOMEM; |
98 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); | 98 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); |
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c index e139e9cbf5f7..4730eac0747b 100644 --- a/arch/sparc/mm/highmem.c +++ b/arch/sparc/mm/highmem.c | |||
@@ -29,17 +29,17 @@ | |||
29 | #include <asm/tlbflush.h> | 29 | #include <asm/tlbflush.h> |
30 | #include <asm/fixmap.h> | 30 | #include <asm/fixmap.h> |
31 | 31 | ||
32 | void *kmap_atomic(struct page *page, enum km_type type) | 32 | void *__kmap_atomic(struct page *page) |
33 | { | 33 | { |
34 | unsigned long idx; | ||
35 | unsigned long vaddr; | 34 | unsigned long vaddr; |
35 | long idx, type; | ||
36 | 36 | ||
37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
38 | pagefault_disable(); | 38 | pagefault_disable(); |
39 | if (!PageHighMem(page)) | 39 | if (!PageHighMem(page)) |
40 | return page_address(page); | 40 | return page_address(page); |
41 | 41 | ||
42 | debug_kmap_atomic(type); | 42 | type = kmap_atomic_idx_push(); |
43 | idx = type + KM_TYPE_NR*smp_processor_id(); | 43 | idx = type + KM_TYPE_NR*smp_processor_id(); |
44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
45 | 45 | ||
@@ -63,44 +63,52 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
63 | 63 | ||
64 | return (void*) vaddr; | 64 | return (void*) vaddr; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL(kmap_atomic); | 66 | EXPORT_SYMBOL(__kmap_atomic); |
67 | 67 | ||
68 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 68 | void __kunmap_atomic(void *kvaddr) |
69 | { | 69 | { |
70 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
71 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 70 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
72 | unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); | 71 | int type; |
73 | 72 | ||
74 | if (vaddr < FIXADDR_START) { // FIXME | 73 | if (vaddr < FIXADDR_START) { // FIXME |
75 | pagefault_enable(); | 74 | pagefault_enable(); |
76 | return; | 75 | return; |
77 | } | 76 | } |
78 | 77 | ||
79 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)); | 78 | type = kmap_atomic_idx(); |
80 | 79 | ||
81 | /* XXX Fix - Anton */ | 80 | #ifdef CONFIG_DEBUG_HIGHMEM |
81 | { | ||
82 | unsigned long idx; | ||
83 | |||
84 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
85 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)); | ||
86 | |||
87 | /* XXX Fix - Anton */ | ||
82 | #if 0 | 88 | #if 0 |
83 | __flush_cache_one(vaddr); | 89 | __flush_cache_one(vaddr); |
84 | #else | 90 | #else |
85 | flush_cache_all(); | 91 | flush_cache_all(); |
86 | #endif | 92 | #endif |
87 | 93 | ||
88 | /* | 94 | /* |
89 | * force other mappings to Oops if they'll try to access | 95 | * force other mappings to Oops if they'll try to access |
90 | * this pte without first remap it | 96 | * this pte without first remap it |
91 | */ | 97 | */ |
92 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | 98 | pte_clear(&init_mm, vaddr, kmap_pte-idx); |
93 | /* XXX Fix - Anton */ | 99 | /* XXX Fix - Anton */ |
94 | #if 0 | 100 | #if 0 |
95 | __flush_tlb_one(vaddr); | 101 | __flush_tlb_one(vaddr); |
96 | #else | 102 | #else |
97 | flush_tlb_all(); | 103 | flush_tlb_all(); |
98 | #endif | 104 | #endif |
105 | } | ||
99 | #endif | 106 | #endif |
100 | 107 | ||
108 | kmap_atomic_idx_pop(); | ||
101 | pagefault_enable(); | 109 | pagefault_enable(); |
102 | } | 110 | } |
103 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 111 | EXPORT_SYMBOL(__kunmap_atomic); |
104 | 112 | ||
105 | /* We may be fed a pagetable here by ptep_to_xxx and others. */ | 113 | /* We may be fed a pagetable here by ptep_to_xxx and others. */ |
106 | struct page *kmap_atomic_to_page(void *ptr) | 114 | struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index 5fdddf134caa..f4e97646ce23 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c | |||
@@ -214,7 +214,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, | |||
214 | if (pud) { | 214 | if (pud) { |
215 | pmd = pmd_alloc(mm, pud, addr); | 215 | pmd = pmd_alloc(mm, pud, addr); |
216 | if (pmd) | 216 | if (pmd) |
217 | pte = pte_alloc_map(mm, pmd, addr); | 217 | pte = pte_alloc_map(mm, NULL, pmd, addr); |
218 | } | 218 | } |
219 | return pte; | 219 | return pte; |
220 | } | 220 | } |
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index 6d0e02c4fe09..7b00de61c5f1 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c | |||
@@ -37,8 +37,6 @@ | |||
37 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
38 | #include <asm/leon.h> | 38 | #include <asm/leon.h> |
39 | 39 | ||
40 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | ||
41 | |||
42 | unsigned long *sparc_valid_addr_bitmap; | 40 | unsigned long *sparc_valid_addr_bitmap; |
43 | EXPORT_SYMBOL(sparc_valid_addr_bitmap); | 41 | EXPORT_SYMBOL(sparc_valid_addr_bitmap); |
44 | 42 | ||
@@ -75,10 +73,10 @@ void __init kmap_init(void) | |||
75 | kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE); | 73 | kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE); |
76 | } | 74 | } |
77 | 75 | ||
78 | void show_mem(void) | 76 | void show_mem(unsigned int filter) |
79 | { | 77 | { |
80 | printk("Mem-info:\n"); | 78 | printk("Mem-info:\n"); |
81 | show_free_areas(); | 79 | show_free_areas(filter); |
82 | printk("Free swap: %6ldkB\n", | 80 | printk("Free swap: %6ldkB\n", |
83 | nr_swap_pages << (PAGE_SHIFT-10)); | 81 | nr_swap_pages << (PAGE_SHIFT-10)); |
84 | printk("%ld pages of RAM\n", totalram_pages); | 82 | printk("%ld pages of RAM\n", totalram_pages); |
@@ -342,7 +340,7 @@ void __init paging_init(void) | |||
342 | prom_printf("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model); | 340 | prom_printf("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model); |
343 | prom_printf("paging_init: Halting...\n"); | 341 | prom_printf("paging_init: Halting...\n"); |
344 | prom_halt(); | 342 | prom_halt(); |
345 | }; | 343 | } |
346 | 344 | ||
347 | /* Initialize the protection map with non-constant, MMU dependent values. */ | 345 | /* Initialize the protection map with non-constant, MMU dependent values. */ |
348 | protection_map[0] = PAGE_NONE; | 346 | protection_map[0] = PAGE_NONE; |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index f0434513df15..3fd8e18bed80 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -88,7 +88,7 @@ static void __init read_obp_memory(const char *property, | |||
88 | struct linux_prom64_registers *regs, | 88 | struct linux_prom64_registers *regs, |
89 | int *num_ents) | 89 | int *num_ents) |
90 | { | 90 | { |
91 | int node = prom_finddevice("/memory"); | 91 | phandle node = prom_finddevice("/memory"); |
92 | int prop_size = prom_getproplen(node, property); | 92 | int prop_size = prom_getproplen(node, property); |
93 | int ents, ret, i; | 93 | int ents, ret, i; |
94 | 94 | ||
@@ -785,8 +785,7 @@ static int find_node(unsigned long addr) | |||
785 | return -1; | 785 | return -1; |
786 | } | 786 | } |
787 | 787 | ||
788 | static unsigned long long nid_range(unsigned long long start, | 788 | u64 memblock_nid_range(u64 start, u64 end, int *nid) |
789 | unsigned long long end, int *nid) | ||
790 | { | 789 | { |
791 | *nid = find_node(start); | 790 | *nid = find_node(start); |
792 | start += PAGE_SIZE; | 791 | start += PAGE_SIZE; |
@@ -804,8 +803,7 @@ static unsigned long long nid_range(unsigned long long start, | |||
804 | return start; | 803 | return start; |
805 | } | 804 | } |
806 | #else | 805 | #else |
807 | static unsigned long long nid_range(unsigned long long start, | 806 | u64 memblock_nid_range(u64 start, u64 end, int *nid) |
808 | unsigned long long end, int *nid) | ||
809 | { | 807 | { |
810 | *nid = 0; | 808 | *nid = 0; |
811 | return end; | 809 | return end; |
@@ -822,8 +820,7 @@ static void __init allocate_node_data(int nid) | |||
822 | struct pglist_data *p; | 820 | struct pglist_data *p; |
823 | 821 | ||
824 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 822 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
825 | paddr = memblock_alloc_nid(sizeof(struct pglist_data), | 823 | paddr = memblock_alloc_try_nid(sizeof(struct pglist_data), SMP_CACHE_BYTES, nid); |
826 | SMP_CACHE_BYTES, nid, nid_range); | ||
827 | if (!paddr) { | 824 | if (!paddr) { |
828 | prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid); | 825 | prom_printf("Cannot allocate pglist_data for nid[%d]\n", nid); |
829 | prom_halt(); | 826 | prom_halt(); |
@@ -843,8 +840,7 @@ static void __init allocate_node_data(int nid) | |||
843 | if (p->node_spanned_pages) { | 840 | if (p->node_spanned_pages) { |
844 | num_pages = bootmem_bootmap_pages(p->node_spanned_pages); | 841 | num_pages = bootmem_bootmap_pages(p->node_spanned_pages); |
845 | 842 | ||
846 | paddr = memblock_alloc_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid, | 843 | paddr = memblock_alloc_try_nid(num_pages << PAGE_SHIFT, PAGE_SIZE, nid); |
847 | nid_range); | ||
848 | if (!paddr) { | 844 | if (!paddr) { |
849 | prom_printf("Cannot allocate bootmap for nid[%d]\n", | 845 | prom_printf("Cannot allocate bootmap for nid[%d]\n", |
850 | nid); | 846 | nid); |
@@ -866,7 +862,7 @@ static void init_node_masks_nonnuma(void) | |||
866 | for (i = 0; i < NR_CPUS; i++) | 862 | for (i = 0; i < NR_CPUS; i++) |
867 | numa_cpu_lookup_table[i] = 0; | 863 | numa_cpu_lookup_table[i] = 0; |
868 | 864 | ||
869 | numa_cpumask_lookup_table[0] = CPU_MASK_ALL; | 865 | cpumask_setall(&numa_cpumask_lookup_table[0]); |
870 | } | 866 | } |
871 | 867 | ||
872 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 868 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
@@ -972,19 +968,19 @@ int of_node_to_nid(struct device_node *dp) | |||
972 | 968 | ||
973 | static void __init add_node_ranges(void) | 969 | static void __init add_node_ranges(void) |
974 | { | 970 | { |
975 | int i; | 971 | struct memblock_region *reg; |
976 | 972 | ||
977 | for (i = 0; i < memblock.memory.cnt; i++) { | 973 | for_each_memblock(memory, reg) { |
978 | unsigned long size = memblock_size_bytes(&memblock.memory, i); | 974 | unsigned long size = reg->size; |
979 | unsigned long start, end; | 975 | unsigned long start, end; |
980 | 976 | ||
981 | start = memblock.memory.region[i].base; | 977 | start = reg->base; |
982 | end = start + size; | 978 | end = start + size; |
983 | while (start < end) { | 979 | while (start < end) { |
984 | unsigned long this_end; | 980 | unsigned long this_end; |
985 | int nid; | 981 | int nid; |
986 | 982 | ||
987 | this_end = nid_range(start, end, &nid); | 983 | this_end = memblock_nid_range(start, end, &nid); |
988 | 984 | ||
989 | numadbg("Adding active range nid[%d] " | 985 | numadbg("Adding active range nid[%d] " |
990 | "start[%lx] end[%lx]\n", | 986 | "start[%lx] end[%lx]\n", |
@@ -1084,7 +1080,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md, | |||
1084 | { | 1080 | { |
1085 | u64 arc; | 1081 | u64 arc; |
1086 | 1082 | ||
1087 | cpus_clear(*mask); | 1083 | cpumask_clear(mask); |
1088 | 1084 | ||
1089 | mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) { | 1085 | mdesc_for_each_arc(arc, md, grp, MDESC_ARC_TYPE_BACK) { |
1090 | u64 target = mdesc_arc_target(md, arc); | 1086 | u64 target = mdesc_arc_target(md, arc); |
@@ -1095,7 +1091,7 @@ static void __init numa_parse_mdesc_group_cpus(struct mdesc_handle *md, | |||
1095 | continue; | 1091 | continue; |
1096 | id = mdesc_get_property(md, target, "id", NULL); | 1092 | id = mdesc_get_property(md, target, "id", NULL); |
1097 | if (*id < nr_cpu_ids) | 1093 | if (*id < nr_cpu_ids) |
1098 | cpu_set(*id, *mask); | 1094 | cpumask_set_cpu(*id, mask); |
1099 | } | 1095 | } |
1100 | } | 1096 | } |
1101 | 1097 | ||
@@ -1157,13 +1153,13 @@ static int __init numa_parse_mdesc_group(struct mdesc_handle *md, u64 grp, | |||
1157 | 1153 | ||
1158 | numa_parse_mdesc_group_cpus(md, grp, &mask); | 1154 | numa_parse_mdesc_group_cpus(md, grp, &mask); |
1159 | 1155 | ||
1160 | for_each_cpu_mask(cpu, mask) | 1156 | for_each_cpu(cpu, &mask) |
1161 | numa_cpu_lookup_table[cpu] = index; | 1157 | numa_cpu_lookup_table[cpu] = index; |
1162 | numa_cpumask_lookup_table[index] = mask; | 1158 | cpumask_copy(&numa_cpumask_lookup_table[index], &mask); |
1163 | 1159 | ||
1164 | if (numa_debug) { | 1160 | if (numa_debug) { |
1165 | printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index); | 1161 | printk(KERN_INFO "NUMA GROUP[%d]: cpus [ ", index); |
1166 | for_each_cpu_mask(cpu, mask) | 1162 | for_each_cpu(cpu, &mask) |
1167 | printk("%d ", cpu); | 1163 | printk("%d ", cpu); |
1168 | printk("]\n"); | 1164 | printk("]\n"); |
1169 | } | 1165 | } |
@@ -1222,7 +1218,7 @@ static int __init numa_parse_jbus(void) | |||
1222 | index = 0; | 1218 | index = 0; |
1223 | for_each_present_cpu(cpu) { | 1219 | for_each_present_cpu(cpu) { |
1224 | numa_cpu_lookup_table[cpu] = index; | 1220 | numa_cpu_lookup_table[cpu] = index; |
1225 | numa_cpumask_lookup_table[index] = cpumask_of_cpu(cpu); | 1221 | cpumask_copy(&numa_cpumask_lookup_table[index], cpumask_of(cpu)); |
1226 | node_masks[index].mask = ~((1UL << 36UL) - 1UL); | 1222 | node_masks[index].mask = ~((1UL << 36UL) - 1UL); |
1227 | node_masks[index].val = cpu << 36UL; | 1223 | node_masks[index].val = cpu << 36UL; |
1228 | 1224 | ||
@@ -1281,7 +1277,7 @@ static void __init bootmem_init_nonnuma(void) | |||
1281 | { | 1277 | { |
1282 | unsigned long top_of_ram = memblock_end_of_DRAM(); | 1278 | unsigned long top_of_ram = memblock_end_of_DRAM(); |
1283 | unsigned long total_ram = memblock_phys_mem_size(); | 1279 | unsigned long total_ram = memblock_phys_mem_size(); |
1284 | unsigned int i; | 1280 | struct memblock_region *reg; |
1285 | 1281 | ||
1286 | numadbg("bootmem_init_nonnuma()\n"); | 1282 | numadbg("bootmem_init_nonnuma()\n"); |
1287 | 1283 | ||
@@ -1292,15 +1288,14 @@ static void __init bootmem_init_nonnuma(void) | |||
1292 | 1288 | ||
1293 | init_node_masks_nonnuma(); | 1289 | init_node_masks_nonnuma(); |
1294 | 1290 | ||
1295 | for (i = 0; i < memblock.memory.cnt; i++) { | 1291 | for_each_memblock(memory, reg) { |
1296 | unsigned long size = memblock_size_bytes(&memblock.memory, i); | ||
1297 | unsigned long start_pfn, end_pfn; | 1292 | unsigned long start_pfn, end_pfn; |
1298 | 1293 | ||
1299 | if (!size) | 1294 | if (!reg->size) |
1300 | continue; | 1295 | continue; |
1301 | 1296 | ||
1302 | start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT; | 1297 | start_pfn = memblock_region_memory_base_pfn(reg); |
1303 | end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i); | 1298 | end_pfn = memblock_region_memory_end_pfn(reg); |
1304 | add_active_range(0, start_pfn, end_pfn); | 1299 | add_active_range(0, start_pfn, end_pfn); |
1305 | } | 1300 | } |
1306 | 1301 | ||
@@ -1318,7 +1313,7 @@ static void __init reserve_range_in_node(int nid, unsigned long start, | |||
1318 | unsigned long this_end; | 1313 | unsigned long this_end; |
1319 | int n; | 1314 | int n; |
1320 | 1315 | ||
1321 | this_end = nid_range(start, end, &n); | 1316 | this_end = memblock_nid_range(start, end, &n); |
1322 | if (n == nid) { | 1317 | if (n == nid) { |
1323 | numadbg(" MATCH reserving range [%lx:%lx]\n", | 1318 | numadbg(" MATCH reserving range [%lx:%lx]\n", |
1324 | start, this_end); | 1319 | start, this_end); |
@@ -1334,17 +1329,12 @@ static void __init reserve_range_in_node(int nid, unsigned long start, | |||
1334 | 1329 | ||
1335 | static void __init trim_reserved_in_node(int nid) | 1330 | static void __init trim_reserved_in_node(int nid) |
1336 | { | 1331 | { |
1337 | int i; | 1332 | struct memblock_region *reg; |
1338 | 1333 | ||
1339 | numadbg(" trim_reserved_in_node(%d)\n", nid); | 1334 | numadbg(" trim_reserved_in_node(%d)\n", nid); |
1340 | 1335 | ||
1341 | for (i = 0; i < memblock.reserved.cnt; i++) { | 1336 | for_each_memblock(reserved, reg) |
1342 | unsigned long start = memblock.reserved.region[i].base; | 1337 | reserve_range_in_node(nid, reg->base, reg->base + reg->size); |
1343 | unsigned long size = memblock_size_bytes(&memblock.reserved, i); | ||
1344 | unsigned long end = start + size; | ||
1345 | |||
1346 | reserve_range_in_node(nid, start, end); | ||
1347 | } | ||
1348 | } | 1338 | } |
1349 | 1339 | ||
1350 | static void __init bootmem_init_one_node(int nid) | 1340 | static void __init bootmem_init_one_node(int nid) |
@@ -1635,7 +1625,7 @@ static void __init sun4v_ktsb_init(void) | |||
1635 | ktsb_descr[0].pgsz_idx = HV_PGSZ_IDX_4MB; | 1625 | ktsb_descr[0].pgsz_idx = HV_PGSZ_IDX_4MB; |
1636 | ktsb_descr[0].pgsz_mask = HV_PGSZ_MASK_4MB; | 1626 | ktsb_descr[0].pgsz_mask = HV_PGSZ_MASK_4MB; |
1637 | break; | 1627 | break; |
1638 | }; | 1628 | } |
1639 | 1629 | ||
1640 | ktsb_descr[0].assoc = 1; | 1630 | ktsb_descr[0].assoc = 1; |
1641 | ktsb_descr[0].num_ttes = KERNEL_TSB_NENTRIES; | 1631 | ktsb_descr[0].num_ttes = KERNEL_TSB_NENTRIES; |
@@ -2276,7 +2266,7 @@ unsigned long pte_sz_bits(unsigned long sz) | |||
2276 | return _PAGE_SZ512K_4V; | 2266 | return _PAGE_SZ512K_4V; |
2277 | case 4 * 1024 * 1024: | 2267 | case 4 * 1024 * 1024: |
2278 | return _PAGE_SZ4MB_4V; | 2268 | return _PAGE_SZ4MB_4V; |
2279 | }; | 2269 | } |
2280 | } else { | 2270 | } else { |
2281 | switch (sz) { | 2271 | switch (sz) { |
2282 | case 8 * 1024: | 2272 | case 8 * 1024: |
@@ -2288,7 +2278,7 @@ unsigned long pte_sz_bits(unsigned long sz) | |||
2288 | return _PAGE_SZ512K_4U; | 2278 | return _PAGE_SZ512K_4U; |
2289 | case 4 * 1024 * 1024: | 2279 | case 4 * 1024 * 1024: |
2290 | return _PAGE_SZ4MB_4U; | 2280 | return _PAGE_SZ4MB_4U; |
2291 | }; | 2281 | } |
2292 | } | 2282 | } |
2293 | } | 2283 | } |
2294 | 2284 | ||
diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c index c0e01297e64e..e485a6804998 100644 --- a/arch/sparc/mm/leon_mm.c +++ b/arch/sparc/mm/leon_mm.c | |||
@@ -226,7 +226,7 @@ void leon3_getCacheRegs(struct leon3_cacheregs *regs) | |||
226 | * Leon2 and Leon3 differ in their way of telling cache information | 226 | * Leon2 and Leon3 differ in their way of telling cache information |
227 | * | 227 | * |
228 | */ | 228 | */ |
229 | int leon_flush_needed(void) | 229 | int __init leon_flush_needed(void) |
230 | { | 230 | { |
231 | int flush_needed = -1; | 231 | int flush_needed = -1; |
232 | unsigned int ssize, sets; | 232 | unsigned int ssize, sets; |
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index b0b43aa5e45a..cbef74e793b8 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c | |||
@@ -650,7 +650,7 @@ static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len) | |||
650 | * mappings on the kernel stack without any special code as we did | 650 | * mappings on the kernel stack without any special code as we did |
651 | * need on the sun4c. | 651 | * need on the sun4c. |
652 | */ | 652 | */ |
653 | static struct thread_info *srmmu_alloc_thread_info(void) | 653 | static struct thread_info *srmmu_alloc_thread_info_node(int node) |
654 | { | 654 | { |
655 | struct thread_info *ret; | 655 | struct thread_info *ret; |
656 | 656 | ||
@@ -1262,7 +1262,8 @@ extern unsigned long bootmem_init(unsigned long *pages_avail); | |||
1262 | 1262 | ||
1263 | void __init srmmu_paging_init(void) | 1263 | void __init srmmu_paging_init(void) |
1264 | { | 1264 | { |
1265 | int i, cpunode; | 1265 | int i; |
1266 | phandle cpunode; | ||
1266 | char node_str[128]; | 1267 | char node_str[128]; |
1267 | pgd_t *pgd; | 1268 | pgd_t *pgd; |
1268 | pmd_t *pmd; | 1269 | pmd_t *pmd; |
@@ -1398,7 +1399,8 @@ static void __init srmmu_is_bad(void) | |||
1398 | 1399 | ||
1399 | static void __init init_vac_layout(void) | 1400 | static void __init init_vac_layout(void) |
1400 | { | 1401 | { |
1401 | int nd, cache_lines; | 1402 | phandle nd; |
1403 | int cache_lines; | ||
1402 | char node_str[128]; | 1404 | char node_str[128]; |
1403 | #ifdef CONFIG_SMP | 1405 | #ifdef CONFIG_SMP |
1404 | int cpu = 0; | 1406 | int cpu = 0; |
@@ -1663,7 +1665,7 @@ static void __init init_swift(void) | |||
1663 | default: | 1665 | default: |
1664 | srmmu_modtype = Swift_ok; | 1666 | srmmu_modtype = Swift_ok; |
1665 | break; | 1667 | break; |
1666 | }; | 1668 | } |
1667 | 1669 | ||
1668 | BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM); | 1670 | BTFIXUPSET_CALL(flush_cache_all, swift_flush_cache_all, BTFIXUPCALL_NORM); |
1669 | BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM); | 1671 | BTFIXUPSET_CALL(flush_cache_mm, swift_flush_cache_mm, BTFIXUPCALL_NORM); |
@@ -2067,7 +2069,7 @@ static void __init get_srmmu_type(void) | |||
2067 | /* Some other Cypress revision, assume a 605. */ | 2069 | /* Some other Cypress revision, assume a 605. */ |
2068 | init_cypress_605(mod_rev); | 2070 | init_cypress_605(mod_rev); |
2069 | break; | 2071 | break; |
2070 | }; | 2072 | } |
2071 | return; | 2073 | return; |
2072 | } | 2074 | } |
2073 | 2075 | ||
@@ -2082,7 +2084,7 @@ static void __init get_srmmu_type(void) | |||
2082 | 2084 | ||
2083 | /* Next check for Fujitsu Swift. */ | 2085 | /* Next check for Fujitsu Swift. */ |
2084 | if(psr_typ == 0 && psr_vers == 4) { | 2086 | if(psr_typ == 0 && psr_vers == 4) { |
2085 | int cpunode; | 2087 | phandle cpunode; |
2086 | char node_str[128]; | 2088 | char node_str[128]; |
2087 | 2089 | ||
2088 | /* Look if it is not a TurboSparc emulating Swift... */ | 2090 | /* Look if it is not a TurboSparc emulating Swift... */ |
@@ -2269,7 +2271,7 @@ void __init ld_mmu_srmmu(void) | |||
2269 | 2271 | ||
2270 | BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM); | 2272 | BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM); |
2271 | 2273 | ||
2272 | BTFIXUPSET_CALL(alloc_thread_info, srmmu_alloc_thread_info, BTFIXUPCALL_NORM); | 2274 | BTFIXUPSET_CALL(alloc_thread_info_node, srmmu_alloc_thread_info_node, BTFIXUPCALL_NORM); |
2273 | BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM); | 2275 | BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM); |
2274 | 2276 | ||
2275 | BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM); | 2277 | BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM); |
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 4289f90f8697..1cf4f198709a 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c | |||
@@ -318,7 +318,7 @@ void __init sun4c_probe_vac(void) | |||
318 | prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n", | 318 | prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n", |
319 | sun4c_vacinfo.linesize); | 319 | sun4c_vacinfo.linesize); |
320 | prom_halt(); | 320 | prom_halt(); |
321 | }; | 321 | } |
322 | 322 | ||
323 | sun4c_flush_all(); | 323 | sun4c_flush_all(); |
324 | sun4c_enable_vac(); | 324 | sun4c_enable_vac(); |
@@ -364,7 +364,7 @@ static void __init patch_kernel_fault_handler(void) | |||
364 | prom_printf("Unhandled number of segmaps: %d\n", | 364 | prom_printf("Unhandled number of segmaps: %d\n", |
365 | num_segmaps); | 365 | num_segmaps); |
366 | prom_halt(); | 366 | prom_halt(); |
367 | }; | 367 | } |
368 | switch (num_contexts) { | 368 | switch (num_contexts) { |
369 | case 8: | 369 | case 8: |
370 | /* Default, nothing to do. */ | 370 | /* Default, nothing to do. */ |
@@ -377,7 +377,7 @@ static void __init patch_kernel_fault_handler(void) | |||
377 | prom_printf("Unhandled number of contexts: %d\n", | 377 | prom_printf("Unhandled number of contexts: %d\n", |
378 | num_contexts); | 378 | num_contexts); |
379 | prom_halt(); | 379 | prom_halt(); |
380 | }; | 380 | } |
381 | 381 | ||
382 | if (sun4c_vacinfo.do_hwflushes != 0) { | 382 | if (sun4c_vacinfo.do_hwflushes != 0) { |
383 | PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1); | 383 | PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1); |
@@ -394,7 +394,7 @@ static void __init patch_kernel_fault_handler(void) | |||
394 | prom_printf("Impossible VAC linesize %d, halting...\n", | 394 | prom_printf("Impossible VAC linesize %d, halting...\n", |
395 | sun4c_vacinfo.linesize); | 395 | sun4c_vacinfo.linesize); |
396 | prom_halt(); | 396 | prom_halt(); |
397 | }; | 397 | } |
398 | } | 398 | } |
399 | } | 399 | } |
400 | 400 | ||
@@ -420,7 +420,7 @@ volatile unsigned long __iomem *sun4c_memerr_reg = NULL; | |||
420 | 420 | ||
421 | void __init sun4c_probe_memerr_reg(void) | 421 | void __init sun4c_probe_memerr_reg(void) |
422 | { | 422 | { |
423 | int node; | 423 | phandle node; |
424 | struct linux_prom_registers regs[1]; | 424 | struct linux_prom_registers regs[1]; |
425 | 425 | ||
426 | node = prom_getchild(prom_root_node); | 426 | node = prom_getchild(prom_root_node); |
@@ -435,16 +435,14 @@ void __init sun4c_probe_memerr_reg(void) | |||
435 | 435 | ||
436 | static inline void sun4c_init_ss2_cache_bug(void) | 436 | static inline void sun4c_init_ss2_cache_bug(void) |
437 | { | 437 | { |
438 | extern unsigned long start; | ||
439 | |||
440 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || | 438 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || |
441 | (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || | 439 | (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || |
442 | (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { | 440 | (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { |
443 | /* Whee.. */ | 441 | /* Whee.. */ |
444 | printk("SS2 cache bug detected, uncaching trap table page\n"); | 442 | printk("SS2 cache bug detected, uncaching trap table page\n"); |
445 | sun4c_flush_page((unsigned int) &start); | 443 | sun4c_flush_page((unsigned int) &_start); |
446 | sun4c_put_pte(((unsigned long) &start), | 444 | sun4c_put_pte(((unsigned long) &_start), |
447 | (sun4c_get_pte((unsigned long) &start) | _SUN4C_PAGE_NOCACHE)); | 445 | (sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE)); |
448 | } | 446 | } |
449 | } | 447 | } |
450 | 448 | ||
@@ -924,7 +922,7 @@ static inline void garbage_collect(int entry) | |||
924 | free_locked_segment(BUCKET_ADDR(entry)); | 922 | free_locked_segment(BUCKET_ADDR(entry)); |
925 | } | 923 | } |
926 | 924 | ||
927 | static struct thread_info *sun4c_alloc_thread_info(void) | 925 | static struct thread_info *sun4c_alloc_thread_info_node(int node) |
928 | { | 926 | { |
929 | unsigned long addr, pages; | 927 | unsigned long addr, pages; |
930 | int entry; | 928 | int entry; |
@@ -2157,7 +2155,7 @@ void __init ld_mmu_sun4c(void) | |||
2157 | BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM); | 2155 | BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM); |
2158 | BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM); | 2156 | BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM); |
2159 | 2157 | ||
2160 | BTFIXUPSET_CALL(alloc_thread_info, sun4c_alloc_thread_info, BTFIXUPCALL_NORM); | 2158 | BTFIXUPSET_CALL(alloc_thread_info_node, sun4c_alloc_thread_info_node, BTFIXUPCALL_NORM); |
2161 | BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM); | 2159 | BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM); |
2162 | 2160 | ||
2163 | BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM); | 2161 | BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM); |
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index d8f21e24a82f..b1f279cd00bf 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c | |||
@@ -19,33 +19,34 @@ | |||
19 | 19 | ||
20 | /* Heavily inspired by the ppc64 code. */ | 20 | /* Heavily inspired by the ppc64 code. */ |
21 | 21 | ||
22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 22 | static DEFINE_PER_CPU(struct tlb_batch, tlb_batch); |
23 | 23 | ||
24 | void flush_tlb_pending(void) | 24 | void flush_tlb_pending(void) |
25 | { | 25 | { |
26 | struct mmu_gather *mp = &get_cpu_var(mmu_gathers); | 26 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); |
27 | 27 | ||
28 | if (mp->tlb_nr) { | 28 | if (tb->tlb_nr) { |
29 | flush_tsb_user(mp); | 29 | flush_tsb_user(tb); |
30 | 30 | ||
31 | if (CTX_VALID(mp->mm->context)) { | 31 | if (CTX_VALID(tb->mm->context)) { |
32 | #ifdef CONFIG_SMP | 32 | #ifdef CONFIG_SMP |
33 | smp_flush_tlb_pending(mp->mm, mp->tlb_nr, | 33 | smp_flush_tlb_pending(tb->mm, tb->tlb_nr, |
34 | &mp->vaddrs[0]); | 34 | &tb->vaddrs[0]); |
35 | #else | 35 | #else |
36 | __flush_tlb_pending(CTX_HWBITS(mp->mm->context), | 36 | __flush_tlb_pending(CTX_HWBITS(tb->mm->context), |
37 | mp->tlb_nr, &mp->vaddrs[0]); | 37 | tb->tlb_nr, &tb->vaddrs[0]); |
38 | #endif | 38 | #endif |
39 | } | 39 | } |
40 | mp->tlb_nr = 0; | 40 | tb->tlb_nr = 0; |
41 | } | 41 | } |
42 | 42 | ||
43 | put_cpu_var(mmu_gathers); | 43 | put_cpu_var(tlb_batch); |
44 | } | 44 | } |
45 | 45 | ||
46 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) | 46 | void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, |
47 | pte_t *ptep, pte_t orig, int fullmm) | ||
47 | { | 48 | { |
48 | struct mmu_gather *mp = &__get_cpu_var(mmu_gathers); | 49 | struct tlb_batch *tb = &get_cpu_var(tlb_batch); |
49 | unsigned long nr; | 50 | unsigned long nr; |
50 | 51 | ||
51 | vaddr &= PAGE_MASK; | 52 | vaddr &= PAGE_MASK; |
@@ -77,21 +78,25 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t | |||
77 | 78 | ||
78 | no_cache_flush: | 79 | no_cache_flush: |
79 | 80 | ||
80 | if (mp->fullmm) | 81 | if (fullmm) { |
82 | put_cpu_var(tlb_batch); | ||
81 | return; | 83 | return; |
84 | } | ||
82 | 85 | ||
83 | nr = mp->tlb_nr; | 86 | nr = tb->tlb_nr; |
84 | 87 | ||
85 | if (unlikely(nr != 0 && mm != mp->mm)) { | 88 | if (unlikely(nr != 0 && mm != tb->mm)) { |
86 | flush_tlb_pending(); | 89 | flush_tlb_pending(); |
87 | nr = 0; | 90 | nr = 0; |
88 | } | 91 | } |
89 | 92 | ||
90 | if (nr == 0) | 93 | if (nr == 0) |
91 | mp->mm = mm; | 94 | tb->mm = mm; |
92 | 95 | ||
93 | mp->vaddrs[nr] = vaddr; | 96 | tb->vaddrs[nr] = vaddr; |
94 | mp->tlb_nr = ++nr; | 97 | tb->tlb_nr = ++nr; |
95 | if (nr >= TLB_BATCH_NR) | 98 | if (nr >= TLB_BATCH_NR) |
96 | flush_tlb_pending(); | 99 | flush_tlb_pending(); |
100 | |||
101 | put_cpu_var(tlb_batch); | ||
97 | } | 102 | } |
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index 101d7c82870b..a5f51b22fcbe 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c | |||
@@ -47,12 +47,13 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, unsigned long tsb, unsigned long nentries) | 50 | static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift, |
51 | unsigned long tsb, unsigned long nentries) | ||
51 | { | 52 | { |
52 | unsigned long i; | 53 | unsigned long i; |
53 | 54 | ||
54 | for (i = 0; i < mp->tlb_nr; i++) { | 55 | for (i = 0; i < tb->tlb_nr; i++) { |
55 | unsigned long v = mp->vaddrs[i]; | 56 | unsigned long v = tb->vaddrs[i]; |
56 | unsigned long tag, ent, hash; | 57 | unsigned long tag, ent, hash; |
57 | 58 | ||
58 | v &= ~0x1UL; | 59 | v &= ~0x1UL; |
@@ -65,9 +66,9 @@ static void __flush_tsb_one(struct mmu_gather *mp, unsigned long hash_shift, uns | |||
65 | } | 66 | } |
66 | } | 67 | } |
67 | 68 | ||
68 | void flush_tsb_user(struct mmu_gather *mp) | 69 | void flush_tsb_user(struct tlb_batch *tb) |
69 | { | 70 | { |
70 | struct mm_struct *mm = mp->mm; | 71 | struct mm_struct *mm = tb->mm; |
71 | unsigned long nentries, base, flags; | 72 | unsigned long nentries, base, flags; |
72 | 73 | ||
73 | spin_lock_irqsave(&mm->context.lock, flags); | 74 | spin_lock_irqsave(&mm->context.lock, flags); |
@@ -76,7 +77,7 @@ void flush_tsb_user(struct mmu_gather *mp) | |||
76 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; | 77 | nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; |
77 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 78 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |
78 | base = __pa(base); | 79 | base = __pa(base); |
79 | __flush_tsb_one(mp, PAGE_SHIFT, base, nentries); | 80 | __flush_tsb_one(tb, PAGE_SHIFT, base, nentries); |
80 | 81 | ||
81 | #ifdef CONFIG_HUGETLB_PAGE | 82 | #ifdef CONFIG_HUGETLB_PAGE |
82 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { | 83 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { |
@@ -84,7 +85,7 @@ void flush_tsb_user(struct mmu_gather *mp) | |||
84 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; | 85 | nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; |
85 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) | 86 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) |
86 | base = __pa(base); | 87 | base = __pa(base); |
87 | __flush_tsb_one(mp, HPAGE_SHIFT, base, nentries); | 88 | __flush_tsb_one(tb, HPAGE_SHIFT, base, nentries); |
88 | } | 89 | } |
89 | #endif | 90 | #endif |
90 | spin_unlock_irqrestore(&mm->context.lock, flags); | 91 | spin_unlock_irqrestore(&mm->context.lock, flags); |
@@ -179,7 +180,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign | |||
179 | printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n", | 180 | printk(KERN_ERR "TSB[%s:%d]: Impossible TSB size %lu, killing process.\n", |
180 | current->comm, current->pid, tsb_bytes); | 181 | current->comm, current->pid, tsb_bytes); |
181 | do_exit(SIGSEGV); | 182 | do_exit(SIGSEGV); |
182 | }; | 183 | } |
183 | tte |= pte_sz_bits(page_sz); | 184 | tte |= pte_sz_bits(page_sz); |
184 | 185 | ||
185 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) { | 186 | if (tlb_type == cheetah_plus || tlb_type == hypervisor) { |
@@ -214,7 +215,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign | |||
214 | #endif | 215 | #endif |
215 | default: | 216 | default: |
216 | BUG(); | 217 | BUG(); |
217 | }; | 218 | } |
218 | hp->assoc = 1; | 219 | hp->assoc = 1; |
219 | hp->num_ttes = tsb_bytes / 16; | 220 | hp->num_ttes = tsb_bytes / 16; |
220 | hp->ctx_idx = 0; | 221 | hp->ctx_idx = 0; |
@@ -229,7 +230,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign | |||
229 | #endif | 230 | #endif |
230 | default: | 231 | default: |
231 | BUG(); | 232 | BUG(); |
232 | }; | 233 | } |
233 | hp->tsb_base = tsb_paddr; | 234 | hp->tsb_base = tsb_paddr; |
234 | hp->resv = 0; | 235 | hp->resv = 0; |
235 | } | 236 | } |
diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 1b8c073adb44..8287bbe88768 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile | |||
@@ -5,13 +5,10 @@ asflags := -ansi | |||
5 | ccflags := -Werror | 5 | ccflags := -Werror |
6 | 6 | ||
7 | lib-y := bootstr_$(BITS).o | 7 | lib-y := bootstr_$(BITS).o |
8 | lib-$(CONFIG_SPARC32) += devmap.o | ||
9 | lib-y += devops_$(BITS).o | ||
10 | lib-y += init_$(BITS).o | 8 | lib-y += init_$(BITS).o |
11 | lib-$(CONFIG_SPARC32) += memory.o | 9 | lib-$(CONFIG_SPARC32) += memory.o |
12 | lib-y += misc_$(BITS).o | 10 | lib-y += misc_$(BITS).o |
13 | lib-$(CONFIG_SPARC32) += mp.o | 11 | lib-$(CONFIG_SPARC32) += mp.o |
14 | lib-$(CONFIG_SPARC32) += palloc.o | ||
15 | lib-$(CONFIG_SPARC32) += ranges.o | 12 | lib-$(CONFIG_SPARC32) += ranges.o |
16 | lib-$(CONFIG_SPARC32) += segment.o | 13 | lib-$(CONFIG_SPARC32) += segment.o |
17 | lib-y += console_$(BITS).o | 14 | lib-y += console_$(BITS).o |
diff --git a/arch/sparc/prom/bootstr_32.c b/arch/sparc/prom/bootstr_32.c index 916831da7e67..f5ec32e0d419 100644 --- a/arch/sparc/prom/bootstr_32.c +++ b/arch/sparc/prom/bootstr_32.c | |||
@@ -29,7 +29,8 @@ prom_getbootargs(void) | |||
29 | /* Start from 1 and go over fd(0,0,0)kernel */ | 29 | /* Start from 1 and go over fd(0,0,0)kernel */ |
30 | for(iter = 1; iter < 8; iter++) { | 30 | for(iter = 1; iter < 8; iter++) { |
31 | arg = (*(romvec->pv_v0bootargs))->argv[iter]; | 31 | arg = (*(romvec->pv_v0bootargs))->argv[iter]; |
32 | if(arg == 0) break; | 32 | if (arg == NULL) |
33 | break; | ||
33 | while(*arg != 0) { | 34 | while(*arg != 0) { |
34 | /* Leave place for space and null. */ | 35 | /* Leave place for space and null. */ |
35 | if(cp >= barg_buf + BARG_LEN-2){ | 36 | if(cp >= barg_buf + BARG_LEN-2){ |
diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 5340264b78f5..a00f47b16c10 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c | |||
@@ -16,82 +16,42 @@ | |||
16 | 16 | ||
17 | extern void restore_current(void); | 17 | extern void restore_current(void); |
18 | 18 | ||
19 | /* Non blocking get character from console input device, returns -1 | ||
20 | * if no input was taken. This can be used for polling. | ||
21 | */ | ||
22 | int | ||
23 | prom_nbgetchar(void) | ||
24 | { | ||
25 | static char inc; | ||
26 | int i = -1; | ||
27 | unsigned long flags; | ||
28 | |||
29 | spin_lock_irqsave(&prom_lock, flags); | ||
30 | switch(prom_vers) { | ||
31 | case PROM_V0: | ||
32 | i = (*(romvec->pv_nbgetchar))(); | ||
33 | break; | ||
34 | case PROM_V2: | ||
35 | case PROM_V3: | ||
36 | if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) { | ||
37 | i = inc; | ||
38 | } else { | ||
39 | i = -1; | ||
40 | } | ||
41 | break; | ||
42 | default: | ||
43 | i = -1; | ||
44 | break; | ||
45 | }; | ||
46 | restore_current(); | ||
47 | spin_unlock_irqrestore(&prom_lock, flags); | ||
48 | return i; /* Ugh, we could spin forever on unsupported proms ;( */ | ||
49 | } | ||
50 | |||
51 | /* Non blocking put character to console device, returns -1 if | 19 | /* Non blocking put character to console device, returns -1 if |
52 | * unsuccessful. | 20 | * unsuccessful. |
53 | */ | 21 | */ |
54 | int | 22 | static int prom_nbputchar(const char *buf) |
55 | prom_nbputchar(char c) | ||
56 | { | 23 | { |
57 | static char outc; | ||
58 | unsigned long flags; | 24 | unsigned long flags; |
59 | int i = -1; | 25 | int i = -1; |
60 | 26 | ||
61 | spin_lock_irqsave(&prom_lock, flags); | 27 | spin_lock_irqsave(&prom_lock, flags); |
62 | switch(prom_vers) { | 28 | switch(prom_vers) { |
63 | case PROM_V0: | 29 | case PROM_V0: |
64 | i = (*(romvec->pv_nbputchar))(c); | 30 | if ((*(romvec->pv_nbputchar))(*buf)) |
31 | i = 1; | ||
65 | break; | 32 | break; |
66 | case PROM_V2: | 33 | case PROM_V2: |
67 | case PROM_V3: | 34 | case PROM_V3: |
68 | outc = c; | 35 | if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, |
69 | if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1) | 36 | buf, 0x1) == 1) |
70 | i = 0; | 37 | i = 1; |
71 | else | ||
72 | i = -1; | ||
73 | break; | 38 | break; |
74 | default: | 39 | default: |
75 | i = -1; | ||
76 | break; | 40 | break; |
77 | }; | 41 | } |
78 | restore_current(); | 42 | restore_current(); |
79 | spin_unlock_irqrestore(&prom_lock, flags); | 43 | spin_unlock_irqrestore(&prom_lock, flags); |
80 | return i; /* Ugh, we could spin forever on unsupported proms ;( */ | 44 | return i; /* Ugh, we could spin forever on unsupported proms ;( */ |
81 | } | 45 | } |
82 | 46 | ||
83 | /* Blocking version of get character routine above. */ | 47 | void prom_console_write_buf(const char *buf, int len) |
84 | char | ||
85 | prom_getchar(void) | ||
86 | { | 48 | { |
87 | int character; | 49 | while (len) { |
88 | while((character = prom_nbgetchar()) == -1) ; | 50 | int n = prom_nbputchar(buf); |
89 | return (char) character; | 51 | if (n < 0) |
52 | continue; | ||
53 | len--; | ||
54 | buf++; | ||
55 | } | ||
90 | } | 56 | } |
91 | 57 | ||
92 | /* Blocking version of put character routine above. */ | ||
93 | void | ||
94 | prom_putchar(char c) | ||
95 | { | ||
96 | while(prom_nbputchar(c) == -1) ; | ||
97 | } | ||
diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index 10322dc2f557..9de6c8cfe04a 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c | |||
@@ -13,87 +13,34 @@ | |||
13 | #include <asm/system.h> | 13 | #include <asm/system.h> |
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | 15 | ||
16 | extern int prom_stdin, prom_stdout; | 16 | static int __prom_console_write_buf(const char *buf, int len) |
17 | |||
18 | /* Non blocking get character from console input device, returns -1 | ||
19 | * if no input was taken. This can be used for polling. | ||
20 | */ | ||
21 | inline int | ||
22 | prom_nbgetchar(void) | ||
23 | { | 17 | { |
24 | unsigned long args[7]; | 18 | unsigned long args[7]; |
25 | char inc; | 19 | int ret; |
26 | |||
27 | args[0] = (unsigned long) "read"; | ||
28 | args[1] = 3; | ||
29 | args[2] = 1; | ||
30 | args[3] = (unsigned int) prom_stdin; | ||
31 | args[4] = (unsigned long) &inc; | ||
32 | args[5] = 1; | ||
33 | args[6] = (unsigned long) -1; | ||
34 | |||
35 | p1275_cmd_direct(args); | ||
36 | |||
37 | if (args[6] == 1) | ||
38 | return inc; | ||
39 | return -1; | ||
40 | } | ||
41 | |||
42 | /* Non blocking put character to console device, returns -1 if | ||
43 | * unsuccessful. | ||
44 | */ | ||
45 | inline int | ||
46 | prom_nbputchar(char c) | ||
47 | { | ||
48 | unsigned long args[7]; | ||
49 | char outc; | ||
50 | |||
51 | outc = c; | ||
52 | 20 | ||
53 | args[0] = (unsigned long) "write"; | 21 | args[0] = (unsigned long) "write"; |
54 | args[1] = 3; | 22 | args[1] = 3; |
55 | args[2] = 1; | 23 | args[2] = 1; |
56 | args[3] = (unsigned int) prom_stdout; | 24 | args[3] = (unsigned int) prom_stdout; |
57 | args[4] = (unsigned long) &outc; | 25 | args[4] = (unsigned long) buf; |
58 | args[5] = 1; | 26 | args[5] = (unsigned int) len; |
59 | args[6] = (unsigned long) -1; | 27 | args[6] = (unsigned long) -1; |
60 | 28 | ||
61 | p1275_cmd_direct(args); | 29 | p1275_cmd_direct(args); |
62 | 30 | ||
63 | if (args[6] == 1) | 31 | ret = (int) args[6]; |
64 | return 0; | 32 | if (ret < 0) |
65 | else | ||
66 | return -1; | 33 | return -1; |
34 | return ret; | ||
67 | } | 35 | } |
68 | 36 | ||
69 | /* Blocking version of get character routine above. */ | 37 | void prom_console_write_buf(const char *buf, int len) |
70 | char | ||
71 | prom_getchar(void) | ||
72 | { | 38 | { |
73 | int character; | 39 | while (len) { |
74 | while((character = prom_nbgetchar()) == -1) ; | 40 | int n = __prom_console_write_buf(buf, len); |
75 | return (char) character; | 41 | if (n < 0) |
76 | } | 42 | continue; |
77 | 43 | len -= n; | |
78 | /* Blocking version of put character routine above. */ | 44 | buf += len; |
79 | void | 45 | } |
80 | prom_putchar(char c) | ||
81 | { | ||
82 | prom_nbputchar(c); | ||
83 | } | ||
84 | |||
85 | void | ||
86 | prom_puts(const char *s, int len) | ||
87 | { | ||
88 | unsigned long args[7]; | ||
89 | |||
90 | args[0] = (unsigned long) "write"; | ||
91 | args[1] = 3; | ||
92 | args[2] = 1; | ||
93 | args[3] = (unsigned int) prom_stdout; | ||
94 | args[4] = (unsigned long) s; | ||
95 | args[5] = len; | ||
96 | args[6] = (unsigned long) -1; | ||
97 | |||
98 | p1275_cmd_direct(args); | ||
99 | } | 46 | } |
diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c deleted file mode 100644 index 46157d2aba0d..000000000000 --- a/arch/sparc/prom/devmap.c +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* | ||
2 | * promdevmap.c: Map device/IO areas to virtual addresses. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | |||
11 | #include <asm/openprom.h> | ||
12 | #include <asm/oplib.h> | ||
13 | |||
14 | extern void restore_current(void); | ||
15 | |||
16 | /* Just like the routines in palloc.c, these should not be used | ||
17 | * by the kernel at all. Bootloader facility mainly. And again, | ||
18 | * this is only available on V2 proms and above. | ||
19 | */ | ||
20 | |||
21 | /* Map physical device address 'paddr' in IO space 'ios' of size | ||
22 | * 'num_bytes' to a virtual address, with 'vhint' being a hint to | ||
23 | * the prom as to where you would prefer the mapping. We return | ||
24 | * where the prom actually mapped it. | ||
25 | */ | ||
26 | char * | ||
27 | prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) | ||
28 | { | ||
29 | unsigned long flags; | ||
30 | char *ret; | ||
31 | |||
32 | spin_lock_irqsave(&prom_lock, flags); | ||
33 | if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0; | ||
34 | else | ||
35 | ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, | ||
36 | num_bytes); | ||
37 | restore_current(); | ||
38 | spin_unlock_irqrestore(&prom_lock, flags); | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | /* Unmap an IO/device area that was mapped using the above routine. */ | ||
43 | void | ||
44 | prom_unmapio(char *vaddr, unsigned int num_bytes) | ||
45 | { | ||
46 | unsigned long flags; | ||
47 | |||
48 | if(num_bytes == 0x0) return; | ||
49 | spin_lock_irqsave(&prom_lock, flags); | ||
50 | (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); | ||
51 | restore_current(); | ||
52 | spin_unlock_irqrestore(&prom_lock, flags); | ||
53 | } | ||
diff --git a/arch/sparc/prom/devops_32.c b/arch/sparc/prom/devops_32.c deleted file mode 100644 index 9c5d4687242a..000000000000 --- a/arch/sparc/prom/devops_32.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * devops.c: Device operations using the PROM. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/sched.h> | ||
9 | |||
10 | #include <asm/openprom.h> | ||
11 | #include <asm/oplib.h> | ||
12 | |||
13 | extern void restore_current(void); | ||
14 | |||
15 | /* Open the device described by the string 'dstr'. Returns the handle | ||
16 | * to that device used for subsequent operations on that device. | ||
17 | * Returns -1 on failure. | ||
18 | */ | ||
19 | int | ||
20 | prom_devopen(char *dstr) | ||
21 | { | ||
22 | int handle; | ||
23 | unsigned long flags; | ||
24 | spin_lock_irqsave(&prom_lock, flags); | ||
25 | switch(prom_vers) { | ||
26 | case PROM_V0: | ||
27 | handle = (*(romvec->pv_v0devops.v0_devopen))(dstr); | ||
28 | if(handle == 0) handle = -1; | ||
29 | break; | ||
30 | case PROM_V2: | ||
31 | case PROM_V3: | ||
32 | handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr); | ||
33 | break; | ||
34 | default: | ||
35 | handle = -1; | ||
36 | break; | ||
37 | }; | ||
38 | restore_current(); | ||
39 | spin_unlock_irqrestore(&prom_lock, flags); | ||
40 | |||
41 | return handle; | ||
42 | } | ||
43 | |||
44 | /* Close the device described by device handle 'dhandle'. */ | ||
45 | int | ||
46 | prom_devclose(int dhandle) | ||
47 | { | ||
48 | unsigned long flags; | ||
49 | spin_lock_irqsave(&prom_lock, flags); | ||
50 | switch(prom_vers) { | ||
51 | case PROM_V0: | ||
52 | (*(romvec->pv_v0devops.v0_devclose))(dhandle); | ||
53 | break; | ||
54 | case PROM_V2: | ||
55 | case PROM_V3: | ||
56 | (*(romvec->pv_v2devops.v2_dev_close))(dhandle); | ||
57 | break; | ||
58 | default: | ||
59 | break; | ||
60 | }; | ||
61 | restore_current(); | ||
62 | spin_unlock_irqrestore(&prom_lock, flags); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* Seek to specified location described by 'seekhi' and 'seeklo' | ||
67 | * for device 'dhandle'. | ||
68 | */ | ||
69 | void | ||
70 | prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) | ||
71 | { | ||
72 | unsigned long flags; | ||
73 | spin_lock_irqsave(&prom_lock, flags); | ||
74 | switch(prom_vers) { | ||
75 | case PROM_V0: | ||
76 | (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo); | ||
77 | break; | ||
78 | case PROM_V2: | ||
79 | case PROM_V3: | ||
80 | (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo); | ||
81 | break; | ||
82 | default: | ||
83 | break; | ||
84 | }; | ||
85 | restore_current(); | ||
86 | spin_unlock_irqrestore(&prom_lock, flags); | ||
87 | } | ||
diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c deleted file mode 100644 index a017119e7ef1..000000000000 --- a/arch/sparc/prom/devops_64.c +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /* | ||
2 | * devops.c: Device operations using the PROM. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | */ | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | |||
11 | #include <asm/openprom.h> | ||
12 | #include <asm/oplib.h> | ||
13 | |||
14 | /* Open the device described by the string 'dstr'. Returns the handle | ||
15 | * to that device used for subsequent operations on that device. | ||
16 | * Returns 0 on failure. | ||
17 | */ | ||
18 | int | ||
19 | prom_devopen(const char *dstr) | ||
20 | { | ||
21 | unsigned long args[5]; | ||
22 | |||
23 | args[0] = (unsigned long) "open"; | ||
24 | args[1] = 1; | ||
25 | args[2] = 1; | ||
26 | args[3] = (unsigned long) dstr; | ||
27 | args[4] = (unsigned long) -1; | ||
28 | |||
29 | p1275_cmd_direct(args); | ||
30 | |||
31 | return (int) args[4]; | ||
32 | } | ||
33 | |||
34 | /* Close the device described by device handle 'dhandle'. */ | ||
35 | int | ||
36 | prom_devclose(int dhandle) | ||
37 | { | ||
38 | unsigned long args[4]; | ||
39 | |||
40 | args[0] = (unsigned long) "close"; | ||
41 | args[1] = 1; | ||
42 | args[2] = 0; | ||
43 | args[3] = (unsigned int) dhandle; | ||
44 | |||
45 | p1275_cmd_direct(args); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | /* Seek to specified location described by 'seekhi' and 'seeklo' | ||
51 | * for device 'dhandle'. | ||
52 | */ | ||
53 | void | ||
54 | prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) | ||
55 | { | ||
56 | unsigned long args[7]; | ||
57 | |||
58 | args[0] = (unsigned long) "seek"; | ||
59 | args[1] = 3; | ||
60 | args[2] = 1; | ||
61 | args[3] = (unsigned int) dhandle; | ||
62 | args[4] = seekhi; | ||
63 | args[5] = seeklo; | ||
64 | args[6] = (unsigned long) -1; | ||
65 | |||
66 | p1275_cmd_direct(args); | ||
67 | } | ||
diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c index ccb36c7f9b8c..26c64cea3c9c 100644 --- a/arch/sparc/prom/init_32.c +++ b/arch/sparc/prom/init_32.c | |||
@@ -20,7 +20,7 @@ enum prom_major_version prom_vers; | |||
20 | unsigned int prom_rev, prom_prev; | 20 | unsigned int prom_rev, prom_prev; |
21 | 21 | ||
22 | /* The root node of the prom device tree. */ | 22 | /* The root node of the prom device tree. */ |
23 | int prom_root_node; | 23 | phandle prom_root_node; |
24 | EXPORT_SYMBOL(prom_root_node); | 24 | EXPORT_SYMBOL(prom_root_node); |
25 | 25 | ||
26 | /* Pointer to the device tree operations structure. */ | 26 | /* Pointer to the device tree operations structure. */ |
@@ -53,14 +53,14 @@ void __init prom_init(struct linux_romvec *rp) | |||
53 | romvec->pv_romvers); | 53 | romvec->pv_romvers); |
54 | prom_halt(); | 54 | prom_halt(); |
55 | break; | 55 | break; |
56 | }; | 56 | } |
57 | 57 | ||
58 | prom_rev = romvec->pv_plugin_revision; | 58 | prom_rev = romvec->pv_plugin_revision; |
59 | prom_prev = romvec->pv_printrev; | 59 | prom_prev = romvec->pv_printrev; |
60 | prom_nodeops = romvec->pv_nodeops; | 60 | prom_nodeops = romvec->pv_nodeops; |
61 | 61 | ||
62 | prom_root_node = prom_getsibling(0); | 62 | prom_root_node = prom_getsibling(0); |
63 | if((prom_root_node == 0) || (prom_root_node == -1)) | 63 | if ((prom_root_node == 0) || ((s32)prom_root_node == -1)) |
64 | prom_halt(); | 64 | prom_halt(); |
65 | 65 | ||
66 | if((((unsigned long) prom_nodeops) == 0) || | 66 | if((((unsigned long) prom_nodeops) == 0) || |
diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c index 7b00f89490a4..5016c5e20575 100644 --- a/arch/sparc/prom/init_64.c +++ b/arch/sparc/prom/init_64.c | |||
@@ -18,8 +18,8 @@ | |||
18 | char prom_version[80]; | 18 | char prom_version[80]; |
19 | 19 | ||
20 | /* The root node of the prom device tree. */ | 20 | /* The root node of the prom device tree. */ |
21 | int prom_stdin, prom_stdout; | 21 | int prom_stdout; |
22 | int prom_chosen_node; | 22 | phandle prom_chosen_node; |
23 | 23 | ||
24 | /* You must call prom_init() before you attempt to use any of the | 24 | /* You must call prom_init() before you attempt to use any of the |
25 | * routines in the prom library. It returns 0 on success, 1 on | 25 | * routines in the prom library. It returns 0 on success, 1 on |
@@ -30,19 +30,18 @@ extern void prom_cif_init(void *, void *); | |||
30 | 30 | ||
31 | void __init prom_init(void *cif_handler, void *cif_stack) | 31 | void __init prom_init(void *cif_handler, void *cif_stack) |
32 | { | 32 | { |
33 | int node; | 33 | phandle node; |
34 | 34 | ||
35 | prom_cif_init(cif_handler, cif_stack); | 35 | prom_cif_init(cif_handler, cif_stack); |
36 | 36 | ||
37 | prom_chosen_node = prom_finddevice(prom_chosen_path); | 37 | prom_chosen_node = prom_finddevice(prom_chosen_path); |
38 | if (!prom_chosen_node || prom_chosen_node == -1) | 38 | if (!prom_chosen_node || (s32)prom_chosen_node == -1) |
39 | prom_halt(); | 39 | prom_halt(); |
40 | 40 | ||
41 | prom_stdin = prom_getint(prom_chosen_node, "stdin"); | ||
42 | prom_stdout = prom_getint(prom_chosen_node, "stdout"); | 41 | prom_stdout = prom_getint(prom_chosen_node, "stdout"); |
43 | 42 | ||
44 | node = prom_finddevice("/openprom"); | 43 | node = prom_finddevice("/openprom"); |
45 | if (!node || node == -1) | 44 | if (!node || (s32)node == -1) |
46 | prom_halt(); | 45 | prom_halt(); |
47 | 46 | ||
48 | prom_getstring(node, "version", prom_version, sizeof(prom_version)); | 47 | prom_getstring(node, "version", prom_version, sizeof(prom_version)); |
diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c index fac7899a29c3..3f263a64857d 100644 --- a/arch/sparc/prom/memory.c +++ b/arch/sparc/prom/memory.c | |||
@@ -31,7 +31,8 @@ static int __init prom_meminit_v0(void) | |||
31 | static int __init prom_meminit_v2(void) | 31 | static int __init prom_meminit_v2(void) |
32 | { | 32 | { |
33 | struct linux_prom_registers reg[64]; | 33 | struct linux_prom_registers reg[64]; |
34 | int node, size, num_ents, i; | 34 | phandle node; |
35 | int size, num_ents, i; | ||
35 | 36 | ||
36 | node = prom_searchsiblings(prom_getchild(prom_root_node), "memory"); | 37 | node = prom_searchsiblings(prom_getchild(prom_root_node), "memory"); |
37 | size = prom_getproperty(node, "available", (char *) reg, sizeof(reg)); | 38 | size = prom_getproperty(node, "available", (char *) reg, sizeof(reg)); |
diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c index 4d61c540bb3d..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 | } |
@@ -70,7 +66,7 @@ prom_cmdline(void) | |||
70 | /* Drop into the prom, but completely terminate the program. | 66 | /* Drop into the prom, but completely terminate the program. |
71 | * No chance of continuing. | 67 | * No chance of continuing. |
72 | */ | 68 | */ |
73 | void | 69 | void __noreturn |
74 | prom_halt(void) | 70 | prom_halt(void) |
75 | { | 71 | { |
76 | unsigned long flags; | 72 | unsigned long flags; |
diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 6cb1581d6aef..e4f31d4d3715 100644 --- a/arch/sparc/prom/misc_64.c +++ b/arch/sparc/prom/misc_64.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include <asm/ldc.h> | 19 | #include <asm/ldc.h> |
20 | 20 | ||
21 | int prom_service_exists(const char *service_name) | 21 | static int prom_service_exists(const char *service_name) |
22 | { | 22 | { |
23 | unsigned long args[5]; | 23 | unsigned long args[5]; |
24 | 24 | ||
@@ -150,20 +150,6 @@ void prom_halt_power_off(void) | |||
150 | prom_halt(); | 150 | prom_halt(); |
151 | } | 151 | } |
152 | 152 | ||
153 | /* Set prom sync handler to call function 'funcp'. */ | ||
154 | void prom_setcallback(callback_func_t funcp) | ||
155 | { | ||
156 | unsigned long args[5]; | ||
157 | if (!funcp) | ||
158 | return; | ||
159 | args[0] = (unsigned long) "set-callback"; | ||
160 | args[1] = 1; | ||
161 | args[2] = 1; | ||
162 | args[3] = (unsigned long) funcp; | ||
163 | args[4] = (unsigned long) -1; | ||
164 | p1275_cmd_direct(args); | ||
165 | } | ||
166 | |||
167 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the | 153 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the |
168 | * format type. 'num_bytes' is the number of bytes that your idbuf | 154 | * format type. 'num_bytes' is the number of bytes that your idbuf |
169 | * has space for. Returns 0xff on error. | 155 | * has space for. Returns 0xff on error. |
@@ -183,7 +169,8 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes) | |||
183 | 169 | ||
184 | int prom_get_mmu_ihandle(void) | 170 | int prom_get_mmu_ihandle(void) |
185 | { | 171 | { |
186 | int node, ret; | 172 | phandle node; |
173 | int ret; | ||
187 | 174 | ||
188 | if (prom_mmu_ihandle_cache != 0) | 175 | if (prom_mmu_ihandle_cache != 0) |
189 | return prom_mmu_ihandle_cache; | 176 | return prom_mmu_ihandle_cache; |
@@ -201,7 +188,8 @@ int prom_get_mmu_ihandle(void) | |||
201 | static int prom_get_memory_ihandle(void) | 188 | static int prom_get_memory_ihandle(void) |
202 | { | 189 | { |
203 | static int memory_ihandle_cache; | 190 | static int memory_ihandle_cache; |
204 | int node, ret; | 191 | phandle node; |
192 | int ret; | ||
205 | 193 | ||
206 | if (memory_ihandle_cache != 0) | 194 | if (memory_ihandle_cache != 0) |
207 | return memory_ihandle_cache; | 195 | return memory_ihandle_cache; |
diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c index 4c4dc79f65af..0da8256cf76f 100644 --- a/arch/sparc/prom/mp.c +++ b/arch/sparc/prom/mp.c | |||
@@ -35,85 +35,7 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha | |||
35 | case PROM_V3: | 35 | case PROM_V3: |
36 | ret = (*(romvec->v3_cpustart))(cpunode, (int) ctable_reg, ctx, pc); | 36 | ret = (*(romvec->v3_cpustart))(cpunode, (int) ctable_reg, ctx, pc); |
37 | break; | 37 | break; |
38 | }; | 38 | } |
39 | restore_current(); | ||
40 | spin_unlock_irqrestore(&prom_lock, flags); | ||
41 | |||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | /* Stop CPU with device prom-tree node 'cpunode'. | ||
46 | * XXX Again, what does the return value really mean? XXX | ||
47 | */ | ||
48 | int | ||
49 | prom_stopcpu(int cpunode) | ||
50 | { | ||
51 | int ret; | ||
52 | unsigned long flags; | ||
53 | |||
54 | spin_lock_irqsave(&prom_lock, flags); | ||
55 | switch(prom_vers) { | ||
56 | case PROM_V0: | ||
57 | case PROM_V2: | ||
58 | default: | ||
59 | ret = -1; | ||
60 | break; | ||
61 | case PROM_V3: | ||
62 | ret = (*(romvec->v3_cpustop))(cpunode); | ||
63 | break; | ||
64 | }; | ||
65 | restore_current(); | ||
66 | spin_unlock_irqrestore(&prom_lock, flags); | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | /* Make CPU with device prom-tree node 'cpunode' idle. | ||
72 | * XXX Return value, anyone? XXX | ||
73 | */ | ||
74 | int | ||
75 | prom_idlecpu(int cpunode) | ||
76 | { | ||
77 | int ret; | ||
78 | unsigned long flags; | ||
79 | |||
80 | spin_lock_irqsave(&prom_lock, flags); | ||
81 | switch(prom_vers) { | ||
82 | case PROM_V0: | ||
83 | case PROM_V2: | ||
84 | default: | ||
85 | ret = -1; | ||
86 | break; | ||
87 | case PROM_V3: | ||
88 | ret = (*(romvec->v3_cpuidle))(cpunode); | ||
89 | break; | ||
90 | }; | ||
91 | restore_current(); | ||
92 | spin_unlock_irqrestore(&prom_lock, flags); | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | /* Resume the execution of CPU with nodeid 'cpunode'. | ||
98 | * XXX Come on, somebody has to know... XXX | ||
99 | */ | ||
100 | int | ||
101 | prom_restartcpu(int cpunode) | ||
102 | { | ||
103 | int ret; | ||
104 | unsigned long flags; | ||
105 | |||
106 | spin_lock_irqsave(&prom_lock, flags); | ||
107 | switch(prom_vers) { | ||
108 | case PROM_V0: | ||
109 | case PROM_V2: | ||
110 | default: | ||
111 | ret = -1; | ||
112 | break; | ||
113 | case PROM_V3: | ||
114 | ret = (*(romvec->v3_cpuresume))(cpunode); | ||
115 | break; | ||
116 | }; | ||
117 | restore_current(); | 39 | restore_current(); |
118 | spin_unlock_irqrestore(&prom_lock, flags); | 40 | spin_unlock_irqrestore(&prom_lock, flags); |
119 | 41 | ||
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c index fa6e4e219b9c..d9850c2b9bf2 100644 --- a/arch/sparc/prom/p1275.c +++ b/arch/sparc/prom/p1275.c | |||
@@ -39,7 +39,7 @@ void p1275_cmd_direct(unsigned long *args) | |||
39 | unsigned long flags; | 39 | unsigned long flags; |
40 | 40 | ||
41 | raw_local_save_flags(flags); | 41 | raw_local_save_flags(flags); |
42 | raw_local_irq_restore(PIL_NMI); | 42 | raw_local_irq_restore((unsigned long)PIL_NMI); |
43 | raw_spin_lock(&prom_entry_lock); | 43 | raw_spin_lock(&prom_entry_lock); |
44 | 44 | ||
45 | prom_world(1); | 45 | prom_world(1); |
diff --git a/arch/sparc/prom/palloc.c b/arch/sparc/prom/palloc.c deleted file mode 100644 index 2e2a88b211fb..000000000000 --- a/arch/sparc/prom/palloc.c +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * palloc.c: Memory allocation from the Sun PROM. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #include <asm/openprom.h> | ||
8 | #include <asm/oplib.h> | ||
9 | |||
10 | /* You should not call these routines after memory management | ||
11 | * has been initialized in the kernel, if fact you should not | ||
12 | * use these if at all possible in the kernel. They are mainly | ||
13 | * to be used for a bootloader for temporary allocations which | ||
14 | * it will free before jumping into the kernel it has loaded. | ||
15 | * | ||
16 | * Also, these routines don't work on V0 proms, only V2 and later. | ||
17 | */ | ||
18 | |||
19 | /* Allocate a chunk of memory of size 'num_bytes' giving a suggestion | ||
20 | * of virtual_hint as the preferred virtual base address of this chunk. | ||
21 | * There are no guarantees that you will get the allocation, or that | ||
22 | * the prom will abide by your "hint". So check your return value. | ||
23 | */ | ||
24 | char * | ||
25 | prom_alloc(char *virtual_hint, unsigned int num_bytes) | ||
26 | { | ||
27 | if(prom_vers == PROM_V0) return (char *) 0x0; | ||
28 | if(num_bytes == 0x0) return (char *) 0x0; | ||
29 | return (*(romvec->pv_v2devops.v2_dumb_mem_alloc))(virtual_hint, num_bytes); | ||
30 | } | ||
31 | |||
32 | /* Free a previously allocated chunk back to the prom at virtual address | ||
33 | * 'vaddr' of size 'num_bytes'. NOTE: This vaddr is not the hint you | ||
34 | * used for the allocation, but the virtual address the prom actually | ||
35 | * returned to you. They may be have been the same, they may have not, | ||
36 | * doesn't matter. | ||
37 | */ | ||
38 | void | ||
39 | prom_free(char *vaddr, unsigned int num_bytes) | ||
40 | { | ||
41 | if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return; | ||
42 | (*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes); | ||
43 | } | ||
diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c index ca869266b9f3..d9682f06b3b0 100644 --- a/arch/sparc/prom/printf.c +++ b/arch/sparc/prom/printf.c | |||
@@ -15,22 +15,45 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/spinlock.h> | ||
18 | 19 | ||
19 | #include <asm/openprom.h> | 20 | #include <asm/openprom.h> |
20 | #include <asm/oplib.h> | 21 | #include <asm/oplib.h> |
21 | 22 | ||
23 | #define CONSOLE_WRITE_BUF_SIZE 1024 | ||
24 | |||
22 | static char ppbuf[1024]; | 25 | static char ppbuf[1024]; |
26 | static char console_write_buf[CONSOLE_WRITE_BUF_SIZE]; | ||
27 | static DEFINE_RAW_SPINLOCK(console_write_lock); | ||
23 | 28 | ||
24 | void notrace prom_write(const char *buf, unsigned int n) | 29 | void notrace prom_write(const char *buf, unsigned int n) |
25 | { | 30 | { |
26 | char ch; | 31 | unsigned int dest_len; |
32 | unsigned long flags; | ||
33 | char *dest; | ||
34 | |||
35 | dest = console_write_buf; | ||
36 | raw_spin_lock_irqsave(&console_write_lock, flags); | ||
27 | 37 | ||
28 | while (n != 0) { | 38 | dest_len = 0; |
29 | --n; | 39 | while (n-- != 0) { |
30 | if ((ch = *buf++) == '\n') | 40 | char ch = *buf++; |
31 | prom_putchar('\r'); | 41 | if (ch == '\n') { |
32 | prom_putchar(ch); | 42 | *dest++ = '\r'; |
43 | dest_len++; | ||
44 | } | ||
45 | *dest++ = ch; | ||
46 | dest_len++; | ||
47 | if (dest_len >= CONSOLE_WRITE_BUF_SIZE - 1) { | ||
48 | prom_console_write_buf(console_write_buf, dest_len); | ||
49 | dest = console_write_buf; | ||
50 | dest_len = 0; | ||
51 | } | ||
33 | } | 52 | } |
53 | if (dest_len) | ||
54 | prom_console_write_buf(console_write_buf, dest_len); | ||
55 | |||
56 | raw_spin_unlock_irqrestore(&console_write_lock, flags); | ||
34 | } | 57 | } |
35 | 58 | ||
36 | void notrace prom_printf(const char *fmt, ...) | 59 | void notrace prom_printf(const char *fmt, ...) |
diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c index aeff43e44e45..0857aa9e839d 100644 --- a/arch/sparc/prom/ranges.c +++ b/arch/sparc/prom/ranges.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <asm/types.h> | 13 | #include <asm/types.h> |
14 | #include <asm/system.h> | 14 | #include <asm/system.h> |
15 | 15 | ||
16 | struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; | 16 | static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; |
17 | int num_obio_ranges; | 17 | static int num_obio_ranges; |
18 | 18 | ||
19 | /* Adjust register values based upon the ranges parameters. */ | 19 | /* Adjust register values based upon the ranges parameters. */ |
20 | static void | 20 | static void |
@@ -35,7 +35,7 @@ prom_adjust_regs(struct linux_prom_registers *regp, int nregs, | |||
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
38 | void | 38 | static void |
39 | prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, | 39 | prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, |
40 | struct linux_prom_ranges *ranges2, int nranges2) | 40 | struct linux_prom_ranges *ranges2, int nranges2) |
41 | { | 41 | { |
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(prom_apply_obio_ranges); | |||
68 | 68 | ||
69 | void __init prom_ranges_init(void) | 69 | void __init prom_ranges_init(void) |
70 | { | 70 | { |
71 | int node, obio_node; | 71 | phandle node, obio_node; |
72 | int success; | 72 | int success; |
73 | 73 | ||
74 | num_obio_ranges = 0; | 74 | num_obio_ranges = 0; |
@@ -89,8 +89,8 @@ void __init prom_ranges_init(void) | |||
89 | prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges); | 89 | prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges); |
90 | } | 90 | } |
91 | 91 | ||
92 | void | 92 | void prom_apply_generic_ranges(phandle node, phandle parent, |
93 | prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs) | 93 | struct linux_prom_registers *regs, int nregs) |
94 | { | 94 | { |
95 | int success; | 95 | int success; |
96 | int num_ranges; | 96 | int num_ranges; |
diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c index b21592f8e3fe..f30e8d038f01 100644 --- a/arch/sparc/prom/tree_32.c +++ b/arch/sparc/prom/tree_32.c | |||
@@ -20,10 +20,10 @@ extern void restore_current(void); | |||
20 | static char promlib_buf[128]; | 20 | static char promlib_buf[128]; |
21 | 21 | ||
22 | /* Internal version of prom_getchild that does not alter return values. */ | 22 | /* Internal version of prom_getchild that does not alter return values. */ |
23 | int __prom_getchild(int node) | 23 | static phandle __prom_getchild(phandle node) |
24 | { | 24 | { |
25 | unsigned long flags; | 25 | unsigned long flags; |
26 | int cnode; | 26 | phandle cnode; |
27 | 27 | ||
28 | spin_lock_irqsave(&prom_lock, flags); | 28 | spin_lock_irqsave(&prom_lock, flags); |
29 | cnode = prom_nodeops->no_child(node); | 29 | cnode = prom_nodeops->no_child(node); |
@@ -36,15 +36,15 @@ int __prom_getchild(int node) | |||
36 | /* Return the child of node 'node' or zero if no this node has no | 36 | /* Return the child of node 'node' or zero if no this node has no |
37 | * direct descendent. | 37 | * direct descendent. |
38 | */ | 38 | */ |
39 | int prom_getchild(int node) | 39 | phandle prom_getchild(phandle node) |
40 | { | 40 | { |
41 | int cnode; | 41 | phandle cnode; |
42 | 42 | ||
43 | if (node == -1) | 43 | if ((s32)node == -1) |
44 | return 0; | 44 | return 0; |
45 | 45 | ||
46 | cnode = __prom_getchild(node); | 46 | cnode = __prom_getchild(node); |
47 | if (cnode == 0 || cnode == -1) | 47 | if (cnode == 0 || (s32)cnode == -1) |
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | return cnode; | 50 | return cnode; |
@@ -52,10 +52,10 @@ int prom_getchild(int node) | |||
52 | EXPORT_SYMBOL(prom_getchild); | 52 | EXPORT_SYMBOL(prom_getchild); |
53 | 53 | ||
54 | /* Internal version of prom_getsibling that does not alter return values. */ | 54 | /* Internal version of prom_getsibling that does not alter return values. */ |
55 | int __prom_getsibling(int node) | 55 | static phandle __prom_getsibling(phandle node) |
56 | { | 56 | { |
57 | unsigned long flags; | 57 | unsigned long flags; |
58 | int cnode; | 58 | phandle cnode; |
59 | 59 | ||
60 | spin_lock_irqsave(&prom_lock, flags); | 60 | spin_lock_irqsave(&prom_lock, flags); |
61 | cnode = prom_nodeops->no_nextnode(node); | 61 | cnode = prom_nodeops->no_nextnode(node); |
@@ -68,15 +68,15 @@ int __prom_getsibling(int node) | |||
68 | /* Return the next sibling of node 'node' or zero if no more siblings | 68 | /* Return the next sibling of node 'node' or zero if no more siblings |
69 | * at this level of depth in the tree. | 69 | * at this level of depth in the tree. |
70 | */ | 70 | */ |
71 | int prom_getsibling(int node) | 71 | phandle prom_getsibling(phandle node) |
72 | { | 72 | { |
73 | int sibnode; | 73 | phandle sibnode; |
74 | 74 | ||
75 | if (node == -1) | 75 | if ((s32)node == -1) |
76 | return 0; | 76 | return 0; |
77 | 77 | ||
78 | sibnode = __prom_getsibling(node); | 78 | sibnode = __prom_getsibling(node); |
79 | if (sibnode == 0 || sibnode == -1) | 79 | if (sibnode == 0 || (s32)sibnode == -1) |
80 | return 0; | 80 | return 0; |
81 | 81 | ||
82 | return sibnode; | 82 | return sibnode; |
@@ -86,7 +86,7 @@ EXPORT_SYMBOL(prom_getsibling); | |||
86 | /* Return the length in bytes of property 'prop' at node 'node'. | 86 | /* Return the length in bytes of property 'prop' at node 'node'. |
87 | * Return -1 on error. | 87 | * Return -1 on error. |
88 | */ | 88 | */ |
89 | int prom_getproplen(int node, const char *prop) | 89 | int prom_getproplen(phandle node, const char *prop) |
90 | { | 90 | { |
91 | int ret; | 91 | int ret; |
92 | unsigned long flags; | 92 | unsigned long flags; |
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(prom_getproplen); | |||
106 | * 'buffer' which has a size of 'bufsize'. If the acquisition | 106 | * 'buffer' which has a size of 'bufsize'. If the acquisition |
107 | * was successful the length will be returned, else -1 is returned. | 107 | * was successful the length will be returned, else -1 is returned. |
108 | */ | 108 | */ |
109 | int prom_getproperty(int node, const char *prop, char *buffer, int bufsize) | 109 | int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize) |
110 | { | 110 | { |
111 | int plen, ret; | 111 | int plen, ret; |
112 | unsigned long flags; | 112 | unsigned long flags; |
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(prom_getproperty); | |||
126 | /* Acquire an integer property and return its value. Returns -1 | 126 | /* Acquire an integer property and return its value. Returns -1 |
127 | * on failure. | 127 | * on failure. |
128 | */ | 128 | */ |
129 | int prom_getint(int node, char *prop) | 129 | int prom_getint(phandle node, char *prop) |
130 | { | 130 | { |
131 | static int intprop; | 131 | static int intprop; |
132 | 132 | ||
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(prom_getint); | |||
140 | /* Acquire an integer property, upon error return the passed default | 140 | /* Acquire an integer property, upon error return the passed default |
141 | * integer. | 141 | * integer. |
142 | */ | 142 | */ |
143 | int prom_getintdefault(int node, char *property, int deflt) | 143 | int prom_getintdefault(phandle node, char *property, int deflt) |
144 | { | 144 | { |
145 | int retval; | 145 | int retval; |
146 | 146 | ||
@@ -152,7 +152,7 @@ int prom_getintdefault(int node, char *property, int deflt) | |||
152 | EXPORT_SYMBOL(prom_getintdefault); | 152 | EXPORT_SYMBOL(prom_getintdefault); |
153 | 153 | ||
154 | /* Acquire a boolean property, 1=TRUE 0=FALSE. */ | 154 | /* Acquire a boolean property, 1=TRUE 0=FALSE. */ |
155 | int prom_getbool(int node, char *prop) | 155 | int prom_getbool(phandle node, char *prop) |
156 | { | 156 | { |
157 | int retval; | 157 | int retval; |
158 | 158 | ||
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(prom_getbool); | |||
166 | * string on error. The char pointer is the user supplied string | 166 | * string on error. The char pointer is the user supplied string |
167 | * buffer. | 167 | * buffer. |
168 | */ | 168 | */ |
169 | void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) | 169 | void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size) |
170 | { | 170 | { |
171 | int len; | 171 | int len; |
172 | 172 | ||
@@ -177,27 +177,14 @@ void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) | |||
177 | EXPORT_SYMBOL(prom_getstring); | 177 | EXPORT_SYMBOL(prom_getstring); |
178 | 178 | ||
179 | 179 | ||
180 | /* Does the device at node 'node' have name 'name'? | ||
181 | * YES = 1 NO = 0 | ||
182 | */ | ||
183 | int prom_nodematch(int node, char *name) | ||
184 | { | ||
185 | int error; | ||
186 | |||
187 | static char namebuf[128]; | ||
188 | error = prom_getproperty(node, "name", namebuf, sizeof(namebuf)); | ||
189 | if (error == -1) return 0; | ||
190 | if(strcmp(namebuf, name) == 0) return 1; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | /* Search siblings at 'node_start' for a node with name | 180 | /* Search siblings at 'node_start' for a node with name |
195 | * 'nodename'. Return node if successful, zero if not. | 181 | * 'nodename'. Return node if successful, zero if not. |
196 | */ | 182 | */ |
197 | int prom_searchsiblings(int node_start, char *nodename) | 183 | phandle prom_searchsiblings(phandle node_start, char *nodename) |
198 | { | 184 | { |
199 | 185 | ||
200 | int thisnode, error; | 186 | phandle thisnode; |
187 | int error; | ||
201 | 188 | ||
202 | for(thisnode = node_start; thisnode; | 189 | for(thisnode = node_start; thisnode; |
203 | thisnode=prom_getsibling(thisnode)) { | 190 | thisnode=prom_getsibling(thisnode)) { |
@@ -213,7 +200,7 @@ int prom_searchsiblings(int node_start, char *nodename) | |||
213 | EXPORT_SYMBOL(prom_searchsiblings); | 200 | EXPORT_SYMBOL(prom_searchsiblings); |
214 | 201 | ||
215 | /* Interal version of nextprop that does not alter return values. */ | 202 | /* Interal version of nextprop that does not alter return values. */ |
216 | char * __prom_nextprop(int node, char * oprop) | 203 | static char *__prom_nextprop(phandle node, char * oprop) |
217 | { | 204 | { |
218 | unsigned long flags; | 205 | unsigned long flags; |
219 | char *prop; | 206 | char *prop; |
@@ -226,35 +213,24 @@ char * __prom_nextprop(int node, char * oprop) | |||
226 | return prop; | 213 | return prop; |
227 | } | 214 | } |
228 | 215 | ||
229 | /* Return the first property name for node 'node'. */ | ||
230 | /* buffer is unused argument, but as v9 uses it, we need to have the same interface */ | ||
231 | char * prom_firstprop(int node, char *bufer) | ||
232 | { | ||
233 | if (node == 0 || node == -1) | ||
234 | return ""; | ||
235 | |||
236 | return __prom_nextprop(node, ""); | ||
237 | } | ||
238 | EXPORT_SYMBOL(prom_firstprop); | ||
239 | |||
240 | /* Return the property type string after property type 'oprop' | 216 | /* Return the property type string after property type 'oprop' |
241 | * at node 'node' . Returns empty string if no more | 217 | * at node 'node' . Returns empty string if no more |
242 | * property types for this node. | 218 | * property types for this node. |
243 | */ | 219 | */ |
244 | char * prom_nextprop(int node, char *oprop, char *buffer) | 220 | char *prom_nextprop(phandle node, char *oprop, char *buffer) |
245 | { | 221 | { |
246 | if (node == 0 || node == -1) | 222 | if (node == 0 || (s32)node == -1) |
247 | return ""; | 223 | return ""; |
248 | 224 | ||
249 | return __prom_nextprop(node, oprop); | 225 | return __prom_nextprop(node, oprop); |
250 | } | 226 | } |
251 | EXPORT_SYMBOL(prom_nextprop); | 227 | EXPORT_SYMBOL(prom_nextprop); |
252 | 228 | ||
253 | int prom_finddevice(char *name) | 229 | phandle prom_finddevice(char *name) |
254 | { | 230 | { |
255 | char nbuf[128]; | 231 | char nbuf[128]; |
256 | char *s = name, *d; | 232 | char *s = name, *d; |
257 | int node = prom_root_node, node2; | 233 | phandle node = prom_root_node, node2; |
258 | unsigned int which_io, phys_addr; | 234 | unsigned int which_io, phys_addr; |
259 | struct linux_prom_registers reg[PROMREG_MAX]; | 235 | struct linux_prom_registers reg[PROMREG_MAX]; |
260 | 236 | ||
@@ -277,7 +253,7 @@ int prom_finddevice(char *name) | |||
277 | if (d != s + 3 && (!*d || *d == '/') | 253 | if (d != s + 3 && (!*d || *d == '/') |
278 | && d <= s + 3 + 8) { | 254 | && d <= s + 3 + 8) { |
279 | node2 = node; | 255 | node2 = node; |
280 | while (node2 && node2 != -1) { | 256 | while (node2 && (s32)node2 != -1) { |
281 | if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) { | 257 | if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) { |
282 | if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) { | 258 | if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) { |
283 | node = node2; | 259 | node = node2; |
@@ -285,7 +261,7 @@ int prom_finddevice(char *name) | |||
285 | } | 261 | } |
286 | } | 262 | } |
287 | node2 = prom_getsibling(node2); | 263 | node2 = prom_getsibling(node2); |
288 | if (!node2 || node2 == -1) | 264 | if (!node2 || (s32)node2 == -1) |
289 | break; | 265 | break; |
290 | node2 = prom_searchsiblings(prom_getsibling(node2), nbuf); | 266 | node2 = prom_searchsiblings(prom_getsibling(node2), nbuf); |
291 | } | 267 | } |
@@ -298,29 +274,18 @@ int prom_finddevice(char *name) | |||
298 | } | 274 | } |
299 | EXPORT_SYMBOL(prom_finddevice); | 275 | EXPORT_SYMBOL(prom_finddevice); |
300 | 276 | ||
301 | int prom_node_has_property(int node, char *prop) | ||
302 | { | ||
303 | char *current_property = ""; | ||
304 | |||
305 | do { | ||
306 | current_property = prom_nextprop(node, current_property, NULL); | ||
307 | if(!strcmp(current_property, prop)) | ||
308 | return 1; | ||
309 | } while (*current_property); | ||
310 | return 0; | ||
311 | } | ||
312 | EXPORT_SYMBOL(prom_node_has_property); | ||
313 | |||
314 | /* Set property 'pname' at node 'node' to value 'value' which has a length | 277 | /* Set property 'pname' at node 'node' to value 'value' which has a length |
315 | * of 'size' bytes. Return the number of bytes the prom accepted. | 278 | * of 'size' bytes. Return the number of bytes the prom accepted. |
316 | */ | 279 | */ |
317 | int prom_setprop(int node, const char *pname, char *value, int size) | 280 | int prom_setprop(phandle node, const char *pname, char *value, int size) |
318 | { | 281 | { |
319 | unsigned long flags; | 282 | unsigned long flags; |
320 | int ret; | 283 | int ret; |
321 | 284 | ||
322 | if(size == 0) return 0; | 285 | if (size == 0) |
323 | if((pname == 0) || (value == 0)) return 0; | 286 | return 0; |
287 | if ((pname == NULL) || (value == NULL)) | ||
288 | return 0; | ||
324 | spin_lock_irqsave(&prom_lock, flags); | 289 | spin_lock_irqsave(&prom_lock, flags); |
325 | ret = prom_nodeops->no_setprop(node, pname, value, size); | 290 | ret = prom_nodeops->no_setprop(node, pname, value, size); |
326 | restore_current(); | 291 | restore_current(); |
@@ -329,30 +294,16 @@ int prom_setprop(int node, const char *pname, char *value, int size) | |||
329 | } | 294 | } |
330 | EXPORT_SYMBOL(prom_setprop); | 295 | EXPORT_SYMBOL(prom_setprop); |
331 | 296 | ||
332 | int prom_inst2pkg(int inst) | 297 | phandle prom_inst2pkg(int inst) |
333 | { | 298 | { |
334 | int node; | 299 | phandle node; |
335 | unsigned long flags; | 300 | unsigned long flags; |
336 | 301 | ||
337 | spin_lock_irqsave(&prom_lock, flags); | 302 | spin_lock_irqsave(&prom_lock, flags); |
338 | node = (*romvec->pv_v2devops.v2_inst2pkg)(inst); | 303 | node = (*romvec->pv_v2devops.v2_inst2pkg)(inst); |
339 | restore_current(); | 304 | restore_current(); |
340 | spin_unlock_irqrestore(&prom_lock, flags); | 305 | spin_unlock_irqrestore(&prom_lock, flags); |
341 | if (node == -1) return 0; | 306 | if ((s32)node == -1) |
342 | return node; | 307 | return 0; |
343 | } | ||
344 | |||
345 | /* Return 'node' assigned to a particular prom 'path' | ||
346 | * FIXME: Should work for v0 as well | ||
347 | */ | ||
348 | int prom_pathtoinode(char *path) | ||
349 | { | ||
350 | int node, inst; | ||
351 | |||
352 | inst = prom_devopen (path); | ||
353 | if (inst == -1) return 0; | ||
354 | node = prom_inst2pkg (inst); | ||
355 | prom_devclose (inst); | ||
356 | if (node == -1) return 0; | ||
357 | return node; | 308 | return node; |
358 | } | 309 | } |
diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c index 9d3f9137a43a..92204c3800b5 100644 --- a/arch/sparc/prom/tree_64.c +++ b/arch/sparc/prom/tree_64.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/oplib.h> | 16 | #include <asm/oplib.h> |
17 | #include <asm/ldc.h> | 17 | #include <asm/ldc.h> |
18 | 18 | ||
19 | static int prom_node_to_node(const char *type, int node) | 19 | static phandle prom_node_to_node(const char *type, phandle node) |
20 | { | 20 | { |
21 | unsigned long args[5]; | 21 | unsigned long args[5]; |
22 | 22 | ||
@@ -28,38 +28,38 @@ static int prom_node_to_node(const char *type, int node) | |||
28 | 28 | ||
29 | p1275_cmd_direct(args); | 29 | p1275_cmd_direct(args); |
30 | 30 | ||
31 | return (int) args[4]; | 31 | return (phandle) args[4]; |
32 | } | 32 | } |
33 | 33 | ||
34 | /* Return the child of node 'node' or zero if no this node has no | 34 | /* Return the child of node 'node' or zero if no this node has no |
35 | * direct descendent. | 35 | * direct descendent. |
36 | */ | 36 | */ |
37 | inline int __prom_getchild(int node) | 37 | inline phandle __prom_getchild(phandle node) |
38 | { | 38 | { |
39 | return prom_node_to_node("child", node); | 39 | return prom_node_to_node("child", node); |
40 | } | 40 | } |
41 | 41 | ||
42 | inline int prom_getchild(int node) | 42 | inline phandle prom_getchild(phandle node) |
43 | { | 43 | { |
44 | int cnode; | 44 | phandle cnode; |
45 | 45 | ||
46 | if (node == -1) | 46 | if ((s32)node == -1) |
47 | return 0; | 47 | return 0; |
48 | cnode = __prom_getchild(node); | 48 | cnode = __prom_getchild(node); |
49 | if (cnode == -1) | 49 | if ((s32)cnode == -1) |
50 | return 0; | 50 | return 0; |
51 | return cnode; | 51 | return cnode; |
52 | } | 52 | } |
53 | EXPORT_SYMBOL(prom_getchild); | 53 | EXPORT_SYMBOL(prom_getchild); |
54 | 54 | ||
55 | inline int prom_getparent(int node) | 55 | inline phandle prom_getparent(phandle node) |
56 | { | 56 | { |
57 | int cnode; | 57 | phandle cnode; |
58 | 58 | ||
59 | if (node == -1) | 59 | if ((s32)node == -1) |
60 | return 0; | 60 | return 0; |
61 | cnode = prom_node_to_node("parent", node); | 61 | cnode = prom_node_to_node("parent", node); |
62 | if (cnode == -1) | 62 | if ((s32)cnode == -1) |
63 | return 0; | 63 | return 0; |
64 | return cnode; | 64 | return cnode; |
65 | } | 65 | } |
@@ -67,19 +67,19 @@ inline int prom_getparent(int node) | |||
67 | /* Return the next sibling of node 'node' or zero if no more siblings | 67 | /* Return the next sibling of node 'node' or zero if no more siblings |
68 | * at this level of depth in the tree. | 68 | * at this level of depth in the tree. |
69 | */ | 69 | */ |
70 | inline int __prom_getsibling(int node) | 70 | inline phandle __prom_getsibling(phandle node) |
71 | { | 71 | { |
72 | return prom_node_to_node(prom_peer_name, node); | 72 | return prom_node_to_node(prom_peer_name, node); |
73 | } | 73 | } |
74 | 74 | ||
75 | inline int prom_getsibling(int node) | 75 | inline phandle prom_getsibling(phandle node) |
76 | { | 76 | { |
77 | int sibnode; | 77 | phandle sibnode; |
78 | 78 | ||
79 | if (node == -1) | 79 | if ((s32)node == -1) |
80 | return 0; | 80 | return 0; |
81 | sibnode = __prom_getsibling(node); | 81 | sibnode = __prom_getsibling(node); |
82 | if (sibnode == -1) | 82 | if ((s32)sibnode == -1) |
83 | return 0; | 83 | return 0; |
84 | 84 | ||
85 | return sibnode; | 85 | return sibnode; |
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(prom_getsibling); | |||
89 | /* Return the length in bytes of property 'prop' at node 'node'. | 89 | /* Return the length in bytes of property 'prop' at node 'node'. |
90 | * Return -1 on error. | 90 | * Return -1 on error. |
91 | */ | 91 | */ |
92 | inline int prom_getproplen(int node, const char *prop) | 92 | inline int prom_getproplen(phandle node, const char *prop) |
93 | { | 93 | { |
94 | unsigned long args[6]; | 94 | unsigned long args[6]; |
95 | 95 | ||
@@ -113,7 +113,7 @@ EXPORT_SYMBOL(prom_getproplen); | |||
113 | * 'buffer' which has a size of 'bufsize'. If the acquisition | 113 | * 'buffer' which has a size of 'bufsize'. If the acquisition |
114 | * was successful the length will be returned, else -1 is returned. | 114 | * was successful the length will be returned, else -1 is returned. |
115 | */ | 115 | */ |
116 | inline int prom_getproperty(int node, const char *prop, | 116 | inline int prom_getproperty(phandle node, const char *prop, |
117 | char *buffer, int bufsize) | 117 | char *buffer, int bufsize) |
118 | { | 118 | { |
119 | unsigned long args[8]; | 119 | unsigned long args[8]; |
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(prom_getproperty); | |||
141 | /* Acquire an integer property and return its value. Returns -1 | 141 | /* Acquire an integer property and return its value. Returns -1 |
142 | * on failure. | 142 | * on failure. |
143 | */ | 143 | */ |
144 | inline int prom_getint(int node, const char *prop) | 144 | inline int prom_getint(phandle node, const char *prop) |
145 | { | 145 | { |
146 | int intprop; | 146 | int intprop; |
147 | 147 | ||
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(prom_getint); | |||
156 | * integer. | 156 | * integer. |
157 | */ | 157 | */ |
158 | 158 | ||
159 | int prom_getintdefault(int node, const char *property, int deflt) | 159 | int prom_getintdefault(phandle node, const char *property, int deflt) |
160 | { | 160 | { |
161 | int retval; | 161 | int retval; |
162 | 162 | ||
@@ -169,7 +169,7 @@ int prom_getintdefault(int node, const char *property, int deflt) | |||
169 | EXPORT_SYMBOL(prom_getintdefault); | 169 | EXPORT_SYMBOL(prom_getintdefault); |
170 | 170 | ||
171 | /* Acquire a boolean property, 1=TRUE 0=FALSE. */ | 171 | /* Acquire a boolean property, 1=TRUE 0=FALSE. */ |
172 | int prom_getbool(int node, const char *prop) | 172 | int prom_getbool(phandle node, const char *prop) |
173 | { | 173 | { |
174 | int retval; | 174 | int retval; |
175 | 175 | ||
@@ -184,7 +184,8 @@ EXPORT_SYMBOL(prom_getbool); | |||
184 | * string on error. The char pointer is the user supplied string | 184 | * string on error. The char pointer is the user supplied string |
185 | * buffer. | 185 | * buffer. |
186 | */ | 186 | */ |
187 | void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) | 187 | void prom_getstring(phandle node, const char *prop, char *user_buf, |
188 | int ubuf_size) | ||
188 | { | 189 | { |
189 | int len; | 190 | int len; |
190 | 191 | ||
@@ -198,7 +199,7 @@ EXPORT_SYMBOL(prom_getstring); | |||
198 | /* Does the device at node 'node' have name 'name'? | 199 | /* Does the device at node 'node' have name 'name'? |
199 | * YES = 1 NO = 0 | 200 | * YES = 1 NO = 0 |
200 | */ | 201 | */ |
201 | int prom_nodematch(int node, const char *name) | 202 | int prom_nodematch(phandle node, const char *name) |
202 | { | 203 | { |
203 | char namebuf[128]; | 204 | char namebuf[128]; |
204 | prom_getproperty(node, "name", namebuf, sizeof(namebuf)); | 205 | prom_getproperty(node, "name", namebuf, sizeof(namebuf)); |
@@ -210,10 +211,10 @@ int prom_nodematch(int node, const char *name) | |||
210 | /* Search siblings at 'node_start' for a node with name | 211 | /* Search siblings at 'node_start' for a node with name |
211 | * 'nodename'. Return node if successful, zero if not. | 212 | * 'nodename'. Return node if successful, zero if not. |
212 | */ | 213 | */ |
213 | int prom_searchsiblings(int node_start, const char *nodename) | 214 | phandle prom_searchsiblings(phandle node_start, const char *nodename) |
214 | { | 215 | { |
215 | 216 | phandle thisnode; | |
216 | int thisnode, error; | 217 | int error; |
217 | char promlib_buf[128]; | 218 | char promlib_buf[128]; |
218 | 219 | ||
219 | for(thisnode = node_start; thisnode; | 220 | for(thisnode = node_start; thisnode; |
@@ -234,12 +235,12 @@ static const char *prom_nextprop_name = "nextprop"; | |||
234 | /* Return the first property type for node 'node'. | 235 | /* Return the first property type for node 'node'. |
235 | * buffer should be at least 32B in length | 236 | * buffer should be at least 32B in length |
236 | */ | 237 | */ |
237 | inline char *prom_firstprop(int node, char *buffer) | 238 | inline char *prom_firstprop(phandle node, char *buffer) |
238 | { | 239 | { |
239 | unsigned long args[7]; | 240 | unsigned long args[7]; |
240 | 241 | ||
241 | *buffer = 0; | 242 | *buffer = 0; |
242 | if (node == -1) | 243 | if ((s32)node == -1) |
243 | return buffer; | 244 | return buffer; |
244 | 245 | ||
245 | args[0] = (unsigned long) prom_nextprop_name; | 246 | args[0] = (unsigned long) prom_nextprop_name; |
@@ -260,12 +261,12 @@ EXPORT_SYMBOL(prom_firstprop); | |||
260 | * at node 'node' . Returns NULL string if no more | 261 | * at node 'node' . Returns NULL string if no more |
261 | * property types for this node. | 262 | * property types for this node. |
262 | */ | 263 | */ |
263 | inline char *prom_nextprop(int node, const char *oprop, char *buffer) | 264 | inline char *prom_nextprop(phandle node, const char *oprop, char *buffer) |
264 | { | 265 | { |
265 | unsigned long args[7]; | 266 | unsigned long args[7]; |
266 | char buf[32]; | 267 | char buf[32]; |
267 | 268 | ||
268 | if (node == -1) { | 269 | if ((s32)node == -1) { |
269 | *buffer = 0; | 270 | *buffer = 0; |
270 | return buffer; | 271 | return buffer; |
271 | } | 272 | } |
@@ -288,8 +289,7 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer) | |||
288 | } | 289 | } |
289 | EXPORT_SYMBOL(prom_nextprop); | 290 | EXPORT_SYMBOL(prom_nextprop); |
290 | 291 | ||
291 | int | 292 | phandle prom_finddevice(const char *name) |
292 | prom_finddevice(const char *name) | ||
293 | { | 293 | { |
294 | unsigned long args[5]; | 294 | unsigned long args[5]; |
295 | 295 | ||
@@ -307,7 +307,7 @@ prom_finddevice(const char *name) | |||
307 | } | 307 | } |
308 | EXPORT_SYMBOL(prom_finddevice); | 308 | EXPORT_SYMBOL(prom_finddevice); |
309 | 309 | ||
310 | int prom_node_has_property(int node, const char *prop) | 310 | int prom_node_has_property(phandle node, const char *prop) |
311 | { | 311 | { |
312 | char buf [32]; | 312 | char buf [32]; |
313 | 313 | ||
@@ -325,7 +325,7 @@ EXPORT_SYMBOL(prom_node_has_property); | |||
325 | * of 'size' bytes. Return the number of bytes the prom accepted. | 325 | * of 'size' bytes. Return the number of bytes the prom accepted. |
326 | */ | 326 | */ |
327 | int | 327 | int |
328 | prom_setprop(int node, const char *pname, char *value, int size) | 328 | prom_setprop(phandle node, const char *pname, char *value, int size) |
329 | { | 329 | { |
330 | unsigned long args[8]; | 330 | unsigned long args[8]; |
331 | 331 | ||
@@ -355,10 +355,10 @@ prom_setprop(int node, const char *pname, char *value, int size) | |||
355 | } | 355 | } |
356 | EXPORT_SYMBOL(prom_setprop); | 356 | EXPORT_SYMBOL(prom_setprop); |
357 | 357 | ||
358 | inline int prom_inst2pkg(int inst) | 358 | inline phandle prom_inst2pkg(int inst) |
359 | { | 359 | { |
360 | unsigned long args[5]; | 360 | unsigned long args[5]; |
361 | int node; | 361 | phandle node; |
362 | 362 | ||
363 | args[0] = (unsigned long) "instance-to-package"; | 363 | args[0] = (unsigned long) "instance-to-package"; |
364 | args[1] = 1; | 364 | args[1] = 1; |
@@ -369,25 +369,7 @@ inline int prom_inst2pkg(int inst) | |||
369 | p1275_cmd_direct(args); | 369 | p1275_cmd_direct(args); |
370 | 370 | ||
371 | node = (int) args[4]; | 371 | node = (int) args[4]; |
372 | if (node == -1) | 372 | if ((s32)node == -1) |
373 | return 0; | ||
374 | return node; | ||
375 | } | ||
376 | |||
377 | /* Return 'node' assigned to a particular prom 'path' | ||
378 | * FIXME: Should work for v0 as well | ||
379 | */ | ||
380 | int | ||
381 | prom_pathtoinode(const char *path) | ||
382 | { | ||
383 | int node, inst; | ||
384 | |||
385 | inst = prom_devopen (path); | ||
386 | if (inst == 0) | ||
387 | return 0; | ||
388 | node = prom_inst2pkg(inst); | ||
389 | prom_devclose(inst); | ||
390 | if (node == -1) | ||
391 | return 0; | 373 | return 0; |
392 | return node; | 374 | return node; |
393 | } | 375 | } |