summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-05-10 21:08:37 +1000
committerPaul Mackerras <paulus@samba.org>2007-05-10 21:08:37 +1000
commit2ecf042ef530dd0943e41d84b6344f507941af3e (patch)
tree73100361dd74e3f80f14c7c81ba4675948983f44 /arch
parent32a56ebb24f23da1bbaf24292acf85b6c04526ab (diff)
parentde5603748af8bf7deac403e6ba92887f8d18e812 (diff)
downloadlinux-2ecf042ef530dd0943e41d84b6344f507941af3e.tar.bz2
Merge branch 'linux-2.6'
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/Makefile5
-rw-r--r--arch/arm/kernel/head-nommu.S2
-rw-r--r--arch/arm/kernel/head.S2
-rw-r--r--arch/arm/kernel/init_task.c2
-rw-r--r--arch/arm/kernel/module.c4
-rw-r--r--arch/arm/kernel/smp.c4
-rw-r--r--arch/arm/kernel/vmlinux.lds.S12
-rw-r--r--arch/arm/mach-at91/Kconfig2
-rw-r--r--arch/arm/mach-omap1/Kconfig7
-rw-r--r--arch/arm/mach-omap1/Makefile1
-rw-r--r--arch/arm/mach-omap1/board-fsample.c2
-rw-r--r--arch/arm/mach-omap1/board-h3.c2
-rw-r--r--arch/arm/mach-omap1/board-innovator.c2
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c2
-rw-r--r--arch/arm/mach-omap1/devices.c71
-rw-r--r--arch/arm/mach-omap1/io.c4
-rw-r--r--arch/arm/mach-omap1/mailbox.c206
-rw-r--r--arch/arm/mach-omap2/Kconfig2
-rw-r--r--arch/arm/mach-omap2/board-h4.c14
-rw-r--r--arch/arm/mach-omap2/devices.c66
-rw-r--r--arch/arm/mach-omap2/gpmc.c12
-rw-r--r--arch/arm/mach-omap2/io.c21
-rw-r--r--arch/arm/mach-omap2/mailbox.c318
-rw-r--r--arch/arm/mach-s3c2410/sleep.S2
-rw-r--r--arch/arm/mm/Kconfig32
-rw-r--r--arch/arm/mm/Makefile3
-rw-r--r--arch/arm/mm/abort-ev7.S32
-rw-r--r--arch/arm/mm/cache-v7.S253
-rw-r--r--arch/arm/mm/context.c17
-rw-r--r--arch/arm/mm/proc-macros.S12
-rw-r--r--arch/arm/mm/proc-v7.S262
-rw-r--r--arch/arm/plat-omap/Kconfig13
-rw-r--r--arch/arm/plat-omap/Makefile5
-rw-r--r--arch/arm/plat-omap/clock.c37
-rw-r--r--arch/arm/plat-omap/common.c8
-rw-r--r--arch/arm/plat-omap/debug-leds.c314
-rw-r--r--arch/arm/plat-omap/devices.c74
-rw-r--r--arch/arm/plat-omap/dma.c25
-rw-r--r--arch/arm/plat-omap/dmtimer.c2
-rw-r--r--arch/arm/plat-omap/fb.c305
-rw-r--r--arch/arm/plat-omap/gpio.c3
-rw-r--r--arch/arm/plat-omap/mailbox.c509
-rw-r--r--arch/arm/plat-omap/mailbox.h100
-rw-r--r--arch/arm/plat-omap/sram.c56
-rw-r--r--arch/arm/plat-omap/usb.c199
-rw-r--r--arch/arm/plat-s3c24xx/sleep.S2
-rw-r--r--arch/avr32/Makefile2
-rw-r--r--arch/avr32/kernel/process.c6
-rw-r--r--arch/avr32/kernel/ptrace.c2
-rw-r--r--arch/avr32/kernel/syscall_table.S1
-rw-r--r--arch/avr32/kernel/traps.c2
-rw-r--r--arch/avr32/kernel/vmlinux.lds.c2
-rw-r--r--arch/avr32/mach-at32ap/clock.c2
-rw-r--r--arch/avr32/mm/dma-coherent.c12
-rw-r--r--arch/blackfin/kernel/asm-offsets.c2
-rw-r--r--arch/blackfin/kernel/ptrace.c6
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig2
-rw-r--r--arch/frv/Kconfig6
-rw-r--r--arch/frv/kernel/process.c4
-rw-r--r--arch/frv/mm/pgalloc.c22
-rw-r--r--arch/h8300/Kconfig.debug4
-rw-r--r--arch/h8300/kernel/asm-offsets.c2
-rw-r--r--arch/i386/Kconfig4
-rw-r--r--arch/i386/Kconfig.cpu4
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/therm_throt.c4
-rw-r--r--arch/i386/kernel/cpu/transmeta.c6
-rw-r--r--arch/i386/kernel/cpuid.c2
-rw-r--r--arch/i386/kernel/microcode.c59
-rw-r--r--arch/i386/kernel/msr.c2
-rw-r--r--arch/i386/kernel/traps.c2
-rw-r--r--arch/i386/mach-generic/probe.c2
-rw-r--r--arch/i386/mach-voyager/voyager_basic.c4
-rw-r--r--arch/i386/pci/init.c2
-rw-r--r--arch/ia64/Kconfig2
-rw-r--r--arch/ia64/ia32/ia32_entry.S39
-rw-r--r--arch/ia64/ia32/ia32_signal.c65
-rw-r--r--arch/ia64/kernel/entry.S30
-rw-r--r--arch/ia64/kernel/err_inject.c2
-rw-r--r--arch/ia64/kernel/iosapic.c2
-rw-r--r--arch/ia64/kernel/irq_ia64.c27
-rw-r--r--arch/ia64/kernel/mca.c2
-rw-r--r--arch/ia64/kernel/palinfo.c2
-rw-r--r--arch/ia64/kernel/process.c8
-rw-r--r--arch/ia64/kernel/relocate_kernel.S11
-rw-r--r--arch/ia64/kernel/salinfo.c2
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/sigframe.h2
-rw-r--r--arch/ia64/kernel/signal.c71
-rw-r--r--arch/ia64/kernel/smp.c68
-rw-r--r--arch/ia64/kernel/topology.c2
-rw-r--r--arch/ia64/kernel/traps.c6
-rw-r--r--arch/ia64/kernel/unwind.c9
-rw-r--r--arch/ia64/mm/tlb.c6
-rw-r--r--arch/ia64/sn/kernel/irq.c58
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c65
-rw-r--r--arch/m68knommu/Kconfig.debug2
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c2
-rw-r--r--arch/mips/Kconfig6
-rw-r--r--arch/mips/Makefile2
-rw-r--r--arch/mips/kernel/asm-offsets.c2
-rw-r--r--arch/mips/kernel/smtc.c2
-rw-r--r--arch/mips/pci/fixup-sb1250.c4
-rw-r--r--arch/parisc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/Kconfig.debug2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c2
-rw-r--r--arch/powerpc/kernel/sysfs.c2
-rw-r--r--arch/powerpc/mm/numa.c3
-rw-r--r--arch/powerpc/oprofile/op_model_cell.c2
-rw-r--r--arch/powerpc/platforms/8xx/mpc86xads_setup.c2
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c2
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c2
-rw-r--r--arch/ppc/kernel/asm-offsets.c2
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c2
-rw-r--r--arch/ppc/syslib/ipic.c2
-rw-r--r--arch/s390/appldata/appldata_base.c2
-rw-r--r--arch/s390/crypto/Kconfig2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/smp.c2
-rw-r--r--arch/sh/Kconfig29
-rw-r--r--arch/sh/boards/landisk/setup.c1
-rw-r--r--arch/sh/boards/se/7751/setup.c2
-rw-r--r--arch/sh/drivers/Makefile3
-rw-r--r--arch/sh/drivers/dma/Kconfig20
-rw-r--r--arch/sh/drivers/dma/Makefile4
-rw-r--r--arch/sh/drivers/dma/dmabrg.c196
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile5
-rw-r--r--arch/sh/kernel/cpu/sh2a/opcode_helper.c55
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c1
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S2
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S13
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile6
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S62
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c3
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh73180.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7343.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7770.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7780.c2
-rw-r--r--arch/sh/kernel/process.c16
-rw-r--r--arch/sh/kernel/setup.c2
-rw-r--r--arch/sh/kernel/sh_ksyms.c2
-rw-r--r--arch/sh/kernel/signal.c13
-rw-r--r--arch/sh/kernel/stacktrace.c2
-rw-r--r--arch/sh/kernel/syscalls.S1
-rw-r--r--arch/sh/kernel/time.c172
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c182
-rw-r--r--arch/sh/kernel/traps.c20
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c2
-rw-r--r--arch/sh/lib/delay.c5
-rw-r--r--arch/sh/mm/Kconfig7
-rw-r--r--arch/sh/mm/fault.c2
-rw-r--r--arch/sh/mm/init.c2
-rw-r--r--arch/sparc/kernel/asm-offsets.c2
-rw-r--r--arch/sparc64/kernel/traps.c1
-rw-r--r--arch/um/Kconfig16
-rw-r--r--arch/um/Kconfig.scsi58
-rw-r--r--arch/um/include/sysdep-i386/archsetjmp.h2
-rw-r--r--arch/um/include/sysdep-x86_64/archsetjmp.h2
-rw-r--r--arch/um/kernel/skas/process.c9
-rw-r--r--arch/um/os-Linux/process.c2
-rw-r--r--arch/um/os-Linux/skas/mem.c2
-rw-r--r--arch/um/os-Linux/skas/process.c2
-rw-r--r--arch/v850/kernel/asm-offsets.c2
-rw-r--r--arch/v850/kernel/entry.S2
-rw-r--r--arch/x86_64/kernel/io_apic.c2
-rw-r--r--arch/x86_64/kernel/irq.c2
-rw-r--r--arch/x86_64/kernel/mce.c2
-rw-r--r--arch/x86_64/kernel/mce_amd.c2
-rw-r--r--arch/x86_64/kernel/vsyscall.c2
-rw-r--r--arch/xtensa/kernel/asm-offsets.c2
-rw-r--r--arch/xtensa/kernel/pci-dma.c2
172 files changed, 3762 insertions, 923 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0d8fac3b0371..d7c0984d4a86 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -354,6 +354,7 @@ config ARCH_SA1100
config ARCH_S3C2410
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
select GENERIC_GPIO
+ select GENERIC_TIME
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ab9f2d4bd04e..00ea4305ad5d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,8 +47,13 @@ comma = ,
# Note that GCC does not numerically define an architecture version
# macro, but instead defines a whole series of macros which makes
# testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a)
arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+# Only override the compiler option if ARMv6. The ARMv6K extensions are
+# always available in ARMv7
+ifeq ($(CONFIG_CPU_32v6),y)
arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
+endif
arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0119c0d5f978..5d78ffb8a9a7 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -33,7 +33,7 @@
* numbers for r1.
*
*/
- __INIT
+ .section ".text.head", "ax"
.type stext, %function
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 1d35edacc011..41f98b4ba2ee 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -73,7 +73,7 @@
* crap here - that's what the boot loader (or in extreme, well justified
* circumstances, zImage) is for.
*/
- __INIT
+ .section ".text.head", "ax"
.type stext, %function
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index a00cca0000bd..bd4ef53bc6b9 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(init_mm);
* The things we do for performance..
*/
union thread_union init_thread_union
- __attribute__((__section__(".init.task"))) =
+ __attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
/*
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1b061583408e..79b7e5cf5416 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -116,8 +116,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
offset += sym->st_value - loc;
if (offset & 3 ||
- offset <= (s32)0xfc000000 ||
- offset >= (s32)0x04000000) {
+ offset <= (s32)0xfe000000 ||
+ offset >= (s32)0x02000000) {
printk(KERN_ERR
"%s: relocation out of range, section "
"%d reloc %d sym '%s'\n", module->name,
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 070bcb7a6306..1b76d87fa335 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -486,7 +486,7 @@ static void ipi_timer(void)
}
#ifdef CONFIG_LOCAL_TIMERS
-asmlinkage void do_local_timer(struct pt_regs *regs)
+asmlinkage void __exception do_local_timer(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
int cpu = smp_processor_id();
@@ -551,7 +551,7 @@ static void ipi_cpu_stop(unsigned int cpu)
*
* Bit 0 - Inter-processor function call
*/
-asmlinkage void do_IPI(struct pt_regs *regs)
+asmlinkage void __exception do_IPI(struct pt_regs *regs)
{
unsigned int cpu = smp_processor_id();
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 6be67296f333..e4156e7868ce 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -23,11 +23,15 @@ SECTIONS
#else
. = PAGE_OFFSET + TEXT_OFFSET;
#endif
- .init : { /* Init code and data */
+ .text.head : {
_stext = .;
- _sinittext = .;
+ _sinittext = .;
+ *(.text.head)
+ }
+
+ .init : { /* Init code and data */
*(.init.text)
- _einittext = .;
+ _einittext = .;
__proc_info_begin = .;
*(.proc.info.init)
__proc_info_end = .;
@@ -119,7 +123,7 @@ SECTIONS
* first, the init task union, aligned
* to an 8192 byte boundary.
*/
- *(.init.task)
+ *(.data.init_task)
#ifdef CONFIG_XIP_KERNEL
. = ALIGN(4096);
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index e238ad8cfd8f..018d637f87fc 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -107,7 +107,7 @@ config ARCH_AT91SAM9260_SAM9XE
depends on ARCH_AT91SAM9260
help
Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
- They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+ They are basically AT91SAM9260s with various sizes of embedded Flash.
comment "AT91SAM9260 / AT91SAM9XE Board Type"
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 8781aaeb576b..856c681ebbbc 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -22,6 +22,7 @@ comment "OMAP Board Type"
config MACH_OMAP_INNOVATOR
bool "TI Innovator"
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
+ select OMAP_MCBSP
help
TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
have such a board.
@@ -29,6 +30,7 @@ config MACH_OMAP_INNOVATOR
config MACH_OMAP_H2
bool "TI H2 Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select OMAP_MCBSP
help
TI OMAP 1610/1611B H2 board support. Say Y here if you have such
a board.
@@ -36,6 +38,7 @@ config MACH_OMAP_H2
config MACH_OMAP_H3
bool "TI H3 Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select GPIOEXPANDER_OMAP
help
TI OMAP 1710 H3 board support. Say Y here if you have such
a board.
@@ -43,7 +46,7 @@ config MACH_OMAP_H3
config MACH_OMAP_OSK
bool "TI OSK Support"
depends on ARCH_OMAP1 && ARCH_OMAP16XX
- select TPS65010
+ select OMAP_MCBSP
help
TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
if you have such a board.
@@ -84,7 +87,7 @@ config MACH_OMAP_PALMTE
Support for the Palm Tungsten E PDA. Currently only the LCD panel
is supported. To boot the kernel, you'll need a PalmOS compatible
bootloader; check out http://palmtelinux.sourceforge.net for more
- informations.
+ information.
Say Y here if you have such a PDA, say NO otherwise.
config MACH_NOKIA770
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 7165f74f78da..a8b9a00cea22 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -37,4 +37,3 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o
obj-$(CONFIG_LEDS) += $(led-y)
-
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 62e42c7a628e..f65baa95986e 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -246,7 +246,7 @@ static void __init fsample_init_smc91x(void)
mdelay(50);
}
-void omap_fsample_init_irq(void)
+static void __init omap_fsample_init_irq(void)
{
omap1_init_common_hw();
omap_init_irq();
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 9d2346fb68f4..7b260b7c537b 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -455,7 +455,7 @@ static void __init h3_init_smc91x(void)
}
}
-void h3_init_irq(void)
+static void __init h3_init_irq(void)
{
omap1_init_common_hw();
omap_init_irq();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index cb00530ad279..7e63a41e37c6 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -308,7 +308,7 @@ static void __init innovator_init_smc91x(void)
}
}
-void innovator_init_irq(void)
+static void __init innovator_init_irq(void)
{
omap1_init_common_hw();
omap_init_irq();
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index fa4be962df67..1d5c8d509722 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -246,7 +246,7 @@ static void __init perseus2_init_smc91x(void)
mdelay(50);
}
-void omap_perseus2_init_irq(void)
+static void __init omap_perseus2_init_irq(void)
{
omap1_init_common_hw();
omap_init_irq();
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 6dcd10ab4496..da8a3ac47e13 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -24,35 +24,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
-
-static u64 irda_dmamask = 0xffffffff;
-
-static struct platform_device omap1610ir_device = {
- .name = "omap1610-ir",
- .id = -1,
- .dev = {
- .dma_mask = &irda_dmamask,
- },
-};
-
-static void omap_init_irda(void)
-{
- /* FIXME define and use a boot tag, members something like:
- * u8 uart; // uart1, or uart3
- * ... but driver only handles uart3 for now
- * s16 fir_sel; // gpio for SIR vs FIR
- * ... may prefer a callback for SIR/MIR/FIR mode select;
- * while h2 uses a GPIO, H3 uses a gpio expander
- */
- if (machine_is_omap_h2()
- || machine_is_omap_h3())
- (void) platform_device_register(&omap1610ir_device);
-}
-#else
-static inline void omap_init_irda(void) {}
-#endif
-
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -90,6 +61,45 @@ static void omap_init_rtc(void)
static inline void omap_init_rtc(void) {}
#endif
+#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+
+#if defined(CONFIG_ARCH_OMAP15XX)
+# define OMAP1_MBOX_SIZE 0x23
+# define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1
+#elif defined(CONFIG_ARCH_OMAP16XX)
+# define OMAP1_MBOX_SIZE 0x2f
+# define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1
+#endif
+
+#define OMAP1_MBOX_BASE IO_ADDRESS(OMAP16XX_MAILBOX_BASE)
+
+static struct resource mbox_resources[] = {
+ {
+ .start = OMAP1_MBOX_BASE,
+ .end = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_DSP_MAILBOX1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mbox_device = {
+ .name = "mailbox",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mbox_resources),
+ .resource = mbox_resources,
+};
+
+static inline void omap_init_mbox(void)
+{
+ platform_device_register(&mbox_device);
+}
+#else
+static inline void omap_init_mbox(void) { }
+#endif
+
#if defined(CONFIG_OMAP_STI)
#define OMAP1_STI_BASE IO_ADDRESS(0xfffea000)
@@ -154,7 +164,8 @@ static int __init omap1_init_devices(void)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
- omap_init_irda();
+
+ omap_init_mbox();
omap_init_rtc();
omap_init_sti();
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index fab8b0b27cfb..81c4e738506c 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -17,11 +17,11 @@
#include <asm/io.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
-#include <asm/arch/omapfb.h>
extern int omap1_clk_init(void);
extern void omap_check_revision(void);
extern void omap_sram_init(void);
+extern void omapfb_reserve_sdram(void);
/*
* The machine specific code may provide the extra mapping besides the
@@ -121,7 +121,7 @@ void __init omap1_map_common_io(void)
#endif
omap_sram_init();
- omapfb_reserve_mem();
+ omapfb_reserve_sdram();
}
/*
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
new file mode 100644
index 000000000000..d3abf5609902
--- /dev/null
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -0,0 +1,206 @@
+/*
+ * Mailbox reservation modules for DSP
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/resource.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/irqs.h>
+#include <asm/io.h>
+
+#define MAILBOX_ARM2DSP1 0x00
+#define MAILBOX_ARM2DSP1b 0x04
+#define MAILBOX_DSP2ARM1 0x08
+#define MAILBOX_DSP2ARM1b 0x0c
+#define MAILBOX_DSP2ARM2 0x10
+#define MAILBOX_DSP2ARM2b 0x14
+#define MAILBOX_ARM2DSP1_Flag 0x18
+#define MAILBOX_DSP2ARM1_Flag 0x1c
+#define MAILBOX_DSP2ARM2_Flag 0x20
+
+unsigned long mbox_base;
+
+struct omap_mbox1_fifo {
+ unsigned long cmd;
+ unsigned long data;
+ unsigned long flag;
+};
+
+struct omap_mbox1_priv {
+ struct omap_mbox1_fifo tx_fifo;
+ struct omap_mbox1_fifo rx_fifo;
+};
+
+static inline int mbox_read_reg(unsigned int reg)
+{
+ return __raw_readw(mbox_base + reg);
+}
+
+static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+{
+ __raw_writew(val, mbox_base + reg);
+}
+
+/* msg */
+static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+ mbox_msg_t msg;
+
+ msg = mbox_read_reg(fifo->data);
+ msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
+
+ return msg;
+}
+
+static inline void
+omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
+
+ mbox_write_reg(msg & 0xffff, fifo->data);
+ mbox_write_reg(msg >> 16, fifo->cmd);
+}
+
+static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
+{
+ return 0;
+}
+
+static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+
+ return (mbox_read_reg(fifo->flag));
+}
+
+/* irq */
+static inline void
+omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_RX)
+ enable_irq(mbox->irq);
+}
+
+static inline void
+omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_RX)
+ disable_irq(mbox->irq);
+}
+
+static inline int
+omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_TX)
+ return 0;
+ return 1;
+}
+
+static struct omap_mbox_ops omap1_mbox_ops = {
+ .type = OMAP_MBOX_TYPE1,
+ .fifo_read = omap1_mbox_fifo_read,
+ .fifo_write = omap1_mbox_fifo_write,
+ .fifo_empty = omap1_mbox_fifo_empty,
+ .fifo_full = omap1_mbox_fifo_full,
+ .enable_irq = omap1_mbox_enable_irq,
+ .disable_irq = omap1_mbox_disable_irq,
+ .is_irq = omap1_mbox_is_irq,
+};
+
+/* FIXME: the following struct should be created automatically by the user id */
+
+/* DSP */
+static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
+ .tx_fifo = {
+ .cmd = MAILBOX_ARM2DSP1b,
+ .data = MAILBOX_ARM2DSP1,
+ .flag = MAILBOX_ARM2DSP1_Flag,
+ },
+ .rx_fifo = {
+ .cmd = MAILBOX_DSP2ARM1b,
+ .data = MAILBOX_DSP2ARM1,
+ .flag = MAILBOX_DSP2ARM1_Flag,
+ },
+};
+
+struct omap_mbox mbox_dsp_info = {
+ .name = "dsp",
+ .ops = &omap1_mbox_ops,
+ .priv = &omap1_mbox_dsp_priv,
+};
+EXPORT_SYMBOL(mbox_dsp_info);
+
+static int __init omap1_mbox_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret = 0;
+
+ if (pdev->num_resources != 2) {
+ dev_err(&pdev->dev, "invalid number of resources: %d\n",
+ pdev->num_resources);
+ return -ENODEV;
+ }
+
+ /* MBOX base */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "invalid mem resource\n");
+ return -ENODEV;
+ }
+ mbox_base = res->start;
+
+ /* DSP IRQ */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "invalid irq resource\n");
+ return -ENODEV;
+ }
+ mbox_dsp_info.irq = res->start;
+
+ ret = omap_mbox_register(&mbox_dsp_info);
+
+ return ret;
+}
+
+static int omap1_mbox_remove(struct platform_device *pdev)
+{
+ omap_mbox_unregister(&mbox_dsp_info);
+
+ return 0;
+}
+
+static struct platform_driver omap1_mbox_driver = {
+ .probe = omap1_mbox_probe,
+ .remove = omap1_mbox_remove,
+ .driver = {
+ .name = "mailbox",
+ },
+};
+
+static int __init omap1_mbox_init(void)
+{
+ return platform_driver_register(&omap1_mbox_driver);
+}
+
+static void __exit omap1_mbox_exit(void)
+{
+ platform_driver_unregister(&omap1_mbox_driver);
+}
+
+module_init(omap1_mbox_init);
+module_exit(omap1_mbox_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index aab97ccf1e63..7393109f5c30 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -9,6 +9,7 @@ config ARCH_OMAP2420
bool "OMAP2420 support"
depends on ARCH_OMAP24XX
select OMAP_DM_TIMER
+ select ARCH_OMAP_OTG
comment "OMAP Board Type"
depends on ARCH_OMAP2
@@ -20,6 +21,7 @@ config MACH_OMAP_GENERIC
config MACH_OMAP_H4
bool "OMAP 2420 H4 board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
+ select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG
config MACH_OMAP_APOLLON
bool "OMAP 2420 Apollon board"
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 1e7ed6d22ca9..452193f01531 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -266,12 +266,26 @@ static struct platform_device h4_lcd_device = {
.id = -1,
};
+static struct resource h4_led_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device h4_led_device = {
+ .name = "omap_dbg_led",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(h4_led_resources),
+ .resource = h4_led_resources,
+};
+
static struct platform_device *h4_devices[] __initdata = {
&h4_smc91x_device,
&h4_flash_device,
&h4_irda_device,
&h4_kp_device,
&h4_lcd_device,
+ &h4_led_device,
};
static inline void __init h4_init_smc91x(void)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index aa4322451e8b..52ec2f2d6360 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -24,7 +24,7 @@
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
-#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
#define OMAP2_I2C_BASE2 0x48072000
#define OMAP2_I2C_INT2 57
@@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = {
};
static struct platform_device omap_i2c_device2 = {
- .name = "i2c_omap",
- .id = 2,
+ .name = "i2c_omap",
+ .id = 2,
.num_resources = ARRAY_SIZE(i2c_resources2),
.resource = i2c_resources2,
};
@@ -66,6 +66,40 @@ static void omap_init_i2c(void) {}
#endif
+#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
+
+static struct resource mbox_resources[] = {
+ {
+ .start = OMAP2_MBOX_BASE,
+ .end = OMAP2_MBOX_BASE + 0x11f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_24XX_MAIL_U0_MPU,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = INT_24XX_MAIL_U3_MPU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mbox_device = {
+ .name = "mailbox",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mbox_resources),
+ .resource = mbox_resources,
+};
+
+static inline void omap_init_mbox(void)
+{
+ platform_device_register(&mbox_device);
+}
+#else
+static inline void omap_init_mbox(void) { }
+#endif
+
#if defined(CONFIG_OMAP_STI)
#define OMAP2_STI_BASE IO_ADDRESS(0x48068000)
@@ -111,29 +145,45 @@ static inline void omap_init_sti(void) {}
#define OMAP2_MCSPI1_BASE 0x48098000
#define OMAP2_MCSPI2_BASE 0x4809a000
-/* FIXME: use resources instead */
-
static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
- .base = io_p2v(OMAP2_MCSPI1_BASE),
.num_cs = 4,
};
+static struct resource omap2_mcspi1_resources[] = {
+ {
+ .start = OMAP2_MCSPI1_BASE,
+ .end = OMAP2_MCSPI1_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
struct platform_device omap2_mcspi1 = {
.name = "omap2_mcspi",
.id = 1,
+ .num_resources = ARRAY_SIZE(omap2_mcspi1_resources),
+ .resource = omap2_mcspi1_resources,
.dev = {
.platform_data = &omap2_mcspi1_config,
},
};
static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
- .base = io_p2v(OMAP2_MCSPI2_BASE),
.num_cs = 2,
};
+static struct resource omap2_mcspi2_resources[] = {
+ {
+ .start = OMAP2_MCSPI2_BASE,
+ .end = OMAP2_MCSPI2_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
struct platform_device omap2_mcspi2 = {
.name = "omap2_mcspi",
.id = 2,
+ .num_resources = ARRAY_SIZE(omap2_mcspi2_resources),
+ .resource = omap2_mcspi2_resources,
.dev = {
.platform_data = &omap2_mcspi2_config,
},
@@ -157,10 +207,10 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_i2c();
+ omap_init_mbox();
omap_init_mcspi();
omap_init_sti();
return 0;
}
arch_initcall(omap2_init_devices);
-
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index d8f57824423f..54c836a98456 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -246,14 +246,22 @@ static int gpmc_cs_mem_enabled(int cs)
return l & (1 << 6);
}
-static void gpmc_cs_set_reserved(int cs, int reserved)
+int gpmc_cs_set_reserved(int cs, int reserved)
{
+ if (cs > GPMC_CS_NUM)
+ return -ENODEV;
+
gpmc_cs_map &= ~(1 << cs);
gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+
+ return 0;
}
-static int gpmc_cs_reserved(int cs)
+int gpmc_cs_reserved(int cs)
{
+ if (cs > GPMC_CS_NUM)
+ return -ENODEV;
+
return gpmc_cs_map & (1 << cs);
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index a0728c33e5d9..82dc70f6b779 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -27,6 +27,7 @@ extern void omap_sram_init(void);
extern int omap2_clk_init(void);
extern void omap2_check_revision(void);
extern void gpmc_init(void);
+extern void omapfb_reserve_sdram(void);
/*
* The machine specific code may provide the extra mapping besides the
@@ -40,9 +41,21 @@ static struct map_desc omap2_io_desc[] __initdata = {
.type = MT_DEVICE
},
{
- .virtual = L4_24XX_VIRT,
- .pfn = __phys_to_pfn(L4_24XX_PHYS),
- .length = L4_24XX_SIZE,
+ .virtual = DSP_MEM_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS),
+ .length = DSP_MEM_24XX_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = DSP_IPI_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS),
+ .length = DSP_IPI_24XX_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = DSP_MMU_24XX_VIRT,
+ .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS),
+ .length = DSP_MMU_24XX_SIZE,
.type = MT_DEVICE
}
};
@@ -60,7 +73,7 @@ void __init omap2_map_common_io(void)
omap2_check_revision();
omap_sram_init();
- omapfb_reserve_mem();
+ omapfb_reserve_sdram();
}
void __init omap2_init_common_hw(void)
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
new file mode 100644
index 000000000000..b03cd06e055b
--- /dev/null
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -0,0 +1,318 @@
+/*
+ * Mailbox reservation modules for OMAP2
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ * and Paul Mundt <paul.mundt@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <asm/arch/mailbox.h>
+#include <asm/arch/irqs.h>
+#include <asm/io.h>
+
+#define MAILBOX_REVISION 0x00
+#define MAILBOX_SYSCONFIG 0x10
+#define MAILBOX_SYSSTATUS 0x14
+#define MAILBOX_MESSAGE_0 0x40
+#define MAILBOX_MESSAGE_1 0x44
+#define MAILBOX_MESSAGE_2 0x48
+#define MAILBOX_MESSAGE_3 0x4c
+#define MAILBOX_MESSAGE_4 0x50
+#define MAILBOX_MESSAGE_5 0x54
+#define MAILBOX_FIFOSTATUS_0 0x80
+#define MAILBOX_FIFOSTATUS_1 0x84
+#define MAILBOX_FIFOSTATUS_2 0x88
+#define MAILBOX_FIFOSTATUS_3 0x8c
+#define MAILBOX_FIFOSTATUS_4 0x90
+#define MAILBOX_FIFOSTATUS_5 0x94
+#define MAILBOX_MSGSTATUS_0 0xc0
+#define MAILBOX_MSGSTATUS_1 0xc4
+#define MAILBOX_MSGSTATUS_2 0xc8
+#define MAILBOX_MSGSTATUS_3 0xcc
+#define MAILBOX_MSGSTATUS_4 0xd0
+#define MAILBOX_MSGSTATUS_5 0xd4
+#define MAILBOX_IRQSTATUS_0 0x100
+#define MAILBOX_IRQENABLE_0 0x104
+#define MAILBOX_IRQSTATUS_1 0x108
+#define MAILBOX_IRQENABLE_1 0x10c
+#define MAILBOX_IRQSTATUS_2 0x110
+#define MAILBOX_IRQENABLE_2 0x114
+#define MAILBOX_IRQSTATUS_3 0x118
+#define MAILBOX_IRQENABLE_3 0x11c
+
+static unsigned long mbox_base;
+
+#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1))
+#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n)))
+
+struct omap_mbox2_fifo {
+ unsigned long msg;
+ unsigned long fifo_stat;
+ unsigned long msg_stat;
+};
+
+struct omap_mbox2_priv {
+ struct omap_mbox2_fifo tx_fifo;
+ struct omap_mbox2_fifo rx_fifo;
+ unsigned long irqenable;
+ unsigned long irqstatus;
+ u32 newmsg_bit;
+ u32 notfull_bit;
+};
+
+static struct clk *mbox_ick_handle;
+
+static inline unsigned int mbox_read_reg(unsigned int reg)
+{
+ return __raw_readl(mbox_base + reg);
+}
+
+static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+{
+ __raw_writel(val, mbox_base + reg);
+}
+
+/* Mailbox H/W preparations */
+static inline int omap2_mbox_startup(struct omap_mbox *mbox)
+{
+ unsigned int l;
+
+ mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
+ if (IS_ERR(mbox_ick_handle)) {
+ printk("Could not get mailboxes_ick\n");
+ return -ENODEV;
+ }
+ clk_enable(mbox_ick_handle);
+
+ /* set smart-idle & autoidle */
+ l = mbox_read_reg(MAILBOX_SYSCONFIG);
+ l |= 0x00000011;
+ mbox_write_reg(l, MAILBOX_SYSCONFIG);
+
+ return 0;
+}
+
+static inline void omap2_mbox_shutdown(struct omap_mbox *mbox)
+{
+ clk_disable(mbox_ick_handle);
+ clk_put(mbox_ick_handle);
+}
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
+{
+ struct omap_mbox2_fifo *fifo =
+ &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+ return (mbox_msg_t) mbox_read_reg(fifo->msg);
+}
+
+static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ struct omap_mbox2_fifo *fifo =
+ &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+ mbox_write_reg(msg, fifo->msg);
+}
+
+static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
+{
+ struct omap_mbox2_fifo *fifo =
+ &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+ return (mbox_read_reg(fifo->msg_stat) == 0);
+}
+
+static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox)
+{
+ struct omap_mbox2_fifo *fifo =
+ &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+ return (mbox_read_reg(fifo->fifo_stat));
+}
+
+/* Mailbox IRQ handle functions */
+static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
+{
+ struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+ u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+ l = mbox_read_reg(p->irqenable);
+ l |= bit;
+ mbox_write_reg(l, p->irqenable);
+}
+
+static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
+{
+ struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+ u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+ l = mbox_read_reg(p->irqenable);
+ l &= ~bit;
+ mbox_write_reg(l, p->irqenable);
+}
+
+static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
+{
+ struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+ mbox_write_reg(bit, p->irqstatus);
+}
+
+static inline int omap2_mbox_is_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
+{
+ struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+ u32 enable = mbox_read_reg(p->irqenable);
+ u32 status = mbox_read_reg(p->irqstatus);
+
+ return (enable & status & bit);
+}
+
+static struct omap_mbox_ops omap2_mbox_ops = {
+ .type = OMAP_MBOX_TYPE2,
+ .startup = omap2_mbox_startup,
+ .shutdown = omap2_mbox_shutdown,
+ .fifo_read = omap2_mbox_fifo_read,
+ .fifo_write = omap2_mbox_fifo_write,
+ .fifo_empty = omap2_mbox_fifo_empty,
+ .fifo_full = omap2_mbox_fifo_full,
+ .enable_irq = omap2_mbox_enable_irq,
+ .disable_irq = omap2_mbox_disable_irq,
+ .ack_irq = omap2_mbox_ack_irq,
+ .is_irq = omap2_mbox_is_irq,
+};
+
+/*
+ * MAILBOX 0: ARM -> DSP,
+ * MAILBOX 1: ARM <- DSP.
+ * MAILBOX 2: ARM -> IVA,
+ * MAILBOX 3: ARM <- IVA.
+ */
+
+/* FIXME: the following structs should be filled automatically by the user id */
+
+/* DSP */
+static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE_0,
+ .fifo_stat = MAILBOX_FIFOSTATUS_0,
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE_1,
+ .msg_stat = MAILBOX_MSGSTATUS_1,
+ },
+ .irqenable = MAILBOX_IRQENABLE_0,
+ .irqstatus = MAILBOX_IRQSTATUS_0,
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
+};
+
+struct omap_mbox mbox_dsp_info = {
+ .name = "dsp",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_dsp_priv,
+};
+EXPORT_SYMBOL(mbox_dsp_info);
+
+/* IVA */
+static struct omap_mbox2_priv omap2_mbox_iva_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE_2,
+ .fifo_stat = MAILBOX_FIFOSTATUS_2,
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE_3,
+ .msg_stat = MAILBOX_MSGSTATUS_3,
+ },
+ .irqenable = MAILBOX_IRQENABLE_3,
+ .irqstatus = MAILBOX_IRQSTATUS_3,
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(2),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(3),
+};
+
+static struct omap_mbox mbox_iva_info = {
+ .name = "iva",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_iva_priv,
+};
+
+static int __init omap2_mbox_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret = 0;
+
+ if (pdev->num_resources != 3) {
+ dev_err(&pdev->dev, "invalid number of resources: %d\n",
+ pdev->num_resources);
+ return -ENODEV;
+ }
+
+ /* MBOX base */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "invalid mem resource\n");
+ return -ENODEV;
+ }
+ mbox_base = res->start;
+
+ /* DSP IRQ */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "invalid irq resource\n");
+ return -ENODEV;
+ }
+ mbox_dsp_info.irq = res->start;
+
+ ret = omap_mbox_register(&mbox_dsp_info);
+
+ /* IVA IRQ */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ if (unlikely(!res)) {
+ dev_err(&pdev->dev, "invalid irq resource\n");
+ return -ENODEV;
+ }
+ mbox_iva_info.irq = res->start;
+
+ ret = omap_mbox_register(&mbox_iva_info);
+
+ return ret;
+}
+
+static int omap2_mbox_remove(struct platform_device *pdev)
+{
+ omap_mbox_unregister(&mbox_dsp_info);
+ return 0;
+}
+
+static struct platform_driver omap2_mbox_driver = {
+ .probe = omap2_mbox_probe,
+ .remove = omap2_mbox_remove,
+ .driver = {
+ .name = "mailbox",
+ },
+};
+
+static int __init omap2_mbox_init(void)
+{
+ return platform_driver_register(&omap2_mbox_driver);
+}
+
+static void __exit omap2_mbox_exit(void)
+{
+ platform_driver_unregister(&omap2_mbox_driver);
+}
+
+module_init(omap2_mbox_init);
+module_exit(omap2_mbox_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 637aaba65390..d1eeed2ad47c 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
+/* linux/arch/arm/mach-s3c2410/sleep.S
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index e684e9b38216..b81391a4e374 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -366,6 +366,19 @@ config CPU_32v6K
enabled will not boot on processors with do not support these
instructions.
+# ARMv7
+config CPU_V7
+ bool "Support ARM V7 processor"
+ depends on ARCH_INTEGRATOR
+ select CPU_32v6K
+ select CPU_32v7
+ select CPU_ABRT_EV7
+ select CPU_CACHE_V7
+ select CPU_CACHE_VIPT
+ select CPU_CP15_MMU
+ select CPU_COPY_V6 if MMU
+ select CPU_TLB_V6 if MMU
+
# Figure out what processor architecture version we should be using.
# This defines the compiler instruction set which depends on the machine type.
config CPU_32v3
@@ -391,6 +404,9 @@ config CPU_32v5
config CPU_32v6
bool
+config CPU_32v7
+ bool
+
# The abort model
config CPU_ABRT_NOMMU
bool
@@ -413,6 +429,9 @@ config CPU_ABRT_EV5TJ
config CPU_ABRT_EV6
bool
+config CPU_ABRT_EV7
+ bool
+
# The cache model
config CPU_CACHE_V3
bool
@@ -429,6 +448,9 @@ config CPU_CACHE_V4WB
config CPU_CACHE_V6
bool
+config CPU_CACHE_V7
+ bool
+
config CPU_CACHE_VIVT
bool
@@ -503,7 +525,7 @@ comment "Processor Features"
config ARM_THUMB
bool "Support Thumb user binaries"
- depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6
+ depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7
default y
help
Say Y if you want to include kernel support for running user space
@@ -578,9 +600,15 @@ config CPU_CACHE_ROUND_ROBIN
Say Y here to use the predictable round-robin cache replacement
policy. Unless you specifically require this or are unsure, say N.
+config CPU_L2CACHE_DISABLE
+ bool "Disable level 2 cache"
+ depends on CPU_V7
+ help
+ Say Y here to disable the level 2 cache. If unsure, say N.
+
config CPU_BPREDICT_DISABLE
bool "Disable branch prediction"
- depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3
+ depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7
help
Say Y here to disable branch prediction. If unsure, say N.
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 2f8b95947774..b5bd335ff14a 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -24,12 +24,14 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o
obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o
obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o
obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o
+obj-$(CONFIG_CPU_ABRT_EV7) += abort-ev7.o
obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o
obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o
obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o
obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o
obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o
+obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o
obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o
obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o
@@ -66,5 +68,6 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
obj-$(CONFIG_CPU_V6) += proc-v6.o
+obj-$(CONFIG_CPU_V7) += proc-v7.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
new file mode 100644
index 000000000000..eb90bce38e14
--- /dev/null
+++ b/arch/arm/mm/abort-ev7.S
@@ -0,0 +1,32 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: v7_early_abort
+ *
+ * Params : r2 = address of aborted instruction
+ * : r3 = saved SPSR
+ *
+ * Returns : r0 = address of abort
+ * : r1 = FSR, bit 11 = write
+ * : r2-r8 = corrupted
+ * : r9 = preserved
+ * : sp = pointer to registers
+ *
+ * Purpose : obtain information about current aborted instruction.
+ */
+ .align 5
+ENTRY(v7_early_abort)
+ /*
+ * The effect of data aborts on on the exclusive access monitor are
+ * UNPREDICTABLE. Do a CLREX to clear the state
+ */
+ clrex
+
+ mrc p15, 0, r1, c5, c0, 0 @ get FSR
+ mrc p15, 0, r0, c6, c0, 0 @ get FAR
+
+ /*
+ * V6 code adjusts the returned DFSR.
+ * New designs should not need to patch up faults.
+ */
+ mov pc, lr
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
new file mode 100644
index 000000000000..35ffc4d95997
--- /dev/null
+++ b/arch/arm/mm/cache-v7.S
@@ -0,0 +1,253 @@
+/*
+ * linux/arch/arm/mm/cache-v7.S
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2005 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is the "shell" of the ARMv7 processor support.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+#include "proc-macros.S"
+
+/*
+ * v7_flush_dcache_all()
+ *
+ * Flush the whole D-cache.
+ *
+ * Corrupted registers: r0-r5, r7, r9-r11
+ *
+ * - mm - mm_struct describing address space
+ */
+ENTRY(v7_flush_dcache_all)
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished @ if loc is 0, then no need to clean
+ mov r10, #0 @ start clean at cache level 0
+loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
+ and r1, r1, #7 @ mask of the bits for current cache only
+ cmp r1, #2 @ see what cache we have at this level
+ blt skip @ skip if no cache, or just i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ isb @ isb to sych the new cssr&csidr
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
+ clz r5, r4 @ find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
+loop2:
+ mov r9, r4 @ create working copy of max way size
+loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge loop3
+ subs r7, r7, #1 @ decrement the index
+ bge loop2
+skip:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt loop1
+finished:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ isb
+ mov pc, lr
+
+/*
+ * v7_flush_cache_all()
+ *
+ * Flush the entire cache system.
+ * The data cache flush is now achieved using atomic clean / invalidates
+ * working outwards from L1 cache. This is done using Set/Way based cache
+ * maintainance instructions.
+ * The instruction cache can still be invalidated back to the point of
+ * unification in a single instruction.
+ *
+ */
+ENTRY(v7_flush_kern_cache_all)
+ stmfd sp!, {r4-r5, r7, r9-r11, lr}
+ bl v7_flush_dcache_all
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+ ldmfd sp!, {r4-r5, r7, r9-r11, lr}
+ mov pc, lr
+
+/*
+ * v7_flush_cache_all()
+ *
+ * Flush all TLB entries in a particular address space
+ *
+ * - mm - mm_struct describing address space
+ */
+ENTRY(v7_flush_user_cache_all)
+ /*FALLTHROUGH*/
+
+/*
+ * v7_flush_cache_range(start, end, flags)
+ *
+ * Flush a range of TLB entries in the specified address space.
+ *
+ * - start - start address (may not be aligned)
+ * - end - end address (exclusive, may not be aligned)
+ * - flags - vm_area_struct flags describing address space
+ *
+ * It is assumed that:
+ * - we have a VIPT cache.
+ */
+ENTRY(v7_flush_user_cache_range)
+ mov pc, lr
+
+/*
+ * v7_coherent_kern_range(start,end)
+ *
+ * Ensure that the I and D caches are coherent within specified
+ * region. This is typically used when code has been written to
+ * a memory region, and will be executed.
+ *
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ *
+ * It is assumed that:
+ * - the Icache does not read data from the write buffer
+ */
+ENTRY(v7_coherent_kern_range)
+ /* FALLTHROUGH */
+
+/*
+ * v7_coherent_user_range(start,end)
+ *
+ * Ensure that the I and D caches are coherent within specified
+ * region. This is typically used when code has been written to
+ * a memory region, and will be executed.
+ *
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ *
+ * It is assumed that:
+ * - the Icache does not read data from the write buffer
+ */
+ENTRY(v7_coherent_user_range)
+ dcache_line_size r2, r3
+ sub r3, r2, #1
+ bic r0, r0, r3
+1: mcr p15, 0, r0, c7, c11, 1 @ clean D line to the point of unification
+ dsb
+ mcr p15, 0, r0, c7, c5, 1 @ invalidate I line
+ add r0, r0, r2
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
+ dsb
+ isb
+ mov pc, lr
+
+/*
+ * v7_flush_kern_dcache_page(kaddr)
+ *
+ * Ensure that the data held in the page kaddr is written back
+ * to the page in question.
+ *
+ * - kaddr - kernel address (guaranteed to be page aligned)
+ */
+ENTRY(v7_flush_kern_dcache_page)
+ dcache_line_size r2, r3
+ add r1, r0, #PAGE_SZ
+1:
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line
+ add r0, r0, r2
+ cmp r0, r1
+ blo 1b
+ dsb
+ mov pc, lr
+
+/*
+ * v7_dma_inv_range(start,end)
+ *
+ * Invalidate the data cache within the specified region; we will
+ * be performing a DMA operation in this region and we want to
+ * purge old data in the cache.
+ *
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ */
+ENTRY(v7_dma_inv_range)
+ dcache_line_size r2, r3
+ sub r3, r2, #1
+ tst r0, r3
+ bic r0, r0, r3
+ mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
+
+ tst r1, r3
+ bic r1, r1, r3
+ mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line
+1:
+ mcr p15, 0, r0, c7, c6, 1 @ invalidate D / U line
+ add r0, r0, r2
+ cmp r0, r1
+ blo 1b
+ dsb
+ mov pc, lr
+
+/*
+ * v7_dma_clean_range(start,end)
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ */
+ENTRY(v7_dma_clean_range)
+ dcache_line_size r2, r3
+ sub r3, r2, #1
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
+ add r0, r0, r2
+ cmp r0, r1
+ blo 1b
+ dsb
+ mov pc, lr
+
+/*
+ * v7_dma_flush_range(start,end)
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ */
+ENTRY(v7_dma_flush_range)
+ dcache_line_size r2, r3
+ sub r3, r2, #1
+ bic r0, r0, r3
+1:
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
+ add r0, r0, r2
+ cmp r0, r1
+ blo 1b
+ dsb
+ mov pc, lr
+
+ __INITDATA
+
+ .type v7_cache_fns, #object
+ENTRY(v7_cache_fns)
+ .long v7_flush_kern_cache_all
+ .long v7_flush_user_cache_all
+ .long v7_flush_user_cache_range
+ .long v7_coherent_kern_range
+ .long v7_coherent_user_range
+ .long v7_flush_kern_dcache_page
+ .long v7_dma_inv_range
+ .long v7_dma_clean_range
+ .long v7_dma_flush_range
+ .size v7_cache_fns, . - v7_cache_fns
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 9da43a0fdcdf..fc84fcc74380 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -14,7 +14,8 @@
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
-unsigned int cpu_last_asid = { 1 << ASID_BITS };
+static DEFINE_SPINLOCK(cpu_asid_lock);
+unsigned int cpu_last_asid = ASID_FIRST_VERSION;
/*
* We fork()ed a process, and we need a new context for the child
@@ -31,15 +32,16 @@ void __new_context(struct mm_struct *mm)
{
unsigned int asid;
+ spin_lock(&cpu_asid_lock);
asid = ++cpu_last_asid;
if (asid == 0)
- asid = cpu_last_asid = 1 << ASID_BITS;
+ asid = cpu_last_asid = ASID_FIRST_VERSION;
/*
* If we've used up all our ASIDs, we need
* to start a new version and flush the TLB.
*/
- if ((asid & ~ASID_MASK) == 0) {
+ if (unlikely((asid & ~ASID_MASK) == 0)) {
asid = ++cpu_last_asid;
/* set the reserved ASID before flushing the TLB */
asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n"
@@ -47,7 +49,16 @@ void __new_context(struct mm_struct *mm)
: "r" (0));
isb();
flush_tlb_all();
+ if (icache_is_vivt_asid_tagged()) {
+ asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
+ "mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB\n"
+ :
+ : "r" (0));
+ dsb();
+ }
}
+ spin_unlock(&cpu_asid_lock);
+ mm->cpu_vm_mask = cpumask_of_cpu(smp_processor_id());
mm->context.id = asid;
}
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index 9e2c89eb2115..b13150052a76 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -59,3 +59,15 @@
.word \ucset
#endif
.endm
+
+/*
+ * cache_line_size - get the cache line size from the CSIDR register
+ * (available on ARMv7+). It assumes that the CSSR register was configured
+ * to access the L1 data cache CSIDR.
+ */
+ .macro dcache_line_size, reg, tmp
+ mrc p15, 1, \tmp, c0, c0, 0 @ read CSIDR
+ and \tmp, \tmp, #7 @ cache line size encoding
+ mov \reg, #16 @ size offset
+ mov \reg, \reg, lsl \tmp @ actual cache line size
+ .endm
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
new file mode 100644
index 000000000000..dd823dd4a374
--- /dev/null
+++ b/arch/arm/mm/proc-v7.S
@@ -0,0 +1,262 @@
+/*
+ * linux/arch/arm/mm/proc-v7.S
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is the "shell" of the ARMv7 processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/elf.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+#define TTB_C (1 << 0)
+#define TTB_S (1 << 1)
+#define TTB_RGN_OC_WT (2 << 3)
+#define TTB_RGN_OC_WB (3 << 3)
+
+ENTRY(cpu_v7_proc_init)
+ mov pc, lr
+
+ENTRY(cpu_v7_proc_fin)
+ mov pc, lr
+
+/*
+ * cpu_v7_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * - loc - location to jump to for soft reset
+ *
+ * It is assumed that:
+ */
+ .align 5
+ENTRY(cpu_v7_reset)
+ mov pc, r0
+
+/*
+ * cpu_v7_do_idle()
+ *
+ * Idle the processor (eg, wait for interrupt).
+ *
+ * IRQs are already disabled.
+ */
+ENTRY(cpu_v7_do_idle)
+ .long 0xe320f003 @ ARM V7 WFI instruction
+ mov pc, lr
+
+ENTRY(cpu_v7_dcache_clean_area)
+#ifndef TLB_CAN_READ_FROM_L1_CACHE
+ dcache_line_size r2, r3
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, r2
+ subs r1, r1, r2
+ bhi 1b
+ dsb
+#endif
+ mov pc, lr
+
+/*
+ * cpu_v7_switch_mm(pgd_phys, tsk)
+ *
+ * Set the translation table base pointer to be pgd_phys
+ *
+ * - pgd_phys - physical address of new TTB
+ *
+ * It is assumed that:
+ * - we are not using split page tables
+ */
+ENTRY(cpu_v7_switch_mm)
+ mov r2, #0
+ ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
+ orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB
+ mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
+ isb
+1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
+ isb
+ mcr p15, 0, r1, c13, c0, 1 @ set context ID
+ isb
+ mov pc, lr
+
+/*
+ * cpu_v7_set_pte_ext(ptep, pte)
+ *
+ * Set a level 2 translation table entry.
+ *
+ * - ptep - pointer to level 2 translation table entry
+ * (hardware version is stored at -1024 bytes)
+ * - pte - PTE value to store
+ * - ext - value for extended PTE bits
+ *
+ * Permissions:
+ * YUWD APX AP1 AP0 SVC User
+ * 0xxx 0 0 0 no acc no acc
+ * 100x 1 0 1 r/o no acc
+ * 10x0 1 0 1 r/o no acc
+ * 1011 0 0 1 r/w no acc
+ * 110x 0 1 0 r/w r/o
+ * 11x0 0 1 0 r/w r/o
+ * 1111 0 1 1 r/w r/w
+ */
+ENTRY(cpu_v7_set_pte_ext)
+ str r1, [r0], #-2048 @ linux version
+
+ bic r3, r1, #0x000003f0
+ bic r3, r3, #0x00000003
+ orr r3, r3, r2
+ orr r3, r3, #PTE_EXT_AP0 | 2
+
+ tst r1, #L_PTE_WRITE
+ tstne r1, #L_PTE_DIRTY
+ orreq r3, r3, #PTE_EXT_APX
+
+ tst r1, #L_PTE_USER
+ orrne r3, r3, #PTE_EXT_AP1
+ tstne r3, #PTE_EXT_APX
+ bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+
+ tst r1, #L_PTE_YOUNG
+ biceq r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK
+
+ tst r1, #L_PTE_EXEC
+ orreq r3, r3, #PTE_EXT_XN
+
+ tst r1, #L_PTE_PRESENT
+ moveq r3, #0
+
+ str r3, [r0]
+ mcr p15, 0, r0, c7, c10, 1 @ flush_pte
+ mov pc, lr
+
+cpu_v7_name:
+ .ascii "ARMv7 Processor"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
+/*
+ * __v7_setup
+ *
+ * Initialise TLB, Caches, and MMU state ready to switch the MMU
+ * on. Return in r0 the new CP15 C1 control register setting.
+ *
+ * We automatically detect if we have a Harvard cache, and use the
+ * Harvard cache control instructions insead of the unified cache
+ * control instructions.
+ *
+ * This should be able to cover all ARMv7 cores.
+ *
+ * It is assumed that:
+ * - cache type register is implemented
+ */
+__v7_setup:
+ adr r12, __v7_setup_stack @ the local stack
+ stmia r12, {r0-r5, r7, r9, r11, lr}
+ bl v7_flush_dcache_all
+ ldmia r12, {r0-r5, r7, r9, r11, lr}
+ mov r10, #0
+#ifdef HARVARD_CACHE
+ mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
+#endif
+ dsb
+ mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
+ mcr p15, 0, r10, c2, c0, 2 @ TTB control register
+ orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB
+ mcr p15, 0, r4, c2, c0, 0 @ load TTB0
+ mcr p15, 0, r4, c2, c0, 1 @ load TTB1
+ mov r10, #0x1f @ domains 0, 1 = manager
+ mcr p15, 0, r10, c3, c0, 0 @ load domain access register
+#ifndef CONFIG_CPU_L2CACHE_DISABLE
+ @ L2 cache configuration in the L2 aux control register
+ mrc p15, 1, r10, c9, c0, 2
+ bic r10, r10, #(1 << 16) @ L2 outer cache
+ mcr p15, 1, r10, c9, c0, 2
+ @ L2 cache is enabled in the aux control register
+ mrc p15, 0, r10, c1, c0, 1
+ orr r10, r10, #2
+ mcr p15, 0, r10, c1, c0, 1
+#endif
+ mrc p15, 0, r0, c1, c0, 0 @ read control register
+ ldr r10, cr1_clear @ get mask for bits to clear
+ bic r0, r0, r10 @ clear bits them
+ ldr r10, cr1_set @ get mask for bits to set
+ orr r0, r0, r10 @ set them
+ mov pc, lr @ return to head.S:__ret
+
+ /*
+ * V X F I D LR
+ * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
+ * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
+ * 0 110 0011 1.00 .111 1101 < we want
+ */
+ .type cr1_clear, #object
+ .type cr1_set, #object
+cr1_clear:
+ .word 0x0120c302
+cr1_set:
+ .word 0x00c0387d
+
+__v7_setup_stack:
+ .space 4 * 11 @ 11 registers
+
+ .type v7_processor_functions, #object
+ENTRY(v7_processor_functions)
+ .word v7_early_abort
+ .word cpu_v7_proc_init
+ .word cpu_v7_proc_fin
+ .word cpu_v7_reset
+ .word cpu_v7_do_idle
+ .word cpu_v7_dcache_clean_area
+ .word cpu_v7_switch_mm
+ .word cpu_v7_set_pte_ext
+ .size v7_processor_functions, . - v7_processor_functions
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv7"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v7"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info.init", #alloc, #execinstr
+
+ /*
+ * Match any ARMv7 processor core.
+ */
+ .type __v7_proc_info, #object
+__v7_proc_info:
+ .long 0x000f0000 @ Required ID value
+ .long 0x000f0000 @ Mask for ID
+ .long PMD_TYPE_SECT | \
+ PMD_SECT_BUFFERABLE | \
+ PMD_SECT_CACHEABLE | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+ .long PMD_TYPE_SECT | \
+ PMD_SECT_XN | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+ b __v7_setup
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_v7_name
+ .long v7_processor_functions
+ .long v6wbi_tlb_fns
+ .long v6_user_fns
+ .long v7_cache_fns
+ .size __v7_proc_info, . - __v7_proc_info
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 9e8d21eca4ec..cfc69f3842fd 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -20,6 +20,11 @@ endchoice
comment "OMAP Feature Selections"
+config OMAP_DEBUG_LEDS
+ bool
+ help
+ For debug card leds on TI reference boards.
+
config OMAP_RESET_CLOCKS
bool "Reset unused clocks during boot"
depends on ARCH_OMAP
@@ -58,6 +63,14 @@ config OMAP_MUX_WARNINGS
to change the pin multiplexing setup. When there are no warnings
printed, it's safe to deselect OMAP_MUX for your product.
+config OMAP_MCBSP
+ bool "McBSP support"
+ depends on ARCH_OMAP
+ default y
+ help
+ Say Y here if you want support for the OMAP Multichannel
+ Buffered Serial Port.
+
choice
prompt "System timer"
default OMAP_MPU_TIMER
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 2896b4546411..41a3c1cf3bd4 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,7 +3,8 @@
#
# Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \
+ usb.o fb.o
obj-m :=
obj-n :=
obj- :=
@@ -16,4 +17,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
-
+obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index f1179ad4be1b..0a603242f367 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -33,6 +33,41 @@ static DEFINE_SPINLOCK(clockfw_lock);
static struct clk_functions *arch_clock;
+#ifdef CONFIG_PM_DEBUG
+
+static void print_parents(struct clk *clk)
+{
+ struct clk *p;
+ int printed = 0;
+
+ list_for_each_entry(p, &clocks, node) {
+ if (p->parent == clk && p->usecount) {
+ if (!clk->usecount && !printed) {
+ printk("MISMATCH: %s\n", clk->name);
+ printed = 1;
+ }
+ printk("\t%-15s\n", p->name);
+ }
+ }
+}
+
+void clk_print_usecounts(void)
+{
+ unsigned long flags;
+ struct clk *p;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ list_for_each_entry(p, &clocks, node) {
+ if (p->usecount)
+ printk("%-15s: %d\n", p->name, p->usecount);
+ print_parents(p);
+
+ }
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+
+#endif
+
/*-------------------------------------------------------------------------
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
@@ -249,6 +284,8 @@ void followparent_recalc(struct clk *clk)
return;
clk->rate = clk->parent->rate;
+ if (unlikely(clk->flags & RATE_PROPAGATES))
+ propagate_rate(clk);
}
/* Propagate rate to children */
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index fecd3d625995..dd8708ad0a71 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -93,8 +93,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
* in the kernel. */
for (i = 0; i < omap_board_config_size; i++) {
if (omap_board_config[i].tag == tag) {
- kinfo = &omap_board_config[i];
- break;
+ if (skip == 0) {
+ kinfo = &omap_board_config[i];
+ break;
+ } else {
+ skip--;
+ }
}
}
if (kinfo == NULL)
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
new file mode 100644
index 000000000000..9128a80d228f
--- /dev/null
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -0,0 +1,314 @@
+/*
+ * linux/arch/arm/plat-omap/debug-leds.c
+ *
+ * Copyright 2003 by Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/fpga.h>
+#include <asm/arch/gpio.h>
+
+
+/* Many OMAP development platforms reuse the same "debug board"; these
+ * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the
+ * debug board (all green), accessed through FPGA registers.
+ *
+ * The "surfer" expansion board and H2 sample board also have two-color
+ * green+red LEDs (in parallel), used here for timer and idle indicators
+ * in preference to the ones on the debug board, for a "Disco LED" effect.
+ *
+ * This driver exports either the original ARM LED API, the new generic
+ * one, or both.
+ */
+
+static spinlock_t lock;
+static struct h2p2_dbg_fpga __iomem *fpga;
+static u16 led_state, hw_led_state;
+
+
+#ifdef CONFIG_LEDS_OMAP_DEBUG
+#define new_led_api() 1
+#else
+#define new_led_api() 0
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/* original ARM debug LED API:
+ * - timer and idle leds (some boards use non-FPGA leds here);
+ * - up to 4 generic leds, easily accessed in-kernel (any context)
+ */
+
+#define GPIO_LED_RED 3
+#define GPIO_LED_GREEN OMAP_MPUIO(4)
+
+#define LED_STATE_ENABLED 0x01
+#define LED_STATE_CLAIMED 0x02
+#define LED_TIMER_ON 0x04
+
+#define GPIO_IDLE GPIO_LED_GREEN
+#define GPIO_TIMER GPIO_LED_RED
+
+static void h2p2_dbg_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&lock, flags);
+
+ if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+ goto done;
+
+ switch (evt) {
+ case led_start:
+ if (fpga)
+ led_state |= LED_STATE_ENABLED;
+ break;
+
+ case led_stop:
+ case led_halted:
+ /* all leds off during suspend or shutdown */
+
+ if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) {
+ omap_set_gpio_dataout(GPIO_TIMER, 0);
+ omap_set_gpio_dataout(GPIO_IDLE, 0);
+ }
+
+ __raw_writew(~0, &fpga->leds);
+ led_state &= ~LED_STATE_ENABLED;
+ goto done;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ led_state ^= LED_TIMER_ON;
+
+ if (machine_is_omap_perseus2() || machine_is_omap_h4())
+ hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
+ else {
+ omap_set_gpio_dataout(GPIO_TIMER,
+ led_state & LED_TIMER_ON);
+ goto done;
+ }
+
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ /* LED lit iff busy */
+ case led_idle_start:
+ if (machine_is_omap_perseus2() || machine_is_omap_h4())
+ hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
+ else {
+ omap_set_gpio_dataout(GPIO_IDLE, 1);
+ goto done;
+ }
+
+ break;
+
+ case led_idle_end:
+ if (machine_is_omap_perseus2() || machine_is_omap_h4())
+ hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
+ else {
+ omap_set_gpio_dataout(GPIO_IDLE, 0);
+ goto done;
+ }
+
+ break;
+#endif
+
+ case led_green_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
+ break;
+ case led_green_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
+ break;
+
+ case led_amber_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
+ break;
+ case led_amber_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
+ break;
+
+ case led_red_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_RED;
+ break;
+ case led_red_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
+ break;
+
+ case led_blue_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
+ break;
+ case led_blue_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
+ break;
+
+ default:
+ break;
+ }
+
+
+ /*
+ * Actually burn the LEDs
+ */
+ if (led_state & LED_STATE_ENABLED)
+ __raw_writew(~hw_led_state, &fpga->leds);
+
+done:
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* "new" LED API
+ * - with syfs access and generic triggering
+ * - not readily accessible to in-kernel drivers
+ */
+
+struct dbg_led {
+ struct led_classdev cdev;
+ u16 mask;
+};
+
+static struct dbg_led dbg_leds[] = {
+ /* REVISIT at least H2 uses different timer & cpu leds... */
+#ifndef CONFIG_LEDS_TIMER
+ { .mask = 1 << 0, .cdev.name = "d4:green",
+ .cdev.default_trigger = "heartbeat", },
+#endif
+#ifndef CONFIG_LEDS_CPU
+ { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */
+#endif
+ { .mask = 1 << 2, .cdev.name = "d6:green", },
+ { .mask = 1 << 3, .cdev.name = "d7:green", },
+
+ { .mask = 1 << 4, .cdev.name = "d8:green", },
+ { .mask = 1 << 5, .cdev.name = "d9:green", },
+ { .mask = 1 << 6, .cdev.name = "d10:green", },
+ { .mask = 1 << 7, .cdev.name = "d11:green", },
+
+ { .mask = 1 << 8, .cdev.name = "d12:green", },
+ { .mask = 1 << 9, .cdev.name = "d13:green", },
+ { .mask = 1 << 10, .cdev.name = "d14:green", },
+ { .mask = 1 << 11, .cdev.name = "d15:green", },
+
+#ifndef CONFIG_LEDS
+ { .mask = 1 << 12, .cdev.name = "d16:green", },
+ { .mask = 1 << 13, .cdev.name = "d17:green", },
+ { .mask = 1 << 14, .cdev.name = "d18:green", },
+ { .mask = 1 << 15, .cdev.name = "d19:green", },
+#endif
+};
+
+static void
+fpga_led_set(struct led_classdev *cdev, enum led_brightness value)
+{
+ struct dbg_led *led = container_of(cdev, struct dbg_led, cdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&lock, flags);
+ if (value == LED_OFF)
+ hw_led_state &= ~led->mask;
+ else
+ hw_led_state |= led->mask;
+ __raw_writew(~hw_led_state, &fpga->leds);
+ spin_unlock_irqrestore(&lock, flags);
+}
+
+static void __init newled_init(struct device *dev)
+{
+ unsigned i;
+ struct dbg_led *led;
+ int status;
+
+ for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) {
+ led->cdev.brightness_set = fpga_led_set;
+ status = led_classdev_register(dev, &led->cdev);
+ if (status < 0)
+ break;
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int /* __init */ fpga_probe(struct platform_device *pdev)
+{
+ struct resource *iomem;
+
+ spin_lock_init(&lock);
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem)
+ return -ENODEV;
+
+ fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE);
+ __raw_writew(~0, &fpga->leds);
+
+#ifdef CONFIG_LEDS
+ leds_event = h2p2_dbg_leds_event;
+ leds_event(led_start);
+#endif
+
+ if (new_led_api()) {
+ newled_init(&pdev->dev);
+ }
+
+ return 0;
+}
+
+static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+ __raw_writew(~0, &fpga->leds);
+ return 0;
+}
+
+static int fpga_resume_early(struct platform_device *pdev)
+{
+ __raw_writew(~hw_led_state, &fpga->leds);
+ return 0;
+}
+
+
+static struct platform_driver led_driver = {
+ .driver.name = "omap_dbg_led",
+ .probe = fpga_probe,
+ .suspend_late = fpga_suspend_late,
+ .resume_early = fpga_resume_early,
+};
+
+static int __init fpga_init(void)
+{
+ if (machine_is_omap_h4()
+ || machine_is_omap_h3()
+ || machine_is_omap_h2()
+ || machine_is_omap_perseus2()
+ )
+ return platform_driver_register(&led_driver);
+ return 0;
+}
+fs_initcall(fpga_init);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index eeb33fed6f7c..c5dab1d6417e 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -25,7 +25,71 @@
#include <asm/arch/gpio.h>
#include <asm/arch/menelaus.h>
-#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
+#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
+
+#include "../plat-omap/dsp/dsp_common.h"
+
+static struct dsp_platform_data dsp_pdata = {
+ .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list),
+};
+
+static struct resource omap_dsp_resources[] = {
+ {
+ .name = "dsp_mmu",
+ .start = -1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device omap_dsp_device = {
+ .name = "dsp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(omap_dsp_resources),
+ .resource = omap_dsp_resources,
+ .dev = {
+ .platform_data = &dsp_pdata,
+ },
+};
+
+static inline void omap_init_dsp(void)
+{
+ struct resource *res;
+ int irq;
+
+ if (cpu_is_omap15xx())
+ irq = INT_1510_DSP_MMU;
+ else if (cpu_is_omap16xx())
+ irq = INT_1610_DSP_MMU;
+ else if (cpu_is_omap24xx())
+ irq = INT_24XX_DSP_MMU;
+
+ res = platform_get_resource_byname(&omap_dsp_device,
+ IORESOURCE_IRQ, "dsp_mmu");
+ res->start = irq;
+
+ platform_device_register(&omap_dsp_device);
+}
+
+int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev)
+{
+ static DEFINE_MUTEX(dsp_pdata_lock);
+
+ mutex_init(&kdev->lock);
+
+ mutex_lock(&dsp_pdata_lock);
+ list_add_tail(&kdev->entry, &dsp_pdata.kdev_list);
+ mutex_unlock(&dsp_pdata_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(dsp_kfunc_device_register);
+
+#else
+static inline void omap_init_dsp(void) { }
+#endif /* CONFIG_OMAP_DSP */
+
+/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
#define OMAP1_I2C_BASE 0xfffb3800
#define OMAP2_I2C_BASE1 0x48070000
@@ -48,8 +112,8 @@ static struct resource i2c_resources1[] = {
/* DMA not used; works around erratum writing to non-empty i2c fifo */
static struct platform_device omap_i2c_device1 = {
- .name = "i2c_omap",
- .id = 1,
+ .name = "i2c_omap",
+ .id = 1,
.num_resources = ARRAY_SIZE(i2c_resources1),
.resource = i2c_resources1,
};
@@ -376,7 +440,7 @@ static inline void omap_init_wdt(void) {}
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE)
+#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE)
#ifdef CONFIG_ARCH_OMAP24XX
#define OMAP_RNG_BASE 0x480A0000
@@ -436,6 +500,7 @@ static int __init omap_init_devices(void)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
+ omap_init_dsp();
omap_init_i2c();
omap_init_kp();
omap_init_mmc();
@@ -446,4 +511,3 @@ static int __init omap_init_devices(void)
return 0;
}
arch_initcall(omap_init_devices);
-
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f3f84fbf8b87..2d86b106ff3e 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -925,10 +925,17 @@ static int omap2_dma_handle_ch(int ch)
{
u32 status = OMAP_DMA_CSR_REG(ch);
- if (!status)
+ if (!status) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch);
return 0;
- if (unlikely(dma_chan[ch].dev_id == -1))
+ }
+ if (unlikely(dma_chan[ch].dev_id == -1)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
+ "channel %d\n", status, ch);
return 0;
+ }
if (unlikely(status & OMAP_DMA_DROP_IRQ))
printk(KERN_INFO
"DMA synchronization event drop occurred with device "
@@ -959,11 +966,15 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
int i;
val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
-
- for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) {
- int active = val & (1 << (i - 1));
- if (active)
- omap2_dma_handle_ch(i - 1);
+ if (val == 0) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "Spurious DMA IRQ\n");
+ return IRQ_HANDLED;
+ }
+ for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) {
+ if (val & 1)
+ omap2_dma_handle_ch(i);
+ val >>= 1;
}
return IRQ_HANDLED;
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 659619f235ca..36073dfaa4db 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
/* When the functional clock disappears, too quick writes seem to
* cause an abort. */
- __delay(15000);
+ __delay(150000);
}
#endif
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index 56acb8720f78..4493bcff5172 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -1,3 +1,26 @@
+/*
+ * File: arch/arm/plat-omap/fb.c
+ *
+ * Framebuffer device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -16,6 +39,8 @@
#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
static struct omapfb_platform_data omapfb_config;
+static int config_invalid;
+static int configured_regions;
static u64 omap_fb_dma_mask = ~(u32)0;
@@ -30,39 +55,270 @@ static struct platform_device omap_fb_device = {
.num_resources = 0,
};
-/* called from map_io */
-void omapfb_reserve_mem(void)
+static inline int ranges_overlap(unsigned long start1, unsigned long size1,
+ unsigned long start2, unsigned long size2)
{
- const struct omap_fbmem_config *fbmem_conf;
+ return (start1 >= start2 && start1 < start2 + size2) ||
+ (start2 >= start1 && start2 < start1 + size1);
+}
- omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
- omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+static inline int range_included(unsigned long start1, unsigned long size1,
+ unsigned long start2, unsigned long size2)
+{
+ return start1 >= start2 && start1 + size1 <= start2 + size2;
+}
- fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
- if (fbmem_conf != NULL) {
- /* indicate that the bootloader already initialized the
- * fb device, so we'll skip that part in the fb driver
- */
- omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
- omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
- if (fbmem_conf->fb_sdram_size) {
- pr_info("Reserving %u bytes SDRAM for frame buffer\n",
- fbmem_conf->fb_sdram_size);
- reserve_bootmem(fbmem_conf->fb_sdram_start,
- fbmem_conf->fb_sdram_size);
+/* Check if there is an overlapping region. */
+static int fbmem_region_reserved(unsigned long start, size_t size)
+{
+ struct omapfb_mem_region *rg;
+ int i;
+
+ rg = &omapfb_config.mem_desc.region[0];
+ for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) {
+ if (!rg->paddr)
+ /* Empty slot. */
+ continue;
+ if (ranges_overlap(start, size, rg->paddr, rg->size))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Get the region_idx`th region from board config/ATAG and convert it to
+ * our internal format.
+ */
+static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
+{
+ const struct omap_fbmem_config *conf;
+ u32 paddr;
+
+ conf = omap_get_nr_config(OMAP_TAG_FBMEM,
+ struct omap_fbmem_config, region_idx);
+ if (conf == NULL)
+ return -ENOENT;
+
+ paddr = conf->start;
+ /*
+ * Low bits encode the page allocation mode, if high bits
+ * are zero. Otherwise we need a page aligned fixed
+ * address.
+ */
+ memset(rg, 0, sizeof(*rg));
+ rg->type = paddr & ~PAGE_MASK;
+ rg->paddr = paddr & PAGE_MASK;
+ rg->size = PAGE_ALIGN(conf->size);
+ return 0;
+}
+
+static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type,
+ unsigned long mem_start,
+ unsigned long mem_size)
+{
+ /*
+ * Check if the configuration specifies the type explicitly.
+ * type = 0 && paddr = 0, a default don't care case maps to
+ * the SDRAM type.
+ */
+ if (rg->type || (!rg->type && !rg->paddr))
+ return 0;
+ if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) {
+ rg->type = mem_type;
+ return 0;
+ }
+ /* Can't determine it. */
+ return -1;
+}
+
+static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
+ unsigned long start_avail, unsigned size_avail)
+{
+ unsigned long paddr = rg->paddr;
+ size_t size = rg->size;
+
+ if (rg->type > OMAPFB_MEMTYPE_MAX) {
+ printk(KERN_ERR
+ "Invalid start address for FB region %d\n", region_idx);
+ return -EINVAL;
+ }
+
+ if (!rg->size) {
+ printk(KERN_ERR "Zero size for FB region %d\n", region_idx);
+ return -EINVAL;
+ }
+
+ if (!paddr)
+ /* Allocate this dynamically, leave paddr 0 for now. */
+ return 0;
+
+ /*
+ * Fixed region for the given RAM range. Check if it's already
+ * reserved by the FB code or someone else.
+ */
+ if (fbmem_region_reserved(paddr, size) ||
+ !range_included(paddr, size, start_avail, size_avail)) {
+ printk(KERN_ERR "Trying to use reserved memory "
+ "for FB region %d\n", region_idx);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Called from map_io. We need to call to this early enough so that we
+ * can reserve the fixed SDRAM regions before VM could get hold of them.
+ */
+void omapfb_reserve_sdram(void)
+{
+ struct bootmem_data *bdata;
+ unsigned long sdram_start, sdram_size;
+ unsigned long reserved;
+ int i;
+
+ if (config_invalid)
+ return;
+
+ bdata = NODE_DATA(0)->bdata;
+ sdram_start = bdata->node_boot_start;
+ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
+ reserved = 0;
+ for (i = 0; ; i++) {
+ struct omapfb_mem_region rg;
+
+ if (get_fbmem_region(i, &rg) < 0)
+ break;
+ if (i == OMAPFB_PLANE_NUM) {
+ printk(KERN_ERR
+ "Extraneous FB mem configuration entries\n");
+ config_invalid = 1;
+ return;
}
+ /* Check if it's our memory type. */
+ if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM,
+ sdram_start, sdram_size) < 0 ||
+ (rg.type != OMAPFB_MEMTYPE_SDRAM))
+ continue;
+ BUG_ON(omapfb_config.mem_desc.region[i].size);
+ if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) {
+ config_invalid = 1;
+ return;
+ }
+ if (rg.paddr)
+ reserve_bootmem(rg.paddr, rg.size);
+ reserved += rg.size;
+ omapfb_config.mem_desc.region[i] = rg;
+ configured_regions++;
}
+ omapfb_config.mem_desc.region_cnt = i;
+ if (reserved)
+ pr_info("Reserving %lu bytes SDRAM for frame buffer\n",
+ reserved);
+}
+
+/*
+ * Called at sram init time, before anything is pushed to the SRAM stack.
+ * Because of the stack scheme, we will allocate everything from the
+ * start of the lowest address region to the end of SRAM. This will also
+ * include padding for page alignment and possible holes between regions.
+ *
+ * As opposed to the SDRAM case, we'll also do any dynamic allocations at
+ * this point, since the driver built as a module would have problem with
+ * freeing / reallocating the regions.
+ */
+unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_vstart,
+ unsigned long sram_size,
+ unsigned long pstart_avail,
+ unsigned long size_avail)
+{
+ struct omapfb_mem_region rg;
+ unsigned long pend_avail;
+ unsigned long reserved;
+ int i;
+
+ if (config_invalid)
+ return 0;
+
+ reserved = 0;
+ pend_avail = pstart_avail + size_avail;
+ for (i = 0; ; i++) {
+ if (get_fbmem_region(i, &rg) < 0)
+ break;
+ if (i == OMAPFB_PLANE_NUM) {
+ printk(KERN_ERR
+ "Extraneous FB mem configuration entries\n");
+ config_invalid = 1;
+ return 0;
+ }
+
+ /* Check if it's our memory type. */
+ if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM,
+ sram_pstart, sram_size) < 0 ||
+ (rg.type != OMAPFB_MEMTYPE_SRAM))
+ continue;
+ BUG_ON(omapfb_config.mem_desc.region[i].size);
+
+ if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) {
+ config_invalid = 1;
+ return 0;
+ }
+
+ if (!rg.paddr) {
+ /* Dynamic allocation */
+ if ((size_avail & PAGE_MASK) < rg.size) {
+ printk("Not enough SRAM for FB region %d\n",
+ i);
+ config_invalid = 1;
+ return 0;
+ }
+ size_avail = (size_avail - rg.size) & PAGE_MASK;
+ rg.paddr = pstart_avail + size_avail;
+ }
+ /* Reserve everything above the start of the region. */
+ if (pend_avail - rg.paddr > reserved)
+ reserved = pend_avail - rg.paddr;
+ size_avail = pend_avail - reserved - pstart_avail;
+
+ /*
+ * We have a kernel mapping for this already, so the
+ * driver won't have to make one.
+ */
+ rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart);
+ omapfb_config.mem_desc.region[i] = rg;
+ configured_regions++;
+ }
+ omapfb_config.mem_desc.region_cnt = i;
+ if (reserved)
+ pr_info("Reserving %lu bytes SRAM for frame buffer\n",
+ reserved);
+ return reserved;
+}
+
+void omapfb_set_ctrl_platform_data(void *data)
+{
+ omapfb_config.ctrl_platform_data = data;
}
static inline int omap_init_fb(void)
{
const struct omap_lcd_config *conf;
+ if (config_invalid)
+ return 0;
+ if (configured_regions != omapfb_config.mem_desc.region_cnt) {
+ printk(KERN_ERR "Invalid FB mem configuration entries\n");
+ return 0;
+ }
conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
- if (conf == NULL)
+ if (conf == NULL) {
+ if (configured_regions)
+ /* FB mem config, but no LCD config? */
+ printk(KERN_ERR "Missing LCD configuration\n");
return 0;
-
+ }
omapfb_config.lcd = *conf;
return platform_device_register(&omap_fb_device);
@@ -72,7 +328,16 @@ arch_initcall(omap_init_fb);
#else
-void omapfb_reserve_mem(void) {}
+void omapfb_reserve_sdram(void) {}
+unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_vstart,
+ unsigned long sram_size,
+ unsigned long start_avail,
+ unsigned long size_avail)
+{
+ return 0;
+}
+
#endif
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 9dc6d3617bdb..337455dfe64d 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/sysdev.h>
#include <linux/err.h>
@@ -1545,7 +1544,7 @@ void omap2_gpio_resume_after_retention(void)
* This may get called early from board specific init
* for boards that have interrupts routed via FPGA.
*/
-int omap_gpio_init(void)
+int __init omap_gpio_init(void)
{
if (!initialized)
return _omap_gpio_init();
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
new file mode 100644
index 000000000000..de7e6ef48bd0
--- /dev/null
+++ b/arch/arm/plat-omap/mailbox.c
@@ -0,0 +1,509 @@
+/*
+ * OMAP mailbox driver
+ *
+ * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
+ * Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/blkdev.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/arch/mailbox.h>
+#include "mailbox.h"
+
+static struct omap_mbox *mboxes;
+static DEFINE_RWLOCK(mboxes_lock);
+
+/* Mailbox Sequence Bit function */
+void omap_mbox_init_seq(struct omap_mbox *mbox)
+{
+ mbox_seq_init(mbox);
+}
+EXPORT_SYMBOL(omap_mbox_init_seq);
+
+/*
+ * message sender
+ */
+static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg)
+{
+ int ret = 0, i = 1000;
+
+ while (mbox_fifo_full(mbox)) {
+ if (mbox->ops->type == OMAP_MBOX_TYPE2)
+ return -1;
+ if (--i == 0)
+ return -1;
+ udelay(1);
+ }
+
+ if (arg && mbox->txq->callback) {
+ ret = mbox->txq->callback(arg);
+ if (ret)
+ goto out;
+ }
+
+ mbox_seq_toggle(mbox, &msg);
+ mbox_fifo_write(mbox, msg);
+ out:
+ return ret;
+}
+
+int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg)
+{
+ struct request *rq;
+ struct request_queue *q = mbox->txq->queue;
+ int ret = 0;
+
+ rq = blk_get_request(q, WRITE, GFP_ATOMIC);
+ if (unlikely(!rq)) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ rq->data = (void *)msg;
+ blk_insert_request(q, rq, 0, arg);
+
+ schedule_work(&mbox->txq->work);
+ fail:
+ return ret;
+}
+EXPORT_SYMBOL(omap_mbox_msg_send);
+
+static void mbox_tx_work(struct work_struct *work)
+{
+ int ret;
+ struct request *rq;
+ struct omap_mbox_queue *mq = container_of(work,
+ struct omap_mbox_queue, work);
+ struct omap_mbox *mbox = mq->queue->queuedata;
+ struct request_queue *q = mbox->txq->queue;
+
+ while (1) {
+ spin_lock(q->queue_lock);
+ rq = elv_next_request(q);
+ spin_unlock(q->queue_lock);
+
+ if (!rq)
+ break;
+
+ ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special);
+ if (ret) {
+ enable_mbox_irq(mbox, IRQ_TX);
+ return;
+ }
+
+ spin_lock(q->queue_lock);
+ blkdev_dequeue_request(rq);
+ end_that_request_last(rq, 0);
+ spin_unlock(q->queue_lock);
+ }
+}
+
+/*
+ * Message receiver(workqueue)
+ */
+static void mbox_rx_work(struct work_struct *work)
+{
+ struct omap_mbox_queue *mq =
+ container_of(work, struct omap_mbox_queue, work);
+ struct omap_mbox *mbox = mq->queue->queuedata;
+ struct request_queue *q = mbox->rxq->queue;
+ struct request *rq;
+ mbox_msg_t msg;
+ unsigned long flags;
+
+ if (mbox->rxq->callback == NULL) {
+ sysfs_notify(&mbox->dev.kobj, NULL, "mbox");
+ return;
+ }
+
+ while (1) {
+ spin_lock_irqsave(q->queue_lock, flags);
+ rq = elv_next_request(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ if (!rq)
+ break;
+
+ msg = (mbox_msg_t) rq->data;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blkdev_dequeue_request(rq);
+ end_that_request_last(rq, 0);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ mbox->rxq->callback((void *)msg);
+ }
+}
+
+/*
+ * Mailbox interrupt handler
+ */
+static void mbox_txq_fn(request_queue_t * q)
+{
+}
+
+static void mbox_rxq_fn(request_queue_t * q)
+{
+}
+
+static void __mbox_tx_interrupt(struct omap_mbox *mbox)
+{
+ disable_mbox_irq(mbox, IRQ_TX);
+ ack_mbox_irq(mbox, IRQ_TX);
+ schedule_work(&mbox->txq->work);
+}
+
+static void __mbox_rx_interrupt(struct omap_mbox *mbox)
+{
+ struct request *rq;
+ mbox_msg_t msg;
+ request_queue_t *q = mbox->rxq->queue;
+
+ disable_mbox_irq(mbox, IRQ_RX);
+
+ while (!mbox_fifo_empty(mbox)) {
+ rq = blk_get_request(q, WRITE, GFP_ATOMIC);
+ if (unlikely(!rq))
+ goto nomem;
+
+ msg = mbox_fifo_read(mbox);
+ rq->data = (void *)msg;
+
+ if (unlikely(mbox_seq_test(mbox, msg))) {
+ pr_info("mbox: Illegal seq bit!(%08x)\n", msg);
+ if (mbox->err_notify)
+ mbox->err_notify();
+ }
+
+ blk_insert_request(q, rq, 0, NULL);
+ if (mbox->ops->type == OMAP_MBOX_TYPE1)
+ break;
+ }
+
+ /* no more messages in the fifo. clear IRQ source. */
+ ack_mbox_irq(mbox, IRQ_RX);
+ enable_mbox_irq(mbox, IRQ_RX);
+ nomem:
+ schedule_work(&mbox->rxq->work);
+}
+
+static irqreturn_t mbox_interrupt(int irq, void *p)
+{
+ struct omap_mbox *mbox = (struct omap_mbox *)p;
+
+ if (is_mbox_irq(mbox, IRQ_TX))
+ __mbox_tx_interrupt(mbox);
+
+ if (is_mbox_irq(mbox, IRQ_RX))
+ __mbox_rx_interrupt(mbox);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * sysfs files
+ */
+static ssize_t
+omap_mbox_write(struct device *dev, struct device_attribute *attr,
+ const char * buf, size_t count)
+{
+ int ret;
+ mbox_msg_t *p = (mbox_msg_t *)buf;
+ struct omap_mbox *mbox = dev_get_drvdata(dev);
+
+ for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) {
+ ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL);
+ if (ret)
+ return -EAGAIN;
+ p++;
+ }
+
+ return (size_t)((char *)p - buf);
+}
+
+static ssize_t
+omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ struct request *rq;
+ mbox_msg_t *p = (mbox_msg_t *) buf;
+ struct omap_mbox *mbox = dev_get_drvdata(dev);
+ struct request_queue *q = mbox->rxq->queue;
+
+ while (1) {
+ spin_lock_irqsave(q->queue_lock, flags);
+ rq = elv_next_request(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (!rq)
+ break;
+
+ *p = (mbox_msg_t) rq->data;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blkdev_dequeue_request(rq);
+ end_that_request_last(rq, 0);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (unlikely(mbox_seq_test(mbox, *p))) {
+ pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p);
+ continue;
+ }
+ p++;
+ }
+
+ pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
+
+ return (size_t) ((char *)p - buf);
+}
+
+static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write);
+
+static ssize_t mbox_show(struct class *class, char *buf)
+{
+ return sprintf(buf, "mbox");
+}
+
+static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
+
+static struct class omap_mbox_class = {
+ .name = "omap_mbox",
+};
+
+static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
+ request_fn_proc * proc,
+ void (*work) (struct work_struct *))
+{
+ request_queue_t *q;
+ struct omap_mbox_queue *mq;
+
+ mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
+ if (!mq)
+ return NULL;
+
+ spin_lock_init(&mq->lock);
+
+ q = blk_init_queue(proc, &mq->lock);
+ if (!q)
+ goto error;
+ q->queuedata = mbox;
+ mq->queue = q;
+
+ INIT_WORK(&mq->work, work);
+
+ return mq;
+error:
+ kfree(mq);
+ return NULL;
+}
+
+static void mbox_queue_free(struct omap_mbox_queue *q)
+{
+ blk_cleanup_queue(q->queue);
+ kfree(q);
+}
+
+static int omap_mbox_init(struct omap_mbox *mbox)
+{
+ int ret;
+ struct omap_mbox_queue *mq;
+
+ if (likely(mbox->ops->startup)) {
+ ret = mbox->ops->startup(mbox);
+ if (unlikely(ret))
+ return ret;
+ }
+
+ mbox->dev.class = &omap_mbox_class;
+ strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN);
+ dev_set_drvdata(&mbox->dev, mbox);
+
+ ret = device_register(&mbox->dev);
+ if (unlikely(ret))
+ goto fail_device_reg;
+
+ ret = device_create_file(&mbox->dev, &dev_attr_mbox);
+ if (unlikely(ret)) {
+ printk(KERN_ERR
+ "device_create_file failed: %d\n", ret);
+ goto fail_create_mbox;
+ }
+
+ ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
+ mbox->name, mbox);
+ if (unlikely(ret)) {
+ printk(KERN_ERR
+ "failed to register mailbox interrupt:%d\n", ret);
+ goto fail_request_irq;
+ }
+ enable_mbox_irq(mbox, IRQ_RX);
+
+ mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work);
+ if (!mq) {
+ ret = -ENOMEM;
+ goto fail_alloc_txq;
+ }
+ mbox->txq = mq;
+
+ mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work);
+ if (!mq) {
+ ret = -ENOMEM;
+ goto fail_alloc_rxq;
+ }
+ mbox->rxq = mq;
+
+ return 0;
+
+ fail_alloc_rxq:
+ mbox_queue_free(mbox->txq);
+ fail_alloc_txq:
+ free_irq(mbox->irq, mbox);
+ fail_request_irq:
+ device_remove_file(&mbox->dev, &dev_attr_mbox);
+ fail_create_mbox:
+ device_unregister(&mbox->dev);
+ fail_device_reg:
+ if (unlikely(mbox->ops->shutdown))
+ mbox->ops->shutdown(mbox);
+
+ return ret;
+}
+
+static void omap_mbox_fini(struct omap_mbox *mbox)
+{
+ mbox_queue_free(mbox->txq);
+ mbox_queue_free(mbox->rxq);
+
+ free_irq(mbox->irq, mbox);
+ device_remove_file(&mbox->dev, &dev_attr_mbox);
+ class_unregister(&omap_mbox_class);
+
+ if (unlikely(mbox->ops->shutdown))
+ mbox->ops->shutdown(mbox);
+}
+
+static struct omap_mbox **find_mboxes(const char *name)
+{
+ struct omap_mbox **p;
+
+ for (p = &mboxes; *p; p = &(*p)->next) {
+ if (strcmp((*p)->name, name) == 0)
+ break;
+ }
+
+ return p;
+}
+
+struct omap_mbox *omap_mbox_get(const char *name)
+{
+ struct omap_mbox *mbox;
+ int ret;
+
+ read_lock(&mboxes_lock);
+ mbox = *(find_mboxes(name));
+ if (mbox == NULL) {
+ read_unlock(&mboxes_lock);
+ return ERR_PTR(-ENOENT);
+ }
+
+ read_unlock(&mboxes_lock);
+
+ ret = omap_mbox_init(mbox);
+ if (ret)
+ return ERR_PTR(-ENODEV);
+
+ return mbox;
+}
+EXPORT_SYMBOL(omap_mbox_get);
+
+void omap_mbox_put(struct omap_mbox *mbox)
+{
+ omap_mbox_fini(mbox);
+}
+EXPORT_SYMBOL(omap_mbox_put);
+
+int omap_mbox_register(struct omap_mbox *mbox)
+{
+ int ret = 0;
+ struct omap_mbox **tmp;
+
+ if (!mbox)
+ return -EINVAL;
+ if (mbox->next)
+ return -EBUSY;
+
+ write_lock(&mboxes_lock);
+ tmp = find_mboxes(mbox->name);
+ if (*tmp)
+ ret = -EBUSY;
+ else
+ *tmp = mbox;
+ write_unlock(&mboxes_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(omap_mbox_register);
+
+int omap_mbox_unregister(struct omap_mbox *mbox)
+{
+ struct omap_mbox **tmp;
+
+ write_lock(&mboxes_lock);
+ tmp = &mboxes;
+ while (*tmp) {
+ if (mbox == *tmp) {
+ *tmp = mbox->next;
+ mbox->next = NULL;
+ write_unlock(&mboxes_lock);
+ return 0;
+ }
+ tmp = &(*tmp)->next;
+ }
+ write_unlock(&mboxes_lock);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int __init omap_mbox_class_init(void)
+{
+ int ret = class_register(&omap_mbox_class);
+ if (!ret)
+ ret = class_create_file(&omap_mbox_class, &class_attr_mbox);
+
+ return ret;
+}
+
+static void __exit omap_mbox_class_exit(void)
+{
+ class_remove_file(&omap_mbox_class, &class_attr_mbox);
+ class_unregister(&omap_mbox_class);
+}
+
+subsys_initcall(omap_mbox_class_init);
+module_exit(omap_mbox_class_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h
new file mode 100644
index 000000000000..67c6740b8ad5
--- /dev/null
+++ b/arch/arm/plat-omap/mailbox.h
@@ -0,0 +1,100 @@
+/*
+ * Mailbox internal functions
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ARCH_ARM_PLAT_MAILBOX_H
+#define __ARCH_ARM_PLAT_MAILBOX_H
+
+/*
+ * Mailbox sequence bit API
+ */
+#if defined(CONFIG_ARCH_OMAP1)
+# define MBOX_USE_SEQ_BIT
+#elif defined(CONFIG_ARCH_OMAP2)
+# define MBOX_USE_SEQ_BIT
+#endif
+
+#ifdef MBOX_USE_SEQ_BIT
+/* seq_rcv should be initialized with any value other than
+ * 0 and 1 << 31, to allow either value for the first
+ * message. */
+static inline void mbox_seq_init(struct omap_mbox *mbox)
+{
+ /* any value other than 0 and 1 << 31 */
+ mbox->seq_rcv = 0xffffffff;
+}
+
+static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
+{
+ /* add seq_snd to msg */
+ *msg = (*msg & 0x7fffffff) | mbox->seq_snd;
+ /* flip seq_snd */
+ mbox->seq_snd ^= 1 << 31;
+}
+
+static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ mbox_msg_t seq = msg & (1 << 31);
+ if (seq == mbox->seq_rcv)
+ return -1;
+ mbox->seq_rcv = seq;
+ return 0;
+}
+#else
+static inline void mbox_seq_init(struct omap_mbox *mbox)
+{
+}
+static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
+{
+}
+static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ return 0;
+}
+#endif
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_read(mbox);
+}
+static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ mbox->ops->fifo_write(mbox, msg);
+}
+static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_empty(mbox);
+}
+static inline int mbox_fifo_full(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_full(mbox);
+}
+
+/* Mailbox IRQ handle functions */
+static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ mbox->ops->enable_irq(mbox, irq);
+}
+static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ mbox->ops->disable_irq(mbox, irq);
+}
+static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ if (mbox->ops->ack_irq)
+ mbox->ops->ack_irq(mbox, irq);
+}
+static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ return mbox->ops->is_irq(mbox, irq);
+}
+
+#endif /* __ARCH_ARM_PLAT_MAILBOX_H */
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 19014b2ff4c6..bc46f33aede3 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -46,14 +46,19 @@
#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
+static unsigned long omap_sram_start;
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
-unsigned long omap_fb_sram_start;
-unsigned long omap_fb_sram_size;
+extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+ unsigned long sram_vstart,
+ unsigned long sram_size,
+ unsigned long pstart_avail,
+ unsigned long size_avail);
-/* Depending on the target RAMFS firewall setup, the public usable amount of
+/*
+ * Depending on the target RAMFS firewall setup, the public usable amount of
* SRAM varies. The default accessable size for all device types is 2k. A GP
* device allows ARM11 but not other initators for full size. This
* functionality seems ok until some nice security API happens.
@@ -77,32 +82,6 @@ static int is_sram_locked(void)
return 1; /* assume locked with no PPA or security driver */
}
-void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
- unsigned long *start, unsigned long *size)
-{
- const struct omap_fbmem_config *fbmem_conf;
-
- fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
- if (fbmem_conf != NULL) {
- *start = fbmem_conf->fb_sram_start;
- *size = fbmem_conf->fb_sram_size;
- } else {
- *size = 0;
- *start = 0;
- }
-
- if (*size && (
- *start < start_avail ||
- *start + *size > start_avail + size_avail)) {
- printk(KERN_ERR "invalid FB SRAM configuration\n");
- *start = start_avail;
- *size = size_avail;
- }
-
- if (*size)
- pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
-}
-
/*
* The amount of SRAM depends on the core type.
* Note that we cannot try to test for SRAM here because writes
@@ -111,16 +90,16 @@ void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
*/
void __init omap_detect_sram(void)
{
- unsigned long sram_start;
+ unsigned long reserved;
if (cpu_is_omap24xx()) {
if (is_sram_locked()) {
omap_sram_base = OMAP2_SRAM_PUB_VA;
- sram_start = OMAP2_SRAM_PUB_PA;
+ omap_sram_start = OMAP2_SRAM_PUB_PA;
omap_sram_size = 0x800; /* 2K */
} else {
omap_sram_base = OMAP2_SRAM_VA;
- sram_start = OMAP2_SRAM_PA;
+ omap_sram_start = OMAP2_SRAM_PA;
if (cpu_is_omap242x())
omap_sram_size = 0xa0000; /* 640K */
else if (cpu_is_omap243x())
@@ -128,7 +107,7 @@ void __init omap_detect_sram(void)
}
} else {
omap_sram_base = OMAP1_SRAM_VA;
- sram_start = OMAP1_SRAM_PA;
+ omap_sram_start = OMAP1_SRAM_PA;
if (cpu_is_omap730())
omap_sram_size = 0x32000; /* 200K */
@@ -144,12 +123,11 @@ void __init omap_detect_sram(void)
omap_sram_size = 0x4000;
}
}
- get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
- omap_sram_size - SRAM_BOOTLOADER_SZ,
- &omap_fb_sram_start, &omap_fb_sram_size);
- if (omap_fb_sram_size)
- omap_sram_size -= sram_start + omap_sram_size -
- omap_fb_sram_start;
+ reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base,
+ omap_sram_size,
+ omap_sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ);
+ omap_sram_size -= reserved;
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 7e8096809be2..25489aafb113 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -37,9 +37,27 @@
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
+#ifdef CONFIG_ARCH_OMAP1
+
+#define INT_USB_IRQ_GEN IH2_BASE + 20
+#define INT_USB_IRQ_NISO IH2_BASE + 30
+#define INT_USB_IRQ_ISO IH2_BASE + 29
+#define INT_USB_IRQ_HGEN INT_USB_HHC_1
+#define INT_USB_IRQ_OTG IH2_BASE + 8
+
+#else
+
+#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN
+#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO
+#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO
+#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN
+#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG
+
+#endif
+
+
/* These routines should handle the standard chip-specific modes
* for usb0/1/2 ports, covering basic mux and transceiver setup.
- * Call omap_usb_init() once, from INIT_MACHINE().
*
* Some board-*.c files will need to set up additional mux options,
* like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
@@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
{
u32 syscon1 = 0;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL);
+
if (nwires == 0) {
- if (!cpu_is_omap15xx()) {
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx()) {
/* pulldown D+/D- */
USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
}
return 0;
}
- if (is_device)
- omap_cfg_reg(W4_USB_PUEN);
+ if (is_device) {
+ if (cpu_is_omap24xx())
+ omap_cfg_reg(J20_24XX_USB0_PUEN);
+ else
+ omap_cfg_reg(W4_USB_PUEN);
+ }
- /* internal transceiver */
- if (nwires == 2) {
+ /* internal transceiver (unavailable on 17xx, 24xx) */
+ if (!cpu_class_is_omap2() && nwires == 2) {
// omap_cfg_reg(P9_USB_DP);
// omap_cfg_reg(R8_USB_DM);
@@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
return 0;
}
- omap_cfg_reg(V6_USB0_TXD);
- omap_cfg_reg(W9_USB0_TXEN);
- omap_cfg_reg(W5_USB0_SE0);
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(K18_24XX_USB0_DAT);
+ omap_cfg_reg(K19_24XX_USB0_TXEN);
+ omap_cfg_reg(J14_24XX_USB0_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(J18_24XX_USB0_RCV);
+ } else {
+ omap_cfg_reg(V6_USB0_TXD);
+ omap_cfg_reg(W9_USB0_TXEN);
+ omap_cfg_reg(W5_USB0_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(Y5_USB0_RCV);
+ }
- /* NOTE: SPEED and SUSP aren't configured here */
+ /* NOTE: SPEED and SUSP aren't configured here. OTG hosts
+ * may be able to use I2C requests to set those bits along
+ * with VBUS switching and overcurrent detction.
+ */
- if (nwires != 3)
- omap_cfg_reg(Y5_USB0_RCV);
- if (nwires != 6)
+ if (cpu_class_is_omap1() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
switch (nwires) {
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR);
break;
case 6:
syscon1 = 3;
- omap_cfg_reg(AA9_USB0_VP);
- omap_cfg_reg(R9_USB0_VM);
- USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(J19_24XX_USB0_VP);
+ omap_cfg_reg(K20_24XX_USB0_VM);
+ CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR);
+ } else {
+ omap_cfg_reg(AA9_USB0_VP);
+ omap_cfg_reg(R9_USB0_VM);
+ USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+ }
break;
default:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
@@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires)
{
u32 syscon1 = 0;
- if (nwires != 6 && !cpu_is_omap15xx())
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL);
+
if (nwires == 0)
return 0;
/* external transceiver */
- omap_cfg_reg(USB1_TXD);
- omap_cfg_reg(USB1_TXEN);
+ if (cpu_class_is_omap1()) {
+ omap_cfg_reg(USB1_TXD);
+ omap_cfg_reg(USB1_TXEN);
+ if (nwires != 3)
+ omap_cfg_reg(USB1_RCV);
+ }
+
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB1_SEO);
omap_cfg_reg(USB1_SPEED);
@@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires)
} else if (cpu_is_omap1710()) {
omap_cfg_reg(R13_1710_USB1_SE0);
// SUSP
+ } else if (cpu_is_omap24xx()) {
+ /* NOTE: board-specific code must set up pin muxing for usb1,
+ * since each signal could come out on either of two balls.
+ */
} else {
- pr_debug("usb unrecognized\n");
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
}
- if (nwires != 3)
- omap_cfg_reg(USB1_RCV);
switch (nwires) {
+ case 2:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL);
+ break;
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR);
break;
case 6:
+ if (cpu_is_omap24xx())
+ goto bad;
syscon1 = 3;
omap_cfg_reg(USB1_VP);
omap_cfg_reg(USB1_VM);
@@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires)
USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
break;
default:
+bad:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
1, nwires);
}
@@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
{
u32 syscon1 = 0;
- /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */
+ if (cpu_is_omap24xx()) {
+ CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL)
+ | USBT2TLL5PI);
+ alt_pingroup = 0;
+ }
+
+ /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
if (alt_pingroup || nwires == 0)
return 0;
- if (nwires != 6 && !cpu_is_omap15xx())
+
+ if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6)
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
/* external transceiver */
@@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
if (nwires != 3)
omap_cfg_reg(Y5_USB2_RCV);
// FIXME omap_cfg_reg(USB2_SPEED);
+ } else if (cpu_is_omap24xx()) {
+ omap_cfg_reg(Y11_24XX_USB2_DAT);
+ omap_cfg_reg(AA10_24XX_USB2_SE0);
+ if (nwires > 2)
+ omap_cfg_reg(AA12_24XX_USB2_TXEN);
+ if (nwires > 3)
+ omap_cfg_reg(AA6_24XX_USB2_RCV);
} else {
- pr_debug("usb unrecognized\n");
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
}
- // omap_cfg_reg(USB2_SUSP);
+ // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP);
switch (nwires) {
+ case 2:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM
+ */
+ syscon1 = 1;
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL);
+ break;
case 3:
syscon1 = 2;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
break;
case 4:
syscon1 = 1;
+ if (cpu_is_omap24xx())
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR);
+ break;
+ case 5:
+ if (!cpu_is_omap24xx())
+ goto bad;
+ omap_cfg_reg(AA4_24XX_USB2_TLLSE0);
+ /* NOTE: board-specific code must override this setting if
+ * this TLL link is not using DP/DM. Something must also
+ * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
+ */
+ syscon1 = 3;
+ CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL)
+ | USBT2TLL5PI;
break;
case 6:
+ if (cpu_is_omap24xx())
+ goto bad;
syscon1 = 3;
if (cpu_is_omap15xx()) {
omap_cfg_reg(USB2_VP);
@@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
}
break;
default:
+bad:
printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
2, nwires);
}
@@ -294,13 +410,13 @@ static struct resource udc_resources[] = {
.end = UDC_BASE + 0xff,
.flags = IORESOURCE_MEM,
}, { /* general IRQ */
- .start = IH2_BASE + 20,
+ .start = INT_USB_IRQ_GEN,
.flags = IORESOURCE_IRQ,
}, { /* PIO IRQ */
- .start = IH2_BASE + 30,
+ .start = INT_USB_IRQ_NISO,
.flags = IORESOURCE_IRQ,
}, { /* SOF IRQ */
- .start = IH2_BASE + 29,
+ .start = INT_USB_IRQ_ISO,
.flags = IORESOURCE_IRQ,
},
};
@@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0;
static struct resource ohci_resources[] = {
{
.start = OMAP_OHCI_BASE,
- .end = OMAP_OHCI_BASE + 4096 - 1,
+ .end = OMAP_OHCI_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
{
- .start = INT_USB_HHC_1,
+ .start = INT_USB_IRQ_HGEN,
.flags = IORESOURCE_IRQ,
},
};
@@ -361,7 +477,7 @@ static struct resource otg_resources[] = {
.end = OTG_BASE + 0xff,
.flags = IORESOURCE_MEM,
}, {
- .start = IH2_BASE + 8,
+ .start = INT_USB_IRQ_OTG,
.flags = IORESOURCE_IRQ,
},
};
@@ -385,7 +501,7 @@ static struct platform_device otg_device = {
// FIXME correct answer depends on hmc_mode,
-// as does any nonzero value for config->otg port number
+// as does (on omap1) any nonzero value for config->otg port number
#ifdef CONFIG_USB_GADGET_OMAP
#define is_usb0_device(config) 1
#else
@@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config)
if (config->otg)
syscon |= OTG_EN;
#endif
- pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
+ if (cpu_class_is_omap1())
+ pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
OTG_SYSCON_2_REG = syscon;
printk("USB: hmc %d", config->hmc_mode);
- if (alt_pingroup)
+ if (!alt_pingroup)
printk(", usb2 alt %d wires", config->pins[2]);
else if (config->pins[0])
printk(", usb0 %d wires%s", config->pins[0],
@@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config)
printk(", Mini-AB on usb%d", config->otg - 1);
printk("\n");
- /* leave USB clocks/controllers off until needed */
- ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
- ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
- ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+ if (cpu_class_is_omap1()) {
+ /* leave USB clocks/controllers off until needed */
+ ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
+ ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
+ ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
+ }
syscon = OTG_SYSCON_1_REG;
syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
@@ -585,7 +704,7 @@ omap_usb_init(void)
}
platform_data = *config;
- if (cpu_is_omap730() || cpu_is_omap16xx())
+ if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx())
omap_otg_init(&platform_data);
else if (cpu_is_omap15xx())
omap_1510_usb_init(&platform_data);
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index 435349dc3243..7b7ae790b00d 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/plat-s3c24xx/sleep.S
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index 6115fc1f0cfa..dc6bc01f232c 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -16,7 +16,7 @@ AFLAGS += -mrelax -mno-pic
CFLAGS_MODULE += -mno-relax
LDFLAGS_vmlinux += --relax
-cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000
+cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000
CFLAGS += $(cpuflags-y)
AFLAGS += $(cpuflags-y)
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 4e4181ed1c6d..13f988402613 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -330,13 +330,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
{
struct pt_regs *childregs;
- childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1;
+ childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
*childregs = *regs;
if (user_mode(regs))
childregs->sp = usp;
else
- childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE;
+ childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
childregs->r12 = 0; /* Set return value for child */
@@ -403,7 +403,7 @@ unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)p->thread_info;
+ stack_page = (unsigned long)task_stack_page(p);
BUG_ON(!stack_page);
/*
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 8ac74dddbbde..3c36c2d16148 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -24,7 +24,7 @@
static struct pt_regs *get_user_regs(struct task_struct *tsk)
{
- return (struct pt_regs *)((unsigned long) tsk->thread_info +
+ return (struct pt_regs *)((unsigned long)task_stack_page(tsk) +
THREAD_SIZE - sizeof(struct pt_regs));
}
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 7c279586fbba..07f6a6fa340d 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -291,4 +291,5 @@ sys_call_table:
.long sys_shmget /* 275 */
.long sys_shmdt
.long sys_shmctl
+ .long sys_utimensat
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 4de9edf96ed2..86d107511dd4 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -123,7 +123,7 @@ asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
/* This way of handling undefined instructions is stolen from ARM */
static LIST_HEAD(undef_hook);
-static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(undef_lock);
void register_undef_hook(struct undef_hook *hook)
{
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
index 7ad20cfb48a8..e7f72c995a32 100644
--- a/arch/avr32/kernel/vmlinux.lds.c
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -35,7 +35,7 @@ SECTIONS
_einittext = .;
. = ALIGN(4);
__tagtable_begin = .;
- *(.taglist)
+ *(.taglist.init)
__tagtable_end = .;
*(.init.data)
. = ALIGN(16);
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 00c435452d7e..0f8c89c9f832 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -18,7 +18,7 @@
#include "clock.h"
-static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clk_lock);
struct clk *clk_get(struct device *dev, const char *id)
{
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
index b68d669f823d..099212d4567c 100644
--- a/arch/avr32/mm/dma-coherent.c
+++ b/arch/avr32/mm/dma-coherent.c
@@ -112,16 +112,21 @@ void dma_free_coherent(struct device *dev, size_t size,
}
EXPORT_SYMBOL(dma_free_coherent);
-#if 0
void *dma_alloc_writecombine(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp)
{
struct page *page;
+ dma_addr_t phys;
page = __dma_alloc(dev, size, handle, gfp);
+ if (!page)
+ return NULL;
+
+ phys = page_to_phys(page);
+ *handle = phys;
/* Now, map the page into P3 with write-combining turned on */
- return __ioremap(page_to_phys(page), size, _PAGE_BUFFER);
+ return __ioremap(phys, size, _PAGE_BUFFER);
}
EXPORT_SYMBOL(dma_alloc_writecombine);
@@ -132,8 +137,7 @@ void dma_free_writecombine(struct device *dev, size_t size,
iounmap(cpu_addr);
- page = bus_to_page(handle);
+ page = phys_to_page(handle);
__dma_free(dev, size, page, handle);
}
EXPORT_SYMBOL(dma_free_writecombine);
-#endif
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index 41d9a9f89700..e455f4504509 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -46,7 +46,7 @@ int main(void)
DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
- DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index d7c8e514cb92..e718bb4a1ef0 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -73,7 +73,7 @@
static inline struct pt_regs *get_user_regs(struct task_struct *task)
{
return (struct pt_regs *)
- ((unsigned long)task->thread_info +
+ ((unsigned long)task_stack_page(task) +
(THREAD_SIZE - sizeof(struct pt_regs)));
}
@@ -99,7 +99,7 @@ static inline long get_reg(struct task_struct *task, int regno)
unsigned char *reg_ptr;
struct pt_regs *regs =
- (struct pt_regs *)((unsigned long)task->thread_info +
+ (struct pt_regs *)((unsigned long)task_stack_page(task) +
(THREAD_SIZE - sizeof(struct pt_regs)));
reg_ptr = (char *)regs;
@@ -125,7 +125,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data)
char * reg_ptr;
struct pt_regs *regs =
- (struct pt_regs *)((unsigned long)task->thread_info +
+ (struct pt_regs *)((unsigned long)task_stack_page(task) +
(THREAD_SIZE - sizeof(struct pt_regs)));
reg_ptr = (char *)regs;
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index f64624fc4504..1d859c16931e 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -603,7 +603,7 @@ config ETRAX_CARDBUS
select HOTPLUG
select PCCARD_NONSTATIC
help
- Enabled the ETRAX Carbus driver.
+ Enabled the ETRAX Cardbus driver.
config PCI
bool
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index eed694312a79..114738a45582 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -45,15 +45,15 @@ config TIME_LOW_RES
bool
default y
-config ARCH_HAS_ILOG2_U32
+config QUICKLIST
bool
default y
-config ARCH_HAS_ILOG2_U64
+config ARCH_HAS_ILOG2_U32
bool
default y
-config ARCH_USES_SLAB_PAGE_STRUCT
+config ARCH_HAS_ILOG2_U64
bool
default y
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 515a5cea5469..9583a338e9d6 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -25,12 +25,14 @@
#include <linux/elf.h>
#include <linux/reboot.h>
#include <linux/interrupt.h>
+#include <linux/pagemap.h>
#include <asm/asm-offsets.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
+#include <asm/tlb.h>
#include <asm/gdb-stub.h>
#include <asm/mb-regs.h>
@@ -88,6 +90,8 @@ void cpu_idle(void)
while (!need_resched()) {
irq_stat[cpu].idle_timestamp = jiffies;
+ check_pgt_cache();
+
if (!frv_dma_inprogress && idle)
idle();
}
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 598a26ab8ad8..7787c3cc52c6 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -13,12 +13,12 @@
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/quicklist.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
-struct kmem_cache *pgd_cache;
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
@@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd)
set_page_private(next, (unsigned long) pprev);
}
-void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+void pgd_ctor(void *pgd)
{
unsigned long flags;
@@ -120,7 +120,7 @@ void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
}
/* never called when PTRS_PER_PMD > 1 */
-void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+void pgd_dtor(void *pgd)
{
unsigned long flags; /* can be called from interrupt context */
@@ -133,7 +133,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd;
- pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+ pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
if (!pgd)
return pgd;
@@ -143,15 +143,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
void pgd_free(pgd_t *pgd)
{
/* in the non-PAE case, clear_page_tables() clears user pgd entries */
- kmem_cache_free(pgd_cache, pgd);
+ quicklist_free(0, pgd_dtor, pgd);
}
void __init pgtable_cache_init(void)
{
- pgd_cache = kmem_cache_create("pgd",
- PTRS_PER_PGD * sizeof(pgd_t),
- PTRS_PER_PGD * sizeof(pgd_t),
- SLAB_PANIC,
- pgd_ctor,
- pgd_dtor);
}
+
+void check_pgt_cache(void)
+{
+ quicklist_trim(0, pgd_dtor, 25, 16);
+}
+
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
index e0e9bcb015a9..554efe604a08 100644
--- a/arch/h8300/Kconfig.debug
+++ b/arch/h8300/Kconfig.debug
@@ -21,12 +21,12 @@ config GDB_MAGICPRINT
bool "Message Output for GDB MagicPrint service"
depends on (H8300H_SIM || H8S_SIM)
help
- kernel messages output useing MagicPrint service from GDB
+ kernel messages output using MagicPrint service from GDB
config SYSCALL_PRINT
bool "SystemCall trace print"
help
- outout history of systemcall
+ output history of systemcall
config GDB_DEBUG
bool "Use gdb stub"
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
index b78b82ad28a3..fc30b4fd0914 100644
--- a/arch/h8300/kernel/asm-offsets.c
+++ b/arch/h8300/kernel/asm-offsets.c
@@ -30,7 +30,7 @@ int main(void)
DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
- DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 64ad10f984a1..30944ee2e61a 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -858,9 +858,9 @@ config RELOCATABLE
bool "Build a relocatable kernel(EXPERIMENTAL)"
depends on EXPERIMENTAL
help
- This build a kernel image that retains relocation information
+ This builds a kernel image that retains relocation information
so it can be loaded someplace besides the default 1MB.
- The relocations tend to the kernel binary about 10% larger,
+ The relocations tend to make the kernel binary about 10% larger,
but are discarded at runtime.
One use is for the kexec on panic case where the recovery kernel
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index dce6124cb842..d7f6fb0b30f2 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -108,7 +108,7 @@ config MCORE2
bool "Core 2/newer Xeon"
help
Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
- CPUs. You can distingush newer from older Xeons by the CPU family
+ CPUs. You can distinguish newer from older Xeons by the CPU family
in /proc/cpuinfo. Newer ones have 6.
config MPENTIUM4
@@ -172,7 +172,7 @@ config MWINCHIP3D
help
Select this for an IDT Winchip-2A or 3. Linux and GCC
treat this chip as a 586TSC with some extended instructions
- and alignment reqirements. Also enable out of order memory
+ and alignment requirements. Also enable out of order memory
stores for this CPU, which can increase performance of some
operations.
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 80b4c5d421b1..e5be819492ef 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -733,9 +733,11 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
cache_add_dev(sys_dev);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
cache_remove_dev(sys_dev);
break;
}
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
index 065005c3f168..7ba7c3abd3a4 100644
--- a/arch/i386/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c
+ * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c
*
* Thermal throttle event support code (such as syslog messaging and rate
* limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
@@ -137,10 +137,12 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
mutex_lock(&therm_cpu_lock);
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
err = thermal_throttle_add_dev(sys_dev);
WARN_ON(err);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
thermal_throttle_remove_dev(sys_dev);
break;
}
diff --git a/arch/i386/kernel/cpu/transmeta.c b/arch/i386/kernel/cpu/transmeta.c
index 6471a5a13202..200fb3f9ebfb 100644
--- a/arch/i386/kernel/cpu/transmeta.c
+++ b/arch/i386/kernel/cpu/transmeta.c
@@ -77,8 +77,10 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
/* If we can run i686 user-space code, call us an i686 */
-#define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV)
- if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 )
+#define USER686 ((1 << X86_FEATURE_TSC)|\
+ (1 << X86_FEATURE_CX8)|\
+ (1 << X86_FEATURE_CMOV))
+ if (c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686)
c->x86 = 6;
#ifdef CONFIG_SYSCTL
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index eeae0d992337..5c2faa10e9fa 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -169,9 +169,11 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
cpuid_device_create(cpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break;
}
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index cbe7ec8dbb9f..83f825f2e2d7 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -567,7 +567,7 @@ static int cpu_request_microcode(int cpu)
return error;
}
-static int apply_microcode_on_cpu(int cpu)
+static int apply_microcode_check_cpu(int cpu)
{
struct cpuinfo_x86 *c = cpu_data + cpu;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -575,8 +575,9 @@ static int apply_microcode_on_cpu(int cpu)
unsigned int val[2];
int err = 0;
+ /* Check if the microcode is available */
if (!uci->mc)
- return -EINVAL;
+ return 0;
old = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(cpu));
@@ -614,7 +615,7 @@ static int apply_microcode_on_cpu(int cpu)
return err;
}
-static void microcode_init_cpu(int cpu)
+static void microcode_init_cpu(int cpu, int resume)
{
cpumask_t old;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -624,8 +625,7 @@ static void microcode_init_cpu(int cpu)
set_cpus_allowed(current, cpumask_of_cpu(cpu));
mutex_lock(&microcode_mutex);
collect_cpu_info(cpu);
- if (uci->valid && system_state == SYSTEM_RUNNING &&
- !suspend_cpu_hotplug)
+ if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
cpu_request_microcode(cpu);
mutex_unlock(&microcode_mutex);
set_cpus_allowed(current, old);
@@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = {
.name = "microcode",
};
-static int mc_sysdev_add(struct sys_device *sys_dev)
+static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
{
int err, cpu = sys_dev->id;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -711,39 +711,31 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
return 0;
pr_debug("Microcode:CPU %d added\n", cpu);
- /* If suspend_cpu_hotplug is set, the system is resuming and we should
- * use the data from before the suspend.
- */
- if (suspend_cpu_hotplug) {
- err = apply_microcode_on_cpu(cpu);
- if (err)
- microcode_fini_cpu(cpu);
- }
- if (!uci->valid)
- memset(uci, 0, sizeof(*uci));
+ memset(uci, 0, sizeof(*uci));
err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
if (err)
return err;
- if (!uci->valid)
- microcode_init_cpu(cpu);
+ microcode_init_cpu(cpu, resume);
return 0;
}
+static int mc_sysdev_add(struct sys_device *sys_dev)
+{
+ return __mc_sysdev_add(sys_dev, 0);
+}
+
static int mc_sysdev_remove(struct sys_device *sys_dev)
{
int cpu = sys_dev->id;
if (!cpu_online(cpu))
return 0;
+
pr_debug("Microcode:CPU %d removed\n", cpu);
- /* If suspend_cpu_hotplug is set, the system is suspending and we should
- * keep the microcode in memory for the resume.
- */
- if (!suspend_cpu_hotplug)
- microcode_fini_cpu(cpu);
+ microcode_fini_cpu(cpu);
sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
return 0;
}
@@ -774,13 +766,34 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
+ case CPU_UP_CANCELED_FROZEN:
+ /* The CPU refused to come up during a system resume */
+ microcode_fini_cpu(cpu);
+ break;
case CPU_ONLINE:
case CPU_DOWN_FAILED:
mc_sysdev_add(sys_dev);
break;
+ case CPU_ONLINE_FROZEN:
+ /* System-wide resume is in progress, try to apply microcode */
+ if (apply_microcode_check_cpu(cpu)) {
+ /* The application of microcode failed */
+ microcode_fini_cpu(cpu);
+ __mc_sysdev_add(sys_dev, 1);
+ break;
+ }
+ case CPU_DOWN_FAILED_FROZEN:
+ if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
+ printk(KERN_ERR "Microcode: Failed to create the sysfs "
+ "group for CPU%d\n", cpu);
+ break;
case CPU_DOWN_PREPARE:
mc_sysdev_remove(sys_dev);
break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ /* Suspend is in progress, only remove the interface */
+ sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+ break;
}
return NOTIFY_OK;
}
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 8cd0a91ce107..0c1069b8d638 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -153,9 +153,11 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
msr_device_create(cpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break;
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 4bec0cbf407a..c05e7e861b29 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -305,7 +305,7 @@ void show_registers(struct pt_regs *regs)
regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
TASK_COMM_LEN, current->comm, current->pid,
- current_thread_info(), current, current->thread_info);
+ current_thread_info(), current, task_thread_info(current));
/*
* When in-kernel, we also print out the stack and code at the
* time of the fault..
diff --git a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c
index a7b3999bb37a..74f3da634423 100644
--- a/arch/i386/mach-generic/probe.c
+++ b/arch/i386/mach-generic/probe.c
@@ -119,9 +119,7 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 0;
}
-#ifdef CONFIG_SMP
int hard_smp_processor_id(void)
{
return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
}
-#endif
diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
index 8fe7e4593d5f..9b77b39b71a6 100644
--- a/arch/i386/mach-voyager/voyager_basic.c
+++ b/arch/i386/mach-voyager/voyager_basic.c
@@ -292,8 +292,8 @@ machine_emergency_restart(void)
void
mca_nmi_hook(void)
{
- __u8 dumpval __attribute__((unused)) = inb(0xf823);
- __u8 swnmi __attribute__((unused)) = inb(0xf813);
+ __u8 dumpval __maybe_unused = inb(0xf823);
+ __u8 swnmi __maybe_unused = inb(0xf813);
/* FIXME: assume dump switch pressed */
/* check to see if the dump switch was pressed */
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
index 1cf11af96de2..3de9f9ba2da6 100644
--- a/arch/i386/pci/init.c
+++ b/arch/i386/pci/init.c
@@ -6,7 +6,7 @@
in the right sequence from here. */
static __init int pci_access_init(void)
{
- int type __attribute__((unused)) = 0;
+ int type __maybe_unused = 0;
#ifdef CONFIG_PCI_DIRECT
type = pci_direct_probe();
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index e23af4b6ae8c..6e41471449c0 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -468,7 +468,7 @@ config KEXEC
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
- but it is indepedent of the system firmware. And like a reboot
+ but it is independent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.
The name comes from the similiarity to the exec system call.
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 687e5fdc9683..99b665e2b1d5 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -52,43 +52,6 @@ ENTRY(ia32_clone)
br.ret.sptk.many rp
END(ia32_clone)
-ENTRY(sys32_rt_sigsuspend)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
- mov loc0=rp
- mov out0=in0 // mask
- mov out1=in1 // sigsetsize
- mov out2=sp // out2 = &sigscratch
- .fframe 16
- adds sp=-16,sp // allocate dummy "sigscratch"
- ;;
- .body
- br.call.sptk.many rp=ia32_rt_sigsuspend
-1: .restore sp
- adds sp=16,sp
- mov rp=loc0
- mov ar.pfs=loc1
- br.ret.sptk.many rp
-END(sys32_rt_sigsuspend)
-
-ENTRY(sys32_sigsuspend)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
- mov loc0=rp
- mov out0=in2 // mask (first two args are ignored)
- ;;
- mov out1=sp // out1 = &sigscratch
- .fframe 16
- adds sp=-16,sp // allocate dummy "sigscratch"
- .body
- br.call.sptk.many rp=ia32_sigsuspend
-1: .restore sp
- adds sp=16,sp
- mov rp=loc0
- mov ar.pfs=loc1
- br.ret.sptk.many rp
-END(sys32_sigsuspend)
-
GLOBAL_ENTRY(ia32_ret_from_clone)
PT_REGS_UNWIND_INFO(0)
{ /*
@@ -389,7 +352,7 @@ ia32_syscall_table:
data8 sys_rt_sigpending
data8 compat_sys_rt_sigtimedwait
data8 sys32_rt_sigqueueinfo
- data8 sys32_rt_sigsuspend
+ data8 compat_sys_rt_sigsuspend
data8 sys32_pread /* 180 */
data8 sys32_pwrite
data8 sys_chown /* 16-bit version */
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 10510e585204..85e82f32e480 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -451,59 +451,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
}
-long
-__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr)
+asmlinkage long
+sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
{
- extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
- sigset_t oldset, set;
-
- scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
- memset(&set, 0, sizeof(set));
-
- memcpy(&set.sig, &sset->sig, sigsetsize);
-
- sigdelsetmask(&set, ~_BLOCKABLE);
-
+ mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- {
- oldset = current->blocked;
- current->blocked = set;
- recalc_sigpending();
- }
+ current->saved_sigmask = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- /*
- * The return below usually returns to the signal handler. We need to pre-set the
- * correct error code here to ensure that the right values get saved in sigcontext
- * by ia64_do_signal.
- */
- scr->pt.r8 = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (ia64_do_signal(&oldset, scr, 1))
- return -EINTR;
- }
-}
-
-asmlinkage long
-ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
-{
- compat_sigset_t set;
-
- if (sigsetsize > sizeof(compat_sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
- return -EFAULT;
-
- return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
-}
-
-asmlinkage long
-ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
-{
- return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage long
@@ -810,7 +771,11 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
}
/* Legacy stack switching not supported */
- return (void __user *)((esp - frame_size) & -8ul);
+ esp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+ esp = ((esp + 4) & -16ul) - 4;
+ return (void __user *) esp;
}
static int
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 55fd2d5471e1..b50bf208678e 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user)
br.ret.sptk.many rp
END(notify_resume_user)
-GLOBAL_ENTRY(sys_rt_sigsuspend)
- .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
- alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
- mov r9=ar.unat
- mov loc0=rp // save return address
- mov out0=in0 // mask
- mov out1=in1 // sigsetsize
- adds out2=8,sp // out2=&sigscratch->ar_pfs
- ;;
- .fframe 16
- .spillsp ar.unat, 16
- st8 [sp]=r9,-16 // allocate space for ar.unat and save it
- st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
- .body
- br.call.sptk.many rp=ia64_rt_sigsuspend
-.ret17: .restore sp
- adds sp=16,sp // pop scratch stack space
- ;;
- ld8 r9=[sp] // load new unat from sw->caller_unat
- mov rp=loc0
- ;;
- mov ar.unat=r9
- mov ar.pfs=loc1
- br.ret.sptk.many rp
-END(sys_rt_sigsuspend)
-
ENTRY(sys_rt_sigreturn)
PT_REGS_UNWIND_INFO(0)
/*
@@ -1598,8 +1572,8 @@ sys_call_table:
data8 sys_readlinkat
data8 sys_fchmodat
data8 sys_faccessat
- data8 sys_ni_syscall // reserved for pselect
- data8 sys_ni_syscall // 1295 reserved for ppoll
+ data8 sys_pselect6
+ data8 sys_ppoll
data8 sys_unshare
data8 sys_splice
data8 sys_set_robust_list
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
index d3e9f33e8bdd..6a49600cf337 100644
--- a/arch/ia64/kernel/err_inject.c
+++ b/arch/ia64/kernel/err_inject.c
@@ -236,9 +236,11 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb,
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
err_inject_add_dev(sys_dev);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
err_inject_remove_dev(sys_dev);
break;
}
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 93d9ab14ba24..37f46527d233 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -1012,7 +1012,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
/*
* ACPI calls this when it finds an entry for a legacy ISA IRQ override.
*/
-void __init
+void __devinit
iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long polarity,
unsigned long trigger)
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 1c5044a80958..bc47049f060f 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -38,6 +38,7 @@
#include <asm/machvec.h>
#include <asm/pgtable.h>
#include <asm/system.h>
+#include <asm/tlbflush.h>
#ifdef CONFIG_PERFMON
# include <asm/perfmon.h>
@@ -126,8 +127,10 @@ void destroy_irq(unsigned int irq)
#ifdef CONFIG_SMP
# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
+# define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH)
#else
# define IS_RESCHEDULE(vec) (0)
+# define IS_LOCAL_TLB_FLUSH(vec) (0)
#endif
/*
* That's where the IVT branches when we get an external
@@ -179,8 +182,11 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
ia64_srlz_d();
while (vector != IA64_SPURIOUS_INT_VECTOR) {
- if (unlikely(IS_RESCHEDULE(vector)))
- kstat_this_cpu.irqs[vector]++;
+ if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
+ smp_local_flush_tlb();
+ kstat_this_cpu.irqs[vector]++;
+ } else if (unlikely(IS_RESCHEDULE(vector)))
+ kstat_this_cpu.irqs[vector]++;
else {
ia64_setreg(_IA64_REG_CR_TPR, vector);
ia64_srlz_d();
@@ -226,8 +232,11 @@ void ia64_process_pending_intr(void)
* Perform normal interrupt style processing
*/
while (vector != IA64_SPURIOUS_INT_VECTOR) {
- if (unlikely(IS_RESCHEDULE(vector)))
- kstat_this_cpu.irqs[vector]++;
+ if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
+ smp_local_flush_tlb();
+ kstat_this_cpu.irqs[vector]++;
+ } else if (unlikely(IS_RESCHEDULE(vector)))
+ kstat_this_cpu.irqs[vector]++;
else {
struct pt_regs *old_regs = set_irq_regs(NULL);
@@ -259,12 +268,12 @@ void ia64_process_pending_intr(void)
#ifdef CONFIG_SMP
-extern irqreturn_t handle_IPI (int irq, void *dev_id);
static irqreturn_t dummy_handler (int irq, void *dev_id)
{
BUG();
}
+extern irqreturn_t handle_IPI (int irq, void *dev_id);
static struct irqaction ipi_irqaction = {
.handler = handle_IPI,
@@ -277,6 +286,13 @@ static struct irqaction resched_irqaction = {
.flags = IRQF_DISABLED,
.name = "resched"
};
+
+static struct irqaction tlb_irqaction = {
+ .handler = dummy_handler,
+ .flags = IRQF_DISABLED,
+ .name = "tlb_flush"
+};
+
#endif
void
@@ -302,6 +318,7 @@ init_IRQ (void)
#ifdef CONFIG_SMP
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
+ register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
#endif
#ifdef CONFIG_PERFMON
pfm_init_percpu();
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 1d7cc7e2ce32..f8ae709de0b5 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1689,7 +1689,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
ti->preempt_count = 1;
ti->task = p;
ti->cpu = cpu;
- p->thread_info = ti;
+ p->stack = ti;
p->state = TASK_UNINTERRUPTIBLE;
cpu_set(cpu, p->cpus_allowed);
INIT_LIST_HEAD(&p->tasks);
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index a71df9ae0397..85829e27785c 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -975,9 +975,11 @@ static int palinfo_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
create_palinfo_proc_entries(hotcpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
remove_palinfo_proc_entries(hotcpu);
break;
}
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 8bb571a8a738..d1c3ed9943e5 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -155,7 +155,7 @@ show_regs (struct pt_regs *regs)
}
void
-do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
+do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
{
if (fsys_mode(current, &scr->pt)) {
/* defer signal-handling etc. until we return to privilege-level 0. */
@@ -170,8 +170,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall
#endif
/* deal with pending signal delivery */
- if (test_thread_flag(TIF_SIGPENDING))
- ia64_do_signal(oldset, scr, in_syscall);
+ if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
+ ia64_do_signal(scr, in_syscall);
}
static int pal_halt = 1;
@@ -236,6 +236,7 @@ void cpu_idle_wait(void)
{
unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
+ cpumask_t tmp = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
put_cpu();
@@ -257,6 +258,7 @@ void cpu_idle_wait(void)
}
cpus_and(map, map, cpu_online_map);
} while (!cpus_empty(map));
+ set_cpus_allowed(current, tmp);
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
index ae473e3f2a0d..903babd22d62 100644
--- a/arch/ia64/kernel/relocate_kernel.S
+++ b/arch/ia64/kernel/relocate_kernel.S
@@ -94,7 +94,7 @@ GLOBAL_ENTRY(relocate_new_kernel)
4:
srlz.i
;;
- //purge TR entry for kernel text and data
+ // purge TR entry for kernel text and data
movl r16=KERNEL_START
mov r18=KERNEL_TR_PAGE_SHIFT<<2
;;
@@ -104,15 +104,6 @@ GLOBAL_ENTRY(relocate_new_kernel)
srlz.i
;;
- // purge TR entry for percpu data
- movl r16=PERCPU_ADDR
- mov r18=PERCPU_PAGE_SHIFT<<2
- ;;
- ptr.d r16,r18
- ;;
- srlz.d
- ;;
-
// purge TR entry for pal code
mov r16=in3
mov r18=IA64_GRANULE_SHIFT<<2
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index a51f1d0bfb70..89f6b138a62c 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -582,6 +582,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu
struct salinfo_data *data;
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
spin_lock_irqsave(&data_saved_lock, flags);
for (i = 0, data = salinfo_data;
i < ARRAY_SIZE(salinfo_data);
@@ -592,6 +593,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu
spin_unlock_irqrestore(&data_saved_lock, flags);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
spin_lock_irqsave(&data_saved_lock, flags);
for (i = 0, data = salinfo_data;
i < ARRAY_SIZE(salinfo_data);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 6e19da122ae3..9df1efe7487d 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -786,7 +786,7 @@ identify_cpu (struct cpuinfo_ia64 *c)
c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
}
-void
+void __init
setup_per_cpu_areas (void)
{
/* start_kernel() requires this... */
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
index 37b986cb86e0..9fd9a1933b3d 100644
--- a/arch/ia64/kernel/sigframe.h
+++ b/arch/ia64/kernel/sigframe.h
@@ -22,4 +22,4 @@ struct sigframe {
struct sigcontext sc;
};
-extern long ia64_do_signal (sigset_t *, struct sigscratch *, long);
+extern void ia64_do_signal (struct sigscratch *, long);
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 0dcd56da6001..aeec8184e862 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -40,47 +40,6 @@
# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
#endif
-long
-ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
-{
- sigset_t oldset, set;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (!access_ok(VERIFY_READ, uset, sigsetsize))
- return -EFAULT;
-
- if (GET_SIGSET(&set, uset))
- return -EFAULT;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- {
- oldset = current->blocked;
- current->blocked = set;
- recalc_sigpending();
- }
- spin_unlock_irq(&current->sighand->siglock);
-
- /*
- * The return below usually returns to the signal handler. We need to
- * pre-set the correct error code here to ensure that the right values
- * get saved in sigcontext by ia64_do_signal.
- */
- scr->pt.r8 = EINTR;
- scr->pt.r10 = -1;
-
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (ia64_do_signal(&oldset, scr, 1))
- return -EINTR;
- }
-}
-
asmlinkage long
sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
long arg3, long arg4, long arg5, long arg6, long arg7,
@@ -477,10 +436,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
* Note that `init' is a special process: it doesn't get signals it doesn't want to
* handle. Thus you cannot kill init even with a SIGKILL even by mistake.
*/
-long
-ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
+void
+ia64_do_signal (struct sigscratch *scr, long in_syscall)
{
struct k_sigaction ka;
+ sigset_t *oldset;
siginfo_t info;
long restart = in_syscall;
long errno = scr->pt.r8;
@@ -492,9 +452,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* doing anything if so.
*/
if (!user_mode(&scr->pt))
- return 0;
+ return;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
/*
@@ -557,8 +519,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV...
*/
- if (handle_signal(signr, &ka, &info, oldset, scr))
- return 1;
+ if (handle_signal(signr, &ka, &info, oldset, scr)) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ return;
+ }
}
/* Did we come from a system call? */
@@ -584,5 +553,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
}
}
}
- return 0;
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
}
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 55ddd809b02d..221de3804560 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -50,6 +50,18 @@
#include <asm/mca.h>
/*
+ * Note: alignment of 4 entries/cacheline was empirically determined
+ * to be a good tradeoff between hot cachelines & spreading the array
+ * across too many cacheline.
+ */
+static struct local_tlb_flush_counts {
+ unsigned int count;
+} __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS];
+
+static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_aligned;
+
+
+/*
* Structure and data for smp_call_function(). This is designed to minimise static memory
* requirements. It also looks cleaner.
*/
@@ -248,6 +260,62 @@ smp_send_reschedule (int cpu)
platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
}
+/*
+ * Called with preeemption disabled.
+ */
+static void
+smp_send_local_flush_tlb (int cpu)
+{
+ platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0);
+}
+
+void
+smp_local_flush_tlb(void)
+{
+ /*
+ * Use atomic ops. Otherwise, the load/increment/store sequence from
+ * a "++" operation can have the line stolen between the load & store.
+ * The overhead of the atomic op in negligible in this case & offers
+ * significant benefit for the brief periods where lots of cpus
+ * are simultaneously flushing TLBs.
+ */
+ ia64_fetchadd(1, &local_tlb_flush_counts[smp_processor_id()].count, acq);
+ local_flush_tlb_all();
+}
+
+#define FLUSH_DELAY 5 /* Usec backoff to eliminate excessive cacheline bouncing */
+
+void
+smp_flush_tlb_cpumask(cpumask_t xcpumask)
+{
+ unsigned int *counts = __ia64_per_cpu_var(shadow_flush_counts);
+ cpumask_t cpumask = xcpumask;
+ int mycpu, cpu, flush_mycpu = 0;
+
+ preempt_disable();
+ mycpu = smp_processor_id();
+
+ for_each_cpu_mask(cpu, cpumask)
+ counts[cpu] = local_tlb_flush_counts[cpu].count;
+
+ mb();
+ for_each_cpu_mask(cpu, cpumask) {
+ if (cpu == mycpu)
+ flush_mycpu = 1;
+ else
+ smp_send_local_flush_tlb(cpu);
+ }
+
+ if (flush_mycpu)
+ smp_local_flush_tlb();
+
+ for_each_cpu_mask(cpu, cpumask)
+ while(counts[cpu] == local_tlb_flush_counts[cpu].count)
+ udelay(FLUSH_DELAY);
+
+ preempt_enable();
+}
+
void
smp_flush_tlb_all (void)
{
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 687500ddb4b8..94ae3c87d828 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -412,9 +412,11 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
cache_add_dev(sys_dev);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
cache_remove_dev(sys_dev);
break;
}
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 5bfb8be02b70..b8e0d70bf989 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -43,9 +43,9 @@ die (const char *str, struct pt_regs *regs, long err)
u32 lock_owner;
int lock_owner_depth;
} die = {
- .lock = SPIN_LOCK_UNLOCKED,
- .lock_owner = -1,
- .lock_owner_depth = 0
+ .lock = __SPIN_LOCK_UNLOCKED(die.lock),
+ .lock_owner = -1,
+ .lock_owner_depth = 0
};
static int die_counter;
int cpu = get_cpu();
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 93d5a3b41f69..fe1426266b9b 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -60,6 +60,7 @@
# define UNW_DEBUG_ON(n) unw_debug_level >= n
/* Do not code a printk level, not all debug lines end in newline */
# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+# undef inline
# define inline
#else /* !UNW_DEBUG */
# define UNW_DEBUG_ON(n) 0
@@ -145,7 +146,7 @@ static struct {
# endif
} unw = {
.tables = &unw.kernel_table,
- .lock = SPIN_LOCK_UNLOCKED,
+ .lock = __SPIN_LOCK_UNLOCKED(unw.lock),
.save_order = {
UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
@@ -1943,9 +1944,9 @@ EXPORT_SYMBOL(unw_unwind);
int
unw_unwind_to_user (struct unw_frame_info *info)
{
- unsigned long ip, sp, pr = 0;
+ unsigned long ip, sp, pr = info->pr;
- while (unw_unwind(info) >= 0) {
+ do {
unw_get_sp(info, &sp);
if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
< IA64_PT_REGS_SIZE) {
@@ -1963,7 +1964,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
__FUNCTION__, ip);
return -1;
}
- }
+ } while (unw_unwind(info) >= 0);
unw_get_ip(info, &ip);
UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
__FUNCTION__, ip);
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index ffad7624436c..fa4e6d4810f3 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -32,9 +32,9 @@ static struct {
} purge;
struct ia64_ctx ia64_ctx = {
- .lock = SPIN_LOCK_UNLOCKED,
- .next = 1,
- .max_ctx = ~0U
+ .lock = __SPIN_LOCK_UNLOCKED(ia64_ctx.lock),
+ .next = 1,
+ .max_ctx = ~0U
};
DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 8d2a1bfbfe7c..7f6d2360a262 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -59,6 +59,22 @@ void sn_intr_free(nasid_t local_nasid, int local_widget,
(u64) sn_irq_info->irq_cookie, 0, 0);
}
+u64 sn_intr_redirect(nasid_t local_nasid, int local_widget,
+ struct sn_irq_info *sn_irq_info,
+ nasid_t req_nasid, int req_slice)
+{
+ struct ia64_sal_retval ret_stuff;
+ ret_stuff.status = 0;
+ ret_stuff.v0 = 0;
+
+ SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
+ (u64) SAL_INTR_REDIRECT, (u64) local_nasid,
+ (u64) local_widget, __pa(sn_irq_info),
+ (u64) req_nasid, (u64) req_slice, 0);
+
+ return ret_stuff.status;
+}
+
static unsigned int sn_startup_irq(unsigned int irq)
{
return 0;
@@ -127,15 +143,8 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
struct sn_irq_info *new_irq_info;
struct sn_pcibus_provider *pci_provider;
- new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
- if (new_irq_info == NULL)
- return NULL;
-
- memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
-
- bridge = (u64) new_irq_info->irq_bridge;
+ bridge = (u64) sn_irq_info->irq_bridge;
if (!bridge) {
- kfree(new_irq_info);
return NULL; /* irq is not a device interrupt */
}
@@ -145,8 +154,25 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
local_widget = TIO_SWIN_WIDGETNUM(bridge);
else
local_widget = SWIN_WIDGETNUM(bridge);
-
vector = sn_irq_info->irq_irq;
+
+ /* Make use of SAL_INTR_REDIRECT if PROM supports it */
+ status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice);
+ if (!status) {
+ new_irq_info = sn_irq_info;
+ goto finish_up;
+ }
+
+ /*
+ * PROM does not support SAL_INTR_REDIRECT, or it failed.
+ * Revert to old method.
+ */
+ new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+ if (new_irq_info == NULL)
+ return NULL;
+
+ memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
+
/* Free the old PROM new_irq_info structure */
sn_intr_free(local_nasid, local_widget, new_irq_info);
unregister_intr_pda(new_irq_info);
@@ -162,11 +188,18 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
return NULL;
}
+ register_intr_pda(new_irq_info);
+ spin_lock(&sn_irq_info_lock);
+ list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+ spin_unlock(&sn_irq_info_lock);
+ call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+
+
+finish_up:
/* Update kernels new_irq_info with new target info */
cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
new_irq_info->irq_slice);
new_irq_info->irq_cpuid = cpuid;
- register_intr_pda(new_irq_info);
pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
@@ -178,11 +211,6 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
pci_provider && pci_provider->target_interrupt)
(pci_provider->target_interrupt)(new_irq_info);
- spin_lock(&sn_irq_info_lock);
- list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
- spin_unlock(&sn_irq_info_lock);
- call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
-
#ifdef CONFIG_SMP
cpuphys = cpu_physical_id(cpuid);
set_irq_affinity_info((vector & 0xff), cpuphys, 0);
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 601747b1e22a..5d318b579fb1 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -46,6 +46,9 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats);
static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
+/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */
+static int sn2_flush_opt = 0;
+
extern unsigned long
sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
volatile unsigned long *, unsigned long,
@@ -76,6 +79,8 @@ struct ptc_stats {
unsigned long shub_itc_clocks;
unsigned long shub_itc_clocks_max;
unsigned long shub_ptc_flushes_not_my_mm;
+ unsigned long shub_ipi_flushes;
+ unsigned long shub_ipi_flushes_itc_clocks;
};
#define sn2_ptctest 0
@@ -121,6 +126,18 @@ void sn_tlb_migrate_finish(struct mm_struct *mm)
flush_tlb_mm(mm);
}
+static void
+sn2_ipi_flush_all_tlb(struct mm_struct *mm)
+{
+ unsigned long itc;
+
+ itc = ia64_get_itc();
+ smp_flush_tlb_cpumask(mm->cpu_vm_mask);
+ itc = ia64_get_itc() - itc;
+ __get_cpu_var(ptcstats).shub_ipi_flushes_itc_clocks += itc;
+ __get_cpu_var(ptcstats).shub_ipi_flushes++;
+}
+
/**
* sn2_global_tlb_purge - globally purge translation cache of virtual address range
* @mm: mm_struct containing virtual address range
@@ -154,7 +171,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
short nasids[MAX_NUMNODES], nix;
nodemask_t nodes_flushed;
- int active, max_active, deadlock;
+ int active, max_active, deadlock, flush_opt = sn2_flush_opt;
+
+ if (flush_opt > 2) {
+ sn2_ipi_flush_all_tlb(mm);
+ return;
+ }
nodes_clear(nodes_flushed);
i = 0;
@@ -189,6 +211,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
return;
}
+ if (flush_opt == 2) {
+ sn2_ipi_flush_all_tlb(mm);
+ preempt_enable();
+ return;
+ }
+
itc = ia64_get_itc();
nix = 0;
for_each_node_mask(cnode, nodes_flushed)
@@ -256,6 +284,8 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
}
if (active >= max_active || i == (nix - 1)) {
if ((deadlock = wait_piowc())) {
+ if (flush_opt == 1)
+ goto done;
sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
if (reset_max_active_on_deadlock())
max_active = 1;
@@ -267,6 +297,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
start += (1UL << nbits);
} while (start < end);
+done:
itc2 = ia64_get_itc() - itc2;
__get_cpu_var(ptcstats).shub_itc_clocks += itc2;
if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
@@ -279,6 +310,11 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
spin_unlock_irqrestore(PTC_LOCK(shub1), flags);
+ if (flush_opt == 1 && deadlock) {
+ __get_cpu_var(ptcstats).deadlocks++;
+ sn2_ipi_flush_all_tlb(mm);
+ }
+
preempt_enable();
}
@@ -425,24 +461,42 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data)
if (!cpu) {
seq_printf(file,
- "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n");
- seq_printf(file, "# ptctest %d\n", sn2_ptctest);
+ "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n");
+ seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt);
}
if (cpu < NR_CPUS && cpu_online(cpu)) {
stat = &per_cpu(ptcstats, cpu);
- seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
+ seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
stat->deadlocks,
1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
stat->shub_ptc_flushes_not_my_mm,
- stat->deadlocks2);
+ stat->deadlocks2,
+ stat->shub_ipi_flushes,
+ 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec);
}
return 0;
}
+static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data)
+{
+ int cpu;
+ char optstr[64];
+
+ if (copy_from_user(optstr, user, count))
+ return -EFAULT;
+ optstr[count - 1] = '\0';
+ sn2_flush_opt = simple_strtoul(optstr, NULL, 0);
+
+ for_each_online_cpu(cpu)
+ memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats));
+
+ return count;
+}
+
static struct seq_operations sn2_ptc_seq_ops = {
.start = sn2_ptc_seq_start,
.next = sn2_ptc_seq_next,
@@ -458,6 +512,7 @@ static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
static const struct file_operations proc_sn2_ptc_operations = {
.open = sn2_ptc_proc_open,
.read = seq_read,
+ .write = sn2_ptc_proc_write,
.llseek = seq_lseek,
.release = seq_release,
};
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
index 763c9aa0b4fd..9ff47bd09aee 100644
--- a/arch/m68knommu/Kconfig.debug
+++ b/arch/m68knommu/Kconfig.debug
@@ -5,7 +5,7 @@ source "lib/Kconfig.debug"
config FULLDEBUG
bool "Full Symbolic/Source Debugging support"
help
- Enable debuging symbols on kernel build.
+ Enable debugging symbols on kernel build.
config HIGHPROFILE
bool "Use fast second timer for profiling"
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index b988c7bdc6e4..7cd183d346ef 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -31,7 +31,7 @@ int main(void)
DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
- DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b7cb048bc771..16ecea3c0813 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -956,7 +956,7 @@ choice
byte order. These modes require different kernels and a different
Linux distribution. In general there is one preferred byteorder for a
particular system but some systems are just as commonly used in the
- one or the other endianess.
+ one or the other endianness.
config CPU_BIG_ENDIAN
bool "Big endian"
@@ -1750,7 +1750,7 @@ config ARCH_DISCONTIGMEM_ENABLE
bool
default y if SGI_IP27
help
- Say Y to upport efficient handling of discontiguous physical memory,
+ Say Y to support efficient handling of discontiguous physical memory,
for architectures which are either NUMA (Non-Uniform Memory Access)
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
@@ -1938,7 +1938,7 @@ config KEXEC
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
- but it is indepedent of the system firmware. And like a reboot
+ but it is independent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.
The name comes from the similiarity to the exec system call.
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f2f742df32c7..4892db88a86a 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -92,7 +92,7 @@ cflags-y += -ffreestanding
# when fed the toolchain default!
#
# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of
-# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL
+# 2006-10-10 don't properly change the predefined symbols if -EB / -EL
# are used, so we kludge that here. A bug has been filed at
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413.
#
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 761a779d5c4f..3b27309d54b1 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -82,7 +82,7 @@ void output_task_defines(void)
{
text("/* MIPS task_struct offsets. */");
offset("#define TASK_STATE ", struct task_struct, state);
- offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info);
+ offset("#define TASK_THREAD_INFO ", struct task_struct, stack);
offset("#define TASK_FLAGS ", struct task_struct, flags);
offset("#define TASK_MM ", struct task_struct, mm);
offset("#define TASK_PID ", struct task_struct, pid);
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 5dcfab6b288e..b361edb83dc6 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -560,7 +560,7 @@ void smtc_boot_secondary(int cpu, struct task_struct *idle)
write_tc_gpr_sp(__KSTK_TOS(idle));
/* global pointer */
- write_tc_gpr_gp((unsigned long)idle->thread_info);
+ write_tc_gpr_gp((unsigned long)task_thread_info(idle));
smtc_status |= SMTC_MTC_ACTIVE;
write_tc_c0_tchalt(0);
diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c
index 7a7444874e80..0ad39e53f7b1 100644
--- a/arch/mips/pci/fixup-sb1250.c
+++ b/arch/mips/pci/fixup-sb1250.c
@@ -14,7 +14,7 @@
#include <linux/pci.h>
/*
- * Set the the BCM1250, etc. PCI host bridge's TRDY timeout
+ * Set the BCM1250, etc. PCI host bridge's TRDY timeout
* to the finite max.
*/
static void __init quirk_sb1250_pci(struct pci_dev *dev)
@@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
quirk_sb1250_ht);
/*
- * Set the the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
+ * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
*/
static void __init quirk_sp1011(struct pci_dev *dev)
{
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index 54fdb959149c..d3b7917a87cb 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -54,7 +54,7 @@
int main(void)
{
- DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(TASK_STATE, offsetof(struct task_struct, state));
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index f70e795c262e..346cd3befe1e 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -32,7 +32,7 @@ config HCALL_STATS
depends on PPC_PSERIES && DEBUG_FS
help
Adds code to keep track of the number of hypervisor calls made and
- the amount of time spent in hypervisor callsr. Wall time spent in
+ the amount of time spent in hypervisor calls. Wall time spent in
each call is always calculated, and if available CPU cycles spent
are also calculated. A directory named hcall_inst is added at the
root of the debugfs filesystem. Within the hcall_inst directory
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index d6803fb7b28b..2cb1d9487796 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -58,7 +58,7 @@ int main(void)
#ifdef CONFIG_PPC64
DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
#else
- DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index cae39d9dfe48..68991c2d4a1b 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -342,10 +342,12 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
register_cpu_online(cpu);
break;
#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
unregister_cpu_online(cpu);
break;
#endif
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b3a592b25ab3..de45aa82d97b 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -252,12 +252,15 @@ static int __cpuinit cpu_numa_callback(struct notifier_block *nfb,
switch (action) {
case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
numa_setup_cpu(lcpu);
ret = NOTIFY_OK;
break;
#ifdef CONFIG_HOTPLUG_CPU
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
unmap_cpu_from_node(lcpu);
break;
ret = NOTIFY_OK;
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index 626b29f38304..c29293befba9 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -747,7 +747,7 @@ cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr)
* counter value etc.) are not copied to the actual registers
* until the performance monitor is enabled. In order to get
* this to work as desired, the permormance monitor needs to
- * be disabled while writting to the latches. This is a
+ * be disabled while writing to the latches. This is a
* HW design issue.
*/
cbe_enable_pm(cpu);
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index a35315af5c53..cf0e7bc8c2e7 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc86xads-setup.c
+/*arch/powerpc/platforms/8xx/mpc86xads_setup.c
*
* Platform setup for the Freescale mpc86xads board
*
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index a57b57785acd..c36e475d93dc 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc885ads-setup.c
+/*arch/powerpc/platforms/8xx/mpc885ads_setup.c
*
* Platform setup for the Freescale mpc885ads board
*
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index d68d920eb2c4..7fb92f23f380 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -74,7 +74,7 @@ static void spider_io_flush(const volatile void __iomem *addr)
/* Fast path if we have a non-0 token, it indicates which bus we
* are on.
*
- * If the token is 0, that means either the the ioremap was done
+ * If the token is 0, that means either that the ioremap was done
* before we initialized this layer, or it's a PIO operation. We
* fallback to a low path in this case. Hopefully, internal devices
* which are ioremap'ed early should use in_XX/out_XX functions
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index c5850a272650..e8e94321b59e 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -35,7 +35,7 @@ int
main(void)
{
DEFINE(THREAD, offsetof(struct task_struct, thread));
- DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
DEFINE(MM, offsetof(struct task_struct, mm));
DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(KSP, offsetof(struct thread_struct, ksp));
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index 7ce5364fdb3b..bf72204125c5 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -1,4 +1,4 @@
-/*arch/ppc/platforms/mpc866ads-setup.c
+/*arch/ppc/platforms/mpc866ads_setup.c
*
* Platform setup for the Freescale mpc866ads board
*
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
index 10659c24b1be..9192777d0f78 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/ppc/syslib/ipic.c
@@ -1,5 +1,5 @@
/*
- * include/asm-ppc/ipic.c
+ * arch/ppc/syslib/ipic.c
*
* IPIC routines implementations.
*
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index ee89b33145d5..81a2b92ab0c2 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -567,9 +567,11 @@ appldata_cpu_notify(struct notifier_block *self,
{
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
appldata_online_cpu((long) hcpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
appldata_offline_cpu((long) hcpu);
break;
default:
diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig
index 99ff9f08e4d7..d1defbbfcd81 100644
--- a/arch/s390/crypto/Kconfig
+++ b/arch/s390/crypto/Kconfig
@@ -54,7 +54,7 @@ config S390_PRNG
default "m"
help
Select this option if you want to use the s390 pseudo random number
- generator. The PRNG is part of the cryptograhic processor functions
+ generator. The PRNG is part of the cryptographic processor functions
and uses triple-DES to generate secure random numbers like the
ANSI X9.17 standard. The PRNG is usable via the char device
/dev/prandom.
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index ec514fe5ccd0..1375f8a4469e 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -15,7 +15,7 @@
int main(void)
{
- DEFINE(__THREAD_info, offsetof(struct task_struct, thread_info),);
+ DEFINE(__THREAD_info, offsetof(struct task_struct, stack),);
DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
DEFINE(__THREAD_mm_segment,
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b7977027a28f..09f028a3266b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -789,10 +789,12 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
if (sysdev_create_file(s, &attr_capability))
return NOTIFY_BAD;
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
sysdev_remove_file(s, &attr_capability);
break;
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d74eb120a9c6..038179ecf6a9 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -52,6 +52,9 @@ config GENERIC_IOMAP
config GENERIC_TIME
def_bool n
+config GENERIC_CLOCKEVENTS
+ def_bool n
+
config SYS_SUPPORTS_APM_EMULATION
bool
@@ -436,11 +439,11 @@ endmenu
menu "Timer and clock configuration"
-if !GENERIC_TIME
-
config SH_TMU
bool "TMU timer support"
depends on CPU_SH3 || CPU_SH4
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
default y
help
This enables the use of the TMU as the system timer.
@@ -459,8 +462,6 @@ config SH_MTU2
help
This enables the use of the MTU2 as the system timer.
-endif
-
config SH_TIMER_IRQ
int
default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
@@ -468,24 +469,6 @@ config SH_TIMER_IRQ
default "140" if CPU_SUBTYPE_SH7206
default "16"
-config NO_IDLE_HZ
- bool "Dynamic tick timer"
- help
- Select this option if you want to disable continuous timer ticks
- and have them programmed to occur as required. This option saves
- power as the system can remain in idle state for longer.
-
- By default dynamic tick is disabled during the boot, and can be
- manually enabled with:
-
- echo 1 > /sys/devices/system/timer/timer0/dyn_tick
-
- Alternatively, if you want dynamic tick automatically enabled
- during boot, pass "dyntick=enable" via the kernel command string.
-
- Please note that dynamic tick may affect the accuracy of
- timekeeping on some platforms depending on the implementation.
-
config SH_PCLK_FREQ
int "Peripheral clock frequency (in Hz)"
default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
@@ -509,6 +492,8 @@ config SH_CLK_MD
help
MD2 - MD0 pin setting.
+source "kernel/time/Kconfig"
+
endmenu
menu "CPU Frequency scaling"
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index a83a5d9587bb..4058b4f50d44 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -93,6 +93,7 @@ static void __init landisk_setup(char **cmdline_p)
*/
struct sh_machine_vector mv_landisk __initmv = {
.mv_name = "LANDISK",
+ .mv_nr_irqs = 72,
.mv_setup = landisk_setup,
.mv_init_irq = init_landisk_IRQ,
};
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c
index 770defed9c4a..52c7bfa57c2c 100644
--- a/arch/sh/boards/se/7751/setup.c
+++ b/arch/sh/boards/se/7751/setup.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/sh/kernel/setup_7751se.c
+ * linux/arch/sh/boards/se/7751/setup.c
*
* Copyright (C) 2000 Kazumoto Kojima
*
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index 6cb92676c5fc..e13f06bebd92 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -2,8 +2,9 @@
# Makefile for the Linux SuperH-specific device drivers.
#
+obj-y += dma/
+
obj-$(CONFIG_PCI) += pci/
-obj-$(CONFIG_SH_DMA) += dma/
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_PUSH_SWITCH) += push-switch.o
obj-$(CONFIG_HEARTBEAT) += heartbeat.o
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index defc13c37d48..99935f9daf4b 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -1,12 +1,12 @@
menu "DMA support"
-config SH_DMA
- bool "DMA controller (DMAC) support"
- help
- Selecting this option will provide same API as PC's Direct Memory
- Access Controller(8237A) for SuperH DMAC.
+config SH_DMA_API
+ bool
- If unsure, say N.
+config SH_DMA
+ bool "SuperH on-chip DMA controller (DMAC) support"
+ select SH_DMA_API
+ default n
config NR_ONCHIP_DMA_CHANNELS
depends on SH_DMA
@@ -53,4 +53,12 @@ config DMA_PAGE_OPS_CHANNEL
in case channel 3 is unavailable. On the SH4, channels 1,2, and 3
are dual-address capable.
+config SH_DMABRG
+ bool "SH7760 DMABRG support"
+ depends on CPU_SUBTYPE_SH7760
+ help
+ The DMABRG does data transfers from main memory to Audio/USB units
+ of the SH7760.
+ Say Y if you want to use Audio/USB DMA on your SH7760 board.
+
endmenu
diff --git a/arch/sh/drivers/dma/Makefile b/arch/sh/drivers/dma/Makefile
index db1295d32268..1ac812d24488 100644
--- a/arch/sh/drivers/dma/Makefile
+++ b/arch/sh/drivers/dma/Makefile
@@ -2,8 +2,8 @@
# Makefile for the SuperH DMA specific kernel interface routines under Linux.
#
-obj-y += dma-api.o
+obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o
obj-$(CONFIG_ISA_DMA_API) += dma-isa.o
-obj-$(CONFIG_SYSFS) += dma-sysfs.o
obj-$(CONFIG_SH_DMA) += dma-sh.o
obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o
+obj-$(CONFIG_SH_DMABRG) += dmabrg.o
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
new file mode 100644
index 000000000000..9d0a29370f21
--- /dev/null
+++ b/arch/sh/drivers/dma/dmabrg.c
@@ -0,0 +1,196 @@
+/*
+ * SH7760 DMABRG IRQ handling
+ *
+ * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
+ * licensed under the GPLv2.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/dmabrg.h>
+#include <asm/io.h>
+
+/*
+ * The DMABRG is a special DMA unit within the SH7760. It does transfers
+ * from USB-SRAM/Audio units to main memory (and also the LCDC; but that
+ * part is sensibly placed in the LCDC registers and requires no irqs)
+ * It has 3 IRQ lines which trigger 10 events, and works independently
+ * from the traditional SH DMAC (although it blocks usage of DMAC 0)
+ *
+ * BRGIRQID | component | dir | meaning | source
+ * -----------------------------------------------------
+ * 0 | USB-DMA | ... | xfer done | DMABRGI1
+ * 1 | USB-UAE | ... | USB addr err.| DMABRGI0
+ * 2 | HAC0/SSI0 | play| all done | DMABRGI1
+ * 3 | HAC0/SSI0 | play| half done | DMABRGI2
+ * 4 | HAC0/SSI0 | rec | all done | DMABRGI1
+ * 5 | HAC0/SSI0 | rec | half done | DMABRGI2
+ * 6 | HAC1/SSI1 | play| all done | DMABRGI1
+ * 7 | HAC1/SSI1 | play| half done | DMABRGI2
+ * 8 | HAC1/SSI1 | rec | all done | DMABRGI1
+ * 9 | HAC1/SSI1 | rec | half done | DMABRGI2
+ *
+ * all can be enabled/disabled in the DMABRGCR register,
+ * as well as checked if they occured.
+ *
+ * DMABRGI0 services USB DMA Address errors, but it still must be
+ * enabled/acked in the DMABRGCR register. USB-DMA complete indicator
+ * is grouped together with the audio buffer end indicators, too bad...
+ *
+ * DMABRGCR: Bits 31-24: audio-dma ENABLE flags,
+ * Bits 23-16: audio-dma STATUS flags,
+ * Bits 9-8: USB error/xfer ENABLE,
+ * Bits 1-0: USB error/xfer STATUS.
+ * Ack an IRQ by writing 0 to the STATUS flag.
+ * Mask IRQ by writing 0 to ENABLE flag.
+ *
+ * Usage is almost like with any other IRQ:
+ * dmabrg_request_irq(BRGIRQID, handler, data)
+ * dmabrg_free_irq(BRGIRQID)
+ *
+ * handler prototype: void brgirqhandler(void *data)
+ */
+
+#define DMARSRA 0xfe090000
+#define DMAOR 0xffa00040
+#define DMACHCR0 0xffa0000c
+#define DMABRGCR 0xfe3c0000
+
+#define DMAOR_BRG 0x0000c000
+#define DMAOR_DMEN 0x00000001
+
+#define DMABRGI0 68
+#define DMABRGI1 69
+#define DMABRGI2 70
+
+struct dmabrg_handler {
+ void (*handler)(void *);
+ void *data;
+} *dmabrg_handlers;
+
+static inline void dmabrg_call_handler(int i)
+{
+ dmabrg_handlers[i].handler(dmabrg_handlers[i].data);
+}
+
+/*
+ * main DMABRG irq handler. It acks irqs and then
+ * handles every set and unmasked bit sequentially.
+ * No locking and no validity checks; it should be
+ * as fast as possible (audio!)
+ */
+static irqreturn_t dmabrg_irq(int irq, void *data)
+{
+ unsigned long dcr;
+ unsigned int i;
+
+ dcr = ctrl_inl(DMABRGCR);
+ ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */
+ dcr &= dcr >> 8; /* ignore masked */
+
+ /* USB stuff, get it out of the way first */
+ if (dcr & 1)
+ dmabrg_call_handler(DMABRGIRQ_USBDMA);
+ if (dcr & 2)
+ dmabrg_call_handler(DMABRGIRQ_USBDMAERR);
+
+ /* Audio */
+ dcr >>= 16;
+ while (dcr) {
+ i = __ffs(dcr);
+ dcr &= dcr - 1;
+ dmabrg_call_handler(i + DMABRGIRQ_A0TXF);
+ }
+ return IRQ_HANDLED;
+}
+
+static void dmabrg_disable_irq(unsigned int dmairq)
+{
+ unsigned long dcr;
+ dcr = ctrl_inl(DMABRGCR);
+ dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+ ctrl_outl(dcr, DMABRGCR);
+}
+
+static void dmabrg_enable_irq(unsigned int dmairq)
+{
+ unsigned long dcr;
+ dcr = ctrl_inl(DMABRGCR);
+ dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8));
+ ctrl_outl(dcr, DMABRGCR);
+}
+
+int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*),
+ void *data)
+{
+ if ((dmairq > 9) || !handler)
+ return -ENOENT;
+ if (dmabrg_handlers[dmairq].handler)
+ return -EBUSY;
+
+ dmabrg_handlers[dmairq].handler = handler;
+ dmabrg_handlers[dmairq].data = data;
+
+ dmabrg_enable_irq(dmairq);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dmabrg_request_irq);
+
+void dmabrg_free_irq(unsigned int dmairq)
+{
+ if (likely(dmairq < 10)) {
+ dmabrg_disable_irq(dmairq);
+ dmabrg_handlers[dmairq].handler = NULL;
+ dmabrg_handlers[dmairq].data = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(dmabrg_free_irq);
+
+static int __init dmabrg_init(void)
+{
+ unsigned long or;
+ int ret;
+
+ dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler),
+ GFP_KERNEL);
+ if (!dmabrg_handlers)
+ return -ENOMEM;
+
+#ifdef CONFIG_SH_DMA
+ /* request DMAC channel 0 before anyone else can get it */
+ ret = request_dma(0, "DMAC 0 (DMABRG)");
+ if (ret < 0)
+ printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n");
+#endif
+
+ ctrl_outl(0, DMABRGCR);
+ ctrl_outl(0, DMACHCR0);
+ ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */
+
+ /* enable DMABRG mode, enable the DMAC */
+ or = ctrl_inl(DMAOR);
+ ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR);
+
+ ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED,
+ "DMABRG USB address error", NULL);
+ if (ret)
+ goto out0;
+
+ ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED,
+ "DMABRG Transfer End", NULL);
+ if (ret)
+ goto out1;
+
+ ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED,
+ "DMABRG Transfer Half", NULL);
+ if (ret == 0)
+ return ret;
+
+ free_irq(DMABRGI1, 0);
+out1: free_irq(DMABRGI0, 0);
+out0: kfree(dmabrg_handlers);
+ return ret;
+}
+subsys_initcall(dmabrg_init);
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 350972ae9410..965fa2572b23 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -2,9 +2,8 @@
# Makefile for the Linux/SuperH SH-2A backends.
#
-obj-y := common.o probe.o
+obj-y := common.o probe.o opcode_helper.o
-common-y += $(addprefix ../sh2/, ex.o)
-common-y += $(addprefix ../sh2/, entry.o)
+common-y += $(addprefix ../sh2/, ex.o entry.o)
obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
new file mode 100644
index 000000000000..9704b7926d8b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
@@ -0,0 +1,55 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/opcode_helper.c
+ *
+ * Helper for the SH-2A 32-bit opcodes.
+ *
+ * Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <asm/system.h>
+
+/*
+ * Instructions on SH are generally fixed at 16-bits, however, SH-2A
+ * introduces some 32-bit instructions. Since there are no real
+ * constraints on their use (and they can be mixed and matched), we need
+ * to check the instruction encoding to work out if it's a true 32-bit
+ * instruction or not.
+ *
+ * Presently, 32-bit opcodes have only slight variations in what the
+ * actual encoding looks like in the first-half of the instruction, which
+ * makes it fairly straightforward to differentiate from the 16-bit ones.
+ *
+ * First 16-bits of encoding Used by
+ *
+ * 0011nnnnmmmm0001 mov.b, mov.w, mov.l, fmov.d,
+ * fmov.s, movu.b, movu.w
+ *
+ * 0011nnnn0iii1001 bclr.b, bld.b, bset.b, bst.b, band.b,
+ * bandnot.b, bldnot.b, bor.b, bornot.b,
+ * bxor.b
+ *
+ * 0000nnnniiii0000 movi20
+ * 0000nnnniiii0001 movi20s
+ */
+unsigned int instruction_size(unsigned int insn)
+{
+ /* Look for the common cases */
+ switch ((insn & 0xf00f)) {
+ case 0x0000: /* movi20 */
+ case 0x0001: /* movi20s */
+ case 0x3001: /* 32-bit mov/fmov/movu variants */
+ return 4;
+ }
+
+ /* And the special cases.. */
+ switch ((insn & 0xf08f)) {
+ case 0x3009: /* 32-bit b*.b bit operations */
+ return 4;
+ }
+
+ return 2;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 426f6db01fc6..f455c3509789 100644
--- a/arch/sh/kernel/cpu/sh2a/probe.c
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -18,6 +18,7 @@ int __init detect_cpu_and_cache_system(void)
{
/* Just SH7206 for now .. */
current_cpu_data.type = CPU_SH7206;
+ current_cpu_data.flags |= CPU_HAS_OP32;
current_cpu_data.dcache.ways = 4;
current_cpu_data.dcache.way_incr = (1 << 11);
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index f3e827f29a46..832c0b4a1e6c 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/entry.S
+ * arch/sh/kernel/cpu/sh3/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2003 - 2006 Paul Mundt
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index ba3082d640b5..2b2a9e02fb75 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -1,7 +1,7 @@
/*
* arch/sh/kernel/cpu/sh3/ex.S
*
- * The SH-3 exception vector table.
+ * The SH-3 and SH-4 exception vector table.
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2003 - 2006 Paul Mundt
@@ -9,7 +9,6 @@
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
- *
*/
#include <linux/linkage.h>
@@ -36,8 +35,12 @@ ENTRY(exception_handling_table)
.long exception_error ! address error load
.long exception_error ! address error store /* 100 */
#endif
- .long exception_error ! fpu_exception /* 120 */
- .long exception_error /* 140 */
+#if defined(CONFIG_SH_FPU)
+ .long do_fpu_error /* 120 */
+#else
+ .long exception_error /* 120 */
+#endif
+ .long exception_error /* 140 */
.long system_call ! Unconditional Trap /* 160 */
.long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
.long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
@@ -55,4 +58,4 @@ ENTRY(user_break_point_trap)
* away offsets can be manually inserted in to their appropriate
* location via set_exception_table_{evt,vec}().
*/
- .balign 4096,0,4096
+ .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 19ca68c71884..8add10bd8268 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -2,10 +2,10 @@
# Makefile for the Linux/SuperH SH-4 backends.
#
-obj-y := ex.o probe.o common.o
-common-y += $(addprefix ../sh3/, entry.o)
+obj-y := probe.o common.o
+common-y += $(addprefix ../sh3/, entry.o ex.o)
-obj-$(CONFIG_SH_FPU) += fpu.o
+obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
# CPU subtype setup
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
deleted file mode 100644
index ac8ab57413cc..000000000000
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * arch/sh/kernel/cpu/sh4/ex.S
- *
- * The SH-4 exception vector table.
-
- * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2003 - 2006 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
-#include <linux/linkage.h>
-
- .align 2
- .data
-
-ENTRY(exception_handling_table)
- .long exception_error /* 000 */
- .long exception_error
-#if defined(CONFIG_MMU)
- .long tlb_miss_load /* 040 */
- .long tlb_miss_store
- .long initial_page_write
- .long tlb_protection_violation_load
- .long tlb_protection_violation_store
- .long address_error_load
- .long address_error_store /* 100 */
-#else
- .long exception_error ! tlb miss load /* 040 */
- .long exception_error ! tlb miss store
- .long exception_error ! initial page write
- .long exception_error ! tlb prot violation load
- .long exception_error ! tlb prot violation store
- .long exception_error ! address error load
- .long exception_error ! address error store /* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
- .long do_fpu_error /* 120 */
-#else
- .long exception_error /* 120 */
-#endif
- .long exception_error /* 140 */
- .long system_call ! Unconditional Trap /* 160 */
- .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
- .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
-#if defined (CONFIG_KGDB_NMI)
- .long debug_enter /* 1C0 */ ! Allow trap to debugger
-#else
- .long exception_none /* 1C0 */ ! Not implemented yet
-#endif
-ENTRY(user_break_point_trap)
- .long break_point_trap /* 1E0 */
-
- /*
- * Pad the remainder of the table out, exceptions residing in far
- * away offsets can be manually inserted in to their appropriate
- * location via set_exception_table_{evt,vec}().
- */
- .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index 7624677f6628..d61dd599169f 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -16,6 +16,7 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/processor.h>
+#include <asm/system.h>
#include <asm/io.h>
/* The PR (precision) bit in the FP Status Register must be clear when
@@ -265,7 +266,7 @@ ieee_fpe_handler (struct pt_regs *regs)
nextpc = regs->pr;
finsn = *(unsigned short *) (regs->pc + 2);
} else {
- nextpc = regs->pc + 2;
+ nextpc = regs->pc + instruction_size(insn);
finsn = insn;
}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh73180.c b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
index 2fa5cb2ae68d..6d5ba373a75e 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/cpu/sh4/clock-sh73180.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh73180.c
*
* SH73180 support for the clock framework
*
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
index 1707a213f0cf..7adc4f16e95a 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
*
* SH7343/SH7722 support for the clock framework
*
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
index c8694bac6477..8e236062c721 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/cpu/sh4/clock-sh7770.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7770.c
*
* SH7770 support for the clock framework
*
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index 9e6a216750c8..01f3da619d3d 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/cpu/sh4/clock-sh7780.c
+ * arch/sh/kernel/cpu/sh4a/clock-sh7780.c
*
* SH7780 support for the clock framework
*
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 329b3f3051de..6b4f5748d0be 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -15,9 +15,12 @@
#include <linux/pm.h>
#include <linux/kallsyms.h>
#include <linux/kexec.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
#include <asm/ubc.h>
static int hlt_counter;
@@ -58,12 +61,15 @@ void cpu_idle(void)
if (!idle)
idle = default_idle;
+ tick_nohz_stop_sched_tick();
while (!need_resched())
idle();
+ tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
+ check_pgt_cache();
}
}
@@ -495,9 +501,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
/* Rewind */
- regs->pc -= 2;
+ regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
- if (notify_die(DIE_TRAP, regs, regs->tra & 0xff,
+ if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff,
SIGTRAP) == NOTIFY_STOP)
return;
@@ -514,9 +520,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
/* Rewind */
- regs->pc -= 2;
+ regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
- if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff,
+ if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
SIGTRAP) == NOTIFY_STOP)
return;
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 477d2a854fc4..c27729135935 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c)
/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
static const char *cpu_flags[] = {
"none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
- "ptea", "llsc", "l2", NULL
+ "ptea", "llsc", "l2", "op32", NULL
};
static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index fa91641c1f62..c1cfcb9f047c 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -58,8 +58,6 @@ EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__ndelay);
EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__div64_32);
-
#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
/* These symbols are generated by the compiler itself */
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index eb0191c374b6..b32c35a7c0a3 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,7 +23,7 @@
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/freezer.h>
-
+#include <asm/system.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -500,7 +500,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
}
/* fallthrough */
case -ERESTARTNOINTR:
- regs->pc -= 2;
+ regs->pc -= instruction_size(
+ ctrl_inw(regs->pc - 4));
+ break;
}
} else {
/* gUSA handling */
@@ -516,7 +518,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
regs->regs[15] = regs->regs[1];
if (regs->pc < regs->regs[0])
/* Go to rewind point #1 */
- regs->pc = regs->regs[0] + offset - 2;
+ regs->pc = regs->regs[0] + offset -
+ instruction_size(ctrl_inw(regs->pc-4));
}
#ifdef CONFIG_PREEMPT
local_irq_restore(flags);
@@ -600,9 +603,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
regs->regs[0] == -ERESTARTSYS ||
regs->regs[0] == -ERESTARTNOINTR) {
regs->regs[0] = save_r0;
- regs->pc -= 2;
+ regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
} else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
- regs->pc -= 2;
+ regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
regs->regs[3] = __NR_restart_syscall;
}
}
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 4bdd2f83535d..d41e561be20e 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -17,7 +17,7 @@
/*
* Save stack-backtrace addresses into a stack_trace buffer.
*/
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
{
unsigned long *sp = (unsigned long *)current_stack_pointer;
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 38fc8cd3ea3a..4357d1a6358f 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -354,3 +354,4 @@ ENTRY(sys_call_table)
.long sys_move_pages
.long sys_getcpu
.long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index d47e775962e9..a3a67d151e52 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2002 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2007 Paul Mundt
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
*
* Some code taken from i386 version.
@@ -15,6 +15,7 @@
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/sched.h>
+#include <linux/clockchips.h>
#include <asm/clock.h>
#include <asm/rtc.h>
#include <asm/timer.h>
@@ -38,6 +39,14 @@ static int null_rtc_set_time(const time_t secs)
return 0;
}
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static cycle_t null_hpt_read(void)
+{
+ return 0;
+}
+
void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
@@ -101,6 +110,7 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
#endif /* !CONFIG_GENERIC_TIME */
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
/* last time the RTC clock got updated */
static long last_rtc_update;
@@ -138,6 +148,7 @@ void handle_timer_tick(void)
last_rtc_update = xtime.tv_sec - 600;
}
}
+#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
#ifdef CONFIG_PM
int timer_suspend(struct sys_device *dev, pm_message_t state)
@@ -168,136 +179,58 @@ static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
};
-#ifdef CONFIG_NO_IDLE_HZ
-static int timer_dyn_tick_enable(void)
+static int __init timer_init_sysfs(void)
{
- struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
- unsigned long flags;
- int ret = -ENODEV;
-
- if (dyn_tick) {
- spin_lock_irqsave(&dyn_tick->lock, flags);
- ret = 0;
- if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
- ret = dyn_tick->enable();
-
- if (ret == 0)
- dyn_tick->state |= DYN_TICK_ENABLED;
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
- }
+ int ret = sysdev_class_register(&timer_sysclass);
+ if (ret != 0)
+ return ret;
- return ret;
+ sys_timer->dev.cls = &timer_sysclass;
+ return sysdev_register(&sys_timer->dev);
}
+device_initcall(timer_init_sysfs);
-static int timer_dyn_tick_disable(void)
-{
- struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
- unsigned long flags;
- int ret = -ENODEV;
-
- if (dyn_tick) {
- spin_lock_irqsave(&dyn_tick->lock, flags);
- ret = 0;
- if (dyn_tick->state & DYN_TICK_ENABLED) {
- ret = dyn_tick->disable();
-
- if (ret == 0)
- dyn_tick->state &= ~DYN_TICK_ENABLED;
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
- }
-
- return ret;
-}
+void (*board_time_init)(void);
/*
- * Reprogram the system timer for at least the calculated time interval.
- * This function should be called from the idle thread with IRQs disabled,
- * immediately before sleeping.
+ * Shamelessly based on the MIPS and Sparc64 work.
*/
-void timer_dyn_reprogram(void)
-{
- struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
- unsigned long next, seq, flags;
-
- if (!dyn_tick)
- return;
-
- spin_lock_irqsave(&dyn_tick->lock, flags);
- if (dyn_tick->state & DYN_TICK_ENABLED) {
- next = next_timer_interrupt();
- do {
- seq = read_seqbegin(&xtime_lock);
- dyn_tick->reprogram(next - jiffies);
- } while (read_seqretry(&xtime_lock, seq));
- }
- spin_unlock_irqrestore(&dyn_tick->lock, flags);
-}
+static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
+unsigned long sh_hpt_frequency = 0;
+
+#define NSEC_PER_CYC_SHIFT 10
+
+struct clocksource clocksource_sh = {
+ .name = "SuperH",
+ .rating = 200,
+ .mask = CLOCKSOURCE_MASK(32),
+ .read = null_hpt_read,
+ .shift = 16,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
-static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+static void __init init_sh_clocksource(void)
{
- return sprintf(buf, "%i\n",
- (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
-}
+ if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read)
+ return;
-static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
- size_t count)
-{
- unsigned int enable = simple_strtoul(buf, NULL, 2);
+ clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency,
+ clocksource_sh.shift);
- if (enable)
- timer_dyn_tick_enable();
- else
- timer_dyn_tick_disable();
+ timer_ticks_per_nsec_quotient =
+ clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT);
- return count;
+ clocksource_register(&clocksource_sh);
}
-static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
-/*
- * dyntick=enable|disable
- */
-static char dyntick_str[4] __initdata = "";
-
-static int __init dyntick_setup(char *str)
+#ifdef CONFIG_GENERIC_TIME
+unsigned long long sched_clock(void)
{
- if (str)
- strlcpy(dyntick_str, str, sizeof(dyntick_str));
- return 1;
+ unsigned long long ticks = clocksource_sh.read();
+ return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT;
}
-
-__setup("dyntick=", dyntick_setup);
-#endif
-
-static int __init timer_init_sysfs(void)
-{
- int ret = sysdev_class_register(&timer_sysclass);
- if (ret != 0)
- return ret;
-
- sys_timer->dev.cls = &timer_sysclass;
- ret = sysdev_register(&sys_timer->dev);
-
-#ifdef CONFIG_NO_IDLE_HZ
- if (ret == 0 && sys_timer->dyn_tick) {
- ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
-
- /*
- * Turn on dynamic tick after calibrate delay
- * for correct bogomips
- */
- if (ret == 0 && dyntick_str[0] == 'e')
- ret = timer_dyn_tick_enable();
- }
#endif
- return ret;
-}
-device_initcall(timer_init_sysfs);
-
-void (*board_time_init)(void);
-
void __init time_init(void)
{
if (board_time_init)
@@ -316,10 +249,15 @@ void __init time_init(void)
sys_timer = get_sys_timer();
printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
-#ifdef CONFIG_NO_IDLE_HZ
- if (sys_timer->dyn_tick)
- spin_lock_init(&sys_timer->dyn_tick->lock);
-#endif
+ if (sys_timer->ops->read)
+ clocksource_sh.read = sys_timer->ops->read;
+
+ init_sh_clocksource();
+
+ if (sh_hpt_frequency)
+ printk("Using %lu.%03lu MHz high precision timer.\n",
+ ((sh_hpt_frequency + 500) / 1000) / 1000,
+ ((sh_hpt_frequency + 500) / 1000) % 1000);
#if defined(CONFIG_SH_KGDB)
/*
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index d9e3151c891e..2d997e2a5b6c 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -1,7 +1,7 @@
/*
* arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
*
- * Copyright (C) 2005 Paul Mundt
+ * Copyright (C) 2005 - 2007 Paul Mundt
*
* TMU handling code hacked out of arch/sh/kernel/time.c
*
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/seqlock.h>
+#include <linux/clockchips.h>
#include <asm/timer.h>
#include <asm/rtc.h>
#include <asm/io.h>
@@ -25,56 +26,75 @@
#include <asm/clock.h>
#define TMU_TOCR_INIT 0x00
-#define TMU0_TCR_INIT 0x0020
-#define TMU_TSTR_INIT 1
+#define TMU_TCR_INIT 0x0020
-#define TMU0_TCR_CALIB 0x0000
+static int tmu_timer_start(void)
+{
+ ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
+ return 0;
+}
-static unsigned long tmu_timer_get_offset(void)
+static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
{
- int count;
- static int count_p = 0x7fffffff; /* for the first call after boot */
- static unsigned long jiffies_p = 0;
+ ctrl_outl(interval, TMU0_TCNT);
/*
- * cache volatile jiffies temporarily; we have IRQs turned off.
+ * TCNT reloads from TCOR on underflow, clear it if we don't
+ * intend to auto-reload
*/
- unsigned long jiffies_t;
+ if (reload)
+ ctrl_outl(interval, TMU0_TCOR);
+ else
+ ctrl_outl(0, TMU0_TCOR);
- /* timer count may underflow right here */
- count = ctrl_inl(TMU0_TCNT); /* read the latched count */
+ tmu_timer_start();
+}
- jiffies_t = jiffies;
+static int tmu_timer_stop(void)
+{
+ ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
+ return 0;
+}
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there is one kind of problem that must be avoided here:
- * 1. the timer counter underflows
- */
+static cycle_t tmu_timer_read(void)
+{
+ return ~ctrl_inl(TMU1_TCNT);
+}
+
+static int tmu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ tmu0_timer_set_interval(cycles, 1);
+ return 0;
+}
- if (jiffies_t == jiffies_p) {
- if (count > count_p) {
- /* the nutcase */
- if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
- count -= LATCH;
- } else {
- printk("%s (): hardware timer problem?\n",
- __FUNCTION__);
- }
- }
- } else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
-
- return count;
+static void tmu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ ctrl_outl(0, TMU0_TCOR);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ break;
+ }
}
+static struct clock_event_device tmu0_clockevent = {
+ .name = "tmu0",
+ .shift = 32,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = tmu_set_mode,
+ .set_next_event = tmu_set_next_event,
+};
+
static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
{
+ struct clock_event_device *evt = &tmu0_clockevent;
unsigned long timer_status;
/* Clear UNF bit */
@@ -82,72 +102,76 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
timer_status &= ~0x100;
ctrl_outw(timer_status, TMU0_TCR);
- /*
- * Here we are in the timer irq handler. We just have irqs locally
- * disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
- handle_timer_tick();
- write_sequnlock(&xtime_lock);
+ evt->event_handler(evt);
return IRQ_HANDLED;
}
-static struct irqaction tmu_irq = {
- .name = "timer",
+static struct irqaction tmu0_irq = {
+ .name = "periodic timer",
.handler = tmu_timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.mask = CPU_MASK_NONE,
};
-static void tmu_clk_init(struct clk *clk)
+static void tmu0_clk_init(struct clk *clk)
{
- u8 divisor = TMU0_TCR_INIT & 0x7;
- ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+ u8 divisor = TMU_TCR_INIT & 0x7;
+ ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
clk->rate = clk->parent->rate / (4 << (divisor << 1));
}
-static void tmu_clk_recalc(struct clk *clk)
+static void tmu0_clk_recalc(struct clk *clk)
{
u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
clk->rate = clk->parent->rate / (4 << (divisor << 1));
}
-static struct clk_ops tmu_clk_ops = {
- .init = tmu_clk_init,
- .recalc = tmu_clk_recalc,
+static struct clk_ops tmu0_clk_ops = {
+ .init = tmu0_clk_init,
+ .recalc = tmu0_clk_recalc,
};
static struct clk tmu0_clk = {
.name = "tmu0_clk",
- .ops = &tmu_clk_ops,
+ .ops = &tmu0_clk_ops,
};
-static int tmu_timer_start(void)
+static void tmu1_clk_init(struct clk *clk)
{
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
- return 0;
+ u8 divisor = TMU_TCR_INIT & 0x7;
+ ctrl_outw(divisor, TMU1_TCR);
+ clk->rate = clk->parent->rate / (4 << (divisor << 1));
}
-static int tmu_timer_stop(void)
+static void tmu1_clk_recalc(struct clk *clk)
{
- ctrl_outb(0, TMU_TSTR);
- return 0;
+ u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
+ clk->rate = clk->parent->rate / (4 << (divisor << 1));
}
+static struct clk_ops tmu1_clk_ops = {
+ .init = tmu1_clk_init,
+ .recalc = tmu1_clk_recalc,
+};
+
+static struct clk tmu1_clk = {
+ .name = "tmu1_clk",
+ .ops = &tmu1_clk_ops,
+};
+
static int tmu_timer_init(void)
{
unsigned long interval;
+ unsigned long frequency;
- setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
+ setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq);
tmu0_clk.parent = clk_get(NULL, "module_clk");
+ tmu1_clk.parent = clk_get(NULL, "module_clk");
- /* Start TMU0 */
tmu_timer_stop();
+
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
!defined(CONFIG_CPU_SUBTYPE_SH7760) && \
!defined(CONFIG_CPU_SUBTYPE_SH7785)
@@ -155,15 +179,29 @@ static int tmu_timer_init(void)
#endif
clk_register(&tmu0_clk);
+ clk_register(&tmu1_clk);
clk_enable(&tmu0_clk);
+ clk_enable(&tmu1_clk);
- interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
- printk(KERN_INFO "Interval = %ld\n", interval);
+ frequency = clk_get_rate(&tmu0_clk);
+ interval = (frequency + HZ / 2) / HZ;
- ctrl_outl(interval, TMU0_TCOR);
- ctrl_outl(interval, TMU0_TCNT);
+ sh_hpt_frequency = clk_get_rate(&tmu1_clk);
+ ctrl_outl(~0, TMU1_TCNT);
+ ctrl_outl(~0, TMU1_TCOR);
- tmu_timer_start();
+ tmu0_timer_set_interval(interval, 1);
+
+ tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
+ tmu0_clockevent.shift);
+ tmu0_clockevent.max_delta_ns =
+ clockevent_delta2ns(-1, &tmu0_clockevent);
+ tmu0_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &tmu0_clockevent);
+
+ tmu0_clockevent.cpumask = cpumask_of_cpu(0);
+
+ clockevents_register_device(&tmu0_clockevent);
return 0;
}
@@ -172,9 +210,7 @@ struct sys_timer_ops tmu_timer_ops = {
.init = tmu_timer_init,
.start = tmu_timer_start,
.stop = tmu_timer_stop,
-#ifndef CONFIG_GENERIC_TIME
- .get_offset = tmu_timer_get_offset,
-#endif
+ .read = tmu_timer_read,
};
struct sys_timer tmu_timer = {
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 7b40f0ff3dfc..3a197649cd83 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -20,10 +20,10 @@
#include <linux/io.h>
#include <linux/bug.h>
#include <linux/debug_locks.h>
+#include <linux/kdebug.h>
#include <linux/limits.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/kdebug.h>
#ifdef CONFIG_SH_KGDB
#include <asm/kgdb.h>
@@ -76,20 +76,6 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
}
}
-ATOMIC_NOTIFIER_HEAD(shdie_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&shdie_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
static DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * regs, long err)
@@ -505,7 +491,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
simple:
ret = handle_unaligned_ins(instruction,regs);
if (ret==0)
- regs->pc += 2;
+ regs->pc += instruction_size(instruction);
return ret;
}
#endif /* CONFIG_CPU_SH2A */
@@ -682,7 +668,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
err = do_fpu_inst(inst, regs);
if (!err) {
- regs->pc += 2;
+ regs->pc += instruction_size(inst);
return;
}
/* not a FPU inst. */
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index 7b0f66f03319..e146bafcd14f 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/kernel/vsyscall.c
+ * arch/sh/kernel/vsyscall/vsyscall.c
*
* Copyright (C) 2006 Paul Mundt
*
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c
index 351714694d6d..f3ddd2133e6f 100644
--- a/arch/sh/lib/delay.c
+++ b/arch/sh/lib/delay.c
@@ -24,9 +24,10 @@ inline void __const_udelay(unsigned long xloops)
__asm__("dmulu.l %0, %2\n\t"
"sts mach, %0"
: "=r" (xloops)
- : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
+ : "0" (xloops),
+ "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy)
: "macl", "mach");
- __delay(xloops * HZ);
+ __delay(xloops);
}
void __udelay(unsigned long usecs)
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 12f3d394dc28..253346d7b316 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -218,6 +218,9 @@ endmenu
menu "Memory management options"
+config QUICKLIST
+ def_bool y
+
config MMU
bool "Support for memory management hardware"
depends on !CPU_SH2
@@ -300,6 +303,10 @@ config NODES_SHIFT
config ARCH_FLATMEM_ENABLE
def_bool y
+config MAX_ACTIVE_REGIONS
+ int
+ default "1"
+
config ARCH_POPULATES_NODE_MAP
def_bool y
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 0ecc117cade4..9207da67ff8a 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -15,7 +15,7 @@
#include <linux/mm.h>
#include <linux/hardirq.h>
#include <linux/kprobes.h>
-#include <asm/kdebug.h>
+#include <linux/kdebug.h>
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4d030988b368..8fe223a890ed 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -67,6 +67,8 @@ void show_mem(void)
printk("%d slab pages\n", slab);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n", cached);
+ printk(KERN_INFO "Total of %ld pages in page table cache\n",
+ quicklist_total_size());
}
#ifdef CONFIG_MMU
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index 29d7cfd1c970..6773ed76e414 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -28,7 +28,7 @@ int foo(void)
DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid));
DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid));
DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid));
- /* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */
+ /* DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); */
DEFINE(ASIZ_task_uid, sizeof(current->uid));
DEFINE(ASIZ_task_gid, sizeof(current->gid));
DEFINE(ASIZ_task_euid, sizeof(current->euid));
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index dc652f210290..d0fde36395b4 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/kdebug.h>
+#include <asm/smp.h>
#include <asm/delay.h>
#include <asm/system.h>
#include <asm/ptrace.h>
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 354cc6b70530..b9c0f307a8fa 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -320,21 +320,7 @@ source "crypto/Kconfig"
source "lib/Kconfig"
-menu "SCSI support"
-depends on BROKEN
-
-config SCSI
- tristate "SCSI support"
-
-# This gives us free_dma, which scsi.c wants.
-config GENERIC_ISA_DMA
- bool
- depends on SCSI
- default y
-
-source "arch/um/Kconfig.scsi"
-
-endmenu
+source "drivers/scsi/Kconfig"
source "drivers/md/Kconfig"
diff --git a/arch/um/Kconfig.scsi b/arch/um/Kconfig.scsi
deleted file mode 100644
index c291c942b1a8..000000000000
--- a/arch/um/Kconfig.scsi
+++ /dev/null
@@ -1,58 +0,0 @@
-comment "SCSI support type (disk, tape, CD-ROM)"
- depends on SCSI
-
-config BLK_DEV_SD
- tristate "SCSI disk support"
- depends on SCSI
-
-config SD_EXTRA_DEVS
- int "Maximum number of SCSI disks that can be loaded as modules"
- depends on BLK_DEV_SD
- default "40"
-
-config CHR_DEV_ST
- tristate "SCSI tape support"
- depends on SCSI
-
-config BLK_DEV_SR
- tristate "SCSI CD-ROM support"
- depends on SCSI
-
-config BLK_DEV_SR_VENDOR
- bool "Enable vendor-specific extensions (for SCSI CDROM)"
- depends on BLK_DEV_SR
-
-config SR_EXTRA_DEVS
- int "Maximum number of CDROM devices that can be loaded as modules"
- depends on BLK_DEV_SR
- default "2"
-
-config CHR_DEV_SG
- tristate "SCSI generic support"
- depends on SCSI
-
-comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
- depends on SCSI
-
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-config SCSI_DEBUG_QUEUES
- bool "Enable extra checks in new queueing code"
- depends on SCSI
-
-#fi
-config SCSI_MULTI_LUN
- bool "Probe all LUNs on each SCSI device"
- depends on SCSI
-
-config SCSI_CONSTANTS
- bool "Verbose SCSI error reporting (kernel size +=12K)"
- depends on SCSI
-
-config SCSI_LOGGING
- bool "SCSI logging facility"
- depends on SCSI
-
-config SCSI_DEBUG
- tristate "SCSI debugging host simulator (EXPERIMENTAL)"
- depends on SCSI
-
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h
index 11bafab669e9..0f312085ce1d 100644
--- a/arch/um/include/sysdep-i386/archsetjmp.h
+++ b/arch/um/include/sysdep-i386/archsetjmp.h
@@ -1,5 +1,5 @@
/*
- * arch/i386/include/klibc/archsetjmp.h
+ * arch/um/include/sysdep-i386/archsetjmp.h
*/
#ifndef _KLIBC_ARCHSETJMP_H
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h
index 9a5e1a6ec800..2af8f12ca161 100644
--- a/arch/um/include/sysdep-x86_64/archsetjmp.h
+++ b/arch/um/include/sysdep-x86_64/archsetjmp.h
@@ -1,5 +1,5 @@
/*
- * arch/x86_64/include/klibc/archsetjmp.h
+ * arch/um/include/sysdep-x86_64/archsetjmp.h
*/
#ifndef _KLIBC_ARCHSETJMP_H
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index ef36facd8fe9..a96ae1a0610e 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -178,20 +178,23 @@ int start_uml_skas(void)
int external_pid_skas(struct task_struct *task)
{
-#warning Need to look up userspace_pid by cpu
+ /* FIXME: Need to look up userspace_pid by cpu */
return(userspace_pid[0]);
}
int thread_pid_skas(struct task_struct *task)
{
-#warning Need to look up userspace_pid by cpu
+ /* FIXME: Need to look up userspace_pid by cpu */
return(userspace_pid[0]);
}
void kill_off_processes_skas(void)
{
if(proc_mm)
-#warning need to loop over userspace_pids in kill_off_processes_skas
+ /*
+ * FIXME: need to loop over userspace_pids in
+ * kill_off_processes_skas
+ */
os_kill_ptraced_process(userspace_pid[0], 1);
else {
struct task_struct *p;
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 92a7b59120d6..2d9d2ca39299 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -239,6 +239,7 @@ out:
return ok;
}
+#ifdef UML_CONFIG_MODE_TT
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0, pages;
@@ -260,6 +261,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
"errno = %d\n", errno);
}
}
+#endif
void init_new_thread_signals(void)
{
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 8e490fff3d47..5c8946320799 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -68,7 +68,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
int err, pid = mm_idp->u.pid;
if(proc_mm)
-#warning Need to look up userspace_pid by cpu
+ /* FIXME: Need to look up userspace_pid by cpu */
pid = userspace_pid[0];
multi_count++;
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 5c088a55396c..6a0e466d01e3 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -586,7 +586,7 @@ void switch_mm_skas(struct mm_id *mm_idp)
{
int err;
-#warning need cpu pid in switch_mm_skas
+ /* FIXME: need cpu pid in switch_mm_skas */
if(proc_mm){
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
mm_idp->u.mm_fd);
diff --git a/arch/v850/kernel/asm-offsets.c b/arch/v850/kernel/asm-offsets.c
index 24f291369070..cee5c3142d41 100644
--- a/arch/v850/kernel/asm-offsets.c
+++ b/arch/v850/kernel/asm-offsets.c
@@ -29,7 +29,7 @@ int main (void)
DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
- DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+ DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack));
DEFINE (TASK_MM, offsetof (struct task_struct, mm));
DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
DEFINE (TASK_PID, offsetof (struct task_struct, pid));
diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
index 8bc521ca081f..e4327a8d6bcd 100644
--- a/arch/v850/kernel/entry.S
+++ b/arch/v850/kernel/entry.S
@@ -523,7 +523,7 @@ END(ret_from_trap)
/* This the initial entry point for a new child thread, with an appropriate
- stack in place that makes it look the the child is in the middle of an
+ stack in place that makes it look that the child is in the middle of an
syscall. This function is actually `returned to' from switch_thread
(copy_thread makes ret_from_fork the return address in each new thread's
saved context). */
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 4d582589fa89..d8bfe315471c 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1413,7 +1413,7 @@ static void ack_apic_level(unsigned int irq)
/*
* We must acknowledge the irq before we move it or the acknowledge will
- * not propogate properly.
+ * not propagate properly.
*/
ack_APIC_irq();
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 3bc30d2c13d3..3eaceac32481 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -32,7 +32,7 @@ atomic_t irq_err_count;
*/
static inline void stack_overflow_check(struct pt_regs *regs)
{
- u64 curbase = (u64) current->thread_info;
+ u64 curbase = (u64)task_stack_page(current);
static unsigned long warned = -60*HZ;
if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 442169640e45..a14375dd5425 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -720,9 +720,11 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
mce_create_device(cpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
mce_remove_device(cpu);
break;
}
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index d0bd5d66e103..03356e64f9c8 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -654,9 +654,11 @@ static int threshold_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
threshold_create_device(cpu);
break;
case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
threshold_remove_device(cpu);
break;
default:
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index dc32cef96195..51d4c6fa88c8 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -327,7 +327,7 @@ static int __cpuinit
cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
{
long cpu = (long)arg;
- if (action == CPU_ONLINE)
+ if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
return NOTIFY_DONE;
}
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index b256cfbef344..698079b3a336 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -70,7 +70,7 @@ int main(void)
DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
DEFINE(TASK_PID, offsetof (struct task_struct, pid));
DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
- DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+ DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack));
DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
BLANK();
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index ca76f071666e..f5319d78c876 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -1,5 +1,5 @@
/*
- * arch/xtensa/pci-dma.c
+ * arch/xtensa/kernel/pci-dma.c
*
* DMA coherent memory allocation.
*