diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:32:52 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:32:52 -0500 |
commit | 4073723acb9cdcdbe4df9c0e0c376c65d1697e43 (patch) | |
tree | f41c17eac157b1223ce104845cf9b1e5a9e6a83d /arch/arm | |
parent | 58daf18cdcab550262a5f4681e1f1e073e21965a (diff) | |
parent | 4ec3eb13634529c0bc7466658d84d0bbe3244aea (diff) |
Merge branch 'misc' into devel
Conflicts:
arch/arm/Kconfig
arch/arm/common/Makefile
arch/arm/kernel/Makefile
arch/arm/kernel/smp.c
Diffstat (limited to 'arch/arm')
119 files changed, 1514 insertions, 1263 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2e86b8f62104..32cbf3e888ff 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2,6 +2,7 @@ config ARM | |||
2 | bool | 2 | bool |
3 | default y | 3 | default y |
4 | select HAVE_AOUT | 4 | select HAVE_AOUT |
5 | select HAVE_DMA_API_DEBUG | ||
5 | select HAVE_IDE | 6 | select HAVE_IDE |
6 | select HAVE_MEMBLOCK | 7 | select HAVE_MEMBLOCK |
7 | select RTC_LIB | 8 | select RTC_LIB |
@@ -36,6 +37,9 @@ config ARM | |||
36 | config HAVE_PWM | 37 | config HAVE_PWM |
37 | bool | 38 | bool |
38 | 39 | ||
40 | config MIGHT_HAVE_PCI | ||
41 | bool | ||
42 | |||
39 | config SYS_SUPPORTS_APM_EMULATION | 43 | config SYS_SUPPORTS_APM_EMULATION |
40 | bool | 44 | bool |
41 | 45 | ||
@@ -226,7 +230,7 @@ config ARCH_INTEGRATOR | |||
226 | bool "ARM Ltd. Integrator family" | 230 | bool "ARM Ltd. Integrator family" |
227 | select ARM_AMBA | 231 | select ARM_AMBA |
228 | select ARCH_HAS_CPUFREQ | 232 | select ARCH_HAS_CPUFREQ |
229 | select COMMON_CLKDEV | 233 | select CLKDEV_LOOKUP |
230 | select ICST | 234 | select ICST |
231 | select GENERIC_CLOCKEVENTS | 235 | select GENERIC_CLOCKEVENTS |
232 | select PLAT_VERSATILE | 236 | select PLAT_VERSATILE |
@@ -236,7 +240,7 @@ config ARCH_INTEGRATOR | |||
236 | config ARCH_REALVIEW | 240 | config ARCH_REALVIEW |
237 | bool "ARM Ltd. RealView family" | 241 | bool "ARM Ltd. RealView family" |
238 | select ARM_AMBA | 242 | select ARM_AMBA |
239 | select COMMON_CLKDEV | 243 | select CLKDEV_LOOKUP |
240 | select HAVE_SCHED_CLOCK | 244 | select HAVE_SCHED_CLOCK |
241 | select ICST | 245 | select ICST |
242 | select GENERIC_CLOCKEVENTS | 246 | select GENERIC_CLOCKEVENTS |
@@ -251,7 +255,7 @@ config ARCH_VERSATILE | |||
251 | bool "ARM Ltd. Versatile family" | 255 | bool "ARM Ltd. Versatile family" |
252 | select ARM_AMBA | 256 | select ARM_AMBA |
253 | select ARM_VIC | 257 | select ARM_VIC |
254 | select COMMON_CLKDEV | 258 | select CLKDEV_LOOKUP |
255 | select HAVE_SCHED_CLOCK | 259 | select HAVE_SCHED_CLOCK |
256 | select ICST | 260 | select ICST |
257 | select GENERIC_CLOCKEVENTS | 261 | select GENERIC_CLOCKEVENTS |
@@ -266,7 +270,7 @@ config ARCH_VEXPRESS | |||
266 | select ARCH_WANT_OPTIONAL_GPIOLIB | 270 | select ARCH_WANT_OPTIONAL_GPIOLIB |
267 | select ARM_AMBA | 271 | select ARM_AMBA |
268 | select ARM_TIMER_SP804 | 272 | select ARM_TIMER_SP804 |
269 | select COMMON_CLKDEV | 273 | select CLKDEV_LOOKUP |
270 | select GENERIC_CLOCKEVENTS | 274 | select GENERIC_CLOCKEVENTS |
271 | select HAVE_CLK | 275 | select HAVE_CLK |
272 | select HAVE_SCHED_CLOCK | 276 | select HAVE_SCHED_CLOCK |
@@ -288,7 +292,7 @@ config ARCH_BCMRING | |||
288 | depends on MMU | 292 | depends on MMU |
289 | select CPU_V6 | 293 | select CPU_V6 |
290 | select ARM_AMBA | 294 | select ARM_AMBA |
291 | select COMMON_CLKDEV | 295 | select CLKDEV_LOOKUP |
292 | select GENERIC_CLOCKEVENTS | 296 | select GENERIC_CLOCKEVENTS |
293 | select ARCH_WANT_OPTIONAL_GPIOLIB | 297 | select ARCH_WANT_OPTIONAL_GPIOLIB |
294 | help | 298 | help |
@@ -306,6 +310,7 @@ config ARCH_CNS3XXX | |||
306 | select CPU_V6 | 310 | select CPU_V6 |
307 | select GENERIC_CLOCKEVENTS | 311 | select GENERIC_CLOCKEVENTS |
308 | select ARM_GIC | 312 | select ARM_GIC |
313 | select MIGHT_HAVE_PCI | ||
309 | select PCI_DOMAINS if PCI | 314 | select PCI_DOMAINS if PCI |
310 | help | 315 | help |
311 | Support for Cavium Networks CNS3XXX platform. | 316 | Support for Cavium Networks CNS3XXX platform. |
@@ -335,7 +340,7 @@ config ARCH_EP93XX | |||
335 | select CPU_ARM920T | 340 | select CPU_ARM920T |
336 | select ARM_AMBA | 341 | select ARM_AMBA |
337 | select ARM_VIC | 342 | select ARM_VIC |
338 | select COMMON_CLKDEV | 343 | select CLKDEV_LOOKUP |
339 | select ARCH_REQUIRE_GPIOLIB | 344 | select ARCH_REQUIRE_GPIOLIB |
340 | select ARCH_HAS_HOLES_MEMORYMODEL | 345 | select ARCH_HAS_HOLES_MEMORYMODEL |
341 | select ARCH_USES_GETTIMEOFFSET | 346 | select ARCH_USES_GETTIMEOFFSET |
@@ -355,14 +360,14 @@ config ARCH_MXC | |||
355 | bool "Freescale MXC/iMX-based" | 360 | bool "Freescale MXC/iMX-based" |
356 | select GENERIC_CLOCKEVENTS | 361 | select GENERIC_CLOCKEVENTS |
357 | select ARCH_REQUIRE_GPIOLIB | 362 | select ARCH_REQUIRE_GPIOLIB |
358 | select COMMON_CLKDEV | 363 | select CLKDEV_LOOKUP |
359 | help | 364 | help |
360 | Support for Freescale MXC/iMX-based family of processors | 365 | Support for Freescale MXC/iMX-based family of processors |
361 | 366 | ||
362 | config ARCH_STMP3XXX | 367 | config ARCH_STMP3XXX |
363 | bool "Freescale STMP3xxx" | 368 | bool "Freescale STMP3xxx" |
364 | select CPU_ARM926T | 369 | select CPU_ARM926T |
365 | select COMMON_CLKDEV | 370 | select CLKDEV_LOOKUP |
366 | select ARCH_REQUIRE_GPIOLIB | 371 | select ARCH_REQUIRE_GPIOLIB |
367 | select GENERIC_CLOCKEVENTS | 372 | select GENERIC_CLOCKEVENTS |
368 | select USB_ARCH_HAS_EHCI | 373 | select USB_ARCH_HAS_EHCI |
@@ -442,6 +447,7 @@ config ARCH_IXP4XX | |||
442 | select GENERIC_GPIO | 447 | select GENERIC_GPIO |
443 | select GENERIC_CLOCKEVENTS | 448 | select GENERIC_CLOCKEVENTS |
444 | select HAVE_SCHED_CLOCK | 449 | select HAVE_SCHED_CLOCK |
450 | select MIGHT_HAVE_PCI | ||
445 | select DMABOUNCE if PCI | 451 | select DMABOUNCE if PCI |
446 | help | 452 | help |
447 | Support for Intel's IXP4XX (XScale) family of processors. | 453 | Support for Intel's IXP4XX (XScale) family of processors. |
@@ -481,7 +487,7 @@ config ARCH_LPC32XX | |||
481 | select HAVE_IDE | 487 | select HAVE_IDE |
482 | select ARM_AMBA | 488 | select ARM_AMBA |
483 | select USB_ARCH_HAS_OHCI | 489 | select USB_ARCH_HAS_OHCI |
484 | select COMMON_CLKDEV | 490 | select CLKDEV_LOOKUP |
485 | select GENERIC_TIME | 491 | select GENERIC_TIME |
486 | select GENERIC_CLOCKEVENTS | 492 | select GENERIC_CLOCKEVENTS |
487 | help | 493 | help |
@@ -515,7 +521,7 @@ config ARCH_MMP | |||
515 | bool "Marvell PXA168/910/MMP2" | 521 | bool "Marvell PXA168/910/MMP2" |
516 | depends on MMU | 522 | depends on MMU |
517 | select ARCH_REQUIRE_GPIOLIB | 523 | select ARCH_REQUIRE_GPIOLIB |
518 | select COMMON_CLKDEV | 524 | select CLKDEV_LOOKUP |
519 | select GENERIC_CLOCKEVENTS | 525 | select GENERIC_CLOCKEVENTS |
520 | select HAVE_SCHED_CLOCK | 526 | select HAVE_SCHED_CLOCK |
521 | select TICK_ONESHOT | 527 | select TICK_ONESHOT |
@@ -549,7 +555,7 @@ config ARCH_W90X900 | |||
549 | bool "Nuvoton W90X900 CPU" | 555 | bool "Nuvoton W90X900 CPU" |
550 | select CPU_ARM926T | 556 | select CPU_ARM926T |
551 | select ARCH_REQUIRE_GPIOLIB | 557 | select ARCH_REQUIRE_GPIOLIB |
552 | select COMMON_CLKDEV | 558 | select CLKDEV_LOOKUP |
553 | select GENERIC_CLOCKEVENTS | 559 | select GENERIC_CLOCKEVENTS |
554 | help | 560 | help |
555 | Support for Nuvoton (Winbond logic dept.) ARM9 processor, | 561 | Support for Nuvoton (Winbond logic dept.) ARM9 processor, |
@@ -563,19 +569,19 @@ config ARCH_W90X900 | |||
563 | config ARCH_NUC93X | 569 | config ARCH_NUC93X |
564 | bool "Nuvoton NUC93X CPU" | 570 | bool "Nuvoton NUC93X CPU" |
565 | select CPU_ARM926T | 571 | select CPU_ARM926T |
566 | select COMMON_CLKDEV | 572 | select CLKDEV_LOOKUP |
567 | help | 573 | help |
568 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a | 574 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a |
569 | low-power and high performance MPEG-4/JPEG multimedia controller chip. | 575 | low-power and high performance MPEG-4/JPEG multimedia controller chip. |
570 | 576 | ||
571 | config ARCH_TEGRA | 577 | config ARCH_TEGRA |
572 | bool "NVIDIA Tegra" | 578 | bool "NVIDIA Tegra" |
579 | select CLKDEV_LOOKUP | ||
573 | select GENERIC_TIME | 580 | select GENERIC_TIME |
574 | select GENERIC_CLOCKEVENTS | 581 | select GENERIC_CLOCKEVENTS |
575 | select GENERIC_GPIO | 582 | select GENERIC_GPIO |
576 | select HAVE_CLK | 583 | select HAVE_CLK |
577 | select HAVE_SCHED_CLOCK | 584 | select HAVE_SCHED_CLOCK |
578 | select COMMON_CLKDEV | ||
579 | select ARCH_HAS_BARRIERS if CACHE_L2X0 | 585 | select ARCH_HAS_BARRIERS if CACHE_L2X0 |
580 | select ARCH_HAS_CPUFREQ | 586 | select ARCH_HAS_CPUFREQ |
581 | help | 587 | help |
@@ -585,7 +591,7 @@ config ARCH_TEGRA | |||
585 | config ARCH_PNX4008 | 591 | config ARCH_PNX4008 |
586 | bool "Philips Nexperia PNX4008 Mobile" | 592 | bool "Philips Nexperia PNX4008 Mobile" |
587 | select CPU_ARM926T | 593 | select CPU_ARM926T |
588 | select COMMON_CLKDEV | 594 | select CLKDEV_LOOKUP |
589 | select ARCH_USES_GETTIMEOFFSET | 595 | select ARCH_USES_GETTIMEOFFSET |
590 | help | 596 | help |
591 | This enables support for Philips PNX4008 mobile platform. | 597 | This enables support for Philips PNX4008 mobile platform. |
@@ -595,7 +601,7 @@ config ARCH_PXA | |||
595 | depends on MMU | 601 | depends on MMU |
596 | select ARCH_MTD_XIP | 602 | select ARCH_MTD_XIP |
597 | select ARCH_HAS_CPUFREQ | 603 | select ARCH_HAS_CPUFREQ |
598 | select COMMON_CLKDEV | 604 | select CLKDEV_LOOKUP |
599 | select ARCH_REQUIRE_GPIOLIB | 605 | select ARCH_REQUIRE_GPIOLIB |
600 | select GENERIC_CLOCKEVENTS | 606 | select GENERIC_CLOCKEVENTS |
601 | select HAVE_SCHED_CLOCK | 607 | select HAVE_SCHED_CLOCK |
@@ -774,7 +780,7 @@ config ARCH_TCC_926 | |||
774 | bool "Telechips TCC ARM926-based systems" | 780 | bool "Telechips TCC ARM926-based systems" |
775 | select CPU_ARM926T | 781 | select CPU_ARM926T |
776 | select HAVE_CLK | 782 | select HAVE_CLK |
777 | select COMMON_CLKDEV | 783 | select CLKDEV_LOOKUP |
778 | select GENERIC_CLOCKEVENTS | 784 | select GENERIC_CLOCKEVENTS |
779 | help | 785 | help |
780 | Support for Telechips TCC ARM926-based systems. | 786 | Support for Telechips TCC ARM926-based systems. |
@@ -799,7 +805,7 @@ config ARCH_U300 | |||
799 | select ARM_AMBA | 805 | select ARM_AMBA |
800 | select ARM_VIC | 806 | select ARM_VIC |
801 | select GENERIC_CLOCKEVENTS | 807 | select GENERIC_CLOCKEVENTS |
802 | select COMMON_CLKDEV | 808 | select CLKDEV_LOOKUP |
803 | select GENERIC_GPIO | 809 | select GENERIC_GPIO |
804 | help | 810 | help |
805 | Support for ST-Ericsson U300 series mobile platforms. | 811 | Support for ST-Ericsson U300 series mobile platforms. |
@@ -809,7 +815,7 @@ config ARCH_U8500 | |||
809 | select CPU_V7 | 815 | select CPU_V7 |
810 | select ARM_AMBA | 816 | select ARM_AMBA |
811 | select GENERIC_CLOCKEVENTS | 817 | select GENERIC_CLOCKEVENTS |
812 | select COMMON_CLKDEV | 818 | select CLKDEV_LOOKUP |
813 | select ARCH_REQUIRE_GPIOLIB | 819 | select ARCH_REQUIRE_GPIOLIB |
814 | help | 820 | help |
815 | Support for ST-Ericsson's Ux500 architecture | 821 | Support for ST-Ericsson's Ux500 architecture |
@@ -819,7 +825,7 @@ config ARCH_NOMADIK | |||
819 | select ARM_AMBA | 825 | select ARM_AMBA |
820 | select ARM_VIC | 826 | select ARM_VIC |
821 | select CPU_ARM926T | 827 | select CPU_ARM926T |
822 | select COMMON_CLKDEV | 828 | select CLKDEV_LOOKUP |
823 | select GENERIC_CLOCKEVENTS | 829 | select GENERIC_CLOCKEVENTS |
824 | select ARCH_REQUIRE_GPIOLIB | 830 | select ARCH_REQUIRE_GPIOLIB |
825 | help | 831 | help |
@@ -831,7 +837,7 @@ config ARCH_DAVINCI | |||
831 | select ARCH_REQUIRE_GPIOLIB | 837 | select ARCH_REQUIRE_GPIOLIB |
832 | select ZONE_DMA | 838 | select ZONE_DMA |
833 | select HAVE_IDE | 839 | select HAVE_IDE |
834 | select COMMON_CLKDEV | 840 | select CLKDEV_LOOKUP |
835 | select GENERIC_ALLOCATOR | 841 | select GENERIC_ALLOCATOR |
836 | select ARCH_HAS_HOLES_MEMORYMODEL | 842 | select ARCH_HAS_HOLES_MEMORYMODEL |
837 | help | 843 | help |
@@ -852,7 +858,7 @@ config PLAT_SPEAR | |||
852 | bool "ST SPEAr" | 858 | bool "ST SPEAr" |
853 | select ARM_AMBA | 859 | select ARM_AMBA |
854 | select ARCH_REQUIRE_GPIOLIB | 860 | select ARCH_REQUIRE_GPIOLIB |
855 | select COMMON_CLKDEV | 861 | select CLKDEV_LOOKUP |
856 | select GENERIC_CLOCKEVENTS | 862 | select GENERIC_CLOCKEVENTS |
857 | select HAVE_CLK | 863 | select HAVE_CLK |
858 | help | 864 | help |
@@ -1034,6 +1040,11 @@ config CPU_HAS_PMU | |||
1034 | default y | 1040 | default y |
1035 | bool | 1041 | bool |
1036 | 1042 | ||
1043 | config MULTI_IRQ_HANDLER | ||
1044 | bool | ||
1045 | help | ||
1046 | Allow each machine to specify it's own IRQ handler at run time. | ||
1047 | |||
1037 | if !MMU | 1048 | if !MMU |
1038 | source "arch/arm/Kconfig-nommu" | 1049 | source "arch/arm/Kconfig-nommu" |
1039 | endif | 1050 | endif |
@@ -1181,7 +1192,7 @@ config ISA_DMA_API | |||
1181 | bool | 1192 | bool |
1182 | 1193 | ||
1183 | config PCI | 1194 | config PCI |
1184 | bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE | 1195 | bool "PCI support" if MIGHT_HAVE_PCI |
1185 | help | 1196 | help |
1186 | Find out whether you have a PCI motherboard. PCI is the name of a | 1197 | Find out whether you have a PCI motherboard. PCI is the name of a |
1187 | bus system, i.e. the way the CPU talks to the other stuff inside | 1198 | bus system, i.e. the way the CPU talks to the other stuff inside |
@@ -1253,7 +1264,7 @@ config SMP | |||
1253 | config SMP_ON_UP | 1264 | config SMP_ON_UP |
1254 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" | 1265 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" |
1255 | depends on EXPERIMENTAL | 1266 | depends on EXPERIMENTAL |
1256 | depends on SMP && !XIP && !THUMB2_KERNEL | 1267 | depends on SMP && !XIP |
1257 | default y | 1268 | default y |
1258 | help | 1269 | help |
1259 | SMP kernels contain instructions which fail on non-SMP processors. | 1270 | SMP kernels contain instructions which fail on non-SMP processors. |
@@ -1272,6 +1283,7 @@ config HAVE_ARM_SCU | |||
1272 | config HAVE_ARM_TWD | 1283 | config HAVE_ARM_TWD |
1273 | bool | 1284 | bool |
1274 | depends on SMP | 1285 | depends on SMP |
1286 | select TICK_ONESHOT | ||
1275 | help | 1287 | help |
1276 | This options enables support for the ARM timer and watchdog unit | 1288 | This options enables support for the ARM timer and watchdog unit |
1277 | 1289 | ||
@@ -1335,7 +1347,7 @@ config HZ | |||
1335 | default 100 | 1347 | default 100 |
1336 | 1348 | ||
1337 | config THUMB2_KERNEL | 1349 | config THUMB2_KERNEL |
1338 | bool "Compile the kernel in Thumb-2 mode" | 1350 | bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" |
1339 | depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL | 1351 | depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL |
1340 | select AEABI | 1352 | select AEABI |
1341 | select ARM_ASM_UNIFIED | 1353 | select ARM_ASM_UNIFIED |
@@ -1549,6 +1561,7 @@ config SECCOMP | |||
1549 | 1561 | ||
1550 | config CC_STACKPROTECTOR | 1562 | config CC_STACKPROTECTOR |
1551 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | 1563 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" |
1564 | depends on EXPERIMENTAL | ||
1552 | help | 1565 | help |
1553 | This option turns on the -fstack-protector GCC feature. This | 1566 | This option turns on the -fstack-protector GCC feature. This |
1554 | feature puts, at the beginning of functions, a canary value on | 1567 | feature puts, at the beginning of functions, a canary value on |
@@ -1745,7 +1758,7 @@ config CPU_FREQ_S3C | |||
1745 | Internal configuration node for common cpufreq on Samsung SoC | 1758 | Internal configuration node for common cpufreq on Samsung SoC |
1746 | 1759 | ||
1747 | config CPU_FREQ_S3C24XX | 1760 | config CPU_FREQ_S3C24XX |
1748 | bool "CPUfreq driver for Samsung S3C24XX series CPUs" | 1761 | bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)" |
1749 | depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL | 1762 | depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL |
1750 | select CPU_FREQ_S3C | 1763 | select CPU_FREQ_S3C |
1751 | help | 1764 | help |
@@ -1757,7 +1770,7 @@ config CPU_FREQ_S3C24XX | |||
1757 | If in doubt, say N. | 1770 | If in doubt, say N. |
1758 | 1771 | ||
1759 | config CPU_FREQ_S3C24XX_PLL | 1772 | config CPU_FREQ_S3C24XX_PLL |
1760 | bool "Support CPUfreq changing of PLL frequency" | 1773 | bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" |
1761 | depends on CPU_FREQ_S3C24XX && EXPERIMENTAL | 1774 | depends on CPU_FREQ_S3C24XX && EXPERIMENTAL |
1762 | help | 1775 | help |
1763 | Compile in support for changing the PLL frequency from the | 1776 | Compile in support for changing the PLL frequency from the |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index eac62085f5b2..494224a9b459 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -31,7 +31,7 @@ config FRAME_POINTER | |||
31 | reported is severely limited. | 31 | reported is severely limited. |
32 | 32 | ||
33 | config ARM_UNWIND | 33 | config ARM_UNWIND |
34 | bool "Enable stack unwinding support" | 34 | bool "Enable stack unwinding support (EXPERIMENTAL)" |
35 | depends on AEABI && EXPERIMENTAL | 35 | depends on AEABI && EXPERIMENTAL |
36 | default y | 36 | default y |
37 | help | 37 | help |
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 0a34c8186924..778655f0257a 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig | |||
@@ -37,7 +37,3 @@ config SHARP_PARAM | |||
37 | 37 | ||
38 | config SHARP_SCOOP | 38 | config SHARP_SCOOP |
39 | bool | 39 | bool |
40 | |||
41 | config COMMON_CLKDEV | ||
42 | bool | ||
43 | select HAVE_CLK | ||
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c deleted file mode 100644 index e2b2bb66e094..000000000000 --- a/arch/arm/common/clkdev.c +++ /dev/null | |||
@@ -1,179 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/common/clkdev.c | ||
3 | * | ||
4 | * Copyright (C) 2008 Russell King. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Helper for the clk API to assist looking up a struct clk. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <asm/clkdev.h> | ||
24 | #include <mach/clkdev.h> | ||
25 | |||
26 | static LIST_HEAD(clocks); | ||
27 | static DEFINE_MUTEX(clocks_mutex); | ||
28 | |||
29 | /* | ||
30 | * Find the correct struct clk for the device and connection ID. | ||
31 | * We do slightly fuzzy matching here: | ||
32 | * An entry with a NULL ID is assumed to be a wildcard. | ||
33 | * If an entry has a device ID, it must match | ||
34 | * If an entry has a connection ID, it must match | ||
35 | * Then we take the most specific entry - with the following | ||
36 | * order of precedence: dev+con > dev only > con only. | ||
37 | */ | ||
38 | static struct clk *clk_find(const char *dev_id, const char *con_id) | ||
39 | { | ||
40 | struct clk_lookup *p; | ||
41 | struct clk *clk = NULL; | ||
42 | int match, best = 0; | ||
43 | |||
44 | list_for_each_entry(p, &clocks, node) { | ||
45 | match = 0; | ||
46 | if (p->dev_id) { | ||
47 | if (!dev_id || strcmp(p->dev_id, dev_id)) | ||
48 | continue; | ||
49 | match += 2; | ||
50 | } | ||
51 | if (p->con_id) { | ||
52 | if (!con_id || strcmp(p->con_id, con_id)) | ||
53 | continue; | ||
54 | match += 1; | ||
55 | } | ||
56 | |||
57 | if (match > best) { | ||
58 | clk = p->clk; | ||
59 | if (match != 3) | ||
60 | best = match; | ||
61 | else | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | return clk; | ||
66 | } | ||
67 | |||
68 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) | ||
69 | { | ||
70 | struct clk *clk; | ||
71 | |||
72 | mutex_lock(&clocks_mutex); | ||
73 | clk = clk_find(dev_id, con_id); | ||
74 | if (clk && !__clk_get(clk)) | ||
75 | clk = NULL; | ||
76 | mutex_unlock(&clocks_mutex); | ||
77 | |||
78 | return clk ? clk : ERR_PTR(-ENOENT); | ||
79 | } | ||
80 | EXPORT_SYMBOL(clk_get_sys); | ||
81 | |||
82 | struct clk *clk_get(struct device *dev, const char *con_id) | ||
83 | { | ||
84 | const char *dev_id = dev ? dev_name(dev) : NULL; | ||
85 | |||
86 | return clk_get_sys(dev_id, con_id); | ||
87 | } | ||
88 | EXPORT_SYMBOL(clk_get); | ||
89 | |||
90 | void clk_put(struct clk *clk) | ||
91 | { | ||
92 | __clk_put(clk); | ||
93 | } | ||
94 | EXPORT_SYMBOL(clk_put); | ||
95 | |||
96 | void clkdev_add(struct clk_lookup *cl) | ||
97 | { | ||
98 | mutex_lock(&clocks_mutex); | ||
99 | list_add_tail(&cl->node, &clocks); | ||
100 | mutex_unlock(&clocks_mutex); | ||
101 | } | ||
102 | EXPORT_SYMBOL(clkdev_add); | ||
103 | |||
104 | void __init clkdev_add_table(struct clk_lookup *cl, size_t num) | ||
105 | { | ||
106 | mutex_lock(&clocks_mutex); | ||
107 | while (num--) { | ||
108 | list_add_tail(&cl->node, &clocks); | ||
109 | cl++; | ||
110 | } | ||
111 | mutex_unlock(&clocks_mutex); | ||
112 | } | ||
113 | |||
114 | #define MAX_DEV_ID 20 | ||
115 | #define MAX_CON_ID 16 | ||
116 | |||
117 | struct clk_lookup_alloc { | ||
118 | struct clk_lookup cl; | ||
119 | char dev_id[MAX_DEV_ID]; | ||
120 | char con_id[MAX_CON_ID]; | ||
121 | }; | ||
122 | |||
123 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | ||
124 | const char *dev_fmt, ...) | ||
125 | { | ||
126 | struct clk_lookup_alloc *cla; | ||
127 | |||
128 | cla = kzalloc(sizeof(*cla), GFP_KERNEL); | ||
129 | if (!cla) | ||
130 | return NULL; | ||
131 | |||
132 | cla->cl.clk = clk; | ||
133 | if (con_id) { | ||
134 | strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); | ||
135 | cla->cl.con_id = cla->con_id; | ||
136 | } | ||
137 | |||
138 | if (dev_fmt) { | ||
139 | va_list ap; | ||
140 | |||
141 | va_start(ap, dev_fmt); | ||
142 | vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); | ||
143 | cla->cl.dev_id = cla->dev_id; | ||
144 | va_end(ap); | ||
145 | } | ||
146 | |||
147 | return &cla->cl; | ||
148 | } | ||
149 | EXPORT_SYMBOL(clkdev_alloc); | ||
150 | |||
151 | int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, | ||
152 | struct device *dev) | ||
153 | { | ||
154 | struct clk *r = clk_get(dev, id); | ||
155 | struct clk_lookup *l; | ||
156 | |||
157 | if (IS_ERR(r)) | ||
158 | return PTR_ERR(r); | ||
159 | |||
160 | l = clkdev_alloc(r, alias, alias_dev_name); | ||
161 | clk_put(r); | ||
162 | if (!l) | ||
163 | return -ENODEV; | ||
164 | clkdev_add(l); | ||
165 | return 0; | ||
166 | } | ||
167 | EXPORT_SYMBOL(clk_add_alias); | ||
168 | |||
169 | /* | ||
170 | * clkdev_drop - remove a clock dynamically allocated | ||
171 | */ | ||
172 | void clkdev_drop(struct clk_lookup *cl) | ||
173 | { | ||
174 | mutex_lock(&clocks_mutex); | ||
175 | list_del(&cl->node); | ||
176 | mutex_unlock(&clocks_mutex); | ||
177 | kfree(cl); | ||
178 | } | ||
179 | EXPORT_SYMBOL(clkdev_drop); | ||
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index cc0a932bbea9..e5681636626f 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
@@ -328,7 +328,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, | |||
328 | * substitute the safe buffer for the unsafe one. | 328 | * substitute the safe buffer for the unsafe one. |
329 | * (basically move the buffer from an unsafe area to a safe one) | 329 | * (basically move the buffer from an unsafe area to a safe one) |
330 | */ | 330 | */ |
331 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 331 | dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size, |
332 | enum dma_data_direction dir) | 332 | enum dma_data_direction dir) |
333 | { | 333 | { |
334 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 334 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
338 | 338 | ||
339 | return map_single(dev, ptr, size, dir); | 339 | return map_single(dev, ptr, size, dir); |
340 | } | 340 | } |
341 | EXPORT_SYMBOL(dma_map_single); | 341 | EXPORT_SYMBOL(__dma_map_single); |
342 | 342 | ||
343 | /* | 343 | /* |
344 | * see if a mapped address was really a "safe" buffer and if so, copy | 344 | * see if a mapped address was really a "safe" buffer and if so, copy |
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single); | |||
346 | * the safe buffer. (basically return things back to the way they | 346 | * the safe buffer. (basically return things back to the way they |
347 | * should be) | 347 | * should be) |
348 | */ | 348 | */ |
349 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 349 | void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
350 | enum dma_data_direction dir) | 350 | enum dma_data_direction dir) |
351 | { | 351 | { |
352 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 352 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
354 | 354 | ||
355 | unmap_single(dev, dma_addr, size, dir); | 355 | unmap_single(dev, dma_addr, size, dir); |
356 | } | 356 | } |
357 | EXPORT_SYMBOL(dma_unmap_single); | 357 | EXPORT_SYMBOL(__dma_unmap_single); |
358 | 358 | ||
359 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 359 | dma_addr_t __dma_map_page(struct device *dev, struct page *page, |
360 | unsigned long offset, size_t size, enum dma_data_direction dir) | 360 | unsigned long offset, size_t size, enum dma_data_direction dir) |
361 | { | 361 | { |
362 | dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", | 362 | dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", |
@@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
372 | 372 | ||
373 | return map_single(dev, page_address(page) + offset, size, dir); | 373 | return map_single(dev, page_address(page) + offset, size, dir); |
374 | } | 374 | } |
375 | EXPORT_SYMBOL(dma_map_page); | 375 | EXPORT_SYMBOL(__dma_map_page); |
376 | 376 | ||
377 | /* | 377 | /* |
378 | * see if a mapped address was really a "safe" buffer and if so, copy | 378 | * see if a mapped address was really a "safe" buffer and if so, copy |
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page); | |||
380 | * the safe buffer. (basically return things back to the way they | 380 | * the safe buffer. (basically return things back to the way they |
381 | * should be) | 381 | * should be) |
382 | */ | 382 | */ |
383 | void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | 383 | void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, |
384 | enum dma_data_direction dir) | 384 | enum dma_data_direction dir) |
385 | { | 385 | { |
386 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 386 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
388 | 388 | ||
389 | unmap_single(dev, dma_addr, size, dir); | 389 | unmap_single(dev, dma_addr, size, dir); |
390 | } | 390 | } |
391 | EXPORT_SYMBOL(dma_unmap_page); | 391 | EXPORT_SYMBOL(__dma_unmap_page); |
392 | 392 | ||
393 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, | 393 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, |
394 | unsigned long off, size_t sz, enum dma_data_direction dir) | 394 | unsigned long off, size_t sz, enum dma_data_direction dir) |
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 749bb6622404..bc2d2d75f706 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
21 | #include <asm/domain.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Endian independent macros for shifting bytes within registers. | 24 | * Endian independent macros for shifting bytes within registers. |
@@ -157,16 +158,24 @@ | |||
157 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
158 | #define ALT_SMP(instr...) \ | 159 | #define ALT_SMP(instr...) \ |
159 | 9998: instr | 160 | 9998: instr |
161 | /* | ||
162 | * Note: if you get assembler errors from ALT_UP() when building with | ||
163 | * CONFIG_THUMB2_KERNEL, you almost certainly need to use | ||
164 | * ALT_SMP( W(instr) ... ) | ||
165 | */ | ||
160 | #define ALT_UP(instr...) \ | 166 | #define ALT_UP(instr...) \ |
161 | .pushsection ".alt.smp.init", "a" ;\ | 167 | .pushsection ".alt.smp.init", "a" ;\ |
162 | .long 9998b ;\ | 168 | .long 9998b ;\ |
163 | instr ;\ | 169 | 9997: instr ;\ |
170 | .if . - 9997b != 4 ;\ | ||
171 | .error "ALT_UP() content must assemble to exactly 4 bytes";\ | ||
172 | .endif ;\ | ||
164 | .popsection | 173 | .popsection |
165 | #define ALT_UP_B(label) \ | 174 | #define ALT_UP_B(label) \ |
166 | .equ up_b_offset, label - 9998b ;\ | 175 | .equ up_b_offset, label - 9998b ;\ |
167 | .pushsection ".alt.smp.init", "a" ;\ | 176 | .pushsection ".alt.smp.init", "a" ;\ |
168 | .long 9998b ;\ | 177 | .long 9998b ;\ |
169 | b . + up_b_offset ;\ | 178 | W(b) . + up_b_offset ;\ |
170 | .popsection | 179 | .popsection |
171 | #else | 180 | #else |
172 | #define ALT_SMP(instr...) | 181 | #define ALT_SMP(instr...) |
@@ -177,16 +186,24 @@ | |||
177 | /* | 186 | /* |
178 | * SMP data memory barrier | 187 | * SMP data memory barrier |
179 | */ | 188 | */ |
180 | .macro smp_dmb | 189 | .macro smp_dmb mode |
181 | #ifdef CONFIG_SMP | 190 | #ifdef CONFIG_SMP |
182 | #if __LINUX_ARM_ARCH__ >= 7 | 191 | #if __LINUX_ARM_ARCH__ >= 7 |
192 | .ifeqs "\mode","arm" | ||
183 | ALT_SMP(dmb) | 193 | ALT_SMP(dmb) |
194 | .else | ||
195 | ALT_SMP(W(dmb)) | ||
196 | .endif | ||
184 | #elif __LINUX_ARM_ARCH__ == 6 | 197 | #elif __LINUX_ARM_ARCH__ == 6 |
185 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb | 198 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb |
186 | #else | 199 | #else |
187 | #error Incompatible SMP platform | 200 | #error Incompatible SMP platform |
188 | #endif | 201 | #endif |
202 | .ifeqs "\mode","arm" | ||
189 | ALT_UP(nop) | 203 | ALT_UP(nop) |
204 | .else | ||
205 | ALT_UP(W(nop)) | ||
206 | .endif | ||
190 | #endif | 207 | #endif |
191 | .endm | 208 | .endm |
192 | 209 | ||
@@ -206,12 +223,12 @@ | |||
206 | */ | 223 | */ |
207 | #ifdef CONFIG_THUMB2_KERNEL | 224 | #ifdef CONFIG_THUMB2_KERNEL |
208 | 225 | ||
209 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort | 226 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T() |
210 | 9999: | 227 | 9999: |
211 | .if \inc == 1 | 228 | .if \inc == 1 |
212 | \instr\cond\()bt \reg, [\ptr, #\off] | 229 | \instr\cond\()b\()\t\().w \reg, [\ptr, #\off] |
213 | .elseif \inc == 4 | 230 | .elseif \inc == 4 |
214 | \instr\cond\()t \reg, [\ptr, #\off] | 231 | \instr\cond\()\t\().w \reg, [\ptr, #\off] |
215 | .else | 232 | .else |
216 | .error "Unsupported inc macro argument" | 233 | .error "Unsupported inc macro argument" |
217 | .endif | 234 | .endif |
@@ -246,13 +263,13 @@ | |||
246 | 263 | ||
247 | #else /* !CONFIG_THUMB2_KERNEL */ | 264 | #else /* !CONFIG_THUMB2_KERNEL */ |
248 | 265 | ||
249 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort | 266 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T() |
250 | .rept \rept | 267 | .rept \rept |
251 | 9999: | 268 | 9999: |
252 | .if \inc == 1 | 269 | .if \inc == 1 |
253 | \instr\cond\()bt \reg, [\ptr], #\inc | 270 | \instr\cond\()b\()\t \reg, [\ptr], #\inc |
254 | .elseif \inc == 4 | 271 | .elseif \inc == 4 |
255 | \instr\cond\()t \reg, [\ptr], #\inc | 272 | \instr\cond\()\t \reg, [\ptr], #\inc |
256 | .else | 273 | .else |
257 | .error "Unsupported inc macro argument" | 274 | .error "Unsupported inc macro argument" |
258 | .endif | 275 | .endif |
diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 9d6122096fbe..75fe66bc02b4 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h | |||
@@ -23,4 +23,6 @@ | |||
23 | #define ARCH_SLAB_MINALIGN 8 | 23 | #define ARCH_SLAB_MINALIGN 8 |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) | ||
27 | |||
26 | #endif | 28 | #endif |
diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h index b56c1389b6fa..765d33222369 100644 --- a/arch/arm/include/asm/clkdev.h +++ b/arch/arm/include/asm/clkdev.h | |||
@@ -12,23 +12,13 @@ | |||
12 | #ifndef __ASM_CLKDEV_H | 12 | #ifndef __ASM_CLKDEV_H |
13 | #define __ASM_CLKDEV_H | 13 | #define __ASM_CLKDEV_H |
14 | 14 | ||
15 | struct clk; | 15 | #include <linux/slab.h> |
16 | struct device; | ||
17 | 16 | ||
18 | struct clk_lookup { | 17 | #include <mach/clkdev.h> |
19 | struct list_head node; | ||
20 | const char *dev_id; | ||
21 | const char *con_id; | ||
22 | struct clk *clk; | ||
23 | }; | ||
24 | 18 | ||
25 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | 19 | static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) |
26 | const char *dev_fmt, ...); | 20 | { |
27 | 21 | return kzalloc(size, GFP_KERNEL); | |
28 | void clkdev_add(struct clk_lookup *cl); | 22 | } |
29 | void clkdev_drop(struct clk_lookup *cl); | ||
30 | |||
31 | void clkdev_add_table(struct clk_lookup *, size_t); | ||
32 | int clk_add_alias(const char *, const char *, char *, struct device *); | ||
33 | 23 | ||
34 | #endif | 24 | #endif |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index c568da7dcae4..4fff837363ed 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -5,24 +5,29 @@ | |||
5 | 5 | ||
6 | #include <linux/mm_types.h> | 6 | #include <linux/mm_types.h> |
7 | #include <linux/scatterlist.h> | 7 | #include <linux/scatterlist.h> |
8 | #include <linux/dma-debug.h> | ||
8 | 9 | ||
9 | #include <asm-generic/dma-coherent.h> | 10 | #include <asm-generic/dma-coherent.h> |
10 | #include <asm/memory.h> | 11 | #include <asm/memory.h> |
11 | 12 | ||
13 | #ifdef __arch_page_to_dma | ||
14 | #error Please update to __arch_pfn_to_dma | ||
15 | #endif | ||
16 | |||
12 | /* | 17 | /* |
13 | * page_to_dma/dma_to_virt/virt_to_dma are architecture private functions | 18 | * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private |
14 | * used internally by the DMA-mapping API to provide DMA addresses. They | 19 | * functions used internally by the DMA-mapping API to provide DMA |
15 | * must not be used by drivers. | 20 | * addresses. They must not be used by drivers. |
16 | */ | 21 | */ |
17 | #ifndef __arch_page_to_dma | 22 | #ifndef __arch_pfn_to_dma |
18 | static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) | 23 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) |
19 | { | 24 | { |
20 | return (dma_addr_t)__pfn_to_bus(page_to_pfn(page)); | 25 | return (dma_addr_t)__pfn_to_bus(pfn); |
21 | } | 26 | } |
22 | 27 | ||
23 | static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr) | 28 | static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) |
24 | { | 29 | { |
25 | return pfn_to_page(__bus_to_pfn(addr)); | 30 | return __bus_to_pfn(addr); |
26 | } | 31 | } |
27 | 32 | ||
28 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) | 33 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) |
@@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
35 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); | 40 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); |
36 | } | 41 | } |
37 | #else | 42 | #else |
38 | static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) | 43 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) |
39 | { | 44 | { |
40 | return __arch_page_to_dma(dev, page); | 45 | return __arch_pfn_to_dma(dev, pfn); |
41 | } | 46 | } |
42 | 47 | ||
43 | static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr) | 48 | static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) |
44 | { | 49 | { |
45 | return __arch_dma_to_page(dev, addr); | 50 | return __arch_dma_to_pfn(dev, addr); |
46 | } | 51 | } |
47 | 52 | ||
48 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) | 53 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) |
@@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t); | |||
293 | /* | 298 | /* |
294 | * The DMA API, implemented by dmabounce.c. See below for descriptions. | 299 | * The DMA API, implemented by dmabounce.c. See below for descriptions. |
295 | */ | 300 | */ |
296 | extern dma_addr_t dma_map_single(struct device *, void *, size_t, | 301 | extern dma_addr_t __dma_map_single(struct device *, void *, size_t, |
297 | enum dma_data_direction); | 302 | enum dma_data_direction); |
298 | extern void dma_unmap_single(struct device *, dma_addr_t, size_t, | 303 | extern void __dma_unmap_single(struct device *, dma_addr_t, size_t, |
299 | enum dma_data_direction); | 304 | enum dma_data_direction); |
300 | extern dma_addr_t dma_map_page(struct device *, struct page *, | 305 | extern dma_addr_t __dma_map_page(struct device *, struct page *, |
301 | unsigned long, size_t, enum dma_data_direction); | 306 | unsigned long, size_t, enum dma_data_direction); |
302 | extern void dma_unmap_page(struct device *, dma_addr_t, size_t, | 307 | extern void __dma_unmap_page(struct device *, dma_addr_t, size_t, |
303 | enum dma_data_direction); | 308 | enum dma_data_direction); |
304 | 309 | ||
305 | /* | 310 | /* |
@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, | |||
323 | } | 328 | } |
324 | 329 | ||
325 | 330 | ||
331 | static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr, | ||
332 | size_t size, enum dma_data_direction dir) | ||
333 | { | ||
334 | __dma_single_cpu_to_dev(cpu_addr, size, dir); | ||
335 | return virt_to_dma(dev, cpu_addr); | ||
336 | } | ||
337 | |||
338 | static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page, | ||
339 | unsigned long offset, size_t size, enum dma_data_direction dir) | ||
340 | { | ||
341 | __dma_page_cpu_to_dev(page, offset, size, dir); | ||
342 | return pfn_to_dma(dev, page_to_pfn(page)) + offset; | ||
343 | } | ||
344 | |||
345 | static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle, | ||
346 | size_t size, enum dma_data_direction dir) | ||
347 | { | ||
348 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir); | ||
349 | } | ||
350 | |||
351 | static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, | ||
352 | size_t size, enum dma_data_direction dir) | ||
353 | { | ||
354 | __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)), | ||
355 | handle & ~PAGE_MASK, size, dir); | ||
356 | } | ||
357 | #endif /* CONFIG_DMABOUNCE */ | ||
358 | |||
326 | /** | 359 | /** |
327 | * dma_map_single - map a single buffer for streaming DMA | 360 | * dma_map_single - map a single buffer for streaming DMA |
328 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | 361 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices |
@@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, | |||
340 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | 373 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, |
341 | size_t size, enum dma_data_direction dir) | 374 | size_t size, enum dma_data_direction dir) |
342 | { | 375 | { |
376 | dma_addr_t addr; | ||
377 | |||
343 | BUG_ON(!valid_dma_direction(dir)); | 378 | BUG_ON(!valid_dma_direction(dir)); |
344 | 379 | ||
345 | __dma_single_cpu_to_dev(cpu_addr, size, dir); | 380 | addr = __dma_map_single(dev, cpu_addr, size, dir); |
381 | debug_dma_map_page(dev, virt_to_page(cpu_addr), | ||
382 | (unsigned long)cpu_addr & ~PAGE_MASK, size, | ||
383 | dir, addr, true); | ||
346 | 384 | ||
347 | return virt_to_dma(dev, cpu_addr); | 385 | return addr; |
348 | } | 386 | } |
349 | 387 | ||
350 | /** | 388 | /** |
@@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | |||
364 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | 402 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, |
365 | unsigned long offset, size_t size, enum dma_data_direction dir) | 403 | unsigned long offset, size_t size, enum dma_data_direction dir) |
366 | { | 404 | { |
405 | dma_addr_t addr; | ||
406 | |||
367 | BUG_ON(!valid_dma_direction(dir)); | 407 | BUG_ON(!valid_dma_direction(dir)); |
368 | 408 | ||
369 | __dma_page_cpu_to_dev(page, offset, size, dir); | 409 | addr = __dma_map_page(dev, page, offset, size, dir); |
410 | debug_dma_map_page(dev, page, offset, size, dir, addr, false); | ||
370 | 411 | ||
371 | return page_to_dma(dev, page) + offset; | 412 | return addr; |
372 | } | 413 | } |
373 | 414 | ||
374 | /** | 415 | /** |
@@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
388 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | 429 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, |
389 | size_t size, enum dma_data_direction dir) | 430 | size_t size, enum dma_data_direction dir) |
390 | { | 431 | { |
391 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir); | 432 | debug_dma_unmap_page(dev, handle, size, dir, true); |
433 | __dma_unmap_single(dev, handle, size, dir); | ||
392 | } | 434 | } |
393 | 435 | ||
394 | /** | 436 | /** |
@@ -408,10 +450,9 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | |||
408 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, | 450 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, |
409 | size_t size, enum dma_data_direction dir) | 451 | size_t size, enum dma_data_direction dir) |
410 | { | 452 | { |
411 | __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK, | 453 | debug_dma_unmap_page(dev, handle, size, dir, false); |
412 | size, dir); | 454 | __dma_unmap_page(dev, handle, size, dir); |
413 | } | 455 | } |
414 | #endif /* CONFIG_DMABOUNCE */ | ||
415 | 456 | ||
416 | /** | 457 | /** |
417 | * dma_sync_single_range_for_cpu | 458 | * dma_sync_single_range_for_cpu |
@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, | |||
437 | { | 478 | { |
438 | BUG_ON(!valid_dma_direction(dir)); | 479 | BUG_ON(!valid_dma_direction(dir)); |
439 | 480 | ||
481 | debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir); | ||
482 | |||
440 | if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) | 483 | if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) |
441 | return; | 484 | return; |
442 | 485 | ||
@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev, | |||
449 | { | 492 | { |
450 | BUG_ON(!valid_dma_direction(dir)); | 493 | BUG_ON(!valid_dma_direction(dir)); |
451 | 494 | ||
495 | debug_dma_sync_single_for_device(dev, handle + offset, size, dir); | ||
496 | |||
452 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) | 497 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) |
453 | return; | 498 | return; |
454 | 499 | ||
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index cc7ef4080711..af18ceaacf5d 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h | |||
@@ -45,13 +45,17 @@ | |||
45 | */ | 45 | */ |
46 | #define DOMAIN_NOACCESS 0 | 46 | #define DOMAIN_NOACCESS 0 |
47 | #define DOMAIN_CLIENT 1 | 47 | #define DOMAIN_CLIENT 1 |
48 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
48 | #define DOMAIN_MANAGER 3 | 49 | #define DOMAIN_MANAGER 3 |
50 | #else | ||
51 | #define DOMAIN_MANAGER 1 | ||
52 | #endif | ||
49 | 53 | ||
50 | #define domain_val(dom,type) ((type) << (2*(dom))) | 54 | #define domain_val(dom,type) ((type) << (2*(dom))) |
51 | 55 | ||
52 | #ifndef __ASSEMBLY__ | 56 | #ifndef __ASSEMBLY__ |
53 | 57 | ||
54 | #ifdef CONFIG_MMU | 58 | #ifdef CONFIG_CPU_USE_DOMAINS |
55 | #define set_domain(x) \ | 59 | #define set_domain(x) \ |
56 | do { \ | 60 | do { \ |
57 | __asm__ __volatile__( \ | 61 | __asm__ __volatile__( \ |
@@ -74,5 +78,28 @@ | |||
74 | #define modify_domain(dom,type) do { } while (0) | 78 | #define modify_domain(dom,type) do { } while (0) |
75 | #endif | 79 | #endif |
76 | 80 | ||
81 | /* | ||
82 | * Generate the T (user) versions of the LDR/STR and related | ||
83 | * instructions (inline assembly) | ||
84 | */ | ||
85 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
86 | #define T(instr) #instr "t" | ||
87 | #else | ||
88 | #define T(instr) #instr | ||
77 | #endif | 89 | #endif |
78 | #endif /* !__ASSEMBLY__ */ | 90 | |
91 | #else /* __ASSEMBLY__ */ | ||
92 | |||
93 | /* | ||
94 | * Generate the T (user) versions of the LDR/STR and related | ||
95 | * instructions | ||
96 | */ | ||
97 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
98 | #define T(instr) instr ## t | ||
99 | #else | ||
100 | #define T(instr) instr | ||
101 | #endif | ||
102 | |||
103 | #endif /* __ASSEMBLY__ */ | ||
104 | |||
105 | #endif /* !__ASM_PROC_DOMAIN_H */ | ||
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S new file mode 100644 index 000000000000..ec0bbf79c71f --- /dev/null +++ b/arch/arm/include/asm/entry-macro-multi.S | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Interrupt handling. Preserves r7, r8, r9 | ||
3 | */ | ||
4 | .macro arch_irq_handler_default | ||
5 | get_irqnr_preamble r5, lr | ||
6 | 1: get_irqnr_and_base r0, r6, r5, lr | ||
7 | movne r1, sp | ||
8 | @ | ||
9 | @ routine called with r0 = irq number, r1 = struct pt_regs * | ||
10 | @ | ||
11 | adrne lr, BSYM(1b) | ||
12 | bne asm_do_IRQ | ||
13 | |||
14 | #ifdef CONFIG_SMP | ||
15 | /* | ||
16 | * XXX | ||
17 | * | ||
18 | * this macro assumes that irqstat (r6) and base (r5) are | ||
19 | * preserved from get_irqnr_and_base above | ||
20 | */ | ||
21 | ALT_SMP(test_for_ipi r0, r6, r5, lr) | ||
22 | ALT_UP_B(9997f) | ||
23 | movne r1, sp | ||
24 | adrne lr, BSYM(1b) | ||
25 | bne do_IPI | ||
26 | |||
27 | #ifdef CONFIG_LOCAL_TIMERS | ||
28 | test_for_ltirq r0, r6, r5, lr | ||
29 | movne r0, sp | ||
30 | adrne lr, BSYM(1b) | ||
31 | bne do_local_timer | ||
32 | #endif | ||
33 | #endif | ||
34 | 9997: | ||
35 | .endm | ||
36 | |||
37 | .macro arch_irq_handler, symbol_name | ||
38 | .align 5 | ||
39 | .global \symbol_name | ||
40 | \symbol_name: | ||
41 | mov r4, lr | ||
42 | arch_irq_handler_default | ||
43 | mov pc, r4 | ||
44 | .endm | ||
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 540a044153a5..b33fe7065b38 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h | |||
@@ -13,12 +13,13 @@ | |||
13 | #include <linux/preempt.h> | 13 | #include <linux/preempt.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
16 | #include <asm/domain.h> | ||
16 | 17 | ||
17 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | 18 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ |
18 | __asm__ __volatile__( \ | 19 | __asm__ __volatile__( \ |
19 | "1: ldrt %1, [%2]\n" \ | 20 | "1: " T(ldr) " %1, [%2]\n" \ |
20 | " " insn "\n" \ | 21 | " " insn "\n" \ |
21 | "2: strt %0, [%2]\n" \ | 22 | "2: " T(str) " %0, [%2]\n" \ |
22 | " mov %0, #0\n" \ | 23 | " mov %0, #0\n" \ |
23 | "3:\n" \ | 24 | "3:\n" \ |
24 | " .pushsection __ex_table,\"a\"\n" \ | 25 | " .pushsection __ex_table,\"a\"\n" \ |
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | |||
97 | pagefault_disable(); /* implies preempt_disable() */ | 98 | pagefault_disable(); /* implies preempt_disable() */ |
98 | 99 | ||
99 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" | 100 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" |
100 | "1: ldrt %0, [%3]\n" | 101 | "1: " T(ldr) " %0, [%3]\n" |
101 | " teq %0, %1\n" | 102 | " teq %0, %1\n" |
102 | " it eq @ explicit IT needed for the 2b label\n" | 103 | " it eq @ explicit IT needed for the 2b label\n" |
103 | "2: streqt %2, [%3]\n" | 104 | "2: " T(streq) " %2, [%3]\n" |
104 | "3:\n" | 105 | "3:\n" |
105 | " .pushsection __ex_table,\"a\"\n" | 106 | " .pushsection __ex_table,\"a\"\n" |
106 | " .align 3\n" | 107 | " .align 3\n" |
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index 6d7485aff955..89ad1805e579 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h | |||
@@ -5,13 +5,31 @@ | |||
5 | #include <linux/threads.h> | 5 | #include <linux/threads.h> |
6 | #include <asm/irq.h> | 6 | #include <asm/irq.h> |
7 | 7 | ||
8 | #define NR_IPI 5 | ||
9 | |||
8 | typedef struct { | 10 | typedef struct { |
9 | unsigned int __softirq_pending; | 11 | unsigned int __softirq_pending; |
12 | #ifdef CONFIG_LOCAL_TIMERS | ||
10 | unsigned int local_timer_irqs; | 13 | unsigned int local_timer_irqs; |
14 | #endif | ||
15 | #ifdef CONFIG_SMP | ||
16 | unsigned int ipi_irqs[NR_IPI]; | ||
17 | #endif | ||
11 | } ____cacheline_aligned irq_cpustat_t; | 18 | } ____cacheline_aligned irq_cpustat_t; |
12 | 19 | ||
13 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | 20 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ |
14 | 21 | ||
22 | #define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ | ||
23 | #define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) | ||
24 | |||
25 | #ifdef CONFIG_SMP | ||
26 | u64 smp_irq_stat_cpu(unsigned int cpu); | ||
27 | #else | ||
28 | #define smp_irq_stat_cpu(cpu) 0 | ||
29 | #endif | ||
30 | |||
31 | #define arch_irq_stat_cpu smp_irq_stat_cpu | ||
32 | |||
15 | #if NR_IRQS > 512 | 33 | #if NR_IRQS > 512 |
16 | #define HARDIRQ_BITS 10 | 34 | #define HARDIRQ_BITS 10 |
17 | #elif NR_IRQS > 256 | 35 | #elif NR_IRQS > 256 |
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index 50c7e7cfd670..6bc63ab498ce 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h | |||
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *); | |||
30 | #include "smp_twd.h" | 30 | #include "smp_twd.h" |
31 | 31 | ||
32 | #define local_timer_ack() twd_timer_ack() | 32 | #define local_timer_ack() twd_timer_ack() |
33 | #define local_timer_stop() twd_timer_stop() | ||
34 | 33 | ||
35 | #else | 34 | #else |
36 | 35 | ||
@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *); | |||
40 | */ | 39 | */ |
41 | int local_timer_ack(void); | 40 | int local_timer_ack(void); |
42 | 41 | ||
43 | /* | ||
44 | * Stop a local timer interrupt. | ||
45 | */ | ||
46 | void local_timer_stop(void); | ||
47 | |||
48 | #endif | 42 | #endif |
49 | 43 | ||
50 | /* | 44 | /* |
@@ -52,12 +46,6 @@ void local_timer_stop(void); | |||
52 | */ | 46 | */ |
53 | void local_timer_setup(struct clock_event_device *); | 47 | void local_timer_setup(struct clock_event_device *); |
54 | 48 | ||
55 | #else | ||
56 | |||
57 | static inline void local_timer_stop(void) | ||
58 | { | ||
59 | } | ||
60 | |||
61 | #endif | 49 | #endif |
62 | 50 | ||
63 | #endif | 51 | #endif |
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index d97a964207fa..3a0893a76a3b 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h | |||
@@ -37,12 +37,21 @@ struct machine_desc { | |||
37 | struct meminfo *); | 37 | struct meminfo *); |
38 | void (*reserve)(void);/* reserve mem blocks */ | 38 | void (*reserve)(void);/* reserve mem blocks */ |
39 | void (*map_io)(void);/* IO mapping function */ | 39 | void (*map_io)(void);/* IO mapping function */ |
40 | void (*init_early)(void); | ||
40 | void (*init_irq)(void); | 41 | void (*init_irq)(void); |
41 | struct sys_timer *timer; /* system tick timer */ | 42 | struct sys_timer *timer; /* system tick timer */ |
42 | void (*init_machine)(void); | 43 | void (*init_machine)(void); |
44 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
45 | void (*handle_irq)(struct pt_regs *); | ||
46 | #endif | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /* | 49 | /* |
50 | * Current machine - only accessible during boot. | ||
51 | */ | ||
52 | extern struct machine_desc *machine_desc; | ||
53 | |||
54 | /* | ||
46 | * Set of macros to define architecture features. This is built into | 55 | * Set of macros to define architecture features. This is built into |
47 | * a table by the linker. | 56 | * a table by the linker. |
48 | */ | 57 | */ |
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index ce3eee9fe26c..22ac140edd9e 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h | |||
@@ -17,10 +17,12 @@ struct seq_file; | |||
17 | /* | 17 | /* |
18 | * This is internal. Do not use it. | 18 | * This is internal. Do not use it. |
19 | */ | 19 | */ |
20 | extern unsigned int arch_nr_irqs; | ||
21 | extern void (*init_arch_irq)(void); | ||
22 | extern void init_FIQ(void); | 20 | extern void init_FIQ(void); |
23 | extern int show_fiq_list(struct seq_file *, void *); | 21 | extern int show_fiq_list(struct seq_file *, int); |
22 | |||
23 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
24 | extern void (*handle_arch_irq)(struct pt_regs *); | ||
25 | #endif | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * This is for easy migration, but should be changed in the source | 28 | * This is for easy migration, but should be changed in the source |
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index 35d408f6dccf..883f6be5117a 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h | |||
@@ -43,7 +43,6 @@ struct sys_timer { | |||
43 | #endif | 43 | #endif |
44 | }; | 44 | }; |
45 | 45 | ||
46 | extern struct sys_timer *system_timer; | ||
47 | extern void timer_tick(void); | 46 | extern void timer_tick(void); |
48 | 47 | ||
49 | #endif | 48 | #endif |
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 3d05190797cb..96ed521f2408 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h | |||
@@ -33,27 +33,23 @@ struct seq_file; | |||
33 | /* | 33 | /* |
34 | * generate IPI list text | 34 | * generate IPI list text |
35 | */ | 35 | */ |
36 | extern void show_ipi_list(struct seq_file *p); | 36 | extern void show_ipi_list(struct seq_file *, int); |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Called from assembly code, this handles an IPI. | 39 | * Called from assembly code, this handles an IPI. |
40 | */ | 40 | */ |
41 | asmlinkage void do_IPI(struct pt_regs *regs); | 41 | asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Setup the set of possible CPUs (via set_cpu_possible) | 44 | * Setup the set of possible CPUs (via set_cpu_possible) |
45 | */ | 45 | */ |
46 | extern void smp_init_cpus(void); | 46 | extern void smp_init_cpus(void); |
47 | 47 | ||
48 | /* | ||
49 | * Move global data into per-processor storage. | ||
50 | */ | ||
51 | extern void smp_store_cpu_info(unsigned int cpuid); | ||
52 | 48 | ||
53 | /* | 49 | /* |
54 | * Raise an IPI cross call on CPUs in callmap. | 50 | * Raise an IPI cross call on CPUs in callmap. |
55 | */ | 51 | */ |
56 | extern void smp_cross_call(const struct cpumask *mask); | 52 | extern void smp_cross_call(const struct cpumask *mask, int ipi); |
57 | 53 | ||
58 | /* | 54 | /* |
59 | * Boot a secondary CPU, and assign it the specified idle task. | 55 | * Boot a secondary CPU, and assign it the specified idle task. |
@@ -73,6 +69,11 @@ asmlinkage void secondary_start_kernel(void); | |||
73 | extern void platform_secondary_init(unsigned int cpu); | 69 | extern void platform_secondary_init(unsigned int cpu); |
74 | 70 | ||
75 | /* | 71 | /* |
72 | * Initialize cpu_possible map, and enable coherency | ||
73 | */ | ||
74 | extern void platform_smp_prepare_cpus(unsigned int); | ||
75 | |||
76 | /* | ||
76 | * Initial data for bringing up a secondary CPU. | 77 | * Initial data for bringing up a secondary CPU. |
77 | */ | 78 | */ |
78 | struct secondary_data { | 79 | struct secondary_data { |
@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | |||
97 | /* | 98 | /* |
98 | * show local interrupt info | 99 | * show local interrupt info |
99 | */ | 100 | */ |
100 | extern void show_local_irqs(struct seq_file *); | 101 | extern void show_local_irqs(struct seq_file *, int); |
101 | 102 | ||
102 | #endif /* ifndef __ASM_ARM_SMP_H */ | 103 | #endif /* ifndef __ASM_ARM_SMP_H */ |
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h deleted file mode 100644 index 6a9307d64900..000000000000 --- a/arch/arm/include/asm/smp_mpidr.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #ifndef ASMARM_SMP_MIDR_H | ||
2 | #define ASMARM_SMP_MIDR_H | ||
3 | |||
4 | #define hard_smp_processor_id() \ | ||
5 | ({ \ | ||
6 | unsigned int cpunum; \ | ||
7 | __asm__("\n" \ | ||
8 | "1: mrc p15, 0, %0, c0, c0, 5\n" \ | ||
9 | " .pushsection \".alt.smp.init\", \"a\"\n"\ | ||
10 | " .long 1b\n" \ | ||
11 | " mov %0, #0\n" \ | ||
12 | " .popsection" \ | ||
13 | : "=r" (cpunum)); \ | ||
14 | cpunum &= 0x0F; \ | ||
15 | }) | ||
16 | |||
17 | #endif | ||
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index 634f357be6bb..fed9981fba08 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h | |||
@@ -22,7 +22,6 @@ struct clock_event_device; | |||
22 | 22 | ||
23 | extern void __iomem *twd_base; | 23 | extern void __iomem *twd_base; |
24 | 24 | ||
25 | void twd_timer_stop(void); | ||
26 | int twd_timer_ack(void); | 25 | int twd_timer_ack(void); |
27 | void twd_timer_setup(struct clock_event_device *); | 26 | void twd_timer_setup(struct clock_event_device *); |
28 | 27 | ||
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 3222ab8b3447..97f6d60297d5 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -124,6 +124,13 @@ extern unsigned int user_debug; | |||
124 | #define vectors_high() (0) | 124 | #define vectors_high() (0) |
125 | #endif | 125 | #endif |
126 | 126 | ||
127 | #if __LINUX_ARM_ARCH__ >= 7 || \ | ||
128 | (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K)) | ||
129 | #define sev() __asm__ __volatile__ ("sev" : : : "memory") | ||
130 | #define wfe() __asm__ __volatile__ ("wfe" : : : "memory") | ||
131 | #define wfi() __asm__ __volatile__ ("wfi" : : : "memory") | ||
132 | #endif | ||
133 | |||
127 | #if __LINUX_ARM_ARCH__ >= 7 | 134 | #if __LINUX_ARM_ARCH__ >= 7 |
128 | #define isb() __asm__ __volatile__ ("isb" : : : "memory") | 135 | #define isb() __asm__ __volatile__ ("isb" : : : "memory") |
129 | #define dsb() __asm__ __volatile__ ("dsb" : : : "memory") | 136 | #define dsb() __asm__ __volatile__ ("dsb" : : : "memory") |
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 124475afb007..1b960d5ef6a5 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h | |||
@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr) | |||
46 | extern void __init early_trap_init(void); | 46 | extern void __init early_trap_init(void); |
47 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); | 47 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); |
48 | 48 | ||
49 | extern void *vectors_page; | ||
50 | |||
49 | #endif | 51 | #endif |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 33e4a48fe103..b293616a1a1a 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
@@ -227,7 +227,7 @@ do { \ | |||
227 | 227 | ||
228 | #define __get_user_asm_byte(x,addr,err) \ | 228 | #define __get_user_asm_byte(x,addr,err) \ |
229 | __asm__ __volatile__( \ | 229 | __asm__ __volatile__( \ |
230 | "1: ldrbt %1,[%2]\n" \ | 230 | "1: " T(ldrb) " %1,[%2],#0\n" \ |
231 | "2:\n" \ | 231 | "2:\n" \ |
232 | " .pushsection .fixup,\"ax\"\n" \ | 232 | " .pushsection .fixup,\"ax\"\n" \ |
233 | " .align 2\n" \ | 233 | " .align 2\n" \ |
@@ -263,7 +263,7 @@ do { \ | |||
263 | 263 | ||
264 | #define __get_user_asm_word(x,addr,err) \ | 264 | #define __get_user_asm_word(x,addr,err) \ |
265 | __asm__ __volatile__( \ | 265 | __asm__ __volatile__( \ |
266 | "1: ldrt %1,[%2]\n" \ | 266 | "1: " T(ldr) " %1,[%2],#0\n" \ |
267 | "2:\n" \ | 267 | "2:\n" \ |
268 | " .pushsection .fixup,\"ax\"\n" \ | 268 | " .pushsection .fixup,\"ax\"\n" \ |
269 | " .align 2\n" \ | 269 | " .align 2\n" \ |
@@ -308,7 +308,7 @@ do { \ | |||
308 | 308 | ||
309 | #define __put_user_asm_byte(x,__pu_addr,err) \ | 309 | #define __put_user_asm_byte(x,__pu_addr,err) \ |
310 | __asm__ __volatile__( \ | 310 | __asm__ __volatile__( \ |
311 | "1: strbt %1,[%2]\n" \ | 311 | "1: " T(strb) " %1,[%2],#0\n" \ |
312 | "2:\n" \ | 312 | "2:\n" \ |
313 | " .pushsection .fixup,\"ax\"\n" \ | 313 | " .pushsection .fixup,\"ax\"\n" \ |
314 | " .align 2\n" \ | 314 | " .align 2\n" \ |
@@ -341,7 +341,7 @@ do { \ | |||
341 | 341 | ||
342 | #define __put_user_asm_word(x,__pu_addr,err) \ | 342 | #define __put_user_asm_word(x,__pu_addr,err) \ |
343 | __asm__ __volatile__( \ | 343 | __asm__ __volatile__( \ |
344 | "1: strt %1,[%2]\n" \ | 344 | "1: " T(str) " %1,[%2],#0\n" \ |
345 | "2:\n" \ | 345 | "2:\n" \ |
346 | " .pushsection .fixup,\"ax\"\n" \ | 346 | " .pushsection .fixup,\"ax\"\n" \ |
347 | " .align 2\n" \ | 347 | " .align 2\n" \ |
@@ -366,10 +366,10 @@ do { \ | |||
366 | 366 | ||
367 | #define __put_user_asm_dword(x,__pu_addr,err) \ | 367 | #define __put_user_asm_dword(x,__pu_addr,err) \ |
368 | __asm__ __volatile__( \ | 368 | __asm__ __volatile__( \ |
369 | ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ | 369 | ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \ |
370 | ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ | 370 | ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \ |
371 | THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ | 371 | THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \ |
372 | THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ | 372 | THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \ |
373 | "3:\n" \ | 373 | "3:\n" \ |
374 | " .pushsection .fixup,\"ax\"\n" \ | 374 | " .pushsection .fixup,\"ax\"\n" \ |
375 | " .align 2\n" \ | 375 | " .align 2\n" \ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index fd3ec49bfba6..7c33e6f29bcc 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -30,7 +30,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o | |||
30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o | 30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
31 | obj-$(CONFIG_PCI) += bios32.o isa.o | 31 | obj-$(CONFIG_PCI) += bios32.o isa.o |
32 | obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o | 32 | obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o |
33 | obj-$(CONFIG_SMP) += smp.o | 33 | obj-$(CONFIG_SMP) += smp.o smp_tlb.o |
34 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 34 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
35 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | 35 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
36 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 36 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
@@ -44,6 +44,8 @@ obj-$(CONFIG_KGDB) += kgdb.o | |||
44 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 44 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
45 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 45 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
46 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 46 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
47 | obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o | ||
48 | CFLAGS_swp_emulate.o := -Wa,-march=armv7-a | ||
47 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o | 49 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o |
48 | 50 | ||
49 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o | 51 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bb96a7d4bbf5..27f64489c1cb 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -25,42 +25,22 @@ | |||
25 | #include <asm/tls.h> | 25 | #include <asm/tls.h> |
26 | 26 | ||
27 | #include "entry-header.S" | 27 | #include "entry-header.S" |
28 | #include <asm/entry-macro-multi.S> | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Interrupt handling. Preserves r7, r8, r9 | 31 | * Interrupt handling. Preserves r7, r8, r9 |
31 | */ | 32 | */ |
32 | .macro irq_handler | 33 | .macro irq_handler |
33 | get_irqnr_preamble r5, lr | 34 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
34 | 1: get_irqnr_and_base r0, r6, r5, lr | 35 | ldr r5, =handle_arch_irq |
35 | movne r1, sp | 36 | mov r0, sp |
36 | @ | 37 | ldr r5, [r5] |
37 | @ routine called with r0 = irq number, r1 = struct pt_regs * | 38 | adr lr, BSYM(9997f) |
38 | @ | 39 | teq r5, #0 |
39 | adrne lr, BSYM(1b) | 40 | movne pc, r5 |
40 | bne asm_do_IRQ | ||
41 | |||
42 | #ifdef CONFIG_SMP | ||
43 | /* | ||
44 | * XXX | ||
45 | * | ||
46 | * this macro assumes that irqstat (r6) and base (r5) are | ||
47 | * preserved from get_irqnr_and_base above | ||
48 | */ | ||
49 | ALT_SMP(test_for_ipi r0, r6, r5, lr) | ||
50 | ALT_UP_B(9997f) | ||
51 | movne r0, sp | ||
52 | adrne lr, BSYM(1b) | ||
53 | bne do_IPI | ||
54 | |||
55 | #ifdef CONFIG_LOCAL_TIMERS | ||
56 | test_for_ltirq r0, r6, r5, lr | ||
57 | movne r0, sp | ||
58 | adrne lr, BSYM(1b) | ||
59 | bne do_local_timer | ||
60 | #endif | 41 | #endif |
42 | arch_irq_handler_default | ||
61 | 9997: | 43 | 9997: |
62 | #endif | ||
63 | |||
64 | .endm | 44 | .endm |
65 | 45 | ||
66 | #ifdef CONFIG_KPROBES | 46 | #ifdef CONFIG_KPROBES |
@@ -735,7 +715,7 @@ ENTRY(__switch_to) | |||
735 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack | 715 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack |
736 | THUMB( str sp, [ip], #4 ) | 716 | THUMB( str sp, [ip], #4 ) |
737 | THUMB( str lr, [ip], #4 ) | 717 | THUMB( str lr, [ip], #4 ) |
738 | #ifdef CONFIG_MMU | 718 | #ifdef CONFIG_CPU_USE_DOMAINS |
739 | ldr r6, [r2, #TI_CPU_DOMAIN] | 719 | ldr r6, [r2, #TI_CPU_DOMAIN] |
740 | #endif | 720 | #endif |
741 | set_tls r3, r4, r5 | 721 | set_tls r3, r4, r5 |
@@ -744,7 +724,7 @@ ENTRY(__switch_to) | |||
744 | ldr r8, =__stack_chk_guard | 724 | ldr r8, =__stack_chk_guard |
745 | ldr r7, [r7, #TSK_STACK_CANARY] | 725 | ldr r7, [r7, #TSK_STACK_CANARY] |
746 | #endif | 726 | #endif |
747 | #ifdef CONFIG_MMU | 727 | #ifdef CONFIG_CPU_USE_DOMAINS |
748 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register | 728 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register |
749 | #endif | 729 | #endif |
750 | mov r5, r0 | 730 | mov r5, r0 |
@@ -842,7 +822,7 @@ __kuser_helper_start: | |||
842 | */ | 822 | */ |
843 | 823 | ||
844 | __kuser_memory_barrier: @ 0xffff0fa0 | 824 | __kuser_memory_barrier: @ 0xffff0fa0 |
845 | smp_dmb | 825 | smp_dmb arm |
846 | usr_ret lr | 826 | usr_ret lr |
847 | 827 | ||
848 | .align 5 | 828 | .align 5 |
@@ -959,7 +939,7 @@ kuser_cmpxchg_fixup: | |||
959 | 939 | ||
960 | #else | 940 | #else |
961 | 941 | ||
962 | smp_dmb | 942 | smp_dmb arm |
963 | 1: ldrex r3, [r2] | 943 | 1: ldrex r3, [r2] |
964 | subs r3, r3, r0 | 944 | subs r3, r3, r0 |
965 | strexeq r3, r1, [r2] | 945 | strexeq r3, r1, [r2] |
@@ -1245,3 +1225,9 @@ cr_alignment: | |||
1245 | .space 4 | 1225 | .space 4 |
1246 | cr_no_alignment: | 1226 | cr_no_alignment: |
1247 | .space 4 | 1227 | .space 4 |
1228 | |||
1229 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
1230 | .globl handle_arch_irq | ||
1231 | handle_arch_irq: | ||
1232 | .space 4 | ||
1233 | #endif | ||
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 6ff7919613d7..e72dc34eea1c 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/fiq.h> | 45 | #include <asm/fiq.h> |
46 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | #include <asm/traps.h> | ||
48 | 49 | ||
49 | static unsigned long no_fiq_insn; | 50 | static unsigned long no_fiq_insn; |
50 | 51 | ||
@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = { | |||
67 | 68 | ||
68 | static struct fiq_handler *current_fiq = &default_owner; | 69 | static struct fiq_handler *current_fiq = &default_owner; |
69 | 70 | ||
70 | int show_fiq_list(struct seq_file *p, void *v) | 71 | int show_fiq_list(struct seq_file *p, int prec) |
71 | { | 72 | { |
72 | if (current_fiq != &default_owner) | 73 | if (current_fiq != &default_owner) |
73 | seq_printf(p, "FIQ: %s\n", current_fiq->name); | 74 | seq_printf(p, "%*s: %s\n", prec, "FIQ", |
75 | current_fiq->name); | ||
74 | 76 | ||
75 | return 0; | 77 | return 0; |
76 | } | 78 | } |
77 | 79 | ||
78 | void set_fiq_handler(void *start, unsigned int length) | 80 | void set_fiq_handler(void *start, unsigned int length) |
79 | { | 81 | { |
82 | #if defined(CONFIG_CPU_USE_DOMAINS) | ||
80 | memcpy((void *)0xffff001c, start, length); | 83 | memcpy((void *)0xffff001c, start, length); |
84 | #else | ||
85 | memcpy(vectors_page + 0x1c, start, length); | ||
86 | #endif | ||
81 | flush_icache_range(0xffff001c, 0xffff001c + length); | 87 | flush_icache_range(0xffff001c, 0xffff001c + length); |
82 | if (!vectors_high()) | 88 | if (!vectors_high()) |
83 | flush_icache_range(0x1c, 0x1c + length); | 89 | flush_icache_range(0x1c, 0x1c + length); |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 6bd82d25683c..f17d9a09e8fb 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -91,6 +91,11 @@ ENTRY(stext) | |||
91 | movs r8, r5 @ invalid machine (r5=0)? | 91 | movs r8, r5 @ invalid machine (r5=0)? |
92 | THUMB( it eq ) @ force fixup-able long branch encoding | 92 | THUMB( it eq ) @ force fixup-able long branch encoding |
93 | beq __error_a @ yes, error 'a' | 93 | beq __error_a @ yes, error 'a' |
94 | |||
95 | /* | ||
96 | * r1 = machine no, r2 = atags, | ||
97 | * r8 = machinfo, r9 = cpuid, r10 = procinfo | ||
98 | */ | ||
94 | bl __vet_atags | 99 | bl __vet_atags |
95 | #ifdef CONFIG_SMP_ON_UP | 100 | #ifdef CONFIG_SMP_ON_UP |
96 | bl __fixup_smp | 101 | bl __fixup_smp |
@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on) | |||
387 | 392 | ||
388 | #ifdef CONFIG_SMP_ON_UP | 393 | #ifdef CONFIG_SMP_ON_UP |
389 | __fixup_smp: | 394 | __fixup_smp: |
390 | mov r7, #0x00070000 | 395 | mov r4, #0x00070000 |
391 | orr r6, r7, #0xff000000 @ mask 0xff070000 | 396 | orr r3, r4, #0xff000000 @ mask 0xff070000 |
392 | orr r7, r7, #0x41000000 @ val 0x41070000 | 397 | orr r4, r4, #0x41000000 @ val 0x41070000 |
393 | and r0, r9, r6 | 398 | and r0, r9, r3 |
394 | teq r0, r7 @ ARM CPU and ARMv6/v7? | 399 | teq r0, r4 @ ARM CPU and ARMv6/v7? |
395 | bne __fixup_smp_on_up @ no, assume UP | 400 | bne __fixup_smp_on_up @ no, assume UP |
396 | 401 | ||
397 | orr r6, r6, #0x0000ff00 | 402 | orr r3, r3, #0x0000ff00 |
398 | orr r6, r6, #0x000000f0 @ mask 0xff07fff0 | 403 | orr r3, r3, #0x000000f0 @ mask 0xff07fff0 |
399 | orr r7, r7, #0x0000b000 | 404 | orr r4, r4, #0x0000b000 |
400 | orr r7, r7, #0x00000020 @ val 0x4107b020 | 405 | orr r4, r4, #0x00000020 @ val 0x4107b020 |
401 | and r0, r9, r6 | 406 | and r0, r9, r3 |
402 | teq r0, r7 @ ARM 11MPCore? | 407 | teq r0, r4 @ ARM 11MPCore? |
403 | moveq pc, lr @ yes, assume SMP | 408 | moveq pc, lr @ yes, assume SMP |
404 | 409 | ||
405 | mrc p15, 0, r0, c0, c0, 5 @ read MPIDR | 410 | mrc p15, 0, r0, c0, c0, 5 @ read MPIDR |
@@ -408,15 +413,22 @@ __fixup_smp: | |||
408 | 413 | ||
409 | __fixup_smp_on_up: | 414 | __fixup_smp_on_up: |
410 | adr r0, 1f | 415 | adr r0, 1f |
411 | ldmia r0, {r3, r6, r7} | 416 | ldmia r0, {r3 - r5} |
412 | sub r3, r0, r3 | 417 | sub r3, r0, r3 |
413 | add r6, r6, r3 | 418 | add r4, r4, r3 |
414 | add r7, r7, r3 | 419 | add r5, r5, r3 |
415 | 2: cmp r6, r7 | 420 | 2: cmp r4, r5 |
416 | ldmia r6!, {r0, r4} | 421 | movhs pc, lr |
417 | strlo r4, [r0, r3] | 422 | ldmia r4!, {r0, r6} |
418 | blo 2b | 423 | ARM( str r6, [r0, r3] ) |
419 | mov pc, lr | 424 | THUMB( add r0, r0, r3 ) |
425 | #ifdef __ARMEB__ | ||
426 | THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. | ||
427 | #endif | ||
428 | THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords | ||
429 | THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. | ||
430 | THUMB( strh r6, [r0] ) | ||
431 | b 2b | ||
420 | ENDPROC(__fixup_smp) | 432 | ENDPROC(__fixup_smp) |
421 | 433 | ||
422 | .align | 434 | .align |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 6d616333340f..8135438b8818 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/ftrace.h> | 38 | #include <linux/ftrace.h> |
39 | 39 | ||
40 | #include <asm/system.h> | 40 | #include <asm/system.h> |
41 | #include <asm/mach/arch.h> | ||
41 | #include <asm/mach/irq.h> | 42 | #include <asm/mach/irq.h> |
42 | #include <asm/mach/time.h> | 43 | #include <asm/mach/time.h> |
43 | 44 | ||
@@ -48,8 +49,6 @@ | |||
48 | #define irq_finish(irq) do { } while (0) | 49 | #define irq_finish(irq) do { } while (0) |
49 | #endif | 50 | #endif |
50 | 51 | ||
51 | unsigned int arch_nr_irqs; | ||
52 | void (*init_arch_irq)(void) __initdata = NULL; | ||
53 | unsigned long irq_err_count; | 52 | unsigned long irq_err_count; |
54 | 53 | ||
55 | int show_interrupts(struct seq_file *p, void *v) | 54 | int show_interrupts(struct seq_file *p, void *v) |
@@ -58,11 +57,20 @@ int show_interrupts(struct seq_file *p, void *v) | |||
58 | struct irq_desc *desc; | 57 | struct irq_desc *desc; |
59 | struct irqaction * action; | 58 | struct irqaction * action; |
60 | unsigned long flags; | 59 | unsigned long flags; |
60 | int prec, n; | ||
61 | |||
62 | for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++) | ||
63 | n *= 10; | ||
64 | |||
65 | #ifdef CONFIG_SMP | ||
66 | if (prec < 4) | ||
67 | prec = 4; | ||
68 | #endif | ||
61 | 69 | ||
62 | if (i == 0) { | 70 | if (i == 0) { |
63 | char cpuname[12]; | 71 | char cpuname[12]; |
64 | 72 | ||
65 | seq_printf(p, " "); | 73 | seq_printf(p, "%*s ", prec, ""); |
66 | for_each_present_cpu(cpu) { | 74 | for_each_present_cpu(cpu) { |
67 | sprintf(cpuname, "CPU%d", cpu); | 75 | sprintf(cpuname, "CPU%d", cpu); |
68 | seq_printf(p, " %10s", cpuname); | 76 | seq_printf(p, " %10s", cpuname); |
@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
77 | if (!action) | 85 | if (!action) |
78 | goto unlock; | 86 | goto unlock; |
79 | 87 | ||
80 | seq_printf(p, "%3d: ", i); | 88 | seq_printf(p, "%*d: ", prec, i); |
81 | for_each_present_cpu(cpu) | 89 | for_each_present_cpu(cpu) |
82 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); | 90 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); |
83 | seq_printf(p, " %10s", desc->chip->name ? : "-"); | 91 | seq_printf(p, " %10s", desc->chip->name ? : "-"); |
@@ -90,13 +98,15 @@ unlock: | |||
90 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 98 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
91 | } else if (i == nr_irqs) { | 99 | } else if (i == nr_irqs) { |
92 | #ifdef CONFIG_FIQ | 100 | #ifdef CONFIG_FIQ |
93 | show_fiq_list(p, v); | 101 | show_fiq_list(p, prec); |
94 | #endif | 102 | #endif |
95 | #ifdef CONFIG_SMP | 103 | #ifdef CONFIG_SMP |
96 | show_ipi_list(p); | 104 | show_ipi_list(p, prec); |
97 | show_local_irqs(p); | 105 | #endif |
106 | #ifdef CONFIG_LOCAL_TIMERS | ||
107 | show_local_irqs(p, prec); | ||
98 | #endif | 108 | #endif |
99 | seq_printf(p, "Err: %10lu\n", irq_err_count); | 109 | seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); |
100 | } | 110 | } |
101 | return 0; | 111 | return 0; |
102 | } | 112 | } |
@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) | |||
156 | 166 | ||
157 | void __init init_IRQ(void) | 167 | void __init init_IRQ(void) |
158 | { | 168 | { |
159 | init_arch_irq(); | 169 | machine_desc->init_irq(); |
160 | } | 170 | } |
161 | 171 | ||
162 | #ifdef CONFIG_SPARSE_IRQ | 172 | #ifdef CONFIG_SPARSE_IRQ |
163 | int __init arch_probe_nr_irqs(void) | 173 | int __init arch_probe_nr_irqs(void) |
164 | { | 174 | { |
165 | nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS; | 175 | nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS; |
166 | return nr_irqs; | 176 | return nr_irqs; |
167 | } | 177 | } |
168 | #endif | 178 | #endif |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 336f14e0e5c2..3455ad33de4c 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -75,9 +75,9 @@ extern void reboot_setup(char *str); | |||
75 | 75 | ||
76 | unsigned int processor_id; | 76 | unsigned int processor_id; |
77 | EXPORT_SYMBOL(processor_id); | 77 | EXPORT_SYMBOL(processor_id); |
78 | unsigned int __machine_arch_type; | 78 | unsigned int __machine_arch_type __read_mostly; |
79 | EXPORT_SYMBOL(__machine_arch_type); | 79 | EXPORT_SYMBOL(__machine_arch_type); |
80 | unsigned int cacheid; | 80 | unsigned int cacheid __read_mostly; |
81 | EXPORT_SYMBOL(cacheid); | 81 | EXPORT_SYMBOL(cacheid); |
82 | 82 | ||
83 | unsigned int __atags_pointer __initdata; | 83 | unsigned int __atags_pointer __initdata; |
@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low); | |||
91 | unsigned int system_serial_high; | 91 | unsigned int system_serial_high; |
92 | EXPORT_SYMBOL(system_serial_high); | 92 | EXPORT_SYMBOL(system_serial_high); |
93 | 93 | ||
94 | unsigned int elf_hwcap; | 94 | unsigned int elf_hwcap __read_mostly; |
95 | EXPORT_SYMBOL(elf_hwcap); | 95 | EXPORT_SYMBOL(elf_hwcap); |
96 | 96 | ||
97 | 97 | ||
98 | #ifdef MULTI_CPU | 98 | #ifdef MULTI_CPU |
99 | struct processor processor; | 99 | struct processor processor __read_mostly; |
100 | #endif | 100 | #endif |
101 | #ifdef MULTI_TLB | 101 | #ifdef MULTI_TLB |
102 | struct cpu_tlb_fns cpu_tlb; | 102 | struct cpu_tlb_fns cpu_tlb __read_mostly; |
103 | #endif | 103 | #endif |
104 | #ifdef MULTI_USER | 104 | #ifdef MULTI_USER |
105 | struct cpu_user_fns cpu_user; | 105 | struct cpu_user_fns cpu_user __read_mostly; |
106 | #endif | 106 | #endif |
107 | #ifdef MULTI_CACHE | 107 | #ifdef MULTI_CACHE |
108 | struct cpu_cache_fns cpu_cache; | 108 | struct cpu_cache_fns cpu_cache __read_mostly; |
109 | #endif | 109 | #endif |
110 | #ifdef CONFIG_OUTER_CACHE | 110 | #ifdef CONFIG_OUTER_CACHE |
111 | struct outer_cache_fns outer_cache; | 111 | struct outer_cache_fns outer_cache __read_mostly; |
112 | EXPORT_SYMBOL(outer_cache); | 112 | EXPORT_SYMBOL(outer_cache); |
113 | #endif | 113 | #endif |
114 | 114 | ||
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform); | |||
126 | static const char *cpu_name; | 126 | static const char *cpu_name; |
127 | static const char *machine_name; | 127 | static const char *machine_name; |
128 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; | 128 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; |
129 | struct machine_desc *machine_desc __initdata; | ||
129 | 130 | ||
130 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 131 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
131 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; | 132 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; |
@@ -708,13 +709,11 @@ static struct init_tags { | |||
708 | { 0, ATAG_NONE } | 709 | { 0, ATAG_NONE } |
709 | }; | 710 | }; |
710 | 711 | ||
711 | static void (*init_machine)(void) __initdata; | ||
712 | |||
713 | static int __init customize_machine(void) | 712 | static int __init customize_machine(void) |
714 | { | 713 | { |
715 | /* customizes platform devices, or adds new ones */ | 714 | /* customizes platform devices, or adds new ones */ |
716 | if (init_machine) | 715 | if (machine_desc->init_machine) |
717 | init_machine(); | 716 | machine_desc->init_machine(); |
718 | return 0; | 717 | return 0; |
719 | } | 718 | } |
720 | arch_initcall(customize_machine); | 719 | arch_initcall(customize_machine); |
@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p) | |||
809 | 808 | ||
810 | setup_processor(); | 809 | setup_processor(); |
811 | mdesc = setup_machine(machine_arch_type); | 810 | mdesc = setup_machine(machine_arch_type); |
811 | machine_desc = mdesc; | ||
812 | machine_name = mdesc->name; | 812 | machine_name = mdesc->name; |
813 | 813 | ||
814 | if (mdesc->soft_reboot) | 814 | if (mdesc->soft_reboot) |
@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p) | |||
868 | cpu_init(); | 868 | cpu_init(); |
869 | tcm_init(); | 869 | tcm_init(); |
870 | 870 | ||
871 | /* | 871 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
872 | * Set up various architecture-specific pointers | 872 | handle_arch_irq = mdesc->handle_irq; |
873 | */ | 873 | #endif |
874 | arch_nr_irqs = mdesc->nr_irqs; | ||
875 | init_arch_irq = mdesc->init_irq; | ||
876 | system_timer = mdesc->timer; | ||
877 | init_machine = mdesc->init_machine; | ||
878 | 874 | ||
879 | #ifdef CONFIG_VT | 875 | #ifdef CONFIG_VT |
880 | #if defined(CONFIG_VGA_CONSOLE) | 876 | #if defined(CONFIG_VGA_CONSOLE) |
@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p) | |||
884 | #endif | 880 | #endif |
885 | #endif | 881 | #endif |
886 | early_trap_init(); | 882 | early_trap_init(); |
883 | |||
884 | if (mdesc->init_early) | ||
885 | mdesc->init_early(); | ||
887 | } | 886 | } |
888 | 887 | ||
889 | 888 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b6b78b22031b..5ec79b4ff950 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/percpu.h> | 26 | #include <linux/percpu.h> |
27 | #include <linux/clockchips.h> | 27 | #include <linux/clockchips.h> |
28 | #include <linux/completion.h> | ||
28 | 29 | ||
29 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
30 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
@@ -38,7 +39,6 @@ | |||
38 | #include <asm/tlbflush.h> | 39 | #include <asm/tlbflush.h> |
39 | #include <asm/ptrace.h> | 40 | #include <asm/ptrace.h> |
40 | #include <asm/localtimer.h> | 41 | #include <asm/localtimer.h> |
41 | #include <asm/smp_plat.h> | ||
42 | 42 | ||
43 | /* | 43 | /* |
44 | * as from 2.5, kernels no longer have an init_tasks structure | 44 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -47,22 +47,8 @@ | |||
47 | */ | 47 | */ |
48 | struct secondary_data secondary_data; | 48 | struct secondary_data secondary_data; |
49 | 49 | ||
50 | /* | ||
51 | * structures for inter-processor calls | ||
52 | * - A collection of single bit ipi messages. | ||
53 | */ | ||
54 | struct ipi_data { | ||
55 | spinlock_t lock; | ||
56 | unsigned long ipi_count; | ||
57 | unsigned long bits; | ||
58 | }; | ||
59 | |||
60 | static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { | ||
61 | .lock = SPIN_LOCK_UNLOCKED, | ||
62 | }; | ||
63 | |||
64 | enum ipi_msg_type { | 50 | enum ipi_msg_type { |
65 | IPI_TIMER, | 51 | IPI_TIMER = 2, |
66 | IPI_RESCHEDULE, | 52 | IPI_RESCHEDULE, |
67 | IPI_CALL_FUNC, | 53 | IPI_CALL_FUNC, |
68 | IPI_CALL_FUNC_SINGLE, | 54 | IPI_CALL_FUNC_SINGLE, |
@@ -178,8 +164,12 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
178 | barrier(); | 164 | barrier(); |
179 | } | 165 | } |
180 | 166 | ||
181 | if (!cpu_online(cpu)) | 167 | if (!cpu_online(cpu)) { |
168 | pr_crit("CPU%u: failed to come online\n", cpu); | ||
182 | ret = -EIO; | 169 | ret = -EIO; |
170 | } | ||
171 | } else { | ||
172 | pr_err("CPU%u: failed to boot: %d\n", cpu, ret); | ||
183 | } | 173 | } |
184 | 174 | ||
185 | secondary_data.stack = NULL; | 175 | secondary_data.stack = NULL; |
@@ -195,18 +185,12 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
195 | 185 | ||
196 | pgd_free(&init_mm, pgd); | 186 | pgd_free(&init_mm, pgd); |
197 | 187 | ||
198 | if (ret) { | ||
199 | printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu); | ||
200 | |||
201 | /* | ||
202 | * FIXME: We need to clean up the new idle thread. --rmk | ||
203 | */ | ||
204 | } | ||
205 | |||
206 | return ret; | 188 | return ret; |
207 | } | 189 | } |
208 | 190 | ||
209 | #ifdef CONFIG_HOTPLUG_CPU | 191 | #ifdef CONFIG_HOTPLUG_CPU |
192 | static void percpu_timer_stop(void); | ||
193 | |||
210 | /* | 194 | /* |
211 | * __cpu_disable runs on the processor to be shutdown. | 195 | * __cpu_disable runs on the processor to be shutdown. |
212 | */ | 196 | */ |
@@ -234,7 +218,7 @@ int __cpu_disable(void) | |||
234 | /* | 218 | /* |
235 | * Stop the local timer for this CPU. | 219 | * Stop the local timer for this CPU. |
236 | */ | 220 | */ |
237 | local_timer_stop(); | 221 | percpu_timer_stop(); |
238 | 222 | ||
239 | /* | 223 | /* |
240 | * Flush user cache and TLB mappings, and then remove this CPU | 224 | * Flush user cache and TLB mappings, and then remove this CPU |
@@ -253,12 +237,20 @@ int __cpu_disable(void) | |||
253 | return 0; | 237 | return 0; |
254 | } | 238 | } |
255 | 239 | ||
240 | static DECLARE_COMPLETION(cpu_died); | ||
241 | |||
256 | /* | 242 | /* |
257 | * called on the thread which is asking for a CPU to be shutdown - | 243 | * called on the thread which is asking for a CPU to be shutdown - |
258 | * waits until shutdown has completed, or it is timed out. | 244 | * waits until shutdown has completed, or it is timed out. |
259 | */ | 245 | */ |
260 | void __cpu_die(unsigned int cpu) | 246 | void __cpu_die(unsigned int cpu) |
261 | { | 247 | { |
248 | if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { | ||
249 | pr_err("CPU%u: cpu didn't die\n", cpu); | ||
250 | return; | ||
251 | } | ||
252 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
253 | |||
262 | if (!platform_cpu_kill(cpu)) | 254 | if (!platform_cpu_kill(cpu)) |
263 | printk("CPU%u: unable to kill\n", cpu); | 255 | printk("CPU%u: unable to kill\n", cpu); |
264 | } | 256 | } |
@@ -275,12 +267,17 @@ void __ref cpu_die(void) | |||
275 | { | 267 | { |
276 | unsigned int cpu = smp_processor_id(); | 268 | unsigned int cpu = smp_processor_id(); |
277 | 269 | ||
278 | local_irq_disable(); | ||
279 | idle_task_exit(); | 270 | idle_task_exit(); |
280 | 271 | ||
272 | local_irq_disable(); | ||
273 | mb(); | ||
274 | |||
275 | /* Tell __cpu_die() that this CPU is now safe to dispose of */ | ||
276 | complete(&cpu_died); | ||
277 | |||
281 | /* | 278 | /* |
282 | * actual CPU shutdown procedure is at least platform (if not | 279 | * actual CPU shutdown procedure is at least platform (if not |
283 | * CPU) specific | 280 | * CPU) specific. |
284 | */ | 281 | */ |
285 | platform_cpu_die(cpu); | 282 | platform_cpu_die(cpu); |
286 | 283 | ||
@@ -290,6 +287,7 @@ void __ref cpu_die(void) | |||
290 | * to be repeated to undo the effects of taking the CPU offline. | 287 | * to be repeated to undo the effects of taking the CPU offline. |
291 | */ | 288 | */ |
292 | __asm__("mov sp, %0\n" | 289 | __asm__("mov sp, %0\n" |
290 | " mov fp, #0\n" | ||
293 | " b secondary_start_kernel" | 291 | " b secondary_start_kernel" |
294 | : | 292 | : |
295 | : "r" (task_stack_page(current) + THREAD_SIZE - 8)); | 293 | : "r" (task_stack_page(current) + THREAD_SIZE - 8)); |
@@ -297,6 +295,17 @@ void __ref cpu_die(void) | |||
297 | #endif /* CONFIG_HOTPLUG_CPU */ | 295 | #endif /* CONFIG_HOTPLUG_CPU */ |
298 | 296 | ||
299 | /* | 297 | /* |
298 | * Called by both boot and secondaries to move global data into | ||
299 | * per-processor storage. | ||
300 | */ | ||
301 | static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | ||
302 | { | ||
303 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | ||
304 | |||
305 | cpu_info->loops_per_jiffy = loops_per_jiffy; | ||
306 | } | ||
307 | |||
308 | /* | ||
300 | * This is the secondary CPU boot entry. We're using this CPUs | 309 | * This is the secondary CPU boot entry. We're using this CPUs |
301 | * idle thread stack, but a set of temporary page tables. | 310 | * idle thread stack, but a set of temporary page tables. |
302 | */ | 311 | */ |
@@ -320,6 +329,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
320 | 329 | ||
321 | cpu_init(); | 330 | cpu_init(); |
322 | preempt_disable(); | 331 | preempt_disable(); |
332 | trace_hardirqs_off(); | ||
323 | 333 | ||
324 | /* | 334 | /* |
325 | * Give the platform a chance to do its own initialisation. | 335 | * Give the platform a chance to do its own initialisation. |
@@ -353,17 +363,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
353 | cpu_idle(); | 363 | cpu_idle(); |
354 | } | 364 | } |
355 | 365 | ||
356 | /* | ||
357 | * Called by both boot and secondaries to move global data into | ||
358 | * per-processor storage. | ||
359 | */ | ||
360 | void __cpuinit smp_store_cpu_info(unsigned int cpuid) | ||
361 | { | ||
362 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | ||
363 | |||
364 | cpu_info->loops_per_jiffy = loops_per_jiffy; | ||
365 | } | ||
366 | |||
367 | void __init smp_cpus_done(unsigned int max_cpus) | 366 | void __init smp_cpus_done(unsigned int max_cpus) |
368 | { | 367 | { |
369 | int cpu; | 368 | int cpu; |
@@ -386,61 +385,80 @@ void __init smp_prepare_boot_cpu(void) | |||
386 | per_cpu(cpu_data, cpu).idle = current; | 385 | per_cpu(cpu_data, cpu).idle = current; |
387 | } | 386 | } |
388 | 387 | ||
389 | static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) | 388 | void __init smp_prepare_cpus(unsigned int max_cpus) |
390 | { | 389 | { |
391 | unsigned long flags; | 390 | unsigned int ncores = num_possible_cpus(); |
392 | unsigned int cpu; | ||
393 | |||
394 | local_irq_save(flags); | ||
395 | 391 | ||
396 | for_each_cpu(cpu, mask) { | 392 | smp_store_cpu_info(smp_processor_id()); |
397 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | ||
398 | |||
399 | spin_lock(&ipi->lock); | ||
400 | ipi->bits |= 1 << msg; | ||
401 | spin_unlock(&ipi->lock); | ||
402 | } | ||
403 | 393 | ||
404 | /* | 394 | /* |
405 | * Call the platform specific cross-CPU call function. | 395 | * are we trying to boot more cores than exist? |
406 | */ | 396 | */ |
407 | smp_cross_call(mask); | 397 | if (max_cpus > ncores) |
398 | max_cpus = ncores; | ||
399 | |||
400 | if (max_cpus > 1) { | ||
401 | /* | ||
402 | * Enable the local timer or broadcast device for the | ||
403 | * boot CPU, but only if we have more than one CPU. | ||
404 | */ | ||
405 | percpu_timer_setup(); | ||
408 | 406 | ||
409 | local_irq_restore(flags); | 407 | /* |
408 | * Initialise the SCU if there are more than one CPU | ||
409 | * and let them know where to start. | ||
410 | */ | ||
411 | platform_smp_prepare_cpus(max_cpus); | ||
412 | } | ||
410 | } | 413 | } |
411 | 414 | ||
412 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | 415 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
413 | { | 416 | { |
414 | send_ipi_message(mask, IPI_CALL_FUNC); | 417 | smp_cross_call(mask, IPI_CALL_FUNC); |
415 | } | 418 | } |
416 | 419 | ||
417 | void arch_send_call_function_single_ipi(int cpu) | 420 | void arch_send_call_function_single_ipi(int cpu) |
418 | { | 421 | { |
419 | send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | 422 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); |
420 | } | 423 | } |
421 | 424 | ||
422 | void show_ipi_list(struct seq_file *p) | 425 | static const char *ipi_types[NR_IPI] = { |
426 | #define S(x,s) [x - IPI_TIMER] = s | ||
427 | S(IPI_TIMER, "Timer broadcast interrupts"), | ||
428 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), | ||
429 | S(IPI_CALL_FUNC, "Function call interrupts"), | ||
430 | S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), | ||
431 | S(IPI_CPU_STOP, "CPU stop interrupts"), | ||
432 | }; | ||
433 | |||
434 | void show_ipi_list(struct seq_file *p, int prec) | ||
423 | { | 435 | { |
424 | unsigned int cpu; | 436 | unsigned int cpu, i; |
425 | 437 | ||
426 | seq_puts(p, "IPI:"); | 438 | for (i = 0; i < NR_IPI; i++) { |
439 | seq_printf(p, "%*s%u: ", prec - 1, "IPI", i); | ||
427 | 440 | ||
428 | for_each_present_cpu(cpu) | 441 | for_each_present_cpu(cpu) |
429 | seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); | 442 | seq_printf(p, "%10u ", |
443 | __get_irq_stat(cpu, ipi_irqs[i])); | ||
430 | 444 | ||
431 | seq_putc(p, '\n'); | 445 | seq_printf(p, " %s\n", ipi_types[i]); |
446 | } | ||
432 | } | 447 | } |
433 | 448 | ||
434 | void show_local_irqs(struct seq_file *p) | 449 | u64 smp_irq_stat_cpu(unsigned int cpu) |
435 | { | 450 | { |
436 | unsigned int cpu; | 451 | u64 sum = 0; |
452 | int i; | ||
437 | 453 | ||
438 | seq_printf(p, "LOC: "); | 454 | for (i = 0; i < NR_IPI; i++) |
455 | sum += __get_irq_stat(cpu, ipi_irqs[i]); | ||
439 | 456 | ||
440 | for_each_present_cpu(cpu) | 457 | #ifdef CONFIG_LOCAL_TIMERS |
441 | seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); | 458 | sum += __get_irq_stat(cpu, local_timer_irqs); |
459 | #endif | ||
442 | 460 | ||
443 | seq_putc(p, '\n'); | 461 | return sum; |
444 | } | 462 | } |
445 | 463 | ||
446 | /* | 464 | /* |
@@ -463,18 +481,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | |||
463 | int cpu = smp_processor_id(); | 481 | int cpu = smp_processor_id(); |
464 | 482 | ||
465 | if (local_timer_ack()) { | 483 | if (local_timer_ack()) { |
466 | irq_stat[cpu].local_timer_irqs++; | 484 | __inc_irq_stat(cpu, local_timer_irqs); |
467 | ipi_timer(); | 485 | ipi_timer(); |
468 | } | 486 | } |
469 | 487 | ||
470 | set_irq_regs(old_regs); | 488 | set_irq_regs(old_regs); |
471 | } | 489 | } |
490 | |||
491 | void show_local_irqs(struct seq_file *p, int prec) | ||
492 | { | ||
493 | unsigned int cpu; | ||
494 | |||
495 | seq_printf(p, "%*s: ", prec, "LOC"); | ||
496 | |||
497 | for_each_present_cpu(cpu) | ||
498 | seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs)); | ||
499 | |||
500 | seq_printf(p, " Local timer interrupts\n"); | ||
501 | } | ||
472 | #endif | 502 | #endif |
473 | 503 | ||
474 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 504 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
475 | static void smp_timer_broadcast(const struct cpumask *mask) | 505 | static void smp_timer_broadcast(const struct cpumask *mask) |
476 | { | 506 | { |
477 | send_ipi_message(mask, IPI_TIMER); | 507 | smp_cross_call(mask, IPI_TIMER); |
478 | } | 508 | } |
479 | #else | 509 | #else |
480 | #define smp_timer_broadcast NULL | 510 | #define smp_timer_broadcast NULL |
@@ -511,6 +541,21 @@ void __cpuinit percpu_timer_setup(void) | |||
511 | local_timer_setup(evt); | 541 | local_timer_setup(evt); |
512 | } | 542 | } |
513 | 543 | ||
544 | #ifdef CONFIG_HOTPLUG_CPU | ||
545 | /* | ||
546 | * The generic clock events code purposely does not stop the local timer | ||
547 | * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it | ||
548 | * manually here. | ||
549 | */ | ||
550 | static void percpu_timer_stop(void) | ||
551 | { | ||
552 | unsigned int cpu = smp_processor_id(); | ||
553 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | ||
554 | |||
555 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | ||
556 | } | ||
557 | #endif | ||
558 | |||
514 | static DEFINE_SPINLOCK(stop_lock); | 559 | static DEFINE_SPINLOCK(stop_lock); |
515 | 560 | ||
516 | /* | 561 | /* |
@@ -537,216 +582,76 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
537 | 582 | ||
538 | /* | 583 | /* |
539 | * Main handler for inter-processor interrupts | 584 | * Main handler for inter-processor interrupts |
540 | * | ||
541 | * For ARM, the ipimask now only identifies a single | ||
542 | * category of IPI (Bit 1 IPIs have been replaced by a | ||
543 | * different mechanism): | ||
544 | * | ||
545 | * Bit 0 - Inter-processor function call | ||
546 | */ | 585 | */ |
547 | asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs) | 586 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
548 | { | 587 | { |
549 | unsigned int cpu = smp_processor_id(); | 588 | unsigned int cpu = smp_processor_id(); |
550 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | ||
551 | struct pt_regs *old_regs = set_irq_regs(regs); | 589 | struct pt_regs *old_regs = set_irq_regs(regs); |
552 | 590 | ||
553 | ipi->ipi_count++; | 591 | if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) |
554 | 592 | __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); | |
555 | for (;;) { | ||
556 | unsigned long msgs; | ||
557 | 593 | ||
558 | spin_lock(&ipi->lock); | 594 | switch (ipinr) { |
559 | msgs = ipi->bits; | 595 | case IPI_TIMER: |
560 | ipi->bits = 0; | 596 | ipi_timer(); |
561 | spin_unlock(&ipi->lock); | 597 | break; |
562 | |||
563 | if (!msgs) | ||
564 | break; | ||
565 | |||
566 | do { | ||
567 | unsigned nextmsg; | ||
568 | |||
569 | nextmsg = msgs & -msgs; | ||
570 | msgs &= ~nextmsg; | ||
571 | nextmsg = ffz(~nextmsg); | ||
572 | |||
573 | switch (nextmsg) { | ||
574 | case IPI_TIMER: | ||
575 | ipi_timer(); | ||
576 | break; | ||
577 | 598 | ||
578 | case IPI_RESCHEDULE: | 599 | case IPI_RESCHEDULE: |
579 | /* | 600 | /* |
580 | * nothing more to do - eveything is | 601 | * nothing more to do - eveything is |
581 | * done on the interrupt return path | 602 | * done on the interrupt return path |
582 | */ | 603 | */ |
583 | break; | 604 | break; |
584 | 605 | ||
585 | case IPI_CALL_FUNC: | 606 | case IPI_CALL_FUNC: |
586 | generic_smp_call_function_interrupt(); | 607 | generic_smp_call_function_interrupt(); |
587 | break; | 608 | break; |
588 | 609 | ||
589 | case IPI_CALL_FUNC_SINGLE: | 610 | case IPI_CALL_FUNC_SINGLE: |
590 | generic_smp_call_function_single_interrupt(); | 611 | generic_smp_call_function_single_interrupt(); |
591 | break; | 612 | break; |
592 | 613 | ||
593 | case IPI_CPU_STOP: | 614 | case IPI_CPU_STOP: |
594 | ipi_cpu_stop(cpu); | 615 | ipi_cpu_stop(cpu); |
595 | break; | 616 | break; |
596 | 617 | ||
597 | default: | 618 | default: |
598 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", | 619 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", |
599 | cpu, nextmsg); | 620 | cpu, ipinr); |
600 | break; | 621 | break; |
601 | } | ||
602 | } while (msgs); | ||
603 | } | 622 | } |
604 | |||
605 | set_irq_regs(old_regs); | 623 | set_irq_regs(old_regs); |
606 | } | 624 | } |
607 | 625 | ||
608 | void smp_send_reschedule(int cpu) | 626 | void smp_send_reschedule(int cpu) |
609 | { | 627 | { |
610 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); | 628 | smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); |
611 | } | 629 | } |
612 | 630 | ||
613 | void smp_send_stop(void) | 631 | void smp_send_stop(void) |
614 | { | 632 | { |
615 | cpumask_t mask = cpu_online_map; | 633 | unsigned long timeout; |
616 | cpu_clear(smp_processor_id(), mask); | ||
617 | if (!cpus_empty(mask)) | ||
618 | send_ipi_message(&mask, IPI_CPU_STOP); | ||
619 | } | ||
620 | 634 | ||
621 | /* | 635 | if (num_online_cpus() > 1) { |
622 | * not supported here | 636 | cpumask_t mask = cpu_online_map; |
623 | */ | 637 | cpu_clear(smp_processor_id(), mask); |
624 | int setup_profiling_timer(unsigned int multiplier) | ||
625 | { | ||
626 | return -EINVAL; | ||
627 | } | ||
628 | 638 | ||
629 | static void | 639 | smp_cross_call(&mask, IPI_CPU_STOP); |
630 | on_each_cpu_mask(void (*func)(void *), void *info, int wait, | 640 | } |
631 | const struct cpumask *mask) | ||
632 | { | ||
633 | preempt_disable(); | ||
634 | 641 | ||
635 | smp_call_function_many(mask, func, info, wait); | 642 | /* Wait up to one second for other CPUs to stop */ |
636 | if (cpumask_test_cpu(smp_processor_id(), mask)) | 643 | timeout = USEC_PER_SEC; |
637 | func(info); | 644 | while (num_online_cpus() > 1 && timeout--) |
645 | udelay(1); | ||
638 | 646 | ||
639 | preempt_enable(); | 647 | if (num_online_cpus() > 1) |
648 | pr_warning("SMP: failed to stop secondary CPUs\n"); | ||
640 | } | 649 | } |
641 | 650 | ||
642 | /**********************************************************************/ | ||
643 | |||
644 | /* | 651 | /* |
645 | * TLB operations | 652 | * not supported here |
646 | */ | 653 | */ |
647 | struct tlb_args { | 654 | int setup_profiling_timer(unsigned int multiplier) |
648 | struct vm_area_struct *ta_vma; | ||
649 | unsigned long ta_start; | ||
650 | unsigned long ta_end; | ||
651 | }; | ||
652 | |||
653 | static inline void ipi_flush_tlb_all(void *ignored) | ||
654 | { | ||
655 | local_flush_tlb_all(); | ||
656 | } | ||
657 | |||
658 | static inline void ipi_flush_tlb_mm(void *arg) | ||
659 | { | ||
660 | struct mm_struct *mm = (struct mm_struct *)arg; | ||
661 | |||
662 | local_flush_tlb_mm(mm); | ||
663 | } | ||
664 | |||
665 | static inline void ipi_flush_tlb_page(void *arg) | ||
666 | { | ||
667 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
668 | |||
669 | local_flush_tlb_page(ta->ta_vma, ta->ta_start); | ||
670 | } | ||
671 | |||
672 | static inline void ipi_flush_tlb_kernel_page(void *arg) | ||
673 | { | ||
674 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
675 | |||
676 | local_flush_tlb_kernel_page(ta->ta_start); | ||
677 | } | ||
678 | |||
679 | static inline void ipi_flush_tlb_range(void *arg) | ||
680 | { | ||
681 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
682 | |||
683 | local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | ||
684 | } | ||
685 | |||
686 | static inline void ipi_flush_tlb_kernel_range(void *arg) | ||
687 | { | ||
688 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
689 | |||
690 | local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | ||
691 | } | ||
692 | |||
693 | void flush_tlb_all(void) | ||
694 | { | ||
695 | if (tlb_ops_need_broadcast()) | ||
696 | on_each_cpu(ipi_flush_tlb_all, NULL, 1); | ||
697 | else | ||
698 | local_flush_tlb_all(); | ||
699 | } | ||
700 | |||
701 | void flush_tlb_mm(struct mm_struct *mm) | ||
702 | { | ||
703 | if (tlb_ops_need_broadcast()) | ||
704 | on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | ||
705 | else | ||
706 | local_flush_tlb_mm(mm); | ||
707 | } | ||
708 | |||
709 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | ||
710 | { | ||
711 | if (tlb_ops_need_broadcast()) { | ||
712 | struct tlb_args ta; | ||
713 | ta.ta_vma = vma; | ||
714 | ta.ta_start = uaddr; | ||
715 | on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
716 | } else | ||
717 | local_flush_tlb_page(vma, uaddr); | ||
718 | } | ||
719 | |||
720 | void flush_tlb_kernel_page(unsigned long kaddr) | ||
721 | { | ||
722 | if (tlb_ops_need_broadcast()) { | ||
723 | struct tlb_args ta; | ||
724 | ta.ta_start = kaddr; | ||
725 | on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | ||
726 | } else | ||
727 | local_flush_tlb_kernel_page(kaddr); | ||
728 | } | ||
729 | |||
730 | void flush_tlb_range(struct vm_area_struct *vma, | ||
731 | unsigned long start, unsigned long end) | ||
732 | { | ||
733 | if (tlb_ops_need_broadcast()) { | ||
734 | struct tlb_args ta; | ||
735 | ta.ta_vma = vma; | ||
736 | ta.ta_start = start; | ||
737 | ta.ta_end = end; | ||
738 | on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
739 | } else | ||
740 | local_flush_tlb_range(vma, start, end); | ||
741 | } | ||
742 | |||
743 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
744 | { | 655 | { |
745 | if (tlb_ops_need_broadcast()) { | 656 | return -EINVAL; |
746 | struct tlb_args ta; | ||
747 | ta.ta_start = start; | ||
748 | ta.ta_end = end; | ||
749 | on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | ||
750 | } else | ||
751 | local_flush_tlb_kernel_range(start, end); | ||
752 | } | 657 | } |
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c new file mode 100644 index 000000000000..7dcb35285be7 --- /dev/null +++ b/arch/arm/kernel/smp_tlb.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/smp_tlb.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Limited, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/preempt.h> | ||
11 | #include <linux/smp.h> | ||
12 | |||
13 | #include <asm/smp_plat.h> | ||
14 | #include <asm/tlbflush.h> | ||
15 | |||
16 | static void on_each_cpu_mask(void (*func)(void *), void *info, int wait, | ||
17 | const struct cpumask *mask) | ||
18 | { | ||
19 | preempt_disable(); | ||
20 | |||
21 | smp_call_function_many(mask, func, info, wait); | ||
22 | if (cpumask_test_cpu(smp_processor_id(), mask)) | ||
23 | func(info); | ||
24 | |||
25 | preempt_enable(); | ||
26 | } | ||
27 | |||
28 | /**********************************************************************/ | ||
29 | |||
30 | /* | ||
31 | * TLB operations | ||
32 | */ | ||
33 | struct tlb_args { | ||
34 | struct vm_area_struct *ta_vma; | ||
35 | unsigned long ta_start; | ||
36 | unsigned long ta_end; | ||
37 | }; | ||
38 | |||
39 | static inline void ipi_flush_tlb_all(void *ignored) | ||
40 | { | ||
41 | local_flush_tlb_all(); | ||
42 | } | ||
43 | |||
44 | static inline void ipi_flush_tlb_mm(void *arg) | ||
45 | { | ||
46 | struct mm_struct *mm = (struct mm_struct *)arg; | ||
47 | |||
48 | local_flush_tlb_mm(mm); | ||
49 | } | ||
50 | |||
51 | static inline void ipi_flush_tlb_page(void *arg) | ||
52 | { | ||
53 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
54 | |||
55 | local_flush_tlb_page(ta->ta_vma, ta->ta_start); | ||
56 | } | ||
57 | |||
58 | static inline void ipi_flush_tlb_kernel_page(void *arg) | ||
59 | { | ||
60 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
61 | |||
62 | local_flush_tlb_kernel_page(ta->ta_start); | ||
63 | } | ||
64 | |||
65 | static inline void ipi_flush_tlb_range(void *arg) | ||
66 | { | ||
67 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
68 | |||
69 | local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | ||
70 | } | ||
71 | |||
72 | static inline void ipi_flush_tlb_kernel_range(void *arg) | ||
73 | { | ||
74 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
75 | |||
76 | local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | ||
77 | } | ||
78 | |||
79 | void flush_tlb_all(void) | ||
80 | { | ||
81 | if (tlb_ops_need_broadcast()) | ||
82 | on_each_cpu(ipi_flush_tlb_all, NULL, 1); | ||
83 | else | ||
84 | local_flush_tlb_all(); | ||
85 | } | ||
86 | |||
87 | void flush_tlb_mm(struct mm_struct *mm) | ||
88 | { | ||
89 | if (tlb_ops_need_broadcast()) | ||
90 | on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | ||
91 | else | ||
92 | local_flush_tlb_mm(mm); | ||
93 | } | ||
94 | |||
95 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | ||
96 | { | ||
97 | if (tlb_ops_need_broadcast()) { | ||
98 | struct tlb_args ta; | ||
99 | ta.ta_vma = vma; | ||
100 | ta.ta_start = uaddr; | ||
101 | on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
102 | } else | ||
103 | local_flush_tlb_page(vma, uaddr); | ||
104 | } | ||
105 | |||
106 | void flush_tlb_kernel_page(unsigned long kaddr) | ||
107 | { | ||
108 | if (tlb_ops_need_broadcast()) { | ||
109 | struct tlb_args ta; | ||
110 | ta.ta_start = kaddr; | ||
111 | on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | ||
112 | } else | ||
113 | local_flush_tlb_kernel_page(kaddr); | ||
114 | } | ||
115 | |||
116 | void flush_tlb_range(struct vm_area_struct *vma, | ||
117 | unsigned long start, unsigned long end) | ||
118 | { | ||
119 | if (tlb_ops_need_broadcast()) { | ||
120 | struct tlb_args ta; | ||
121 | ta.ta_vma = vma; | ||
122 | ta.ta_start = start; | ||
123 | ta.ta_end = end; | ||
124 | on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
125 | } else | ||
126 | local_flush_tlb_range(vma, start, end); | ||
127 | } | ||
128 | |||
129 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
130 | { | ||
131 | if (tlb_ops_need_broadcast()) { | ||
132 | struct tlb_args ta; | ||
133 | ta.ta_start = start; | ||
134 | ta.ta_end = end; | ||
135 | on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | ||
136 | } else | ||
137 | local_flush_tlb_kernel_range(start, end); | ||
138 | } | ||
139 | |||
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 67f933ec4177..dd790745b3ef 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -145,13 +145,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
145 | 145 | ||
146 | clockevents_register_device(clk); | 146 | clockevents_register_device(clk); |
147 | } | 147 | } |
148 | |||
149 | #ifdef CONFIG_HOTPLUG_CPU | ||
150 | /* | ||
151 | * take a local timer down | ||
152 | */ | ||
153 | void twd_timer_stop(void) | ||
154 | { | ||
155 | __raw_writel(0, twd_base + TWD_TIMER_CONTROL); | ||
156 | } | ||
157 | #endif | ||
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c new file mode 100644 index 000000000000..7a5760922914 --- /dev/null +++ b/arch/arm/kernel/swp_emulate.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/swp_emulate.c | ||
3 | * | ||
4 | * Copyright (C) 2009 ARM Limited | ||
5 | * __user_* functions adapted from include/asm/uaccess.h | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Implements emulation of the SWP/SWPB instructions using load-exclusive and | ||
12 | * store-exclusive for processors that have them disabled (or future ones that | ||
13 | * might not implement them). | ||
14 | * | ||
15 | * Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>] | ||
16 | * Where: Rt = destination | ||
17 | * Rt2 = source | ||
18 | * Rn = address | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/syscalls.h> | ||
26 | #include <linux/perf_event.h> | ||
27 | |||
28 | #include <asm/traps.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | |||
31 | /* | ||
32 | * Error-checking SWP macros implemented using ldrex{b}/strex{b} | ||
33 | */ | ||
34 | #define __user_swpX_asm(data, addr, res, temp, B) \ | ||
35 | __asm__ __volatile__( \ | ||
36 | " mov %2, %1\n" \ | ||
37 | "0: ldrex"B" %1, [%3]\n" \ | ||
38 | "1: strex"B" %0, %2, [%3]\n" \ | ||
39 | " cmp %0, #0\n" \ | ||
40 | " movne %0, %4\n" \ | ||
41 | "2:\n" \ | ||
42 | " .section .fixup,\"ax\"\n" \ | ||
43 | " .align 2\n" \ | ||
44 | "3: mov %0, %5\n" \ | ||
45 | " b 2b\n" \ | ||
46 | " .previous\n" \ | ||
47 | " .section __ex_table,\"a\"\n" \ | ||
48 | " .align 3\n" \ | ||
49 | " .long 0b, 3b\n" \ | ||
50 | " .long 1b, 3b\n" \ | ||
51 | " .previous" \ | ||
52 | : "=&r" (res), "+r" (data), "=&r" (temp) \ | ||
53 | : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ | ||
54 | : "cc", "memory") | ||
55 | |||
56 | #define __user_swp_asm(data, addr, res, temp) \ | ||
57 | __user_swpX_asm(data, addr, res, temp, "") | ||
58 | #define __user_swpb_asm(data, addr, res, temp) \ | ||
59 | __user_swpX_asm(data, addr, res, temp, "b") | ||
60 | |||
61 | /* | ||
62 | * Macros/defines for extracting register numbers from instruction. | ||
63 | */ | ||
64 | #define EXTRACT_REG_NUM(instruction, offset) \ | ||
65 | (((instruction) & (0xf << (offset))) >> (offset)) | ||
66 | #define RN_OFFSET 16 | ||
67 | #define RT_OFFSET 12 | ||
68 | #define RT2_OFFSET 0 | ||
69 | /* | ||
70 | * Bit 22 of the instruction encoding distinguishes between | ||
71 | * the SWP and SWPB variants (bit set means SWPB). | ||
72 | */ | ||
73 | #define TYPE_SWPB (1 << 22) | ||
74 | |||
75 | static unsigned long swpcounter; | ||
76 | static unsigned long swpbcounter; | ||
77 | static unsigned long abtcounter; | ||
78 | static pid_t previous_pid; | ||
79 | |||
80 | #ifdef CONFIG_PROC_FS | ||
81 | static int proc_read_status(char *page, char **start, off_t off, int count, | ||
82 | int *eof, void *data) | ||
83 | { | ||
84 | char *p = page; | ||
85 | int len; | ||
86 | |||
87 | p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter); | ||
88 | p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter); | ||
89 | p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter); | ||
90 | if (previous_pid != 0) | ||
91 | p += sprintf(p, "Last process:\t\t%d\n", previous_pid); | ||
92 | |||
93 | len = (p - page) - off; | ||
94 | if (len < 0) | ||
95 | len = 0; | ||
96 | |||
97 | *eof = (len <= count) ? 1 : 0; | ||
98 | *start = page + off; | ||
99 | |||
100 | return len; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | /* | ||
105 | * Set up process info to signal segmentation fault - called on access error. | ||
106 | */ | ||
107 | static void set_segfault(struct pt_regs *regs, unsigned long addr) | ||
108 | { | ||
109 | siginfo_t info; | ||
110 | |||
111 | if (find_vma(current->mm, addr) == NULL) | ||
112 | info.si_code = SEGV_MAPERR; | ||
113 | else | ||
114 | info.si_code = SEGV_ACCERR; | ||
115 | |||
116 | info.si_signo = SIGSEGV; | ||
117 | info.si_errno = 0; | ||
118 | info.si_addr = (void *) instruction_pointer(regs); | ||
119 | |||
120 | pr_debug("SWP{B} emulation: access caused memory abort!\n"); | ||
121 | arm_notify_die("Illegal memory access", regs, &info, 0, 0); | ||
122 | |||
123 | abtcounter++; | ||
124 | } | ||
125 | |||
126 | static int emulate_swpX(unsigned int address, unsigned int *data, | ||
127 | unsigned int type) | ||
128 | { | ||
129 | unsigned int res = 0; | ||
130 | |||
131 | if ((type != TYPE_SWPB) && (address & 0x3)) { | ||
132 | /* SWP to unaligned address not permitted */ | ||
133 | pr_debug("SWP instruction on unaligned pointer!\n"); | ||
134 | return -EFAULT; | ||
135 | } | ||
136 | |||
137 | while (1) { | ||
138 | unsigned long temp; | ||
139 | |||
140 | /* | ||
141 | * Barrier required between accessing protected resource and | ||
142 | * releasing a lock for it. Legacy code might not have done | ||
143 | * this, and we cannot determine that this is not the case | ||
144 | * being emulated, so insert always. | ||
145 | */ | ||
146 | smp_mb(); | ||
147 | |||
148 | if (type == TYPE_SWPB) | ||
149 | __user_swpb_asm(*data, address, res, temp); | ||
150 | else | ||
151 | __user_swp_asm(*data, address, res, temp); | ||
152 | |||
153 | if (likely(res != -EAGAIN) || signal_pending(current)) | ||
154 | break; | ||
155 | |||
156 | cond_resched(); | ||
157 | } | ||
158 | |||
159 | if (res == 0) { | ||
160 | /* | ||
161 | * Barrier also required between aquiring a lock for a | ||
162 | * protected resource and accessing the resource. Inserted for | ||
163 | * same reason as above. | ||
164 | */ | ||
165 | smp_mb(); | ||
166 | |||
167 | if (type == TYPE_SWPB) | ||
168 | swpbcounter++; | ||
169 | else | ||
170 | swpcounter++; | ||
171 | } | ||
172 | |||
173 | return res; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * swp_handler logs the id of calling process, dissects the instruction, sanity | ||
178 | * checks the memory location, calls emulate_swpX for the actual operation and | ||
179 | * deals with fixup/error handling before returning | ||
180 | */ | ||
181 | static int swp_handler(struct pt_regs *regs, unsigned int instr) | ||
182 | { | ||
183 | unsigned int address, destreg, data, type; | ||
184 | unsigned int res = 0; | ||
185 | |||
186 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc); | ||
187 | |||
188 | if (current->pid != previous_pid) { | ||
189 | pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n", | ||
190 | current->comm, (unsigned long)current->pid); | ||
191 | previous_pid = current->pid; | ||
192 | } | ||
193 | |||
194 | address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)]; | ||
195 | data = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)]; | ||
196 | destreg = EXTRACT_REG_NUM(instr, RT_OFFSET); | ||
197 | |||
198 | type = instr & TYPE_SWPB; | ||
199 | |||
200 | pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n", | ||
201 | EXTRACT_REG_NUM(instr, RN_OFFSET), address, | ||
202 | destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data); | ||
203 | |||
204 | /* Check access in reasonable access range for both SWP and SWPB */ | ||
205 | if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { | ||
206 | pr_debug("SWP{B} emulation: access to %p not allowed!\n", | ||
207 | (void *)address); | ||
208 | res = -EFAULT; | ||
209 | } else { | ||
210 | res = emulate_swpX(address, &data, type); | ||
211 | } | ||
212 | |||
213 | if (res == 0) { | ||
214 | /* | ||
215 | * On successful emulation, revert the adjustment to the PC | ||
216 | * made in kernel/traps.c in order to resume execution at the | ||
217 | * instruction following the SWP{B}. | ||
218 | */ | ||
219 | regs->ARM_pc += 4; | ||
220 | regs->uregs[destreg] = data; | ||
221 | } else if (res == -EFAULT) { | ||
222 | /* | ||
223 | * Memory errors do not mean emulation failed. | ||
224 | * Set up signal info to return SEGV, then return OK | ||
225 | */ | ||
226 | set_segfault(regs, address); | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Only emulate SWP/SWPB executed in ARM state/User mode. | ||
234 | * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE. | ||
235 | */ | ||
236 | static struct undef_hook swp_hook = { | ||
237 | .instr_mask = 0x0fb00ff0, | ||
238 | .instr_val = 0x01000090, | ||
239 | .cpsr_mask = MODE_MASK | PSR_T_BIT | PSR_J_BIT, | ||
240 | .cpsr_val = USR_MODE, | ||
241 | .fn = swp_handler | ||
242 | }; | ||
243 | |||
244 | /* | ||
245 | * Register handler and create status file in /proc/cpu | ||
246 | * Invoked as late_initcall, since not needed before init spawned. | ||
247 | */ | ||
248 | static int __init swp_emulation_init(void) | ||
249 | { | ||
250 | #ifdef CONFIG_PROC_FS | ||
251 | struct proc_dir_entry *res; | ||
252 | |||
253 | res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL); | ||
254 | |||
255 | if (!res) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | res->read_proc = proc_read_status; | ||
259 | #endif /* CONFIG_PROC_FS */ | ||
260 | |||
261 | printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); | ||
262 | register_undef_hook(&swp_hook); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | late_initcall(swp_emulation_init); | ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 38c261f9951c..f1e2eb19a67d 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -30,12 +30,13 @@ | |||
30 | #include <asm/leds.h> | 30 | #include <asm/leds.h> |
31 | #include <asm/thread_info.h> | 31 | #include <asm/thread_info.h> |
32 | #include <asm/stacktrace.h> | 32 | #include <asm/stacktrace.h> |
33 | #include <asm/mach/arch.h> | ||
33 | #include <asm/mach/time.h> | 34 | #include <asm/mach/time.h> |
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Our system timer. | 37 | * Our system timer. |
37 | */ | 38 | */ |
38 | struct sys_timer *system_timer; | 39 | static struct sys_timer *system_timer; |
39 | 40 | ||
40 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | 41 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) |
41 | /* this needs a better home */ | 42 | /* this needs a better home */ |
@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs); | |||
160 | 161 | ||
161 | void __init time_init(void) | 162 | void __init time_init(void) |
162 | { | 163 | { |
164 | system_timer = machine_desc->timer; | ||
163 | system_timer->init(); | 165 | system_timer->init(); |
164 | } | 166 | } |
165 | 167 | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 446aee97436f..e02f4f7537c5 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -37,6 +37,8 @@ | |||
37 | 37 | ||
38 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; | 38 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; |
39 | 39 | ||
40 | void *vectors_page; | ||
41 | |||
40 | #ifdef CONFIG_DEBUG_USER | 42 | #ifdef CONFIG_DEBUG_USER |
41 | unsigned int user_debug; | 43 | unsigned int user_debug; |
42 | 44 | ||
@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors) | |||
756 | 758 | ||
757 | void __init early_trap_init(void) | 759 | void __init early_trap_init(void) |
758 | { | 760 | { |
761 | #if defined(CONFIG_CPU_USE_DOMAINS) | ||
759 | unsigned long vectors = CONFIG_VECTORS_BASE; | 762 | unsigned long vectors = CONFIG_VECTORS_BASE; |
763 | #else | ||
764 | unsigned long vectors = (unsigned long)vectors_page; | ||
765 | #endif | ||
760 | extern char __stubs_start[], __stubs_end[]; | 766 | extern char __stubs_start[], __stubs_end[]; |
761 | extern char __vectors_start[], __vectors_end[]; | 767 | extern char __vectors_start[], __vectors_end[]; |
762 | extern char __kuser_helper_start[], __kuser_helper_end[]; | 768 | extern char __kuser_helper_start[], __kuser_helper_end[]; |
@@ -780,10 +786,10 @@ void __init early_trap_init(void) | |||
780 | * Copy signal return handlers into the vector page, and | 786 | * Copy signal return handlers into the vector page, and |
781 | * set sigreturn to be a pointer to these. | 787 | * set sigreturn to be a pointer to these. |
782 | */ | 788 | */ |
783 | memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, | 789 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), |
784 | sizeof(sigreturn_codes)); | 790 | sigreturn_codes, sizeof(sigreturn_codes)); |
785 | memcpy((void *)KERN_RESTART_CODE, syscall_restart_code, | 791 | memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE), |
786 | sizeof(syscall_restart_code)); | 792 | syscall_restart_code, sizeof(syscall_restart_code)); |
787 | 793 | ||
788 | flush_icache_range(vectors, vectors + PAGE_SIZE); | 794 | flush_icache_range(vectors, vectors + PAGE_SIZE); |
789 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 795 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 897c1a8f1694..86b66f3f2031 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -168,6 +168,7 @@ SECTIONS | |||
168 | 168 | ||
169 | NOSAVE_DATA | 169 | NOSAVE_DATA |
170 | CACHELINE_ALIGNED_DATA(32) | 170 | CACHELINE_ALIGNED_DATA(32) |
171 | READ_MOSTLY_DATA(32) | ||
171 | 172 | ||
172 | /* | 173 | /* |
173 | * The exception fixup table (might need resorting at runtime) | 174 | * The exception fixup table (might need resorting at runtime) |
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index b1631a7dbe75..1b049cd7a49a 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S | |||
@@ -28,20 +28,21 @@ | |||
28 | */ | 28 | */ |
29 | #include <linux/linkage.h> | 29 | #include <linux/linkage.h> |
30 | #include <asm/errno.h> | 30 | #include <asm/errno.h> |
31 | #include <asm/domain.h> | ||
31 | 32 | ||
32 | ENTRY(__get_user_1) | 33 | ENTRY(__get_user_1) |
33 | 1: ldrbt r2, [r0] | 34 | 1: T(ldrb) r2, [r0] |
34 | mov r0, #0 | 35 | mov r0, #0 |
35 | mov pc, lr | 36 | mov pc, lr |
36 | ENDPROC(__get_user_1) | 37 | ENDPROC(__get_user_1) |
37 | 38 | ||
38 | ENTRY(__get_user_2) | 39 | ENTRY(__get_user_2) |
39 | #ifdef CONFIG_THUMB2_KERNEL | 40 | #ifdef CONFIG_THUMB2_KERNEL |
40 | 2: ldrbt r2, [r0] | 41 | 2: T(ldrb) r2, [r0] |
41 | 3: ldrbt r3, [r0, #1] | 42 | 3: T(ldrb) r3, [r0, #1] |
42 | #else | 43 | #else |
43 | 2: ldrbt r2, [r0], #1 | 44 | 2: T(ldrb) r2, [r0], #1 |
44 | 3: ldrbt r3, [r0] | 45 | 3: T(ldrb) r3, [r0] |
45 | #endif | 46 | #endif |
46 | #ifndef __ARMEB__ | 47 | #ifndef __ARMEB__ |
47 | orr r2, r2, r3, lsl #8 | 48 | orr r2, r2, r3, lsl #8 |
@@ -53,7 +54,7 @@ ENTRY(__get_user_2) | |||
53 | ENDPROC(__get_user_2) | 54 | ENDPROC(__get_user_2) |
54 | 55 | ||
55 | ENTRY(__get_user_4) | 56 | ENTRY(__get_user_4) |
56 | 4: ldrt r2, [r0] | 57 | 4: T(ldr) r2, [r0] |
57 | mov r0, #0 | 58 | mov r0, #0 |
58 | mov pc, lr | 59 | mov pc, lr |
59 | ENDPROC(__get_user_4) | 60 | ENDPROC(__get_user_4) |
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 5a01a23c6c06..c023fc11e86c 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S | |||
@@ -28,9 +28,10 @@ | |||
28 | */ | 28 | */ |
29 | #include <linux/linkage.h> | 29 | #include <linux/linkage.h> |
30 | #include <asm/errno.h> | 30 | #include <asm/errno.h> |
31 | #include <asm/domain.h> | ||
31 | 32 | ||
32 | ENTRY(__put_user_1) | 33 | ENTRY(__put_user_1) |
33 | 1: strbt r2, [r0] | 34 | 1: T(strb) r2, [r0] |
34 | mov r0, #0 | 35 | mov r0, #0 |
35 | mov pc, lr | 36 | mov pc, lr |
36 | ENDPROC(__put_user_1) | 37 | ENDPROC(__put_user_1) |
@@ -39,19 +40,19 @@ ENTRY(__put_user_2) | |||
39 | mov ip, r2, lsr #8 | 40 | mov ip, r2, lsr #8 |
40 | #ifdef CONFIG_THUMB2_KERNEL | 41 | #ifdef CONFIG_THUMB2_KERNEL |
41 | #ifndef __ARMEB__ | 42 | #ifndef __ARMEB__ |
42 | 2: strbt r2, [r0] | 43 | 2: T(strb) r2, [r0] |
43 | 3: strbt ip, [r0, #1] | 44 | 3: T(strb) ip, [r0, #1] |
44 | #else | 45 | #else |
45 | 2: strbt ip, [r0] | 46 | 2: T(strb) ip, [r0] |
46 | 3: strbt r2, [r0, #1] | 47 | 3: T(strb) r2, [r0, #1] |
47 | #endif | 48 | #endif |
48 | #else /* !CONFIG_THUMB2_KERNEL */ | 49 | #else /* !CONFIG_THUMB2_KERNEL */ |
49 | #ifndef __ARMEB__ | 50 | #ifndef __ARMEB__ |
50 | 2: strbt r2, [r0], #1 | 51 | 2: T(strb) r2, [r0], #1 |
51 | 3: strbt ip, [r0] | 52 | 3: T(strb) ip, [r0] |
52 | #else | 53 | #else |
53 | 2: strbt ip, [r0], #1 | 54 | 2: T(strb) ip, [r0], #1 |
54 | 3: strbt r2, [r0] | 55 | 3: T(strb) r2, [r0] |
55 | #endif | 56 | #endif |
56 | #endif /* CONFIG_THUMB2_KERNEL */ | 57 | #endif /* CONFIG_THUMB2_KERNEL */ |
57 | mov r0, #0 | 58 | mov r0, #0 |
@@ -59,18 +60,18 @@ ENTRY(__put_user_2) | |||
59 | ENDPROC(__put_user_2) | 60 | ENDPROC(__put_user_2) |
60 | 61 | ||
61 | ENTRY(__put_user_4) | 62 | ENTRY(__put_user_4) |
62 | 4: strt r2, [r0] | 63 | 4: T(str) r2, [r0] |
63 | mov r0, #0 | 64 | mov r0, #0 |
64 | mov pc, lr | 65 | mov pc, lr |
65 | ENDPROC(__put_user_4) | 66 | ENDPROC(__put_user_4) |
66 | 67 | ||
67 | ENTRY(__put_user_8) | 68 | ENTRY(__put_user_8) |
68 | #ifdef CONFIG_THUMB2_KERNEL | 69 | #ifdef CONFIG_THUMB2_KERNEL |
69 | 5: strt r2, [r0] | 70 | 5: T(str) r2, [r0] |
70 | 6: strt r3, [r0, #4] | 71 | 6: T(str) r3, [r0, #4] |
71 | #else | 72 | #else |
72 | 5: strt r2, [r0], #4 | 73 | 5: T(str) r2, [r0], #4 |
73 | 6: strt r3, [r0] | 74 | 6: T(str) r3, [r0] |
74 | #endif | 75 | #endif |
75 | mov r0, #0 | 76 | mov r0, #0 |
76 | mov pc, lr | 77 | mov pc, lr |
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index fee9f6f88adb..d0ece2aeb70d 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
15 | #include <asm/assembler.h> | 15 | #include <asm/assembler.h> |
16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
17 | #include <asm/domain.h> | ||
17 | 18 | ||
18 | .text | 19 | .text |
19 | 20 | ||
@@ -31,11 +32,11 @@ | |||
31 | rsb ip, ip, #4 | 32 | rsb ip, ip, #4 |
32 | cmp ip, #2 | 33 | cmp ip, #2 |
33 | ldrb r3, [r1], #1 | 34 | ldrb r3, [r1], #1 |
34 | USER( strbt r3, [r0], #1) @ May fault | 35 | USER( T(strb) r3, [r0], #1) @ May fault |
35 | ldrgeb r3, [r1], #1 | 36 | ldrgeb r3, [r1], #1 |
36 | USER( strgebt r3, [r0], #1) @ May fault | 37 | USER( T(strgeb) r3, [r0], #1) @ May fault |
37 | ldrgtb r3, [r1], #1 | 38 | ldrgtb r3, [r1], #1 |
38 | USER( strgtbt r3, [r0], #1) @ May fault | 39 | USER( T(strgtb) r3, [r0], #1) @ May fault |
39 | sub r2, r2, ip | 40 | sub r2, r2, ip |
40 | b .Lc2u_dest_aligned | 41 | b .Lc2u_dest_aligned |
41 | 42 | ||
@@ -58,7 +59,7 @@ ENTRY(__copy_to_user) | |||
58 | addmi ip, r2, #4 | 59 | addmi ip, r2, #4 |
59 | bmi .Lc2u_0nowords | 60 | bmi .Lc2u_0nowords |
60 | ldr r3, [r1], #4 | 61 | ldr r3, [r1], #4 |
61 | USER( strt r3, [r0], #4) @ May fault | 62 | USER( T(str) r3, [r0], #4) @ May fault |
62 | mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction | 63 | mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction |
63 | rsb ip, ip, #0 | 64 | rsb ip, ip, #0 |
64 | movs ip, ip, lsr #32 - PAGE_SHIFT | 65 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
87 | stmneia r0!, {r3 - r4} @ Shouldnt fault | 88 | stmneia r0!, {r3 - r4} @ Shouldnt fault |
88 | tst ip, #4 | 89 | tst ip, #4 |
89 | ldrne r3, [r1], #4 | 90 | ldrne r3, [r1], #4 |
90 | strnet r3, [r0], #4 @ Shouldnt fault | 91 | T(strne) r3, [r0], #4 @ Shouldnt fault |
91 | ands ip, ip, #3 | 92 | ands ip, ip, #3 |
92 | beq .Lc2u_0fupi | 93 | beq .Lc2u_0fupi |
93 | .Lc2u_0nowords: teq ip, #0 | 94 | .Lc2u_0nowords: teq ip, #0 |
94 | beq .Lc2u_finished | 95 | beq .Lc2u_finished |
95 | .Lc2u_nowords: cmp ip, #2 | 96 | .Lc2u_nowords: cmp ip, #2 |
96 | ldrb r3, [r1], #1 | 97 | ldrb r3, [r1], #1 |
97 | USER( strbt r3, [r0], #1) @ May fault | 98 | USER( T(strb) r3, [r0], #1) @ May fault |
98 | ldrgeb r3, [r1], #1 | 99 | ldrgeb r3, [r1], #1 |
99 | USER( strgebt r3, [r0], #1) @ May fault | 100 | USER( T(strgeb) r3, [r0], #1) @ May fault |
100 | ldrgtb r3, [r1], #1 | 101 | ldrgtb r3, [r1], #1 |
101 | USER( strgtbt r3, [r0], #1) @ May fault | 102 | USER( T(strgtb) r3, [r0], #1) @ May fault |
102 | b .Lc2u_finished | 103 | b .Lc2u_finished |
103 | 104 | ||
104 | .Lc2u_not_enough: | 105 | .Lc2u_not_enough: |
@@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
119 | mov r3, r7, pull #8 | 120 | mov r3, r7, pull #8 |
120 | ldr r7, [r1], #4 | 121 | ldr r7, [r1], #4 |
121 | orr r3, r3, r7, push #24 | 122 | orr r3, r3, r7, push #24 |
122 | USER( strt r3, [r0], #4) @ May fault | 123 | USER( T(str) r3, [r0], #4) @ May fault |
123 | mov ip, r0, lsl #32 - PAGE_SHIFT | 124 | mov ip, r0, lsl #32 - PAGE_SHIFT |
124 | rsb ip, ip, #0 | 125 | rsb ip, ip, #0 |
125 | movs ip, ip, lsr #32 - PAGE_SHIFT | 126 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
154 | movne r3, r7, pull #8 | 155 | movne r3, r7, pull #8 |
155 | ldrne r7, [r1], #4 | 156 | ldrne r7, [r1], #4 |
156 | orrne r3, r3, r7, push #24 | 157 | orrne r3, r3, r7, push #24 |
157 | strnet r3, [r0], #4 @ Shouldnt fault | 158 | T(strne) r3, [r0], #4 @ Shouldnt fault |
158 | ands ip, ip, #3 | 159 | ands ip, ip, #3 |
159 | beq .Lc2u_1fupi | 160 | beq .Lc2u_1fupi |
160 | .Lc2u_1nowords: mov r3, r7, get_byte_1 | 161 | .Lc2u_1nowords: mov r3, r7, get_byte_1 |
161 | teq ip, #0 | 162 | teq ip, #0 |
162 | beq .Lc2u_finished | 163 | beq .Lc2u_finished |
163 | cmp ip, #2 | 164 | cmp ip, #2 |
164 | USER( strbt r3, [r0], #1) @ May fault | 165 | USER( T(strb) r3, [r0], #1) @ May fault |
165 | movge r3, r7, get_byte_2 | 166 | movge r3, r7, get_byte_2 |
166 | USER( strgebt r3, [r0], #1) @ May fault | 167 | USER( T(strgeb) r3, [r0], #1) @ May fault |
167 | movgt r3, r7, get_byte_3 | 168 | movgt r3, r7, get_byte_3 |
168 | USER( strgtbt r3, [r0], #1) @ May fault | 169 | USER( T(strgtb) r3, [r0], #1) @ May fault |
169 | b .Lc2u_finished | 170 | b .Lc2u_finished |
170 | 171 | ||
171 | .Lc2u_2fupi: subs r2, r2, #4 | 172 | .Lc2u_2fupi: subs r2, r2, #4 |
@@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
174 | mov r3, r7, pull #16 | 175 | mov r3, r7, pull #16 |
175 | ldr r7, [r1], #4 | 176 | ldr r7, [r1], #4 |
176 | orr r3, r3, r7, push #16 | 177 | orr r3, r3, r7, push #16 |
177 | USER( strt r3, [r0], #4) @ May fault | 178 | USER( T(str) r3, [r0], #4) @ May fault |
178 | mov ip, r0, lsl #32 - PAGE_SHIFT | 179 | mov ip, r0, lsl #32 - PAGE_SHIFT |
179 | rsb ip, ip, #0 | 180 | rsb ip, ip, #0 |
180 | movs ip, ip, lsr #32 - PAGE_SHIFT | 181 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
209 | movne r3, r7, pull #16 | 210 | movne r3, r7, pull #16 |
210 | ldrne r7, [r1], #4 | 211 | ldrne r7, [r1], #4 |
211 | orrne r3, r3, r7, push #16 | 212 | orrne r3, r3, r7, push #16 |
212 | strnet r3, [r0], #4 @ Shouldnt fault | 213 | T(strne) r3, [r0], #4 @ Shouldnt fault |
213 | ands ip, ip, #3 | 214 | ands ip, ip, #3 |
214 | beq .Lc2u_2fupi | 215 | beq .Lc2u_2fupi |
215 | .Lc2u_2nowords: mov r3, r7, get_byte_2 | 216 | .Lc2u_2nowords: mov r3, r7, get_byte_2 |
216 | teq ip, #0 | 217 | teq ip, #0 |
217 | beq .Lc2u_finished | 218 | beq .Lc2u_finished |
218 | cmp ip, #2 | 219 | cmp ip, #2 |
219 | USER( strbt r3, [r0], #1) @ May fault | 220 | USER( T(strb) r3, [r0], #1) @ May fault |
220 | movge r3, r7, get_byte_3 | 221 | movge r3, r7, get_byte_3 |
221 | USER( strgebt r3, [r0], #1) @ May fault | 222 | USER( T(strgeb) r3, [r0], #1) @ May fault |
222 | ldrgtb r3, [r1], #0 | 223 | ldrgtb r3, [r1], #0 |
223 | USER( strgtbt r3, [r0], #1) @ May fault | 224 | USER( T(strgtb) r3, [r0], #1) @ May fault |
224 | b .Lc2u_finished | 225 | b .Lc2u_finished |
225 | 226 | ||
226 | .Lc2u_3fupi: subs r2, r2, #4 | 227 | .Lc2u_3fupi: subs r2, r2, #4 |
@@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
229 | mov r3, r7, pull #24 | 230 | mov r3, r7, pull #24 |
230 | ldr r7, [r1], #4 | 231 | ldr r7, [r1], #4 |
231 | orr r3, r3, r7, push #8 | 232 | orr r3, r3, r7, push #8 |
232 | USER( strt r3, [r0], #4) @ May fault | 233 | USER( T(str) r3, [r0], #4) @ May fault |
233 | mov ip, r0, lsl #32 - PAGE_SHIFT | 234 | mov ip, r0, lsl #32 - PAGE_SHIFT |
234 | rsb ip, ip, #0 | 235 | rsb ip, ip, #0 |
235 | movs ip, ip, lsr #32 - PAGE_SHIFT | 236 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
264 | movne r3, r7, pull #24 | 265 | movne r3, r7, pull #24 |
265 | ldrne r7, [r1], #4 | 266 | ldrne r7, [r1], #4 |
266 | orrne r3, r3, r7, push #8 | 267 | orrne r3, r3, r7, push #8 |
267 | strnet r3, [r0], #4 @ Shouldnt fault | 268 | T(strne) r3, [r0], #4 @ Shouldnt fault |
268 | ands ip, ip, #3 | 269 | ands ip, ip, #3 |
269 | beq .Lc2u_3fupi | 270 | beq .Lc2u_3fupi |
270 | .Lc2u_3nowords: mov r3, r7, get_byte_3 | 271 | .Lc2u_3nowords: mov r3, r7, get_byte_3 |
271 | teq ip, #0 | 272 | teq ip, #0 |
272 | beq .Lc2u_finished | 273 | beq .Lc2u_finished |
273 | cmp ip, #2 | 274 | cmp ip, #2 |
274 | USER( strbt r3, [r0], #1) @ May fault | 275 | USER( T(strb) r3, [r0], #1) @ May fault |
275 | ldrgeb r3, [r1], #1 | 276 | ldrgeb r3, [r1], #1 |
276 | USER( strgebt r3, [r0], #1) @ May fault | 277 | USER( T(strgeb) r3, [r0], #1) @ May fault |
277 | ldrgtb r3, [r1], #0 | 278 | ldrgtb r3, [r1], #0 |
278 | USER( strgtbt r3, [r0], #1) @ May fault | 279 | USER( T(strgtb) r3, [r0], #1) @ May fault |
279 | b .Lc2u_finished | 280 | b .Lc2u_finished |
280 | ENDPROC(__copy_to_user) | 281 | ENDPROC(__copy_to_user) |
281 | 282 | ||
@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user) | |||
294 | .Lcfu_dest_not_aligned: | 295 | .Lcfu_dest_not_aligned: |
295 | rsb ip, ip, #4 | 296 | rsb ip, ip, #4 |
296 | cmp ip, #2 | 297 | cmp ip, #2 |
297 | USER( ldrbt r3, [r1], #1) @ May fault | 298 | USER( T(ldrb) r3, [r1], #1) @ May fault |
298 | strb r3, [r0], #1 | 299 | strb r3, [r0], #1 |
299 | USER( ldrgebt r3, [r1], #1) @ May fault | 300 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
300 | strgeb r3, [r0], #1 | 301 | strgeb r3, [r0], #1 |
301 | USER( ldrgtbt r3, [r1], #1) @ May fault | 302 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
302 | strgtb r3, [r0], #1 | 303 | strgtb r3, [r0], #1 |
303 | sub r2, r2, ip | 304 | sub r2, r2, ip |
304 | b .Lcfu_dest_aligned | 305 | b .Lcfu_dest_aligned |
@@ -321,7 +322,7 @@ ENTRY(__copy_from_user) | |||
321 | .Lcfu_0fupi: subs r2, r2, #4 | 322 | .Lcfu_0fupi: subs r2, r2, #4 |
322 | addmi ip, r2, #4 | 323 | addmi ip, r2, #4 |
323 | bmi .Lcfu_0nowords | 324 | bmi .Lcfu_0nowords |
324 | USER( ldrt r3, [r1], #4) | 325 | USER( T(ldr) r3, [r1], #4) |
325 | str r3, [r0], #4 | 326 | str r3, [r0], #4 |
326 | mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction | 327 | mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction |
327 | rsb ip, ip, #0 | 328 | rsb ip, ip, #0 |
@@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4) | |||
350 | ldmneia r1!, {r3 - r4} @ Shouldnt fault | 351 | ldmneia r1!, {r3 - r4} @ Shouldnt fault |
351 | stmneia r0!, {r3 - r4} | 352 | stmneia r0!, {r3 - r4} |
352 | tst ip, #4 | 353 | tst ip, #4 |
353 | ldrnet r3, [r1], #4 @ Shouldnt fault | 354 | T(ldrne) r3, [r1], #4 @ Shouldnt fault |
354 | strne r3, [r0], #4 | 355 | strne r3, [r0], #4 |
355 | ands ip, ip, #3 | 356 | ands ip, ip, #3 |
356 | beq .Lcfu_0fupi | 357 | beq .Lcfu_0fupi |
357 | .Lcfu_0nowords: teq ip, #0 | 358 | .Lcfu_0nowords: teq ip, #0 |
358 | beq .Lcfu_finished | 359 | beq .Lcfu_finished |
359 | .Lcfu_nowords: cmp ip, #2 | 360 | .Lcfu_nowords: cmp ip, #2 |
360 | USER( ldrbt r3, [r1], #1) @ May fault | 361 | USER( T(ldrb) r3, [r1], #1) @ May fault |
361 | strb r3, [r0], #1 | 362 | strb r3, [r0], #1 |
362 | USER( ldrgebt r3, [r1], #1) @ May fault | 363 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
363 | strgeb r3, [r0], #1 | 364 | strgeb r3, [r0], #1 |
364 | USER( ldrgtbt r3, [r1], #1) @ May fault | 365 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
365 | strgtb r3, [r0], #1 | 366 | strgtb r3, [r0], #1 |
366 | b .Lcfu_finished | 367 | b .Lcfu_finished |
367 | 368 | ||
@@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault | |||
374 | 375 | ||
375 | .Lcfu_src_not_aligned: | 376 | .Lcfu_src_not_aligned: |
376 | bic r1, r1, #3 | 377 | bic r1, r1, #3 |
377 | USER( ldrt r7, [r1], #4) @ May fault | 378 | USER( T(ldr) r7, [r1], #4) @ May fault |
378 | cmp ip, #2 | 379 | cmp ip, #2 |
379 | bgt .Lcfu_3fupi | 380 | bgt .Lcfu_3fupi |
380 | beq .Lcfu_2fupi | 381 | beq .Lcfu_2fupi |
@@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
382 | addmi ip, r2, #4 | 383 | addmi ip, r2, #4 |
383 | bmi .Lcfu_1nowords | 384 | bmi .Lcfu_1nowords |
384 | mov r3, r7, pull #8 | 385 | mov r3, r7, pull #8 |
385 | USER( ldrt r7, [r1], #4) @ May fault | 386 | USER( T(ldr) r7, [r1], #4) @ May fault |
386 | orr r3, r3, r7, push #24 | 387 | orr r3, r3, r7, push #24 |
387 | str r3, [r0], #4 | 388 | str r3, [r0], #4 |
388 | mov ip, r1, lsl #32 - PAGE_SHIFT | 389 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
417 | stmneia r0!, {r3 - r4} | 418 | stmneia r0!, {r3 - r4} |
418 | tst ip, #4 | 419 | tst ip, #4 |
419 | movne r3, r7, pull #8 | 420 | movne r3, r7, pull #8 |
420 | USER( ldrnet r7, [r1], #4) @ May fault | 421 | USER( T(ldrne) r7, [r1], #4) @ May fault |
421 | orrne r3, r3, r7, push #24 | 422 | orrne r3, r3, r7, push #24 |
422 | strne r3, [r0], #4 | 423 | strne r3, [r0], #4 |
423 | ands ip, ip, #3 | 424 | ands ip, ip, #3 |
@@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
437 | addmi ip, r2, #4 | 438 | addmi ip, r2, #4 |
438 | bmi .Lcfu_2nowords | 439 | bmi .Lcfu_2nowords |
439 | mov r3, r7, pull #16 | 440 | mov r3, r7, pull #16 |
440 | USER( ldrt r7, [r1], #4) @ May fault | 441 | USER( T(ldr) r7, [r1], #4) @ May fault |
441 | orr r3, r3, r7, push #16 | 442 | orr r3, r3, r7, push #16 |
442 | str r3, [r0], #4 | 443 | str r3, [r0], #4 |
443 | mov ip, r1, lsl #32 - PAGE_SHIFT | 444 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
473 | stmneia r0!, {r3 - r4} | 474 | stmneia r0!, {r3 - r4} |
474 | tst ip, #4 | 475 | tst ip, #4 |
475 | movne r3, r7, pull #16 | 476 | movne r3, r7, pull #16 |
476 | USER( ldrnet r7, [r1], #4) @ May fault | 477 | USER( T(ldrne) r7, [r1], #4) @ May fault |
477 | orrne r3, r3, r7, push #16 | 478 | orrne r3, r3, r7, push #16 |
478 | strne r3, [r0], #4 | 479 | strne r3, [r0], #4 |
479 | ands ip, ip, #3 | 480 | ands ip, ip, #3 |
@@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
485 | strb r3, [r0], #1 | 486 | strb r3, [r0], #1 |
486 | movge r3, r7, get_byte_3 | 487 | movge r3, r7, get_byte_3 |
487 | strgeb r3, [r0], #1 | 488 | strgeb r3, [r0], #1 |
488 | USER( ldrgtbt r3, [r1], #0) @ May fault | 489 | USER( T(ldrgtb) r3, [r1], #0) @ May fault |
489 | strgtb r3, [r0], #1 | 490 | strgtb r3, [r0], #1 |
490 | b .Lcfu_finished | 491 | b .Lcfu_finished |
491 | 492 | ||
@@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault | |||
493 | addmi ip, r2, #4 | 494 | addmi ip, r2, #4 |
494 | bmi .Lcfu_3nowords | 495 | bmi .Lcfu_3nowords |
495 | mov r3, r7, pull #24 | 496 | mov r3, r7, pull #24 |
496 | USER( ldrt r7, [r1], #4) @ May fault | 497 | USER( T(ldr) r7, [r1], #4) @ May fault |
497 | orr r3, r3, r7, push #8 | 498 | orr r3, r3, r7, push #8 |
498 | str r3, [r0], #4 | 499 | str r3, [r0], #4 |
499 | mov ip, r1, lsl #32 - PAGE_SHIFT | 500 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
528 | stmneia r0!, {r3 - r4} | 529 | stmneia r0!, {r3 - r4} |
529 | tst ip, #4 | 530 | tst ip, #4 |
530 | movne r3, r7, pull #24 | 531 | movne r3, r7, pull #24 |
531 | USER( ldrnet r7, [r1], #4) @ May fault | 532 | USER( T(ldrne) r7, [r1], #4) @ May fault |
532 | orrne r3, r3, r7, push #8 | 533 | orrne r3, r3, r7, push #8 |
533 | strne r3, [r0], #4 | 534 | strne r3, [r0], #4 |
534 | ands ip, ip, #3 | 535 | ands ip, ip, #3 |
@@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
538 | beq .Lcfu_finished | 539 | beq .Lcfu_finished |
539 | cmp ip, #2 | 540 | cmp ip, #2 |
540 | strb r3, [r0], #1 | 541 | strb r3, [r0], #1 |
541 | USER( ldrgebt r3, [r1], #1) @ May fault | 542 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
542 | strgeb r3, [r0], #1 | 543 | strgeb r3, [r0], #1 |
543 | USER( ldrgtbt r3, [r1], #1) @ May fault | 544 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
544 | strgtb r3, [r0], #1 | 545 | strgtb r3, [r0], #1 |
545 | b .Lcfu_finished | 546 | b .Lcfu_finished |
546 | ENDPROC(__copy_from_user) | 547 | ENDPROC(__copy_from_user) |
diff --git a/arch/arm/mach-bcmring/clock.c b/arch/arm/mach-bcmring/clock.c index 14bafc38f2dc..ad237a42d265 100644 --- a/arch/arm/mach-bcmring/clock.c +++ b/arch/arm/mach-bcmring/clock.c | |||
@@ -21,13 +21,12 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/clkdev.h> | ||
24 | #include <mach/csp/hw_cfg.h> | 25 | #include <mach/csp/hw_cfg.h> |
25 | #include <mach/csp/chipcHw_def.h> | 26 | #include <mach/csp/chipcHw_def.h> |
26 | #include <mach/csp/chipcHw_reg.h> | 27 | #include <mach/csp/chipcHw_reg.h> |
27 | #include <mach/csp/chipcHw_inline.h> | 28 | #include <mach/csp/chipcHw_inline.h> |
28 | 29 | ||
29 | #include <asm/clkdev.h> | ||
30 | |||
31 | #include "clock.h" | 30 | #include "clock.h" |
32 | 31 | ||
33 | #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) | 32 | #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) |
diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c index b91b1b0fdff3..8fc2035759fb 100644 --- a/arch/arm/mach-bcmring/core.c +++ b/arch/arm/mach-bcmring/core.c | |||
@@ -30,10 +30,10 @@ | |||
30 | #include <linux/amba/bus.h> | 30 | #include <linux/amba/bus.h> |
31 | #include <linux/clocksource.h> | 31 | #include <linux/clocksource.h> |
32 | #include <linux/clockchips.h> | 32 | #include <linux/clockchips.h> |
33 | #include <linux/clkdev.h> | ||
33 | 34 | ||
34 | #include <mach/csp/mm_addr.h> | 35 | #include <mach/csp/mm_addr.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <asm/clkdev.h> | ||
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
39 | #include <asm/hardware/arm_timer.h> | 39 | #include <asm/hardware/arm_timer.h> |
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index 9ebfcc46feb1..29b13f249aa9 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig | |||
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type" | |||
3 | 3 | ||
4 | config MACH_CNS3420VB | 4 | config MACH_CNS3420VB |
5 | bool "Support for CNS3420 Validation Board" | 5 | bool "Support for CNS3420 Validation Board" |
6 | select MIGHT_HAVE_PCI | ||
6 | help | 7 | help |
7 | Include support for the Cavium Networks CNS3420 MPCore Platform | 8 | Include support for the Cavium Networks CNS3420 MPCore Platform |
8 | Baseboard. | 9 | Baseboard. |
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 11099980b58b..0dd22031ec62 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h | |||
@@ -68,7 +68,7 @@ | |||
68 | #ifndef __ASSEMBLER__ | 68 | #ifndef __ASSEMBLER__ |
69 | 69 | ||
70 | #include <linux/list.h> | 70 | #include <linux/list.h> |
71 | #include <asm/clkdev.h> | 71 | #include <linux/clkdev.h> |
72 | 72 | ||
73 | #define PLLSTAT_GOSTAT BIT(0) | 73 | #define PLLSTAT_GOSTAT BIT(0) |
74 | #define PLLCMD_GOSET BIT(0) | 74 | #define PLLCMD_GOSET BIT(0) |
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index ef06c66a6f16..ca4de7105097 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -19,10 +19,10 @@ | |||
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/clkdev.h> | ||
22 | 23 | ||
23 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
27 | 27 | ||
28 | 28 | ||
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c index daca30b2d5b1..3938a563b280 100644 --- a/arch/arm/mach-imx/clock-imx1.c +++ b/arch/arm/mach-imx/clock-imx1.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | #include <linux/clkdev.h> | |
26 | #include <asm/clkdev.h> | ||
27 | 26 | ||
28 | #include <mach/clock.h> | 27 | #include <mach/clock.h> |
29 | #include <mach/hardware.h> | 28 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c index cf15ea516a72..d7056559715a 100644 --- a/arch/arm/mach-imx/clock-imx21.c +++ b/arch/arm/mach-imx/clock-imx21.c | |||
@@ -21,11 +21,11 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <mach/common.h> | 28 | #include <mach/common.h> |
28 | #include <asm/clkdev.h> | ||
29 | #include <asm/div64.h> | 29 | #include <asm/div64.h> |
30 | 30 | ||
31 | #define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) | 31 | #define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) |
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c index 98a25bada783..ca1017b9028d 100644 --- a/arch/arm/mach-imx/clock-imx27.c +++ b/arch/arm/mach-imx/clock-imx27.c | |||
@@ -21,8 +21,8 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
27 | 27 | ||
28 | #include <mach/clock.h> | 28 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index 27db275b367c..769b0f10c834 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Integrator Options" | |||
4 | 4 | ||
5 | config ARCH_INTEGRATOR_AP | 5 | config ARCH_INTEGRATOR_AP |
6 | bool "Support Integrator/AP and Integrator/PP2 platforms" | 6 | bool "Support Integrator/AP and Integrator/PP2 platforms" |
7 | select MIGHT_HAVE_PCI | ||
7 | help | 8 | help |
8 | Include support for the ARM(R) Integrator/AP and | 9 | Include support for the ARM(R) Integrator/AP and |
9 | Integrator/PP2 platforms. | 10 | Integrator/PP2 platforms. |
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 8f4fb6d638f7..b8e884b450da 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c | |||
@@ -21,9 +21,8 @@ | |||
21 | #include <linux/amba/bus.h> | 21 | #include <linux/amba/bus.h> |
22 | #include <linux/amba/serial.h> | 22 | #include <linux/amba/serial.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <mach/clkdev.h> | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
29 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index fd684bf205e5..5db574f8ae3f 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c | |||
@@ -22,9 +22,8 @@ | |||
22 | #include <linux/amba/clcd.h> | 22 | #include <linux/amba/clcd.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/clkdev.h> | ||
25 | 26 | ||
26 | #include <asm/clkdev.h> | ||
27 | #include <mach/clkdev.h> | ||
28 | #include <asm/hardware/icst.h> | 27 | #include <asm/hardware/icst.h> |
29 | #include <mach/lm.h> | 28 | #include <mach/lm.h> |
30 | #include <mach/impd1.h> | 29 | #include <mach/impd1.h> |
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 1713ecf0c95f..85e48a5f77b9 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c | |||
@@ -21,9 +21,8 @@ | |||
21 | #include <linux/amba/mmci.h> | 21 | #include <linux/amba/mmci.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/gfp.h> | 23 | #include <linux/gfp.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <mach/clkdev.h> | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
29 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index 7415e4338651..3ad455318868 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h | |||
@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) | |||
58 | __dma; \ | 58 | __dma; \ |
59 | }) | 59 | }) |
60 | 60 | ||
61 | #define __arch_page_to_dma(dev, page) \ | 61 | #define __arch_pfn_to_dma(dev, pfn) \ |
62 | ({ \ | 62 | ({ \ |
63 | /* __is_lbus_virt() can never be true for RAM pages */ \ | 63 | /* __is_lbus_virt() can never be true for RAM pages */ \ |
64 | (dma_addr_t)page_to_phys(page); \ | 64 | (dma_addr_t)__pfn_to_phys(pfn); \ |
65 | }) | 65 | }) |
66 | 66 | ||
67 | #define __arch_dma_to_page(dev, addr) phys_to_page(addr) | 67 | #define __arch_dma_to_pfn(dev, addr) __phys_to_pfn(addr) |
68 | 68 | ||
69 | #endif /* CONFIG_ARCH_IOP13XX */ | 69 | #endif /* CONFIG_ARCH_IOP13XX */ |
70 | #endif /* !ASSEMBLY */ | 70 | #endif /* !ASSEMBLY */ |
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig index fe0c82e30b2d..f5c39a8c2b00 100644 --- a/arch/arm/mach-ks8695/Kconfig +++ b/arch/arm/mach-ks8695/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations" | |||
4 | 4 | ||
5 | config MACH_KS8695 | 5 | config MACH_KS8695 |
6 | bool "KS8695 development board" | 6 | bool "KS8695 development board" |
7 | select MIGHT_HAVE_PCI | ||
7 | help | 8 | help |
8 | Say 'Y' here if you want your kernel to run on the original | 9 | Say 'Y' here if you want your kernel to run on the original |
9 | Kendin-Micrel KS8695 development board. | 10 | Kendin-Micrel KS8695 development board. |
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index ffa19aae6e05..bace9a681adc 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h | |||
@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type; | |||
35 | __phys_to_virt(x) : __bus_to_virt(x)); }) | 35 | __phys_to_virt(x) : __bus_to_virt(x)); }) |
36 | #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ | 36 | #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ |
37 | (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) | 37 | (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) |
38 | #define __arch_page_to_dma(dev, x) \ | 38 | #define __arch_pfn_to_dma(dev, pfn) \ |
39 | ({ dma_addr_t __dma = page_to_phys(page); \ | 39 | ({ dma_addr_t __dma = __pfn_to_phys(pfn); \ |
40 | if (!is_lbus_device(dev)) \ | 40 | if (!is_lbus_device(dev)) \ |
41 | __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ | 41 | __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ |
42 | __dma; }) | 42 | __dma; }) |
43 | 43 | ||
44 | #define __arch_dma_to_page(dev, x) \ | 44 | #define __arch_dma_to_pfn(dev, x) \ |
45 | ({ dma_addr_t __dma = x; \ | 45 | ({ dma_addr_t __dma = x; \ |
46 | if (!is_lbus_device(dev)) \ | 46 | if (!is_lbus_device(dev)) \ |
47 | __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \ | 47 | __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \ |
48 | phys_to_page(__dma); \ | 48 | __phys_to_pfn(__dma); \ |
49 | }) | 49 | }) |
50 | 50 | ||
51 | #endif | 51 | #endif |
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 32d63796430a..da0e6498110a 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -90,10 +90,9 @@ | |||
90 | #include <linux/clk.h> | 90 | #include <linux/clk.h> |
91 | #include <linux/amba/bus.h> | 91 | #include <linux/amba/bus.h> |
92 | #include <linux/amba/clcd.h> | 92 | #include <linux/amba/clcd.h> |
93 | #include <linux/clkdev.h> | ||
93 | 94 | ||
94 | #include <mach/hardware.h> | 95 | #include <mach/hardware.h> |
95 | #include <asm/clkdev.h> | ||
96 | #include <mach/clkdev.h> | ||
97 | #include <mach/platform.h> | 96 | #include <mach/platform.h> |
98 | #include "clock.h" | 97 | #include "clock.h" |
99 | #include "common.h" | 98 | #include "common.h" |
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h index 016ae94691c0..9b027d7491f5 100644 --- a/arch/arm/mach-mmp/clock.h +++ b/arch/arm/mach-mmp/clock.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/clkdev.h> | 9 | #include <linux/clkdev.h> |
10 | 10 | ||
11 | struct clkops { | 11 | struct clkops { |
12 | void (*enable)(struct clk *); | 12 | void (*enable)(struct clk *); |
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h index 3ff7bf5e679e..a95f7b9efe31 100644 --- a/arch/arm/mach-msm/include/mach/smp.h +++ b/arch/arm/mach-msm/include/mach/smp.h | |||
@@ -31,9 +31,9 @@ | |||
31 | 31 | ||
32 | #include <asm/hardware/gic.h> | 32 | #include <asm/hardware/gic.h> |
33 | 33 | ||
34 | static inline void smp_cross_call(const struct cpumask *mask) | 34 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
35 | { | 35 | { |
36 | gic_raise_softirq(mask, 1); | 36 | gic_raise_softirq(mask, ipi); |
37 | } | 37 | } |
38 | 38 | ||
39 | #endif | 39 | #endif |
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c index 9e4a5578c2fb..00dcb08019e9 100644 --- a/arch/arm/mach-mx25/clock.c +++ b/arch/arm/mach-mx25/clock.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
28 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c index 109e98f323e0..1cd8b40b7676 100644 --- a/arch/arm/mach-mx3/clock-imx31.c +++ b/arch/arm/mach-mx3/clock-imx31.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/clkdev.h> | ||
26 | 27 | ||
27 | #include <asm/clkdev.h> | ||
28 | #include <asm/div64.h> | 28 | #include <asm/div64.h> |
29 | 29 | ||
30 | #include <mach/clock.h> | 30 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 61e4a318980a..819dd809615a 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
28 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index 8ac36d882927..5975edb47de8 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c | |||
@@ -14,8 +14,8 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/clkdev.h> | ||
17 | 18 | ||
18 | #include <asm/clkdev.h> | ||
19 | #include <asm/div64.h> | 19 | #include <asm/div64.h> |
20 | 20 | ||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-mxc91231/clock.c b/arch/arm/mach-mxc91231/clock.c index 5c85075d8a56..9fab505f1eb1 100644 --- a/arch/arm/mach-mxc91231/clock.c +++ b/arch/arm/mach-mxc91231/clock.c | |||
@@ -2,12 +2,12 @@ | |||
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
5 | #include <linux/clkdev.h> | ||
5 | 6 | ||
6 | #include <mach/clock.h> | 7 | #include <mach/clock.h> |
7 | #include <mach/hardware.h> | 8 | #include <mach/hardware.h> |
8 | #include <mach/common.h> | 9 | #include <mach/common.h> |
9 | 10 | ||
10 | #include <asm/clkdev.h> | ||
11 | #include <asm/bug.h> | 11 | #include <asm/bug.h> |
12 | #include <asm/div64.h> | 12 | #include <asm/div64.h> |
13 | 13 | ||
diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 89f793adf776..48a59f24e10c 100644 --- a/arch/arm/mach-nomadik/clock.c +++ b/arch/arm/mach-nomadik/clock.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
10 | #include <asm/clkdev.h> | 10 | #include <linux/clkdev.h> |
11 | #include "clock.h" | 11 | #include "clock.h" |
12 | 12 | ||
13 | /* | 13 | /* |
diff --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h index 18e51be4816f..4de1f1da9dc5 100644 --- a/arch/arm/mach-nuc93x/clock.h +++ b/arch/arm/mach-nuc93x/clock.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * the Free Software Foundation; either version 2 of the License. | 10 | * the Free Software Foundation; either version 2 of the License. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | 14 | ||
15 | void nuc93x_clk_enable(struct clk *clk, int enable); | 15 | void nuc93x_clk_enable(struct clk *clk, int enable); |
16 | void clks_register(struct clk_lookup *clks, size_t num); | 16 | void clks_register(struct clk_lookup *clks, size_t num); |
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index b8c7fb9d7921..84ef70476b51 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/clkdev.h> | ||
20 | 21 | ||
21 | #include <asm/mach-types.h> | 22 | #include <asm/mach-types.h> |
22 | #include <asm/clkdev.h> | ||
23 | 23 | ||
24 | #include <plat/cpu.h> | 24 | #include <plat/cpu.h> |
25 | #include <plat/usb.h> | 25 | #include <plat/usb.h> |
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index ed8d330522f1..ebb888f59365 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/clkdev.h> | ||
29 | 30 | ||
30 | #include <plat/cpu.h> | 31 | #include <plat/cpu.h> |
31 | #include <plat/clock.h> | 32 | #include <plat/clock.h> |
32 | #include <asm/clkdev.h> | ||
33 | 33 | ||
34 | #include "clock.h" | 34 | #include "clock.h" |
35 | #include "prm.h" | 35 | #include "prm.h" |
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index 6cee456ca542..4976b9393e49 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c | |||
@@ -17,16 +17,13 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/completion.h> | ||
21 | 20 | ||
22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
23 | #include <mach/omap4-common.h> | 22 | #include <mach/omap4-common.h> |
24 | 23 | ||
25 | static DECLARE_COMPLETION(cpu_killed); | ||
26 | |||
27 | int platform_cpu_kill(unsigned int cpu) | 24 | int platform_cpu_kill(unsigned int cpu) |
28 | { | 25 | { |
29 | return wait_for_completion_timeout(&cpu_killed, 5000); | 26 | return 1; |
30 | } | 27 | } |
31 | 28 | ||
32 | /* | 29 | /* |
@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu) | |||
35 | */ | 32 | */ |
36 | void platform_cpu_die(unsigned int cpu) | 33 | void platform_cpu_die(unsigned int cpu) |
37 | { | 34 | { |
38 | unsigned int this_cpu = hard_smp_processor_id(); | ||
39 | |||
40 | if (cpu != this_cpu) { | ||
41 | pr_crit("platform_cpu_die running on %u, should be %u\n", | ||
42 | this_cpu, cpu); | ||
43 | BUG(); | ||
44 | } | ||
45 | pr_notice("CPU%u: shutdown\n", cpu); | ||
46 | complete(&cpu_killed); | ||
47 | flush_cache_all(); | 35 | flush_cache_all(); |
48 | dsb(); | 36 | dsb(); |
49 | 37 | ||
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 9fbac2c39104..b66cfe8bc464 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | 22 | ||
23 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
24 | #include <asm/localtimer.h> | ||
25 | #include <asm/smp_scu.h> | 24 | #include <asm/smp_scu.h> |
26 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
27 | #include <mach/omap4-common.h> | 26 | #include <mach/omap4-common.h> |
@@ -29,22 +28,10 @@ | |||
29 | /* SCU base address */ | 28 | /* SCU base address */ |
30 | static void __iomem *scu_base; | 29 | static void __iomem *scu_base; |
31 | 30 | ||
32 | /* | ||
33 | * Use SCU config register to count number of cores | ||
34 | */ | ||
35 | static inline unsigned int get_core_count(void) | ||
36 | { | ||
37 | if (scu_base) | ||
38 | return scu_get_core_count(scu_base); | ||
39 | return 1; | ||
40 | } | ||
41 | |||
42 | static DEFINE_SPINLOCK(boot_lock); | 31 | static DEFINE_SPINLOCK(boot_lock); |
43 | 32 | ||
44 | void __cpuinit platform_secondary_init(unsigned int cpu) | 33 | void __cpuinit platform_secondary_init(unsigned int cpu) |
45 | { | 34 | { |
46 | trace_hardirqs_off(); | ||
47 | |||
48 | /* | 35 | /* |
49 | * If any interrupts are already enabled for the primary | 36 | * If any interrupts are already enabled for the primary |
50 | * core (e.g. timer irq), then they will not have been enabled | 37 | * core (e.g. timer irq), then they will not have been enabled |
@@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
76 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); | 63 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); |
77 | flush_cache_all(); | 64 | flush_cache_all(); |
78 | smp_wmb(); | 65 | smp_wmb(); |
79 | smp_cross_call(cpumask_of(cpu)); | 66 | smp_cross_call(cpumask_of(cpu), 1); |
80 | 67 | ||
81 | /* | 68 | /* |
82 | * Now the secondary core is starting up let it run its | 69 | * Now the secondary core is starting up let it run its |
@@ -118,25 +105,9 @@ void __init smp_init_cpus(void) | |||
118 | scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); | 105 | scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); |
119 | BUG_ON(!scu_base); | 106 | BUG_ON(!scu_base); |
120 | 107 | ||
121 | ncores = get_core_count(); | 108 | ncores = scu_get_core_count(scu_base); |
122 | |||
123 | for (i = 0; i < ncores; i++) | ||
124 | set_cpu_possible(i, true); | ||
125 | } | ||
126 | |||
127 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
128 | { | ||
129 | unsigned int ncores = get_core_count(); | ||
130 | unsigned int cpu = smp_processor_id(); | ||
131 | int i; | ||
132 | 109 | ||
133 | /* sanity check */ | 110 | /* sanity check */ |
134 | if (ncores == 0) { | ||
135 | printk(KERN_ERR | ||
136 | "OMAP4: strange core count of 0? Default to 1\n"); | ||
137 | ncores = 1; | ||
138 | } | ||
139 | |||
140 | if (ncores > NR_CPUS) { | 111 | if (ncores > NR_CPUS) { |
141 | printk(KERN_WARNING | 112 | printk(KERN_WARNING |
142 | "OMAP4: no. of cores (%d) greater than configured " | 113 | "OMAP4: no. of cores (%d) greater than configured " |
@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
144 | ncores, NR_CPUS); | 115 | ncores, NR_CPUS); |
145 | ncores = NR_CPUS; | 116 | ncores = NR_CPUS; |
146 | } | 117 | } |
147 | smp_store_cpu_info(cpu); | ||
148 | 118 | ||
149 | /* | 119 | for (i = 0; i < ncores; i++) |
150 | * are we trying to boot more cores than exist? | 120 | set_cpu_possible(i, true); |
151 | */ | 121 | } |
152 | if (max_cpus > ncores) | 122 | |
153 | max_cpus = ncores; | 123 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
124 | { | ||
125 | int i; | ||
154 | 126 | ||
155 | /* | 127 | /* |
156 | * Initialise the present map, which describes the set of CPUs | 128 | * Initialise the present map, which describes the set of CPUs |
@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
159 | for (i = 0; i < max_cpus; i++) | 131 | for (i = 0; i < max_cpus; i++) |
160 | set_cpu_present(i, true); | 132 | set_cpu_present(i, true); |
161 | 133 | ||
162 | if (max_cpus > 1) { | 134 | /* |
163 | /* | 135 | * Initialise the SCU and wake up the secondary core using |
164 | * Enable the local timer or broadcast device for the | 136 | * wakeup_secondary(). |
165 | * boot CPU, but only if we have more than one CPU. | 137 | */ |
166 | */ | 138 | scu_enable(scu_base); |
167 | percpu_timer_setup(); | 139 | wakeup_secondary(); |
168 | |||
169 | /* | ||
170 | * Initialise the SCU and wake up the secondary core using | ||
171 | * wakeup_secondary(). | ||
172 | */ | ||
173 | scu_enable(scu_base); | ||
174 | wakeup_secondary(); | ||
175 | } | ||
176 | } | 140 | } |
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c index 9d1975fa4d9f..a4a3819c96cb 100644 --- a/arch/arm/mach-pnx4008/clock.c +++ b/arch/arm/mach-pnx4008/clock.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/clock.h> | 27 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index c93e73d54dd1..c98d81ff250c 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -94,6 +94,7 @@ config MACH_ARMCORE | |||
94 | select PXA27x | 94 | select PXA27x |
95 | select IWMMXT | 95 | select IWMMXT |
96 | select PXA25x | 96 | select PXA25x |
97 | select MIGHT_HAVE_PCI | ||
97 | 98 | ||
98 | config MACH_EM_X270 | 99 | config MACH_EM_X270 |
99 | bool "CompuLab EM-x270 platform" | 100 | bool "CompuLab EM-x270 platform" |
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index abba0089a2ae..4e4a84be96ba 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c | |||
@@ -11,8 +11,8 @@ | |||
11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/clkdev.h> | ||
14 | 15 | ||
15 | #include <asm/clkdev.h> | ||
16 | #include <mach/pxa2xx-regs.h> | 16 | #include <mach/pxa2xx-regs.h> |
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | 18 | ||
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index d8488742b807..12cc0e87e6c4 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h | |||
@@ -1,4 +1,4 @@ | |||
1 | #include <asm/clkdev.h> | 1 | #include <linux/clkdev.h> |
2 | 2 | ||
3 | struct clkops { | 3 | struct clkops { |
4 | void (*enable)(struct clk *); | 4 | void (*enable)(struct clk *); |
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index aad806c5cb12..1c6602cf50e4 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include <linux/ata_platform.h> | 30 | #include <linux/ata_platform.h> |
31 | #include <linux/amba/mmci.h> | 31 | #include <linux/amba/mmci.h> |
32 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
33 | #include <linux/clkdev.h> | ||
33 | 34 | ||
34 | #include <asm/clkdev.h> | ||
35 | #include <asm/system.h> | 35 | #include <asm/system.h> |
36 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -47,7 +47,6 @@ | |||
47 | 47 | ||
48 | #include <asm/hardware/gic.h> | 48 | #include <asm/hardware/gic.h> |
49 | 49 | ||
50 | #include <mach/clkdev.h> | ||
51 | #include <mach/platform.h> | 50 | #include <mach/platform.h> |
52 | #include <mach/irqs.h> | 51 | #include <mach/irqs.h> |
53 | #include <asm/hardware/timer-sp.h> | 52 | #include <asm/hardware/timer-sp.h> |
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index f95521a5e5ce..a87523d095e6 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c | |||
@@ -11,14 +11,11 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | extern volatile int pen_release; | 17 | extern volatile int pen_release; |
19 | 18 | ||
20 | static DECLARE_COMPLETION(cpu_killed); | ||
21 | |||
22 | static inline void cpu_enter_lowpower(void) | 19 | static inline void cpu_enter_lowpower(void) |
23 | { | 20 | { |
24 | unsigned int v; | 21 | unsigned int v; |
@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void) | |||
34 | " bic %0, %0, #0x20\n" | 31 | " bic %0, %0, #0x20\n" |
35 | " mcr p15, 0, %0, c1, c0, 1\n" | 32 | " mcr p15, 0, %0, c1, c0, 1\n" |
36 | " mrc p15, 0, %0, c1, c0, 0\n" | 33 | " mrc p15, 0, %0, c1, c0, 0\n" |
37 | " bic %0, %0, #0x04\n" | 34 | " bic %0, %0, %2\n" |
38 | " mcr p15, 0, %0, c1, c0, 0\n" | 35 | " mcr p15, 0, %0, c1, c0, 0\n" |
39 | : "=&r" (v) | 36 | : "=&r" (v) |
40 | : "r" (0) | 37 | : "r" (0), "Ir" (CR_C) |
41 | : "cc"); | 38 | : "cc"); |
42 | } | 39 | } |
43 | 40 | ||
@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void) | |||
46 | unsigned int v; | 43 | unsigned int v; |
47 | 44 | ||
48 | asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" | 45 | asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" |
49 | " orr %0, %0, #0x04\n" | 46 | " orr %0, %0, %1\n" |
50 | " mcr p15, 0, %0, c1, c0, 0\n" | 47 | " mcr p15, 0, %0, c1, c0, 0\n" |
51 | " mrc p15, 0, %0, c1, c0, 1\n" | 48 | " mrc p15, 0, %0, c1, c0, 1\n" |
52 | " orr %0, %0, #0x20\n" | 49 | " orr %0, %0, #0x20\n" |
53 | " mcr p15, 0, %0, c1, c0, 1\n" | 50 | " mcr p15, 0, %0, c1, c0, 1\n" |
54 | : "=&r" (v) | 51 | : "=&r" (v) |
55 | : | 52 | : "Ir" (CR_C) |
56 | : "cc"); | 53 | : "cc"); |
57 | } | 54 | } |
58 | 55 | ||
59 | static inline void platform_do_lowpower(unsigned int cpu) | 56 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
60 | { | 57 | { |
61 | /* | 58 | /* |
62 | * there is no power-control hardware on this platform, so all | 59 | * there is no power-control hardware on this platform, so all |
@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
80 | } | 77 | } |
81 | 78 | ||
82 | /* | 79 | /* |
83 | * getting here, means that we have come out of WFI without | 80 | * Getting here, means that we have come out of WFI without |
84 | * having been woken up - this shouldn't happen | 81 | * having been woken up - this shouldn't happen |
85 | * | 82 | * |
86 | * The trouble is, letting people know about this is not really | 83 | * Just note it happening - when we're woken, we can report |
87 | * possible, since we are currently running incoherently, and | 84 | * its occurrence. |
88 | * therefore cannot safely call printk() or anything else | ||
89 | */ | 85 | */ |
90 | #ifdef DEBUG | 86 | (*spurious)++; |
91 | printk("CPU%u: spurious wakeup call\n", cpu); | ||
92 | #endif | ||
93 | } | 87 | } |
94 | } | 88 | } |
95 | 89 | ||
96 | int platform_cpu_kill(unsigned int cpu) | 90 | int platform_cpu_kill(unsigned int cpu) |
97 | { | 91 | { |
98 | return wait_for_completion_timeout(&cpu_killed, 5000); | 92 | return 1; |
99 | } | 93 | } |
100 | 94 | ||
101 | /* | 95 | /* |
@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
105 | */ | 99 | */ |
106 | void platform_cpu_die(unsigned int cpu) | 100 | void platform_cpu_die(unsigned int cpu) |
107 | { | 101 | { |
108 | #ifdef DEBUG | 102 | int spurious = 0; |
109 | unsigned int this_cpu = hard_smp_processor_id(); | ||
110 | |||
111 | if (cpu != this_cpu) { | ||
112 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
113 | this_cpu, cpu); | ||
114 | BUG(); | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
119 | complete(&cpu_killed); | ||
120 | 103 | ||
121 | /* | 104 | /* |
122 | * we're ready for shutdown now, so do it | 105 | * we're ready for shutdown now, so do it |
123 | */ | 106 | */ |
124 | cpu_enter_lowpower(); | 107 | cpu_enter_lowpower(); |
125 | platform_do_lowpower(cpu); | 108 | platform_do_lowpower(cpu, &spurious); |
126 | 109 | ||
127 | /* | 110 | /* |
128 | * bring this CPU back into the world of cache | 111 | * bring this CPU back into the world of cache |
129 | * coherency, and then restore interrupts | 112 | * coherency, and then restore interrupts |
130 | */ | 113 | */ |
131 | cpu_leave_lowpower(); | 114 | cpu_leave_lowpower(); |
115 | |||
116 | if (spurious) | ||
117 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
132 | } | 118 | } |
133 | 119 | ||
134 | int platform_cpu_disable(unsigned int cpu) | 120 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index d3cd265cb058..c8221b38ee7c 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h | |||
@@ -2,14 +2,13 @@ | |||
2 | #define ASMARM_ARCH_SMP_H | 2 | #define ASMARM_ARCH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | 10 | { |
12 | gic_raise_softirq(mask, 1); | 11 | gic_raise_softirq(mask, ipi); |
13 | } | 12 | } |
14 | 13 | ||
15 | #endif | 14 | #endif |
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 6da8a2e53c44..a22bf67f2f78 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
22 | #include <asm/localtimer.h> | ||
23 | #include <asm/unified.h> | 22 | #include <asm/unified.h> |
24 | 23 | ||
25 | #include <mach/board-eb.h> | 24 | #include <mach/board-eb.h> |
@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void); | |||
37 | */ | 36 | */ |
38 | volatile int __cpuinitdata pen_release = -1; | 37 | volatile int __cpuinitdata pen_release = -1; |
39 | 38 | ||
39 | /* | ||
40 | * Write pen_release in a way that is guaranteed to be visible to all | ||
41 | * observers, irrespective of whether they're taking part in coherency | ||
42 | * or not. This is necessary for the hotplug code to work reliably. | ||
43 | */ | ||
44 | static void write_pen_release(int val) | ||
45 | { | ||
46 | pen_release = val; | ||
47 | smp_wmb(); | ||
48 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
49 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
50 | } | ||
51 | |||
40 | static void __iomem *scu_base_addr(void) | 52 | static void __iomem *scu_base_addr(void) |
41 | { | 53 | { |
42 | if (machine_is_realview_eb_mp()) | 54 | if (machine_is_realview_eb_mp()) |
@@ -50,20 +62,10 @@ static void __iomem *scu_base_addr(void) | |||
50 | return (void __iomem *)0; | 62 | return (void __iomem *)0; |
51 | } | 63 | } |
52 | 64 | ||
53 | static inline unsigned int get_core_count(void) | ||
54 | { | ||
55 | void __iomem *scu_base = scu_base_addr(); | ||
56 | if (scu_base) | ||
57 | return scu_get_core_count(scu_base); | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static DEFINE_SPINLOCK(boot_lock); | 65 | static DEFINE_SPINLOCK(boot_lock); |
62 | 66 | ||
63 | void __cpuinit platform_secondary_init(unsigned int cpu) | 67 | void __cpuinit platform_secondary_init(unsigned int cpu) |
64 | { | 68 | { |
65 | trace_hardirqs_off(); | ||
66 | |||
67 | /* | 69 | /* |
68 | * if any interrupts are already enabled for the primary | 70 | * if any interrupts are already enabled for the primary |
69 | * core (e.g. timer irq), then they will not have been enabled | 71 | * core (e.g. timer irq), then they will not have been enabled |
@@ -75,8 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
75 | * let the primary processor know we're out of the | 77 | * let the primary processor know we're out of the |
76 | * pen, then head off into the C entry point | 78 | * pen, then head off into the C entry point |
77 | */ | 79 | */ |
78 | pen_release = -1; | 80 | write_pen_release(-1); |
79 | smp_wmb(); | ||
80 | 81 | ||
81 | /* | 82 | /* |
82 | * Synchronise with the boot thread. | 83 | * Synchronise with the boot thread. |
@@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
103 | * Note that "pen_release" is the hardware CPU ID, whereas | 104 | * Note that "pen_release" is the hardware CPU ID, whereas |
104 | * "cpu" is Linux's internal ID. | 105 | * "cpu" is Linux's internal ID. |
105 | */ | 106 | */ |
106 | pen_release = cpu; | 107 | write_pen_release(cpu); |
107 | flush_cache_all(); | ||
108 | 108 | ||
109 | /* | 109 | /* |
110 | * XXX | 110 | * Send the secondary CPU a soft interrupt, thereby causing |
111 | * | 111 | * the boot monitor to read the system wide flags register, |
112 | * This is a later addition to the booting protocol: the | 112 | * and branch to the address found there. |
113 | * bootMonitor now puts secondary cores into WFI, so | ||
114 | * poke_milo() no longer gets the cores moving; we need | ||
115 | * to send a soft interrupt to wake the secondary core. | ||
116 | * Use smp_cross_call() for this, since there's little | ||
117 | * point duplicating the code here | ||
118 | */ | 113 | */ |
119 | smp_cross_call(cpumask_of(cpu)); | 114 | smp_cross_call(cpumask_of(cpu), 1); |
120 | 115 | ||
121 | timeout = jiffies + (1 * HZ); | 116 | timeout = jiffies + (1 * HZ); |
122 | while (time_before(jiffies, timeout)) { | 117 | while (time_before(jiffies, timeout)) { |
@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
136 | return pen_release != -1 ? -ENOSYS : 0; | 131 | return pen_release != -1 ? -ENOSYS : 0; |
137 | } | 132 | } |
138 | 133 | ||
139 | static void __init poke_milo(void) | ||
140 | { | ||
141 | /* nobody is to be released from the pen yet */ | ||
142 | pen_release = -1; | ||
143 | |||
144 | /* | ||
145 | * Write the address of secondary startup into the system-wide flags | ||
146 | * register. The BootMonitor waits for this register to become | ||
147 | * non-zero. | ||
148 | */ | ||
149 | __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), | ||
150 | __io_address(REALVIEW_SYS_FLAGSSET)); | ||
151 | |||
152 | mb(); | ||
153 | } | ||
154 | |||
155 | /* | 134 | /* |
156 | * Initialise the CPU possible map early - this describes the CPUs | 135 | * Initialise the CPU possible map early - this describes the CPUs |
157 | * which may be present or become present in the system. | 136 | * which may be present or become present in the system. |
158 | */ | 137 | */ |
159 | void __init smp_init_cpus(void) | 138 | void __init smp_init_cpus(void) |
160 | { | 139 | { |
161 | unsigned int i, ncores = get_core_count(); | 140 | void __iomem *scu_base = scu_base_addr(); |
141 | unsigned int i, ncores; | ||
162 | 142 | ||
163 | for (i = 0; i < ncores; i++) | 143 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
164 | set_cpu_possible(i, true); | ||
165 | } | ||
166 | |||
167 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
168 | { | ||
169 | unsigned int ncores = get_core_count(); | ||
170 | unsigned int cpu = smp_processor_id(); | ||
171 | int i; | ||
172 | 144 | ||
173 | /* sanity check */ | 145 | /* sanity check */ |
174 | if (ncores == 0) { | ||
175 | printk(KERN_ERR | ||
176 | "Realview: strange CM count of 0? Default to 1\n"); | ||
177 | |||
178 | ncores = 1; | ||
179 | } | ||
180 | |||
181 | if (ncores > NR_CPUS) { | 146 | if (ncores > NR_CPUS) { |
182 | printk(KERN_WARNING | 147 | printk(KERN_WARNING |
183 | "Realview: no. of cores (%d) greater than configured " | 148 | "Realview: no. of cores (%d) greater than configured " |
@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
186 | ncores = NR_CPUS; | 151 | ncores = NR_CPUS; |
187 | } | 152 | } |
188 | 153 | ||
189 | smp_store_cpu_info(cpu); | 154 | for (i = 0; i < ncores; i++) |
155 | set_cpu_possible(i, true); | ||
156 | } | ||
190 | 157 | ||
191 | /* | 158 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
192 | * are we trying to boot more cores than exist? | 159 | { |
193 | */ | 160 | int i; |
194 | if (max_cpus > ncores) | ||
195 | max_cpus = ncores; | ||
196 | 161 | ||
197 | /* | 162 | /* |
198 | * Initialise the present map, which describes the set of CPUs | 163 | * Initialise the present map, which describes the set of CPUs |
@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
201 | for (i = 0; i < max_cpus; i++) | 166 | for (i = 0; i < max_cpus; i++) |
202 | set_cpu_present(i, true); | 167 | set_cpu_present(i, true); |
203 | 168 | ||
169 | scu_enable(scu_base_addr()); | ||
170 | |||
204 | /* | 171 | /* |
205 | * Initialise the SCU if there are more than one CPU and let | 172 | * Write the address of secondary startup into the |
206 | * them know where to start. Note that, on modern versions of | 173 | * system-wide flags register. The BootMonitor waits |
207 | * MILO, the "poke" doesn't actually do anything until each | 174 | * until it receives a soft interrupt, and then the |
208 | * individual core is sent a soft interrupt to get it out of | 175 | * secondary CPU branches to this address. |
209 | * WFI | ||
210 | */ | 176 | */ |
211 | if (max_cpus > 1) { | 177 | __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), |
212 | /* | 178 | __io_address(REALVIEW_SYS_FLAGSSET)); |
213 | * Enable the local timer or broadcast device for the | ||
214 | * boot CPU, but only if we have more than one CPU. | ||
215 | */ | ||
216 | percpu_timer_setup(); | ||
217 | |||
218 | scu_enable(scu_base_addr()); | ||
219 | poke_milo(); | ||
220 | } | ||
221 | } | 179 | } |
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index 6983cb4d4cae..e82ab4aa7ab9 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig | |||
@@ -59,7 +59,7 @@ config MACH_JIVE | |||
59 | Say Y here if you are using the Logitech Jive. | 59 | Say Y here if you are using the Logitech Jive. |
60 | 60 | ||
61 | config MACH_JIVE_SHOW_BOOTLOADER | 61 | config MACH_JIVE_SHOW_BOOTLOADER |
62 | bool "Allow access to bootloader partitions in MTD" | 62 | bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)" |
63 | depends on MACH_JIVE && EXPERIMENTAL | 63 | depends on MACH_JIVE && EXPERIMENTAL |
64 | 64 | ||
65 | config MACH_SMDK2413 | 65 | config MACH_SMDK2413 |
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c index 03652c3605f6..afa5392d9fc0 100644 --- a/arch/arm/mach-s5pv310/hotplug.c +++ b/arch/arm/mach-s5pv310/hotplug.c | |||
@@ -13,14 +13,11 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | #include <linux/completion.h> | ||
17 | 16 | ||
18 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
19 | 18 | ||
20 | extern volatile int pen_release; | 19 | extern volatile int pen_release; |
21 | 20 | ||
22 | static DECLARE_COMPLETION(cpu_killed); | ||
23 | |||
24 | static inline void cpu_enter_lowpower(void) | 21 | static inline void cpu_enter_lowpower(void) |
25 | { | 22 | { |
26 | unsigned int v; | 23 | unsigned int v; |
@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void) | |||
33 | * Turn off coherency | 30 | * Turn off coherency |
34 | */ | 31 | */ |
35 | " mrc p15, 0, %0, c1, c0, 1\n" | 32 | " mrc p15, 0, %0, c1, c0, 1\n" |
36 | " bic %0, %0, #0x20\n" | 33 | " bic %0, %0, %2\n" |
37 | " mcr p15, 0, %0, c1, c0, 1\n" | 34 | " mcr p15, 0, %0, c1, c0, 1\n" |
38 | " mrc p15, 0, %0, c1, c0, 0\n" | 35 | " mrc p15, 0, %0, c1, c0, 0\n" |
39 | " bic %0, %0, #0x04\n" | 36 | " bic %0, %0, #0x04\n" |
40 | " mcr p15, 0, %0, c1, c0, 0\n" | 37 | " mcr p15, 0, %0, c1, c0, 0\n" |
41 | : "=&r" (v) | 38 | : "=&r" (v) |
42 | : "r" (0) | 39 | : "r" (0), "Ir" (CR_C) |
43 | : "cc"); | 40 | : "cc"); |
44 | } | 41 | } |
45 | 42 | ||
@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void) | |||
49 | 46 | ||
50 | asm volatile( | 47 | asm volatile( |
51 | "mrc p15, 0, %0, c1, c0, 0\n" | 48 | "mrc p15, 0, %0, c1, c0, 0\n" |
52 | " orr %0, %0, #0x04\n" | 49 | " orr %0, %0, %1\n" |
53 | " mcr p15, 0, %0, c1, c0, 0\n" | 50 | " mcr p15, 0, %0, c1, c0, 0\n" |
54 | " mrc p15, 0, %0, c1, c0, 1\n" | 51 | " mrc p15, 0, %0, c1, c0, 1\n" |
55 | " orr %0, %0, #0x20\n" | 52 | " orr %0, %0, #0x20\n" |
56 | " mcr p15, 0, %0, c1, c0, 1\n" | 53 | " mcr p15, 0, %0, c1, c0, 1\n" |
57 | : "=&r" (v) | 54 | : "=&r" (v) |
58 | : | 55 | : "Ir" (CR_C) |
59 | : "cc"); | 56 | : "cc"); |
60 | } | 57 | } |
61 | 58 | ||
62 | static inline void platform_do_lowpower(unsigned int cpu) | 59 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
63 | { | 60 | { |
64 | /* | 61 | /* |
65 | * there is no power-control hardware on this platform, so all | 62 | * there is no power-control hardware on this platform, so all |
@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
83 | } | 80 | } |
84 | 81 | ||
85 | /* | 82 | /* |
86 | * getting here, means that we have come out of WFI without | 83 | * Getting here, means that we have come out of WFI without |
87 | * having been woken up - this shouldn't happen | 84 | * having been woken up - this shouldn't happen |
88 | * | 85 | * |
89 | * The trouble is, letting people know about this is not really | 86 | * Just note it happening - when we're woken, we can report |
90 | * possible, since we are currently running incoherently, and | 87 | * its occurrence. |
91 | * therefore cannot safely call printk() or anything else | ||
92 | */ | 88 | */ |
93 | #ifdef DEBUG | 89 | (*spurious)++; |
94 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
95 | #endif | ||
96 | } | 90 | } |
97 | } | 91 | } |
98 | 92 | ||
99 | int platform_cpu_kill(unsigned int cpu) | 93 | int platform_cpu_kill(unsigned int cpu) |
100 | { | 94 | { |
101 | return wait_for_completion_timeout(&cpu_killed, 5000); | 95 | return 1; |
102 | } | 96 | } |
103 | 97 | ||
104 | /* | 98 | /* |
@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
108 | */ | 102 | */ |
109 | void platform_cpu_die(unsigned int cpu) | 103 | void platform_cpu_die(unsigned int cpu) |
110 | { | 104 | { |
111 | #ifdef DEBUG | 105 | int spurious = 0; |
112 | unsigned int this_cpu = hard_smp_processor_id(); | ||
113 | |||
114 | if (cpu != this_cpu) { | ||
115 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
116 | this_cpu, cpu); | ||
117 | BUG(); | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
122 | complete(&cpu_killed); | ||
123 | 106 | ||
124 | /* | 107 | /* |
125 | * we're ready for shutdown now, so do it | 108 | * we're ready for shutdown now, so do it |
126 | */ | 109 | */ |
127 | cpu_enter_lowpower(); | 110 | cpu_enter_lowpower(); |
128 | platform_do_lowpower(cpu); | 111 | platform_do_lowpower(cpu, &spurious); |
129 | 112 | ||
130 | /* | 113 | /* |
131 | * bring this CPU back into the world of cache | 114 | * bring this CPU back into the world of cache |
132 | * coherency, and then restore interrupts | 115 | * coherency, and then restore interrupts |
133 | */ | 116 | */ |
134 | cpu_leave_lowpower(); | 117 | cpu_leave_lowpower(); |
118 | |||
119 | if (spurious) | ||
120 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
135 | } | 121 | } |
136 | 122 | ||
137 | int platform_cpu_disable(unsigned int cpu) | 123 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h index e1cc6a251c6a..393ccbd52c4a 100644 --- a/arch/arm/mach-s5pv310/include/mach/smp.h +++ b/arch/arm/mach-s5pv310/include/mach/smp.h | |||
@@ -7,14 +7,13 @@ | |||
7 | #define ASM_ARCH_SMP_H __FILE__ | 7 | #define ASM_ARCH_SMP_H __FILE__ |
8 | 8 | ||
9 | #include <asm/hardware/gic.h> | 9 | #include <asm/hardware/gic.h> |
10 | #include <asm/smp_mpidr.h> | ||
11 | 10 | ||
12 | /* | 11 | /* |
13 | * We use IRQ1 as the IPI | 12 | * We use IRQ1 as the IPI |
14 | */ | 13 | */ |
15 | static inline void smp_cross_call(const struct cpumask *mask) | 14 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
16 | { | 15 | { |
17 | gic_raise_softirq(mask, 1); | 16 | gic_raise_softirq(mask, ipi); |
18 | } | 17 | } |
19 | 18 | ||
20 | #endif | 19 | #endif |
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c index 15929c169f81..34093b069f67 100644 --- a/arch/arm/mach-s5pv310/platsmp.c +++ b/arch/arm/mach-s5pv310/platsmp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/localtimer.h> | ||
26 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
27 | #include <asm/unified.h> | 26 | #include <asm/unified.h> |
28 | 27 | ||
@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void); | |||
38 | 37 | ||
39 | volatile int __cpuinitdata pen_release = -1; | 38 | volatile int __cpuinitdata pen_release = -1; |
40 | 39 | ||
40 | /* | ||
41 | * Write pen_release in a way that is guaranteed to be visible to all | ||
42 | * observers, irrespective of whether they're taking part in coherency | ||
43 | * or not. This is necessary for the hotplug code to work reliably. | ||
44 | */ | ||
45 | static void write_pen_release(int val) | ||
46 | { | ||
47 | pen_release = val; | ||
48 | smp_wmb(); | ||
49 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
50 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
51 | } | ||
52 | |||
41 | static void __iomem *scu_base_addr(void) | 53 | static void __iomem *scu_base_addr(void) |
42 | { | 54 | { |
43 | return (void __iomem *)(S5P_VA_SCU); | 55 | return (void __iomem *)(S5P_VA_SCU); |
@@ -47,8 +59,6 @@ static DEFINE_SPINLOCK(boot_lock); | |||
47 | 59 | ||
48 | void __cpuinit platform_secondary_init(unsigned int cpu) | 60 | void __cpuinit platform_secondary_init(unsigned int cpu) |
49 | { | 61 | { |
50 | trace_hardirqs_off(); | ||
51 | |||
52 | /* | 62 | /* |
53 | * if any interrupts are already enabled for the primary | 63 | * if any interrupts are already enabled for the primary |
54 | * core (e.g. timer irq), then they will not have been enabled | 64 | * core (e.g. timer irq), then they will not have been enabled |
@@ -60,8 +70,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
60 | * let the primary processor know we're out of the | 70 | * let the primary processor know we're out of the |
61 | * pen, then head off into the C entry point | 71 | * pen, then head off into the C entry point |
62 | */ | 72 | */ |
63 | pen_release = -1; | 73 | write_pen_release(-1); |
64 | smp_wmb(); | ||
65 | 74 | ||
66 | /* | 75 | /* |
67 | * Synchronise with the boot thread. | 76 | * Synchronise with the boot thread. |
@@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
88 | * Note that "pen_release" is the hardware CPU ID, whereas | 97 | * Note that "pen_release" is the hardware CPU ID, whereas |
89 | * "cpu" is Linux's internal ID. | 98 | * "cpu" is Linux's internal ID. |
90 | */ | 99 | */ |
91 | pen_release = cpu; | 100 | write_pen_release(cpu); |
92 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
93 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
94 | 101 | ||
95 | /* | 102 | /* |
96 | * Send the secondary CPU a soft interrupt, thereby causing | 103 | * Send the secondary CPU a soft interrupt, thereby causing |
97 | * the boot monitor to read the system wide flags register, | 104 | * the boot monitor to read the system wide flags register, |
98 | * and branch to the address found there. | 105 | * and branch to the address found there. |
99 | */ | 106 | */ |
100 | smp_cross_call(cpumask_of(cpu)); | 107 | smp_cross_call(cpumask_of(cpu), 1); |
101 | 108 | ||
102 | timeout = jiffies + (1 * HZ); | 109 | timeout = jiffies + (1 * HZ); |
103 | while (time_before(jiffies, timeout)) { | 110 | while (time_before(jiffies, timeout)) { |
@@ -130,13 +137,6 @@ void __init smp_init_cpus(void) | |||
130 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; | 137 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
131 | 138 | ||
132 | /* sanity check */ | 139 | /* sanity check */ |
133 | if (ncores == 0) { | ||
134 | printk(KERN_ERR | ||
135 | "S5PV310: strange CM count of 0? Default to 1\n"); | ||
136 | |||
137 | ncores = 1; | ||
138 | } | ||
139 | |||
140 | if (ncores > NR_CPUS) { | 140 | if (ncores > NR_CPUS) { |
141 | printk(KERN_WARNING | 141 | printk(KERN_WARNING |
142 | "S5PV310: no. of cores (%d) greater than configured " | 142 | "S5PV310: no. of cores (%d) greater than configured " |
@@ -149,18 +149,10 @@ void __init smp_init_cpus(void) | |||
149 | set_cpu_possible(i, true); | 149 | set_cpu_possible(i, true); |
150 | } | 150 | } |
151 | 151 | ||
152 | void __init smp_prepare_cpus(unsigned int max_cpus) | 152 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
153 | { | 153 | { |
154 | unsigned int ncores = num_possible_cpus(); | ||
155 | unsigned int cpu = smp_processor_id(); | ||
156 | int i; | 154 | int i; |
157 | 155 | ||
158 | smp_store_cpu_info(cpu); | ||
159 | |||
160 | /* are we trying to boot more cores than exist? */ | ||
161 | if (max_cpus > ncores) | ||
162 | max_cpus = ncores; | ||
163 | |||
164 | /* | 156 | /* |
165 | * Initialise the present map, which describes the set of CPUs | 157 | * Initialise the present map, which describes the set of CPUs |
166 | * actually populated at the present time. | 158 | * actually populated at the present time. |
@@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
168 | for (i = 0; i < max_cpus; i++) | 160 | for (i = 0; i < max_cpus; i++) |
169 | set_cpu_present(i, true); | 161 | set_cpu_present(i, true); |
170 | 162 | ||
163 | scu_enable(scu_base_addr()); | ||
164 | |||
171 | /* | 165 | /* |
172 | * Initialise the SCU if there are more than one CPU and let | 166 | * Write the address of secondary startup into the |
173 | * them know where to start. | 167 | * system-wide flags register. The boot monitor waits |
168 | * until it receives a soft interrupt, and then the | ||
169 | * secondary CPU branches to this address. | ||
174 | */ | 170 | */ |
175 | if (max_cpus > 1) { | ||
176 | /* | ||
177 | * Enable the local timer or broadcast device for the | ||
178 | * boot CPU, but only if we have more than one CPU. | ||
179 | */ | ||
180 | percpu_timer_setup(); | ||
181 | |||
182 | scu_enable(scu_base_addr()); | ||
183 | |||
184 | /* | ||
185 | * Write the address of secondary startup into the | ||
186 | * system-wide flags register. The boot monitor waits | ||
187 | * until it receives a soft interrupt, and then the | ||
188 | * secondary CPU branches to this address. | ||
189 | */ | ||
190 | __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM); | 171 | __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM); |
191 | } | ||
192 | } | 172 | } |
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 51dcd59eda6a..632933357242 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -6,7 +6,7 @@ config ARCH_SH7367 | |||
6 | bool "SH-Mobile G3 (SH7367)" | 6 | bool "SH-Mobile G3 (SH7367)" |
7 | select CPU_V6 | 7 | select CPU_V6 |
8 | select HAVE_CLK | 8 | select HAVE_CLK |
9 | select COMMON_CLKDEV | 9 | select CLKDEV_LOOKUP |
10 | select SH_CLK_CPG | 10 | select SH_CLK_CPG |
11 | select GENERIC_CLOCKEVENTS | 11 | select GENERIC_CLOCKEVENTS |
12 | 12 | ||
@@ -14,7 +14,7 @@ config ARCH_SH7377 | |||
14 | bool "SH-Mobile G4 (SH7377)" | 14 | bool "SH-Mobile G4 (SH7377)" |
15 | select CPU_V7 | 15 | select CPU_V7 |
16 | select HAVE_CLK | 16 | select HAVE_CLK |
17 | select COMMON_CLKDEV | 17 | select CLKDEV_LOOKUP |
18 | select SH_CLK_CPG | 18 | select SH_CLK_CPG |
19 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
20 | 20 | ||
@@ -22,7 +22,7 @@ config ARCH_SH7372 | |||
22 | bool "SH-Mobile AP4 (SH7372)" | 22 | bool "SH-Mobile AP4 (SH7372)" |
23 | select CPU_V7 | 23 | select CPU_V7 |
24 | select HAVE_CLK | 24 | select HAVE_CLK |
25 | select COMMON_CLKDEV | 25 | select CLKDEV_LOOKUP |
26 | select SH_CLK_CPG | 26 | select SH_CLK_CPG |
27 | select GENERIC_CLOCKEVENTS | 27 | select GENERIC_CLOCKEVENTS |
28 | 28 | ||
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c index 9f78729098f2..6b186aefcbd6 100644 --- a/arch/arm/mach-shmobile/clock-sh7367.c +++ b/arch/arm/mach-shmobile/clock-sh7367.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7367 registers */ | 26 | /* SH7367 registers */ |
27 | #define RTFRQCR 0xe6150000 | 27 | #define RTFRQCR 0xe6150000 |
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 3aa026069435..d98deb497c2f 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7372 registers */ | 26 | /* SH7372 registers */ |
27 | #define FRQCRA 0xe6150000 | 27 | #define FRQCRA 0xe6150000 |
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c index f91395aeb9ab..95942466e63f 100644 --- a/arch/arm/mach-shmobile/clock-sh7377.c +++ b/arch/arm/mach-shmobile/clock-sh7377.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7377 registers */ | 26 | /* SH7377 registers */ |
27 | #define RTFRQCR 0xe6150000 | 27 | #define RTFRQCR 0xe6150000 |
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index ba32a15127ab..3970a9cdce26 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c | |||
@@ -12,8 +12,7 @@ | |||
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | 15 | #include <linux/clkdev.h> | |
16 | #include <asm/clkdev.h> | ||
17 | 16 | ||
18 | #include <mach/clock.h> | 17 | #include <mach/clock.h> |
19 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index ae19f95585be..77948e0f4909 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <asm/clkdev.h> | 28 | #include <linux/clkdev.h> |
29 | 29 | ||
30 | #include "clock.h" | 30 | #include "clock.h" |
31 | #include "board.h" | 31 | #include "board.h" |
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 94fd859770f1..083a4cfc6cf0 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h | |||
@@ -21,7 +21,7 @@ | |||
21 | #define __MACH_TEGRA_CLOCK_H | 21 | #define __MACH_TEGRA_CLOCK_H |
22 | 22 | ||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <asm/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | 25 | ||
26 | #define DIV_BUS (1 << 0) | 26 | #define DIV_BUS (1 << 0) |
27 | #define DIV_U71 (1 << 1) | 27 | #define DIV_U71 (1 << 1) |
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index 8e7f115aa21e..a5cb1ce76ff2 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c | |||
@@ -11,12 +11,9 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | static DECLARE_COMPLETION(cpu_killed); | ||
19 | |||
20 | static inline void cpu_enter_lowpower(void) | 17 | static inline void cpu_enter_lowpower(void) |
21 | { | 18 | { |
22 | unsigned int v; | 19 | unsigned int v; |
@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void) | |||
29 | * Turn off coherency | 26 | * Turn off coherency |
30 | */ | 27 | */ |
31 | " mrc p15, 0, %0, c1, c0, 1\n" | 28 | " mrc p15, 0, %0, c1, c0, 1\n" |
32 | " bic %0, %0, #0x20\n" | 29 | " bic %0, %0, %2\n" |
33 | " mcr p15, 0, %0, c1, c0, 1\n" | 30 | " mcr p15, 0, %0, c1, c0, 1\n" |
34 | " mrc p15, 0, %0, c1, c0, 0\n" | 31 | " mrc p15, 0, %0, c1, c0, 0\n" |
35 | " bic %0, %0, #0x04\n" | 32 | " bic %0, %0, #0x04\n" |
36 | " mcr p15, 0, %0, c1, c0, 0\n" | 33 | " mcr p15, 0, %0, c1, c0, 0\n" |
37 | : "=&r" (v) | 34 | : "=&r" (v) |
38 | : "r" (0) | 35 | : "r" (0), "Ir" (CR_C) |
39 | : "cc"); | 36 | : "cc"); |
40 | } | 37 | } |
41 | 38 | ||
@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void) | |||
45 | 42 | ||
46 | asm volatile( | 43 | asm volatile( |
47 | "mrc p15, 0, %0, c1, c0, 0\n" | 44 | "mrc p15, 0, %0, c1, c0, 0\n" |
48 | " orr %0, %0, #0x04\n" | 45 | " orr %0, %0, %1\n" |
49 | " mcr p15, 0, %0, c1, c0, 0\n" | 46 | " mcr p15, 0, %0, c1, c0, 0\n" |
50 | " mrc p15, 0, %0, c1, c0, 1\n" | 47 | " mrc p15, 0, %0, c1, c0, 1\n" |
51 | " orr %0, %0, #0x20\n" | 48 | " orr %0, %0, #0x20\n" |
52 | " mcr p15, 0, %0, c1, c0, 1\n" | 49 | " mcr p15, 0, %0, c1, c0, 1\n" |
53 | : "=&r" (v) | 50 | : "=&r" (v) |
54 | : | 51 | : "Ir" (CR_C) |
55 | : "cc"); | 52 | : "cc"); |
56 | } | 53 | } |
57 | 54 | ||
58 | static inline void platform_do_lowpower(unsigned int cpu) | 55 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
59 | { | 56 | { |
60 | /* | 57 | /* |
61 | * there is no power-control hardware on this platform, so all | 58 | * there is no power-control hardware on this platform, so all |
@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
79 | /*}*/ | 76 | /*}*/ |
80 | 77 | ||
81 | /* | 78 | /* |
82 | * getting here, means that we have come out of WFI without | 79 | * Getting here, means that we have come out of WFI without |
83 | * having been woken up - this shouldn't happen | 80 | * having been woken up - this shouldn't happen |
84 | * | 81 | * |
85 | * The trouble is, letting people know about this is not really | 82 | * Just note it happening - when we're woken, we can report |
86 | * possible, since we are currently running incoherently, and | 83 | * its occurrence. |
87 | * therefore cannot safely call printk() or anything else | ||
88 | */ | 84 | */ |
89 | #ifdef DEBUG | 85 | (*spurious)++; |
90 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
91 | #endif | ||
92 | } | 86 | } |
93 | } | 87 | } |
94 | 88 | ||
95 | int platform_cpu_kill(unsigned int cpu) | 89 | int platform_cpu_kill(unsigned int cpu) |
96 | { | 90 | { |
97 | return wait_for_completion_timeout(&cpu_killed, 5000); | 91 | return 1; |
98 | } | 92 | } |
99 | 93 | ||
100 | /* | 94 | /* |
@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
104 | */ | 98 | */ |
105 | void platform_cpu_die(unsigned int cpu) | 99 | void platform_cpu_die(unsigned int cpu) |
106 | { | 100 | { |
107 | #ifdef DEBUG | 101 | int spurious = 0; |
108 | unsigned int this_cpu = hard_smp_processor_id(); | ||
109 | |||
110 | if (cpu != this_cpu) { | ||
111 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
112 | this_cpu, cpu); | ||
113 | BUG(); | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
118 | complete(&cpu_killed); | ||
119 | 102 | ||
120 | /* | 103 | /* |
121 | * we're ready for shutdown now, so do it | 104 | * we're ready for shutdown now, so do it |
122 | */ | 105 | */ |
123 | cpu_enter_lowpower(); | 106 | cpu_enter_lowpower(); |
124 | platform_do_lowpower(cpu); | 107 | platform_do_lowpower(cpu, &spurious); |
125 | 108 | ||
126 | /* | 109 | /* |
127 | * bring this CPU back into the world of cache | 110 | * bring this CPU back into the world of cache |
128 | * coherency, and then restore interrupts | 111 | * coherency, and then restore interrupts |
129 | */ | 112 | */ |
130 | cpu_leave_lowpower(); | 113 | cpu_leave_lowpower(); |
114 | |||
115 | if (spurious) | ||
116 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
131 | } | 117 | } |
132 | 118 | ||
133 | int platform_cpu_disable(unsigned int cpu) | 119 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h index e4a34a35a544..c8221b38ee7c 100644 --- a/arch/arm/mach-tegra/include/mach/smp.h +++ b/arch/arm/mach-tegra/include/mach/smp.h | |||
@@ -2,21 +2,13 @@ | |||
2 | #define ASMARM_ARCH_SMP_H | 2 | #define ASMARM_ARCH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | ||
12 | gic_raise_softirq(mask, 1); | ||
13 | } | ||
14 | |||
15 | /* | ||
16 | * Do nothing on MPcore. | ||
17 | */ | ||
18 | static inline void smp_cross_call_done(cpumask_t callmap) | ||
19 | { | 10 | { |
11 | gic_raise_softirq(mask, ipi); | ||
20 | } | 12 | } |
21 | 13 | ||
22 | #endif | 14 | #endif |
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 3b7376c4f356..ec1f68924edf 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
24 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | #include <asm/localtimer.h> | ||
26 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
27 | 26 | ||
28 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
@@ -41,8 +40,6 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); | |||
41 | 40 | ||
42 | void __cpuinit platform_secondary_init(unsigned int cpu) | 41 | void __cpuinit platform_secondary_init(unsigned int cpu) |
43 | { | 42 | { |
44 | trace_hardirqs_off(); | ||
45 | |||
46 | /* | 43 | /* |
47 | * if any interrupts are already enabled for the primary | 44 | * if any interrupts are already enabled for the primary |
48 | * core (e.g. timer irq), then they will not have been enabled | 45 | * core (e.g. timer irq), then they will not have been enabled |
@@ -117,24 +114,20 @@ void __init smp_init_cpus(void) | |||
117 | { | 114 | { |
118 | unsigned int i, ncores = scu_get_core_count(scu_base); | 115 | unsigned int i, ncores = scu_get_core_count(scu_base); |
119 | 116 | ||
117 | if (ncores > NR_CPUS) { | ||
118 | printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n", | ||
119 | ncores, NR_CPUS); | ||
120 | ncores = NR_CPUS; | ||
121 | } | ||
122 | |||
120 | for (i = 0; i < ncores; i++) | 123 | for (i = 0; i < ncores; i++) |
121 | cpu_set(i, cpu_possible_map); | 124 | cpu_set(i, cpu_possible_map); |
122 | } | 125 | } |
123 | 126 | ||
124 | void __init smp_prepare_cpus(unsigned int max_cpus) | 127 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
125 | { | 128 | { |
126 | unsigned int ncores = scu_get_core_count(scu_base); | ||
127 | unsigned int cpu = smp_processor_id(); | ||
128 | int i; | 129 | int i; |
129 | 130 | ||
130 | smp_store_cpu_info(cpu); | ||
131 | |||
132 | /* | ||
133 | * are we trying to boot more cores than exist? | ||
134 | */ | ||
135 | if (max_cpus > ncores) | ||
136 | max_cpus = ncores; | ||
137 | |||
138 | /* | 131 | /* |
139 | * Initialise the present map, which describes the set of CPUs | 132 | * Initialise the present map, which describes the set of CPUs |
140 | * actually populated at the present time. | 133 | * actually populated at the present time. |
@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
142 | for (i = 0; i < max_cpus; i++) | 135 | for (i = 0; i < max_cpus; i++) |
143 | set_cpu_present(i, true); | 136 | set_cpu_present(i, true); |
144 | 137 | ||
145 | /* | 138 | scu_enable(scu_base); |
146 | * Initialise the SCU if there are more than one CPU and let | ||
147 | * them know where to start. Note that, on modern versions of | ||
148 | * MILO, the "poke" doesn't actually do anything until each | ||
149 | * individual core is sent a soft interrupt to get it out of | ||
150 | * WFI | ||
151 | */ | ||
152 | if (max_cpus > 1) { | ||
153 | percpu_timer_setup(); | ||
154 | scu_enable(scu_base); | ||
155 | } | ||
156 | } | 139 | } |
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index ae3b308e22a4..f0dae6d8ba52 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -24,8 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/hrtimer.h> | 26 | #include <linux/hrtimer.h> |
27 | 27 | #include <linux/clkdev.h> | |
28 | #include <asm/clkdev.h> | ||
29 | 28 | ||
30 | #include <mach/iomap.h> | 29 | #include <mach/iomap.h> |
31 | 30 | ||
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 7458fc6df5c6..fabcc49abe80 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
28 | #include <linux/clkdev.h> | ||
28 | 29 | ||
29 | #include <asm/clkdev.h> | ||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/syscon.h> | 31 | #include <mach/syscon.h> |
32 | 32 | ||
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 1675047daf20..531de5c63641 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -13,8 +13,7 @@ | |||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | 16 | #include <linux/clkdev.h> | |
17 | #include <asm/clkdev.h> | ||
18 | 17 | ||
19 | #include <plat/mtu.h> | 18 | #include <plat/mtu.h> |
20 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-ux500/headsmp.S b/arch/arm/mach-ux500/headsmp.S index a6be2cdf2b2f..64fa451edcfd 100644 --- a/arch/arm/mach-ux500/headsmp.S +++ b/arch/arm/mach-ux500/headsmp.S | |||
@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup) | |||
23 | ldmia r4, {r5, r6} | 23 | ldmia r4, {r5, r6} |
24 | sub r4, r4, r5 | 24 | sub r4, r4, r5 |
25 | add r6, r6, r4 | 25 | add r6, r6, r4 |
26 | dsb | ||
27 | pen: ldr r7, [r6] | 26 | pen: ldr r7, [r6] |
28 | cmp r7, r0 | 27 | cmp r7, r0 |
29 | bne pen | 28 | bne pen |
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index b782a03024be..dd8037ebccf8 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c | |||
@@ -11,14 +11,11 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | extern volatile int pen_release; | 17 | extern volatile int pen_release; |
19 | 18 | ||
20 | static DECLARE_COMPLETION(cpu_killed); | ||
21 | |||
22 | static inline void platform_do_lowpower(unsigned int cpu) | 19 | static inline void platform_do_lowpower(unsigned int cpu) |
23 | { | 20 | { |
24 | flush_cache_all(); | 21 | flush_cache_all(); |
@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
38 | 35 | ||
39 | int platform_cpu_kill(unsigned int cpu) | 36 | int platform_cpu_kill(unsigned int cpu) |
40 | { | 37 | { |
41 | return wait_for_completion_timeout(&cpu_killed, 5000); | 38 | return 1; |
42 | } | 39 | } |
43 | 40 | ||
44 | /* | 41 | /* |
@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu) | |||
48 | */ | 45 | */ |
49 | void platform_cpu_die(unsigned int cpu) | 46 | void platform_cpu_die(unsigned int cpu) |
50 | { | 47 | { |
51 | #ifdef DEBUG | ||
52 | unsigned int this_cpu = hard_smp_processor_id(); | ||
53 | |||
54 | if (cpu != this_cpu) { | ||
55 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
56 | this_cpu, cpu); | ||
57 | BUG(); | ||
58 | } | ||
59 | #endif | ||
60 | |||
61 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
62 | complete(&cpu_killed); | ||
63 | |||
64 | /* directly enter low power state, skipping secure registers */ | 48 | /* directly enter low power state, skipping secure registers */ |
65 | platform_do_lowpower(cpu); | 49 | platform_do_lowpower(cpu); |
66 | } | 50 | } |
diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h index 197e8417375e..ca2b15b1b3b1 100644 --- a/arch/arm/mach-ux500/include/mach/smp.h +++ b/arch/arm/mach-ux500/include/mach/smp.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #define ASMARM_ARCH_SMP_H | 10 | #define ASMARM_ARCH_SMP_H |
11 | 11 | ||
12 | #include <asm/hardware/gic.h> | 12 | #include <asm/hardware/gic.h> |
13 | #include <asm/smp_mpidr.h> | ||
14 | 13 | ||
15 | /* This is required to wakeup the secondary core */ | 14 | /* This is required to wakeup the secondary core */ |
16 | extern void u8500_secondary_startup(void); | 15 | extern void u8500_secondary_startup(void); |
@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void); | |||
18 | /* | 17 | /* |
19 | * We use IRQ1 as the IPI | 18 | * We use IRQ1 as the IPI |
20 | */ | 19 | */ |
21 | static inline void smp_cross_call(const struct cpumask *mask) | 20 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
22 | { | 21 | { |
23 | gic_raise_softirq(mask, 1); | 22 | gic_raise_softirq(mask, ipi); |
24 | } | 23 | } |
25 | #endif | 24 | #endif |
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index b5077b4c419f..2115a0cf07b0 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | 19 | ||
20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
21 | #include <asm/localtimer.h> | ||
22 | #include <asm/smp_scu.h> | 21 | #include <asm/smp_scu.h> |
23 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
24 | 23 | ||
@@ -28,17 +27,23 @@ | |||
28 | */ | 27 | */ |
29 | volatile int __cpuinitdata pen_release = -1; | 28 | volatile int __cpuinitdata pen_release = -1; |
30 | 29 | ||
31 | static unsigned int __init get_core_count(void) | 30 | /* |
31 | * Write pen_release in a way that is guaranteed to be visible to all | ||
32 | * observers, irrespective of whether they're taking part in coherency | ||
33 | * or not. This is necessary for the hotplug code to work reliably. | ||
34 | */ | ||
35 | static void write_pen_release(int val) | ||
32 | { | 36 | { |
33 | return scu_get_core_count(__io_address(UX500_SCU_BASE)); | 37 | pen_release = val; |
38 | smp_wmb(); | ||
39 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
40 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
34 | } | 41 | } |
35 | 42 | ||
36 | static DEFINE_SPINLOCK(boot_lock); | 43 | static DEFINE_SPINLOCK(boot_lock); |
37 | 44 | ||
38 | void __cpuinit platform_secondary_init(unsigned int cpu) | 45 | void __cpuinit platform_secondary_init(unsigned int cpu) |
39 | { | 46 | { |
40 | trace_hardirqs_off(); | ||
41 | |||
42 | /* | 47 | /* |
43 | * if any interrupts are already enabled for the primary | 48 | * if any interrupts are already enabled for the primary |
44 | * core (e.g. timer irq), then they will not have been enabled | 49 | * core (e.g. timer irq), then they will not have been enabled |
@@ -50,7 +55,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
50 | * let the primary processor know we're out of the | 55 | * let the primary processor know we're out of the |
51 | * pen, then head off into the C entry point | 56 | * pen, then head off into the C entry point |
52 | */ | 57 | */ |
53 | pen_release = -1; | 58 | write_pen_release(-1); |
54 | 59 | ||
55 | /* | 60 | /* |
56 | * Synchronise with the boot thread. | 61 | * Synchronise with the boot thread. |
@@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
74 | * the holding pen - release it, then wait for it to flag | 79 | * the holding pen - release it, then wait for it to flag |
75 | * that it has been released by resetting pen_release. | 80 | * that it has been released by resetting pen_release. |
76 | */ | 81 | */ |
77 | pen_release = cpu; | 82 | write_pen_release(cpu); |
78 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
79 | outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1); | ||
80 | 83 | ||
81 | smp_cross_call(cpumask_of(cpu)); | 84 | smp_cross_call(cpumask_of(cpu), 1); |
82 | 85 | ||
83 | timeout = jiffies + (1 * HZ); | 86 | timeout = jiffies + (1 * HZ); |
84 | while (time_before(jiffies, timeout)) { | 87 | while (time_before(jiffies, timeout)) { |
@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
97 | 100 | ||
98 | static void __init wakeup_secondary(void) | 101 | static void __init wakeup_secondary(void) |
99 | { | 102 | { |
100 | /* nobody is to be released from the pen yet */ | ||
101 | pen_release = -1; | ||
102 | |||
103 | /* | 103 | /* |
104 | * write the address of secondary startup into the backup ram register | 104 | * write the address of secondary startup into the backup ram register |
105 | * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the | 105 | * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the |
@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void) | |||
126 | */ | 126 | */ |
127 | void __init smp_init_cpus(void) | 127 | void __init smp_init_cpus(void) |
128 | { | 128 | { |
129 | unsigned int i, ncores = get_core_count(); | 129 | unsigned int i, ncores; |
130 | 130 | ||
131 | for (i = 0; i < ncores; i++) | 131 | ncores = scu_get_core_count(__io_address(UX500_SCU_BASE)); |
132 | set_cpu_possible(i, true); | ||
133 | } | ||
134 | |||
135 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
136 | { | ||
137 | unsigned int ncores = get_core_count(); | ||
138 | unsigned int cpu = smp_processor_id(); | ||
139 | int i; | ||
140 | 132 | ||
141 | /* sanity check */ | 133 | /* sanity check */ |
142 | if (ncores == 0) { | 134 | if (ncores > NR_CPUS) { |
143 | printk(KERN_ERR | ||
144 | "U8500: strange CM count of 0? Default to 1\n"); | ||
145 | ncores = 1; | ||
146 | } | ||
147 | |||
148 | if (ncores > num_possible_cpus()) { | ||
149 | printk(KERN_WARNING | 135 | printk(KERN_WARNING |
150 | "U8500: no. of cores (%d) greater than configured " | 136 | "U8500: no. of cores (%d) greater than configured " |
151 | "maximum of %d - clipping\n", | 137 | "maximum of %d - clipping\n", |
152 | ncores, num_possible_cpus()); | 138 | ncores, NR_CPUS); |
153 | ncores = num_possible_cpus(); | 139 | ncores = NR_CPUS; |
154 | } | 140 | } |
155 | 141 | ||
156 | smp_store_cpu_info(cpu); | 142 | for (i = 0; i < ncores; i++) |
143 | set_cpu_possible(i, true); | ||
144 | } | ||
157 | 145 | ||
158 | /* | 146 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
159 | * are we trying to boot more cores than exist? | 147 | { |
160 | */ | 148 | int i; |
161 | if (max_cpus > ncores) | ||
162 | max_cpus = ncores; | ||
163 | 149 | ||
164 | /* | 150 | /* |
165 | * Initialise the present map, which describes the set of CPUs | 151 | * Initialise the present map, which describes the set of CPUs |
@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
168 | for (i = 0; i < max_cpus; i++) | 154 | for (i = 0; i < max_cpus; i++) |
169 | set_cpu_present(i, true); | 155 | set_cpu_present(i, true); |
170 | 156 | ||
171 | if (max_cpus > 1) { | 157 | scu_enable(__io_address(UX500_SCU_BASE)); |
172 | /* | 158 | wakeup_secondary(); |
173 | * Enable the local timer or broadcast device for the | ||
174 | * boot CPU, but only if we have more than one CPU. | ||
175 | */ | ||
176 | percpu_timer_setup(); | ||
177 | scu_enable(__io_address(UX500_SCU_BASE)); | ||
178 | wakeup_secondary(); | ||
179 | } | ||
180 | } | 159 | } |
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig index c781f30c8368..3f7b5e9d83c5 100644 --- a/arch/arm/mach-versatile/Kconfig +++ b/arch/arm/mach-versatile/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Versatile platform type" | |||
4 | config ARCH_VERSATILE_PB | 4 | config ARCH_VERSATILE_PB |
5 | bool "Support Versatile/PB platform" | 5 | bool "Support Versatile/PB platform" |
6 | select CPU_ARM926T | 6 | select CPU_ARM926T |
7 | select MIGHT_HAVE_PCI | ||
7 | default y | 8 | default y |
8 | help | 9 | help |
9 | Include support for the ARM(R) Versatile/PB platform. | 10 | Include support for the ARM(R) Versatile/PB platform. |
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 40a024c71e4b..13a83e45a33b 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
@@ -31,8 +31,8 @@ | |||
31 | #include <linux/amba/pl022.h> | 31 | #include <linux/amba/pl022.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/gfp.h> | 33 | #include <linux/gfp.h> |
34 | #include <linux/clkdev.h> | ||
34 | 35 | ||
35 | #include <asm/clkdev.h> | ||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/leds.h> | 38 | #include <asm/leds.h> |
@@ -46,7 +46,6 @@ | |||
46 | #include <asm/mach/irq.h> | 46 | #include <asm/mach/irq.h> |
47 | #include <asm/mach/time.h> | 47 | #include <asm/mach/time.h> |
48 | #include <asm/mach/map.h> | 48 | #include <asm/mach/map.h> |
49 | #include <mach/clkdev.h> | ||
50 | #include <mach/hardware.h> | 49 | #include <mach/hardware.h> |
51 | #include <mach/platform.h> | 50 | #include <mach/platform.h> |
52 | #include <asm/hardware/timer-sp.h> | 51 | #include <asm/hardware/timer-sp.h> |
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 1b71b77ade22..2c0ac7de2814 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile | |||
@@ -5,4 +5,5 @@ | |||
5 | obj-y := v2m.o | 5 | obj-y := v2m.o |
6 | obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o | 6 | obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o |
7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
8 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
8 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | 9 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o |
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index cb5793ef3ee0..e628402b754c 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c | |||
@@ -8,8 +8,8 @@ | |||
8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
9 | #include <linux/amba/bus.h> | 9 | #include <linux/amba/bus.h> |
10 | #include <linux/amba/clcd.h> | 10 | #include <linux/amba/clcd.h> |
11 | #include <linux/clkdev.h> | ||
11 | 12 | ||
12 | #include <asm/clkdev.h> | ||
13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
14 | #include <asm/hardware/arm_timer.h> | 14 | #include <asm/hardware/arm_timer.h> |
15 | #include <asm/hardware/cache-l2x0.h> | 15 | #include <asm/hardware/cache-l2x0.h> |
@@ -18,7 +18,6 @@ | |||
18 | #include <asm/pmu.h> | 18 | #include <asm/pmu.h> |
19 | #include <asm/smp_twd.h> | 19 | #include <asm/smp_twd.h> |
20 | 20 | ||
21 | #include <mach/clkdev.h> | ||
22 | #include <mach/ct-ca9x4.h> | 21 | #include <mach/ct-ca9x4.h> |
23 | 22 | ||
24 | #include <asm/hardware/timer-sp.h> | 23 | #include <asm/hardware/timer-sp.h> |
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c new file mode 100644 index 000000000000..ea4cbfb90a66 --- /dev/null +++ b/arch/arm/mach-vexpress/hotplug.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-realview/hotplug.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Ltd. | ||
5 | * All Rights Reserved | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/smp.h> | ||
14 | |||
15 | #include <asm/cacheflush.h> | ||
16 | |||
17 | extern volatile int pen_release; | ||
18 | |||
19 | static inline void cpu_enter_lowpower(void) | ||
20 | { | ||
21 | unsigned int v; | ||
22 | |||
23 | flush_cache_all(); | ||
24 | asm volatile( | ||
25 | "mcr p15, 0, %1, c7, c5, 0\n" | ||
26 | " mcr p15, 0, %1, c7, c10, 4\n" | ||
27 | /* | ||
28 | * Turn off coherency | ||
29 | */ | ||
30 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
31 | " bic %0, %0, %3\n" | ||
32 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
33 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
34 | " bic %0, %0, %2\n" | ||
35 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
36 | : "=&r" (v) | ||
37 | : "r" (0), "Ir" (CR_C), "Ir" (0x40) | ||
38 | : "cc"); | ||
39 | } | ||
40 | |||
41 | static inline void cpu_leave_lowpower(void) | ||
42 | { | ||
43 | unsigned int v; | ||
44 | |||
45 | asm volatile( | ||
46 | "mrc p15, 0, %0, c1, c0, 0\n" | ||
47 | " orr %0, %0, %1\n" | ||
48 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
49 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
50 | " orr %0, %0, %2\n" | ||
51 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
52 | : "=&r" (v) | ||
53 | : "Ir" (CR_C), "Ir" (0x40) | ||
54 | : "cc"); | ||
55 | } | ||
56 | |||
57 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | ||
58 | { | ||
59 | /* | ||
60 | * there is no power-control hardware on this platform, so all | ||
61 | * we can do is put the core into WFI; this is safe as the calling | ||
62 | * code will have already disabled interrupts | ||
63 | */ | ||
64 | for (;;) { | ||
65 | /* | ||
66 | * here's the WFI | ||
67 | */ | ||
68 | asm(".word 0xe320f003\n" | ||
69 | : | ||
70 | : | ||
71 | : "memory", "cc"); | ||
72 | |||
73 | if (pen_release == cpu) { | ||
74 | /* | ||
75 | * OK, proper wakeup, we're done | ||
76 | */ | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Getting here, means that we have come out of WFI without | ||
82 | * having been woken up - this shouldn't happen | ||
83 | * | ||
84 | * Just note it happening - when we're woken, we can report | ||
85 | * its occurrence. | ||
86 | */ | ||
87 | (*spurious)++; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | int platform_cpu_kill(unsigned int cpu) | ||
92 | { | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * platform-specific code to shutdown a CPU | ||
98 | * | ||
99 | * Called with IRQs disabled | ||
100 | */ | ||
101 | void platform_cpu_die(unsigned int cpu) | ||
102 | { | ||
103 | int spurious = 0; | ||
104 | |||
105 | /* | ||
106 | * we're ready for shutdown now, so do it | ||
107 | */ | ||
108 | cpu_enter_lowpower(); | ||
109 | platform_do_lowpower(cpu, &spurious); | ||
110 | |||
111 | /* | ||
112 | * bring this CPU back into the world of cache | ||
113 | * coherency, and then restore interrupts | ||
114 | */ | ||
115 | cpu_leave_lowpower(); | ||
116 | |||
117 | if (spurious) | ||
118 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
119 | } | ||
120 | |||
121 | int platform_cpu_disable(unsigned int cpu) | ||
122 | { | ||
123 | /* | ||
124 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
125 | * e.g. clock tick interrupts) | ||
126 | */ | ||
127 | return cpu == 0 ? -EPERM : 0; | ||
128 | } | ||
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h index 5a6da4fd247e..4c05e4a9713a 100644 --- a/arch/arm/mach-vexpress/include/mach/smp.h +++ b/arch/arm/mach-vexpress/include/mach/smp.h | |||
@@ -2,13 +2,12 @@ | |||
2 | #define __MACH_SMP_H | 2 | #define __MACH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | 10 | { |
12 | gic_raise_softirq(mask, 1); | 11 | gic_raise_softirq(mask, ipi); |
13 | } | 12 | } |
14 | #endif | 13 | #endif |
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index dfb591031d17..b1687b6abe63 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
20 | #include <asm/localtimer.h> | ||
21 | #include <asm/smp_scu.h> | 20 | #include <asm/smp_scu.h> |
22 | #include <asm/unified.h> | 21 | #include <asm/unified.h> |
23 | 22 | ||
@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void); | |||
35 | */ | 34 | */ |
36 | volatile int __cpuinitdata pen_release = -1; | 35 | volatile int __cpuinitdata pen_release = -1; |
37 | 36 | ||
37 | /* | ||
38 | * Write pen_release in a way that is guaranteed to be visible to all | ||
39 | * observers, irrespective of whether they're taking part in coherency | ||
40 | * or not. This is necessary for the hotplug code to work reliably. | ||
41 | */ | ||
42 | static void write_pen_release(int val) | ||
43 | { | ||
44 | pen_release = val; | ||
45 | smp_wmb(); | ||
46 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
47 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
48 | } | ||
49 | |||
38 | static void __iomem *scu_base_addr(void) | 50 | static void __iomem *scu_base_addr(void) |
39 | { | 51 | { |
40 | return MMIO_P2V(A9_MPCORE_SCU); | 52 | return MMIO_P2V(A9_MPCORE_SCU); |
@@ -44,8 +56,6 @@ static DEFINE_SPINLOCK(boot_lock); | |||
44 | 56 | ||
45 | void __cpuinit platform_secondary_init(unsigned int cpu) | 57 | void __cpuinit platform_secondary_init(unsigned int cpu) |
46 | { | 58 | { |
47 | trace_hardirqs_off(); | ||
48 | |||
49 | /* | 59 | /* |
50 | * if any interrupts are already enabled for the primary | 60 | * if any interrupts are already enabled for the primary |
51 | * core (e.g. timer irq), then they will not have been enabled | 61 | * core (e.g. timer irq), then they will not have been enabled |
@@ -57,8 +67,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
57 | * let the primary processor know we're out of the | 67 | * let the primary processor know we're out of the |
58 | * pen, then head off into the C entry point | 68 | * pen, then head off into the C entry point |
59 | */ | 69 | */ |
60 | pen_release = -1; | 70 | write_pen_release(-1); |
61 | smp_wmb(); | ||
62 | 71 | ||
63 | /* | 72 | /* |
64 | * Synchronise with the boot thread. | 73 | * Synchronise with the boot thread. |
@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
83 | * since we haven't sent them a soft interrupt, they shouldn't | 92 | * since we haven't sent them a soft interrupt, they shouldn't |
84 | * be there. | 93 | * be there. |
85 | */ | 94 | */ |
86 | pen_release = cpu; | 95 | write_pen_release(cpu); |
87 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
88 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
89 | 96 | ||
90 | /* | 97 | /* |
91 | * Send the secondary CPU a soft interrupt, thereby causing | 98 | * Send the secondary CPU a soft interrupt, thereby causing |
92 | * the boot monitor to read the system wide flags register, | 99 | * the boot monitor to read the system wide flags register, |
93 | * and branch to the address found there. | 100 | * and branch to the address found there. |
94 | */ | 101 | */ |
95 | smp_cross_call(cpumask_of(cpu)); | 102 | smp_cross_call(cpumask_of(cpu), 1); |
96 | 103 | ||
97 | timeout = jiffies + (1 * HZ); | 104 | timeout = jiffies + (1 * HZ); |
98 | while (time_before(jiffies, timeout)) { | 105 | while (time_before(jiffies, timeout)) { |
@@ -124,13 +131,6 @@ void __init smp_init_cpus(void) | |||
124 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; | 131 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
125 | 132 | ||
126 | /* sanity check */ | 133 | /* sanity check */ |
127 | if (ncores == 0) { | ||
128 | printk(KERN_ERR | ||
129 | "vexpress: strange CM count of 0? Default to 1\n"); | ||
130 | |||
131 | ncores = 1; | ||
132 | } | ||
133 | |||
134 | if (ncores > NR_CPUS) { | 134 | if (ncores > NR_CPUS) { |
135 | printk(KERN_WARNING | 135 | printk(KERN_WARNING |
136 | "vexpress: no. of cores (%d) greater than configured " | 136 | "vexpress: no. of cores (%d) greater than configured " |
@@ -143,20 +143,10 @@ void __init smp_init_cpus(void) | |||
143 | set_cpu_possible(i, true); | 143 | set_cpu_possible(i, true); |
144 | } | 144 | } |
145 | 145 | ||
146 | void __init smp_prepare_cpus(unsigned int max_cpus) | 146 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
147 | { | 147 | { |
148 | unsigned int ncores = num_possible_cpus(); | ||
149 | unsigned int cpu = smp_processor_id(); | ||
150 | int i; | 148 | int i; |
151 | 149 | ||
152 | smp_store_cpu_info(cpu); | ||
153 | |||
154 | /* | ||
155 | * are we trying to boot more cores than exist? | ||
156 | */ | ||
157 | if (max_cpus > ncores) | ||
158 | max_cpus = ncores; | ||
159 | |||
160 | /* | 150 | /* |
161 | * Initialise the present map, which describes the set of CPUs | 151 | * Initialise the present map, which describes the set of CPUs |
162 | * actually populated at the present time. | 152 | * actually populated at the present time. |
@@ -164,27 +154,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
164 | for (i = 0; i < max_cpus; i++) | 154 | for (i = 0; i < max_cpus; i++) |
165 | set_cpu_present(i, true); | 155 | set_cpu_present(i, true); |
166 | 156 | ||
157 | scu_enable(scu_base_addr()); | ||
158 | |||
167 | /* | 159 | /* |
168 | * Initialise the SCU if there are more than one CPU and let | 160 | * Write the address of secondary startup into the |
169 | * them know where to start. | 161 | * system-wide flags register. The boot monitor waits |
162 | * until it receives a soft interrupt, and then the | ||
163 | * secondary CPU branches to this address. | ||
170 | */ | 164 | */ |
171 | if (max_cpus > 1) { | 165 | writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); |
172 | /* | 166 | writel(BSYM(virt_to_phys(vexpress_secondary_startup)), |
173 | * Enable the local timer or broadcast device for the | 167 | MMIO_P2V(V2M_SYS_FLAGSSET)); |
174 | * boot CPU, but only if we have more than one CPU. | ||
175 | */ | ||
176 | percpu_timer_setup(); | ||
177 | |||
178 | scu_enable(scu_base_addr()); | ||
179 | |||
180 | /* | ||
181 | * Write the address of secondary startup into the | ||
182 | * system-wide flags register. The boot monitor waits | ||
183 | * until it receives a soft interrupt, and then the | ||
184 | * secondary CPU branches to this address. | ||
185 | */ | ||
186 | writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); | ||
187 | writel(BSYM(virt_to_phys(vexpress_secondary_startup)), | ||
188 | MMIO_P2V(V2M_SYS_FLAGSSET)); | ||
189 | } | ||
190 | } | 168 | } |
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index de13603dc028..a9ed3428a2fa 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -11,8 +11,8 @@ | |||
11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
12 | #include <linux/sysdev.h> | 12 | #include <linux/sysdev.h> |
13 | #include <linux/usb/isp1760.h> | 13 | #include <linux/usb/isp1760.h> |
14 | #include <linux/clkdev.h> | ||
14 | 15 | ||
15 | #include <asm/clkdev.h> | ||
16 | #include <asm/sizes.h> | 16 | #include <asm/sizes.h> |
17 | #include <asm/mach/flash.h> | 17 | #include <asm/mach/flash.h> |
18 | #include <asm/mach/map.h> | 18 | #include <asm/mach/map.h> |
@@ -20,7 +20,6 @@ | |||
20 | #include <asm/hardware/arm_timer.h> | 20 | #include <asm/hardware/arm_timer.h> |
21 | #include <asm/hardware/timer-sp.h> | 21 | #include <asm/hardware/timer-sp.h> |
22 | 22 | ||
23 | #include <mach/clkdev.h> | ||
24 | #include <mach/motherboard.h> | 23 | #include <mach/motherboard.h> |
25 | 24 | ||
26 | #include <plat/sched_clock.h> | 25 | #include <plat/sched_clock.h> |
diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h index c56ddab3d912..b88a1b16b2e9 100644 --- a/arch/arm/mach-w90x900/clock.h +++ b/arch/arm/mach-w90x900/clock.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * the Free Software Foundation; either version 2 of the License. | 10 | * the Free Software Foundation; either version 2 of the License. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | 14 | ||
15 | void nuc900_clk_enable(struct clk *clk, int enable); | 15 | void nuc900_clk_enable(struct clk *clk, int enable); |
16 | void nuc900_subclk_enable(struct clk *clk, int enable); | 16 | void nuc900_subclk_enable(struct clk *clk, int enable); |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 4414a01e1e8a..8493ed04797a 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -599,6 +599,14 @@ config CPU_CP15_MPU | |||
599 | help | 599 | help |
600 | Processor has the CP15 register, which has MPU related registers. | 600 | Processor has the CP15 register, which has MPU related registers. |
601 | 601 | ||
602 | config CPU_USE_DOMAINS | ||
603 | bool | ||
604 | depends on MMU | ||
605 | default y if !CPU_32v6K | ||
606 | help | ||
607 | This option enables or disables the use of domain switching | ||
608 | via the set_fs() function. | ||
609 | |||
602 | # | 610 | # |
603 | # CPU supports 36-bit I/O | 611 | # CPU supports 36-bit I/O |
604 | # | 612 | # |
@@ -628,6 +636,33 @@ config ARM_THUMBEE | |||
628 | Say Y here if you have a CPU with the ThumbEE extension and code to | 636 | Say Y here if you have a CPU with the ThumbEE extension and code to |
629 | make use of it. Say N for code that can run on CPUs without ThumbEE. | 637 | make use of it. Say N for code that can run on CPUs without ThumbEE. |
630 | 638 | ||
639 | config SWP_EMULATE | ||
640 | bool "Emulate SWP/SWPB instructions" | ||
641 | depends on CPU_V7 | ||
642 | select HAVE_PROC_CPU if PROC_FS | ||
643 | default y if SMP | ||
644 | help | ||
645 | ARMv6 architecture deprecates use of the SWP/SWPB instructions. | ||
646 | ARMv7 multiprocessing extensions introduce the ability to disable | ||
647 | these instructions, triggering an undefined instruction exception | ||
648 | when executed. Say Y here to enable software emulation of these | ||
649 | instructions for userspace (not kernel) using LDREX/STREX. | ||
650 | Also creates /proc/cpu/swp_emulation for statistics. | ||
651 | |||
652 | In some older versions of glibc [<=2.8] SWP is used during futex | ||
653 | trylock() operations with the assumption that the code will not | ||
654 | be preempted. This invalid assumption may be more likely to fail | ||
655 | with SWP emulation enabled, leading to deadlock of the user | ||
656 | application. | ||
657 | |||
658 | NOTE: when accessing uncached shared regions, LDREX/STREX rely | ||
659 | on an external transaction monitoring block called a global | ||
660 | monitor to maintain update atomicity. If your system does not | ||
661 | implement a global monitor, this option can cause programs that | ||
662 | perform SWP operations to uncached memory to deadlock. | ||
663 | |||
664 | If unsure, say Y. | ||
665 | |||
631 | config CPU_BIG_ENDIAN | 666 | config CPU_BIG_ENDIAN |
632 | bool "Build big-endian kernel" | 667 | bool "Build big-endian kernel" |
633 | depends on ARCH_SUPPORTS_BIG_ENDIAN | 668 | depends on ARCH_SUPPORTS_BIG_ENDIAN |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 809f1bf9fa29..6b48e0a3d7aa 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -312,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | |||
312 | addr = page_address(page); | 312 | addr = page_address(page); |
313 | 313 | ||
314 | if (addr) | 314 | if (addr) |
315 | *handle = page_to_dma(dev, page); | 315 | *handle = pfn_to_dma(dev, page_to_pfn(page)); |
316 | 316 | ||
317 | return addr; | 317 | return addr; |
318 | } | 318 | } |
@@ -407,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr | |||
407 | if (!arch_is_coherent()) | 407 | if (!arch_is_coherent()) |
408 | __dma_free_remap(cpu_addr, size); | 408 | __dma_free_remap(cpu_addr, size); |
409 | 409 | ||
410 | __dma_free_buffer(dma_to_page(dev, handle), size); | 410 | __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size); |
411 | } | 411 | } |
412 | EXPORT_SYMBOL(dma_free_coherent); | 412 | EXPORT_SYMBOL(dma_free_coherent); |
413 | 413 | ||
@@ -555,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
555 | struct scatterlist *s; | 555 | struct scatterlist *s; |
556 | int i, j; | 556 | int i, j; |
557 | 557 | ||
558 | BUG_ON(!valid_dma_direction(dir)); | ||
559 | |||
558 | for_each_sg(sg, s, nents, i) { | 560 | for_each_sg(sg, s, nents, i) { |
559 | s->dma_address = dma_map_page(dev, sg_page(s), s->offset, | 561 | s->dma_address = __dma_map_page(dev, sg_page(s), s->offset, |
560 | s->length, dir); | 562 | s->length, dir); |
561 | if (dma_mapping_error(dev, s->dma_address)) | 563 | if (dma_mapping_error(dev, s->dma_address)) |
562 | goto bad_mapping; | 564 | goto bad_mapping; |
563 | } | 565 | } |
566 | debug_dma_map_sg(dev, sg, nents, nents, dir); | ||
564 | return nents; | 567 | return nents; |
565 | 568 | ||
566 | bad_mapping: | 569 | bad_mapping: |
567 | for_each_sg(sg, s, i, j) | 570 | for_each_sg(sg, s, i, j) |
568 | dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); | 571 | __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); |
569 | return 0; | 572 | return 0; |
570 | } | 573 | } |
571 | EXPORT_SYMBOL(dma_map_sg); | 574 | EXPORT_SYMBOL(dma_map_sg); |
@@ -586,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
586 | struct scatterlist *s; | 589 | struct scatterlist *s; |
587 | int i; | 590 | int i; |
588 | 591 | ||
592 | debug_dma_unmap_sg(dev, sg, nents, dir); | ||
593 | |||
589 | for_each_sg(sg, s, nents, i) | 594 | for_each_sg(sg, s, nents, i) |
590 | dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); | 595 | __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); |
591 | } | 596 | } |
592 | EXPORT_SYMBOL(dma_unmap_sg); | 597 | EXPORT_SYMBOL(dma_unmap_sg); |
593 | 598 | ||
@@ -612,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | |||
612 | __dma_page_dev_to_cpu(sg_page(s), s->offset, | 617 | __dma_page_dev_to_cpu(sg_page(s), s->offset, |
613 | s->length, dir); | 618 | s->length, dir); |
614 | } | 619 | } |
620 | |||
621 | debug_dma_sync_sg_for_cpu(dev, sg, nents, dir); | ||
615 | } | 622 | } |
616 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); | 623 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); |
617 | 624 | ||
@@ -636,5 +643,16 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
636 | __dma_page_cpu_to_dev(sg_page(s), s->offset, | 643 | __dma_page_cpu_to_dev(sg_page(s), s->offset, |
637 | s->length, dir); | 644 | s->length, dir); |
638 | } | 645 | } |
646 | |||
647 | debug_dma_sync_sg_for_device(dev, sg, nents, dir); | ||
639 | } | 648 | } |
640 | EXPORT_SYMBOL(dma_sync_sg_for_device); | 649 | EXPORT_SYMBOL(dma_sync_sg_for_device); |
650 | |||
651 | #define PREALLOC_DMA_DEBUG_ENTRIES 4096 | ||
652 | |||
653 | static int __init dma_debug_do_init(void) | ||
654 | { | ||
655 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||
656 | return 0; | ||
657 | } | ||
658 | fs_initcall(dma_debug_do_init); | ||
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 55c17a6fb22f..ab506272b2d3 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | |||
204 | /* | 204 | /* |
205 | * Don't allow RAM to be mapped - this causes problems with ARMv6+ | 205 | * Don't allow RAM to be mapped - this causes problems with ARMv6+ |
206 | */ | 206 | */ |
207 | if (pfn_valid(pfn)) { | 207 | if (WARN_ON(pfn_valid(pfn))) |
208 | printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n" | 208 | return NULL; |
209 | "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n" | ||
210 | "will fail in the next kernel release. Please fix your driver.\n"); | ||
211 | WARN_ON(1); | ||
212 | } | ||
213 | 209 | ||
214 | type = get_mem_type(mtype); | 210 | type = get_mem_type(mtype); |
215 | if (!type) | 211 | if (!type) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 72ad3e1f56cf..79c01f540cbe 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/smp_plat.h> | 24 | #include <asm/smp_plat.h> |
25 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
26 | #include <asm/highmem.h> | 26 | #include <asm/highmem.h> |
27 | #include <asm/traps.h> | ||
27 | 28 | ||
28 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
29 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
@@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
914 | { | 915 | { |
915 | struct map_desc map; | 916 | struct map_desc map; |
916 | unsigned long addr; | 917 | unsigned long addr; |
917 | void *vectors; | ||
918 | 918 | ||
919 | /* | 919 | /* |
920 | * Allocate the vector page early. | 920 | * Allocate the vector page early. |
921 | */ | 921 | */ |
922 | vectors = early_alloc(PAGE_SIZE); | 922 | vectors_page = early_alloc(PAGE_SIZE); |
923 | 923 | ||
924 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) | 924 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) |
925 | pmd_clear(pmd_off_k(addr)); | 925 | pmd_clear(pmd_off_k(addr)); |
@@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
959 | * location (0xffff0000). If we aren't using high-vectors, also | 959 | * location (0xffff0000). If we aren't using high-vectors, also |
960 | * create a mapping at the low-vectors virtual address. | 960 | * create a mapping at the low-vectors virtual address. |
961 | */ | 961 | */ |
962 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); | 962 | map.pfn = __phys_to_pfn(virt_to_phys(vectors_page)); |
963 | map.virtual = 0xffff0000; | 963 | map.virtual = 0xffff0000; |
964 | map.length = PAGE_SIZE; | 964 | map.length = PAGE_SIZE; |
965 | map.type = MT_HIGH_VECTORS; | 965 | map.type = MT_HIGH_VECTORS; |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index b795afd0a2c6..f8f777df8d72 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -109,6 +109,10 @@ | |||
109 | * 110x 0 1 0 r/w r/o | 109 | * 110x 0 1 0 r/w r/o |
110 | * 11x0 0 1 0 r/w r/o | 110 | * 11x0 0 1 0 r/w r/o |
111 | * 1111 0 1 1 r/w r/w | 111 | * 1111 0 1 1 r/w r/w |
112 | * | ||
113 | * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed: | ||
114 | * 110x 1 1 1 r/o r/o | ||
115 | * 11x0 1 1 1 r/o r/o | ||
112 | */ | 116 | */ |
113 | .macro armv6_mt_table pfx | 117 | .macro armv6_mt_table pfx |
114 | \pfx\()_mt_table: | 118 | \pfx\()_mt_table: |
@@ -148,8 +152,11 @@ | |||
148 | 152 | ||
149 | tst r1, #L_PTE_USER | 153 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 154 | orrne r3, r3, #PTE_EXT_AP1 |
155 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
156 | @ allow kernel read/write access to read-only user pages | ||
151 | tstne r3, #PTE_EXT_APX | 157 | tstne r3, #PTE_EXT_APX |
152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 158 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
159 | #endif | ||
153 | 160 | ||
154 | tst r1, #L_PTE_EXEC | 161 | tst r1, #L_PTE_EXEC |
155 | orreq r3, r3, #PTE_EXT_XN | 162 | orreq r3, r3, #PTE_EXT_XN |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 9b9ff5d949fd..7401f4d7e676 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -148,8 +148,11 @@ ENTRY(cpu_v7_set_pte_ext) | |||
148 | 148 | ||
149 | tst r1, #L_PTE_USER | 149 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 150 | orrne r3, r3, #PTE_EXT_AP1 |
151 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
152 | @ allow kernel read/write access to read-only user pages | ||
151 | tstne r3, #PTE_EXT_APX | 153 | tstne r3, #PTE_EXT_APX |
152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 154 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
155 | #endif | ||
153 | 156 | ||
154 | tst r1, #L_PTE_EXEC | 157 | tst r1, #L_PTE_EXEC |
155 | orreq r3, r3, #PTE_EXT_XN | 158 | orreq r3, r3, #PTE_EXT_XN |
@@ -273,8 +276,6 @@ __v7_setup: | |||
273 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) | 276 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) |
274 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) | 277 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) |
275 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 278 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
276 | mov r10, #0x1f @ domains 0, 1 = manager | ||
277 | mcr p15, 0, r10, c3, c0, 0 @ load domain access register | ||
278 | /* | 279 | /* |
279 | * Memory region attributes with SCTLR.TRE=1 | 280 | * Memory region attributes with SCTLR.TRE=1 |
280 | * | 281 | * |
@@ -313,6 +314,10 @@ __v7_setup: | |||
313 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 314 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
314 | orr r6, r6, #1 << 25 @ big-endian page tables | 315 | orr r6, r6, #1 << 25 @ big-endian page tables |
315 | #endif | 316 | #endif |
317 | #ifdef CONFIG_SWP_EMULATE | ||
318 | orr r5, r5, #(1 << 10) @ set SW bit in "clear" | ||
319 | bic r6, r6, #(1 << 10) @ clear it in "mmuset" | ||
320 | #endif | ||
316 | mrc p15, 0, r0, c1, c0, 0 @ read control register | 321 | mrc p15, 0, r0, c1, c0, 0 @ read control register |
317 | bic r0, r0, r5 @ clear bits them | 322 | bic r0, r0, r5 @ clear bits them |
318 | orr r0, r0, r6 @ set them | 323 | orr r0, r0, r6 @ set them |
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 92c5bb7909f5..c9408434a855 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -11,13 +11,13 @@ choice | |||
11 | 11 | ||
12 | config ARCH_OMAP1 | 12 | config ARCH_OMAP1 |
13 | bool "TI OMAP1" | 13 | bool "TI OMAP1" |
14 | select COMMON_CLKDEV | 14 | select CLKDEV_LOOKUP |
15 | help | 15 | help |
16 | "Systems based on omap7xx, omap15xx or omap16xx" | 16 | "Systems based on omap7xx, omap15xx or omap16xx" |
17 | 17 | ||
18 | config ARCH_OMAP2PLUS | 18 | config ARCH_OMAP2PLUS |
19 | bool "TI OMAP2/3/4" | 19 | bool "TI OMAP2/3/4" |
20 | select COMMON_CLKDEV | 20 | select CLKDEV_LOOKUP |
21 | help | 21 | help |
22 | "Systems based on OMAP2, OMAP3 or OMAP4" | 22 | "Systems based on OMAP2, OMAP3 or OMAP4" |
23 | 23 | ||
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h index bb937f3fabed..4b2028ab4d2b 100644 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H | 8 | #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H |
9 | #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H | 9 | #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H |
10 | 10 | ||
11 | #include <asm/clkdev.h> | 11 | #include <linux/clkdev.h> |
12 | 12 | ||
13 | struct omap_clk { | 13 | struct omap_clk { |
14 | u16 cpu; | 14 | u16 cpu; |
diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h index d5306bee44b2..f8d922fb5584 100644 --- a/arch/arm/plat-omap/include/plat/memory.h +++ b/arch/arm/plat-omap/include/plat/memory.h | |||
@@ -61,17 +61,17 @@ | |||
61 | #define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) | 61 | #define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) |
62 | #define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) | 62 | #define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) |
63 | 63 | ||
64 | #define __arch_page_to_dma(dev, page) \ | 64 | #define __arch_pfn_to_dma(dev, pfn) \ |
65 | ({ dma_addr_t __dma = page_to_phys(page); \ | 65 | ({ dma_addr_t __dma = __pfn_to_phys(pfn); \ |
66 | if (is_lbus_device(dev)) \ | 66 | if (is_lbus_device(dev)) \ |
67 | __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ | 67 | __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ |
68 | __dma; }) | 68 | __dma; }) |
69 | 69 | ||
70 | #define __arch_dma_to_page(dev, addr) \ | 70 | #define __arch_dma_to_pfn(dev, addr) \ |
71 | ({ dma_addr_t __dma = addr; \ | 71 | ({ dma_addr_t __dma = addr; \ |
72 | if (is_lbus_device(dev)) \ | 72 | if (is_lbus_device(dev)) \ |
73 | __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \ | 73 | __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \ |
74 | phys_to_page(__dma); \ | 74 | __phys_to_pfn(__dma); \ |
75 | }) | 75 | }) |
76 | 76 | ||
77 | #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ | 77 | #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ |
diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h index ecd6a488c497..7a10257909ef 100644 --- a/arch/arm/plat-omap/include/plat/smp.h +++ b/arch/arm/plat-omap/include/plat/smp.h | |||
@@ -18,7 +18,6 @@ | |||
18 | #define OMAP_ARCH_SMP_H | 18 | #define OMAP_ARCH_SMP_H |
19 | 19 | ||
20 | #include <asm/hardware/gic.h> | 20 | #include <asm/hardware/gic.h> |
21 | #include <asm/smp_mpidr.h> | ||
22 | 21 | ||
23 | /* Needed for secondary core boot */ | 22 | /* Needed for secondary core boot */ |
24 | extern void omap_secondary_startup(void); | 23 | extern void omap_secondary_startup(void); |
@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void); | |||
29 | /* | 28 | /* |
30 | * We use Soft IRQ1 as the IPI | 29 | * We use Soft IRQ1 as the IPI |
31 | */ | 30 | */ |
32 | static inline void smp_cross_call(const struct cpumask *mask) | 31 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
33 | { | 32 | { |
34 | gic_raise_softirq(mask, 1); | 33 | gic_raise_softirq(mask, ipi); |
35 | } | 34 | } |
36 | 35 | ||
37 | #endif | 36 | #endif |
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 298bafc0a52f..2572260f990f 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #define __PLAT_CLOCK_H | 15 | #define __PLAT_CLOCK_H |
16 | 16 | ||
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <asm/clkdev.h> | 18 | #include <linux/clkdev.h> |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | 20 | ||
21 | /* clk structure flags */ | 21 | /* clk structure flags */ |
diff --git a/arch/arm/plat-stmp3xxx/clock.c b/arch/arm/plat-stmp3xxx/clock.c index e593a2a801c6..2e712e17ce72 100644 --- a/arch/arm/plat-stmp3xxx/clock.c +++ b/arch/arm/plat-stmp3xxx/clock.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/clkdev.h> | ||
28 | 29 | ||
29 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
30 | #include <asm/clkdev.h> | ||
31 | #include <mach/platform.h> | 31 | #include <mach/platform.h> |
32 | #include <mach/regs-clkctrl.h> | 32 | #include <mach/regs-clkctrl.h> |
33 | 33 | ||
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 8063a322c790..0797cb528b46 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -10,9 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/cpu.h> | ||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/notifier.h> | ||
14 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
15 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/smp.h> | ||
16 | #include <linux/init.h> | 19 | #include <linux/init.h> |
17 | 20 | ||
18 | #include <asm/cputype.h> | 21 | #include <asm/cputype.h> |
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread) | |||
484 | put_cpu(); | 487 | put_cpu(); |
485 | } | 488 | } |
486 | 489 | ||
487 | #include <linux/smp.h> | 490 | /* |
491 | * VFP hardware can lose all context when a CPU goes offline. | ||
492 | * Safely clear our held state when a CPU has been killed, and | ||
493 | * re-enable access to VFP when the CPU comes back online. | ||
494 | * | ||
495 | * Both CPU_DYING and CPU_STARTING are called on the CPU which | ||
496 | * is being offlined/onlined. | ||
497 | */ | ||
498 | static int vfp_hotplug(struct notifier_block *b, unsigned long action, | ||
499 | void *hcpu) | ||
500 | { | ||
501 | if (action == CPU_DYING || action == CPU_DYING_FROZEN) { | ||
502 | unsigned int cpu = (long)hcpu; | ||
503 | last_VFP_context[cpu] = NULL; | ||
504 | } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) | ||
505 | vfp_enable(NULL); | ||
506 | return NOTIFY_OK; | ||
507 | } | ||
488 | 508 | ||
489 | /* | 509 | /* |
490 | * VFP support code initialisation. | 510 | * VFP support code initialisation. |
@@ -514,6 +534,8 @@ static int __init vfp_init(void) | |||
514 | else if (vfpsid & FPSID_NODOUBLE) { | 534 | else if (vfpsid & FPSID_NODOUBLE) { |
515 | printk("no double precision support\n"); | 535 | printk("no double precision support\n"); |
516 | } else { | 536 | } else { |
537 | hotcpu_notifier(vfp_hotplug, 0); | ||
538 | |||
517 | smp_call_function(vfp_enable, NULL, 1); | 539 | smp_call_function(vfp_enable, NULL, 1); |
518 | 540 | ||
519 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | 541 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |